passagemath-graphs 10.5.10__cp39-cp39-macosx_14_0_arm64.whl → 10.5.43__cp39-cp39-macosx_14_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/METADATA +126 -30
  2. passagemath_graphs-10.5.43.dist-info/RECORD +256 -0
  3. {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/WHEEL +2 -1
  4. passagemath_graphs.dylibs/libgmp.10.dylib +0 -0
  5. sage/all__sagemath_graphs.py +5 -0
  6. sage/combinat/abstract_tree.py +1 -1
  7. sage/combinat/binary_tree.py +1 -1
  8. sage/combinat/cluster_algebra_quiver/all.py +1 -1
  9. sage/combinat/cluster_algebra_quiver/cluster_seed.py +28 -24
  10. sage/combinat/cluster_algebra_quiver/interact.py +4 -0
  11. sage/combinat/designs/MOLS_handbook_data.py +5 -5
  12. sage/combinat/designs/bibd.py +10 -9
  13. sage/combinat/designs/covering_array.py +3 -3
  14. sage/combinat/designs/covering_design.py +2 -1
  15. sage/combinat/designs/database.py +11 -10
  16. sage/combinat/designs/designs_pyx.cpython-39-darwin.so +0 -0
  17. sage/combinat/designs/designs_pyx.pyx +13 -45
  18. sage/combinat/designs/difference_family.py +6 -6
  19. sage/combinat/designs/difference_matrices.py +1 -1
  20. sage/combinat/designs/evenly_distributed_sets.cpython-39-darwin.so +0 -0
  21. sage/combinat/designs/evenly_distributed_sets.pyx +15 -22
  22. sage/combinat/designs/ext_rep.py +9 -14
  23. sage/combinat/designs/gen_quadrangles_with_spread.cpython-39-darwin.so +0 -0
  24. sage/combinat/designs/gen_quadrangles_with_spread.pyx +1 -1
  25. sage/combinat/designs/group_divisible_designs.py +1 -1
  26. sage/combinat/designs/incidence_structures.py +8 -8
  27. sage/combinat/designs/latin_squares.py +1 -1
  28. sage/combinat/designs/orthogonal_arrays_build_recursive.py +8 -7
  29. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-39-darwin.so +0 -0
  30. sage/combinat/designs/resolvable_bibd.py +1 -1
  31. sage/combinat/designs/steiner_quadruple_systems.py +1 -1
  32. sage/combinat/designs/subhypergraph_search.cpython-39-darwin.so +0 -0
  33. sage/combinat/designs/subhypergraph_search.pyx +9 -9
  34. sage/combinat/finite_state_machine_generators.py +2 -2
  35. sage/combinat/graph_path.py +3 -3
  36. sage/combinat/interval_posets.py +10 -10
  37. sage/combinat/ordered_tree.py +1 -1
  38. sage/combinat/posets/cartesian_product.py +1 -1
  39. sage/combinat/posets/d_complete.py +1 -1
  40. sage/combinat/posets/forest.py +1 -1
  41. sage/combinat/posets/hasse_cython.cpython-39-darwin.so +0 -0
  42. sage/combinat/posets/hasse_diagram.py +8 -6
  43. sage/combinat/posets/incidence_algebras.py +8 -8
  44. sage/combinat/posets/lattices.py +28 -4
  45. sage/combinat/posets/linear_extension_iterator.cpython-39-darwin.so +0 -0
  46. sage/combinat/posets/linear_extension_iterator.pyx +2 -0
  47. sage/combinat/posets/linear_extensions.py +7 -16
  48. sage/combinat/posets/moebius_algebra.py +1 -1
  49. sage/combinat/posets/poset_examples.py +1 -1
  50. sage/combinat/posets/posets.py +54 -56
  51. sage/combinat/rooted_tree.py +3 -3
  52. sage/combinat/tamari_lattices.py +1 -1
  53. sage/ext_data/kenzo/CP2.txt +45 -0
  54. sage/ext_data/kenzo/CP3.txt +349 -0
  55. sage/ext_data/kenzo/CP4.txt +4774 -0
  56. sage/ext_data/kenzo/README.txt +49 -0
  57. sage/ext_data/kenzo/S4.txt +20 -0
  58. sage/graphs/asteroidal_triples.cpython-39-darwin.so +0 -0
  59. sage/graphs/base/boost_graph.cpython-39-darwin.so +0 -0
  60. sage/graphs/base/boost_graph.pxd +1 -1
  61. sage/graphs/base/boost_graph.pyx +1 -1
  62. sage/graphs/base/c_graph.cpython-39-darwin.so +0 -0
  63. sage/graphs/base/c_graph.pxd +4 -4
  64. sage/graphs/base/c_graph.pyx +270 -184
  65. sage/graphs/base/dense_graph.cpython-39-darwin.so +0 -0
  66. sage/graphs/base/graph_backends.cpython-39-darwin.so +0 -0
  67. sage/graphs/base/sparse_graph.cpython-39-darwin.so +0 -0
  68. sage/graphs/base/static_dense_graph.cpython-39-darwin.so +0 -0
  69. sage/graphs/base/static_sparse_backend.cpython-39-darwin.so +0 -0
  70. sage/graphs/base/static_sparse_backend.pyx +93 -6
  71. sage/graphs/base/static_sparse_graph.cpython-39-darwin.so +0 -0
  72. sage/graphs/base/static_sparse_graph.pyx +1 -1
  73. sage/graphs/bipartite_graph.py +0 -1
  74. sage/graphs/centrality.cpython-39-darwin.so +0 -0
  75. sage/graphs/centrality.pyx +0 -0
  76. sage/graphs/comparability.cpython-39-darwin.so +0 -0
  77. sage/graphs/comparability.pyx +172 -138
  78. sage/graphs/connectivity.cpython-39-darwin.so +0 -0
  79. sage/graphs/connectivity.pyx +194 -18
  80. sage/graphs/convexity_properties.cpython-39-darwin.so +0 -0
  81. sage/graphs/digraph_generators.py +118 -74
  82. sage/graphs/distances_all_pairs.cpython-39-darwin.so +0 -0
  83. sage/graphs/distances_all_pairs.pyx +145 -27
  84. sage/graphs/edge_connectivity.cpython-39-darwin.so +0 -0
  85. sage/graphs/generators/basic.py +471 -130
  86. sage/graphs/generators/distance_regular.cpython-39-darwin.so +0 -0
  87. sage/graphs/generators/distance_regular.pyx +12 -12
  88. sage/graphs/generators/families.py +2 -2
  89. sage/graphs/generators/random.py +8 -13
  90. sage/graphs/generators/smallgraphs.py +12 -11
  91. sage/graphs/generic_graph.py +687 -265
  92. sage/graphs/generic_graph_pyx.cpython-39-darwin.so +0 -0
  93. sage/graphs/genus.cpython-39-darwin.so +0 -0
  94. sage/graphs/graph.py +12 -46
  95. sage/graphs/graph_coloring.cpython-39-darwin.so +0 -0
  96. sage/graphs/graph_database.py +1 -1
  97. sage/graphs/graph_decompositions/bandwidth.cpython-39-darwin.so +0 -0
  98. sage/graphs/graph_decompositions/clique_separators.cpython-39-darwin.so +0 -0
  99. sage/graphs/graph_decompositions/cutwidth.cpython-39-darwin.so +0 -0
  100. sage/graphs/graph_decompositions/fast_digraph.cpython-39-darwin.so +0 -0
  101. sage/graphs/graph_decompositions/graph_products.cpython-39-darwin.so +0 -0
  102. sage/graphs/graph_decompositions/modular_decomposition.cpython-39-darwin.so +0 -0
  103. sage/graphs/graph_decompositions/slice_decomposition.cpython-39-darwin.so +0 -0
  104. sage/graphs/graph_decompositions/tree_decomposition.cpython-39-darwin.so +0 -0
  105. sage/graphs/graph_decompositions/vertex_separation.cpython-39-darwin.so +0 -0
  106. sage/graphs/graph_generators.py +110 -55
  107. sage/graphs/graph_generators_pyx.cpython-39-darwin.so +0 -0
  108. sage/graphs/graph_latex.py +1 -1
  109. sage/graphs/graph_list.py +2 -3
  110. sage/graphs/graph_plot.py +225 -30
  111. sage/graphs/hyperbolicity.cpython-39-darwin.so +0 -0
  112. sage/graphs/independent_sets.cpython-39-darwin.so +0 -0
  113. sage/graphs/isgci.py +3 -8
  114. sage/graphs/isoperimetric_inequalities.cpython-39-darwin.so +0 -0
  115. sage/graphs/line_graph.cpython-39-darwin.so +0 -0
  116. sage/graphs/matching.py +14 -25
  117. sage/graphs/matching_covered_graph.py +871 -60
  118. sage/graphs/orientations.py +190 -134
  119. sage/graphs/path_enumeration.cpython-39-darwin.so +0 -0
  120. sage/graphs/path_enumeration.pyx +25 -25
  121. sage/graphs/spanning_tree.cpython-39-darwin.so +0 -0
  122. sage/graphs/strongly_regular_db.cpython-39-darwin.so +0 -0
  123. sage/graphs/strongly_regular_db.pyx +54 -52
  124. sage/graphs/traversals.cpython-39-darwin.so +0 -0
  125. sage/graphs/traversals.pyx +114 -46
  126. sage/graphs/trees.cpython-39-darwin.so +0 -0
  127. sage/graphs/views.cpython-39-darwin.so +0 -0
  128. sage/graphs/weakly_chordal.cpython-39-darwin.so +0 -0
  129. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-39-darwin.so +0 -0
  130. sage/knots/free_knotinfo_monoid.py +2 -3
  131. sage/knots/knot.py +1 -1
  132. sage/knots/knotinfo.py +4 -4
  133. sage/knots/link.py +58 -57
  134. sage/sandpiles/sandpile.py +2 -3
  135. sage/topology/cell_complex.py +1 -1
  136. sage/topology/cubical_complex.py +7 -7
  137. sage/topology/delta_complex.py +4 -4
  138. sage/topology/simplicial_complex.py +7 -22
  139. passagemath_graphs-10.5.10.dist-info/RECORD +0 -251
  140. {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/top_level.txt +0 -0
@@ -21,13 +21,18 @@ from sage.graphs.graph import Graph
21
21
  from math import sin, cos, pi
22
22
 
23
23
 
24
- def BullGraph():
24
+ def BullGraph(immutable=False):
25
25
  r"""
26
26
  Return a bull graph with 5 nodes.
27
27
 
28
28
  A bull graph is named for its shape. It's a triangle with horns.
29
29
  See the :wikipedia:`Bull_graph` for more information.
30
30
 
31
+ INPUT:
32
+
33
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
34
+ immutable or a mutable graph
35
+
31
36
  PLOTTING:
32
37
 
33
38
  Upon construction, the position dictionary is filled to override the
@@ -85,13 +90,21 @@ def BullGraph():
85
90
  True
86
91
  sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly
87
92
  True
93
+
94
+ TESTS:
95
+
96
+ Check the behavior of parameter ``immutable``::
97
+
98
+ sage: graphs.BullGraph(immutable=True).is_immutable()
99
+ True
88
100
  """
89
101
  edge_list = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 4)]
90
102
  pos_dict = {0: (0, 0), 1: (-1, 1), 2: (1, 1), 3: (-2, 2), 4: (2, 2)}
91
- return Graph(edge_list, pos=pos_dict, name="Bull graph")
103
+ return Graph([range(5), edge_list], format='vertices_and_edges',
104
+ immutable=immutable, pos=pos_dict, name="Bull graph")
92
105
 
93
106
 
94
- def ButterflyGraph():
107
+ def ButterflyGraph(immutable=False):
95
108
  r"""
96
109
  Return the butterfly graph.
97
110
 
@@ -104,6 +117,11 @@ def ButterflyGraph():
104
117
 
105
118
  - :meth:`~sage.graphs.graph_generators.GraphGenerators.FriendshipGraph`
106
119
 
120
+ INPUT:
121
+
122
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
123
+ immutable or a mutable graph
124
+
107
125
  EXAMPLES:
108
126
 
109
127
  The butterfly graph is a planar graph on 5 vertices and having 6 edges::
@@ -133,6 +151,13 @@ def ButterflyGraph():
133
151
  True
134
152
  sage: G.chromatic_number() # needs cliquer
135
153
  3
154
+
155
+ TESTS:
156
+
157
+ Check the behavior of parameter ``immutable``::
158
+
159
+ sage: graphs.ButterflyGraph(immutable=True).is_immutable()
160
+ True
136
161
  """
137
162
  edge_dict = {
138
163
  0: [3, 4],
@@ -145,10 +170,11 @@ def ButterflyGraph():
145
170
  2: [1, -1],
146
171
  3: [-1, -1],
147
172
  4: [0, 0]}
148
- return Graph(edge_dict, pos=pos_dict, name="Butterfly graph")
173
+ return Graph(edge_dict, format='dict_of_lists',
174
+ immutable=immutable, pos=pos_dict, name="Butterfly graph")
149
175
 
150
176
 
151
- def CircularLadderGraph(n):
177
+ def CircularLadderGraph(n, immutable=False):
152
178
  r"""
153
179
  Return a circular ladder graph with `2 * n` nodes.
154
180
 
@@ -167,6 +193,13 @@ def CircularLadderGraph(n):
167
193
  that all edges are visible (otherwise the 4 vertices of the graph would be
168
194
  placed on a single line).
169
195
 
196
+ INPUT:
197
+
198
+ - ``n`` -- nonnegative integer
199
+
200
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
201
+ immutable or a mutable graph
202
+
170
203
  EXAMPLES:
171
204
 
172
205
  Construct and show a circular ladder graph with 26 nodes::
@@ -188,20 +221,29 @@ def CircularLadderGraph(n):
188
221
  ....: j.append(n)
189
222
  sage: G = graphics_array(j) # needs sage.plot
190
223
  sage: G.show() # long time # needs sage.plot
224
+
225
+ TESTS::
226
+
227
+ sage: G = graphs.CircularLadderGraph(4, immutable=True)
228
+ sage: G.is_immutable()
229
+ True
191
230
  """
192
- G = Graph(2 * n, name="Circular Ladder graph")
231
+ from itertools import chain
232
+ edges_1 = zip(range(n), chain(range(1, n), (0,)))
233
+ edges_2 = zip(range(n, 2 * n), chain(range(n + 1, 2 * n), (n,)))
234
+ edges_3 = ((i, i + n) for i in range(n))
235
+ G = Graph([range(2 * n), chain(edges_1, edges_2, edges_3)],
236
+ format='vertices_and_edges', immutable=immutable,
237
+ name="Circular Ladder graph")
193
238
  G._circle_embedding(list(range(n)), radius=1, angle=pi/2)
194
239
  if n == 2:
195
240
  G._circle_embedding(list(range(4)), radius=1, angle=pi/2 + pi/8)
196
241
  else:
197
242
  G._circle_embedding(list(range(n, 2*n)), radius=2, angle=pi/2)
198
- G.add_cycle(list(range(n)))
199
- G.add_cycle(list(range(n, 2 * n)))
200
- G.add_edges((i, i + n) for i in range(n))
201
243
  return G
202
244
 
203
245
 
204
- def ClawGraph():
246
+ def ClawGraph(immutable=False):
205
247
  """
206
248
  Return a claw graph.
207
249
 
@@ -210,6 +252,11 @@ def ClawGraph():
210
252
 
211
253
  PLOTTING: See :meth:`CompleteBipartiteGraph`.
212
254
 
255
+ INPUT:
256
+
257
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
258
+ immutable or a mutable graph
259
+
213
260
  EXAMPLES:
214
261
 
215
262
  Show a Claw graph::
@@ -221,19 +268,34 @@ def ClawGraph():
221
268
  sage: G = graphs.ClawGraph()
222
269
  sage: G
223
270
  Claw graph: Graph on 4 vertices
271
+
272
+ TESTS:
273
+
274
+ Check the behavior of parameter ``immutable``::
275
+
276
+ sage: graphs.ClawGraph(immutable=True).is_immutable()
277
+ True
224
278
  """
225
279
  edge_list = [(0, 1), (0, 2), (0, 3)]
226
280
  pos_dict = {0: (0, 1), 1: (-1, 0), 2: (0, 0), 3: (1, 0)}
227
- return Graph(edge_list, pos=pos_dict, name="Claw graph")
281
+ return Graph([range(4), edge_list], format='vertices_and_edges',
282
+ immutable=immutable, pos=pos_dict, name="Claw graph")
228
283
 
229
284
 
230
- def CycleGraph(n):
285
+ def CycleGraph(n, immutable=False):
231
286
  r"""
232
287
  Return a cycle graph with `n` nodes.
233
288
 
234
289
  A cycle graph is a basic structure which is also typically called an
235
290
  `n`-gon.
236
291
 
292
+ INPUT:
293
+
294
+ - ``n`` -- nonnegative integer; the number of vertices of the cycle graph
295
+
296
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
297
+ immutable or a mutable graph
298
+
237
299
  PLOTTING: Upon construction, the position dictionary is filled to override
238
300
  the spring-layout algorithm. By convention, each cycle graph will be
239
301
  displayed with the first (0) node at the top, with the rest following in a
@@ -300,26 +362,40 @@ def CycleGraph(n):
300
362
  Traceback (most recent call last):
301
363
  ...
302
364
  ValueError: parameter n must be a positive integer
365
+
366
+ Check the behavior of parameter ``immutable``::
367
+
368
+ sage: graphs.CycleGraph(4, immutable=True).is_immutable()
369
+ True
303
370
  """
304
371
  if n < 0:
305
372
  raise ValueError("parameter n must be a positive integer")
306
373
 
307
- G = Graph(n, name="Cycle graph")
374
+ from itertools import chain
375
+ edges = zip(range(n), chain(range(1, n), (0,))) if n > 1 else []
376
+ G = Graph([range(n), edges], format='vertices_and_edges',
377
+ immutable=immutable, name="Cycle graph")
308
378
  if n == 1:
309
379
  G.set_pos({0: (0, 0)})
310
380
  else:
311
381
  G._circle_embedding(list(range(n)), angle=pi/2)
312
- G.add_cycle(list(range(n)))
313
382
  return G
314
383
 
315
384
 
316
- def CompleteGraph(n):
385
+ def CompleteGraph(n, immutable=False):
317
386
  r"""
318
387
  Return a complete graph on `n` nodes.
319
388
 
320
389
  A Complete Graph is a graph in which all nodes are connected to all
321
390
  other nodes.
322
391
 
392
+ INPUT:
393
+
394
+ - ``n`` -- nonnegative integer; the number of vertices of the complete graph
395
+
396
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
397
+ immutable or a mutable graph
398
+
323
399
  PLOTTING: Upon construction, the position dictionary is filled to
324
400
  override the spring-layout algorithm. By convention, each complete
325
401
  graph will be displayed with the first (0) node at the top, with
@@ -393,17 +469,26 @@ def CompleteGraph(n):
393
469
  sage: posdict23 = graphs.CompleteGraph(23)
394
470
  sage: spring23.show() # long time # needs sage.plot
395
471
  sage: posdict23.show() # long time # needs sage.plot
472
+
473
+ TESTS:
474
+
475
+ Check the behavior of parameter ``immutable``::
476
+
477
+ sage: graphs.CompleteGraph(4, immutable=True).is_immutable()
478
+ True
396
479
  """
397
- G = Graph(n, name="Complete graph")
480
+ from itertools import combinations
481
+ G = Graph([range(n), combinations(range(n), 2)],
482
+ format='vertices_and_edges', immutable=immutable,
483
+ name="Complete graph")
398
484
  if n == 1:
399
485
  G.set_pos({0: (0, 0)})
400
486
  else:
401
487
  G._circle_embedding(list(range(n)), angle=pi/2)
402
- G.add_edges((i, j) for i in range(n) for j in range(i + 1, n))
403
488
  return G
404
489
 
405
490
 
406
- def CorrelationGraph(seqs, alpha, include_anticorrelation):
491
+ def CorrelationGraph(seqs, alpha, include_anticorrelation, immutable=False):
407
492
  r"""
408
493
  Return a correlation graph with a node per sequence in ``seqs``.
409
494
 
@@ -423,6 +508,9 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation):
423
508
  - ``include_anticorrelation`` -- boolean; whether to add edges between nodes
424
509
  with correlation coefficient less than ``-alpha`` or not
425
510
 
511
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
512
+ immutable or a mutable graph
513
+
426
514
  EXAMPLES::
427
515
 
428
516
  sage: # needs numpy
@@ -437,6 +525,17 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation):
437
525
  [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)]
438
526
  sage: CG3.edges(sort=False)
439
527
  [(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)]
528
+
529
+ TESTS:
530
+
531
+ Check the behavior of parameter ``immutable``::
532
+
533
+ sage: # needs numpy
534
+ sage: from sage.graphs.generators.basic import CorrelationGraph
535
+ sage: CorrelationGraph(data, 0.9, False, immutable=True).is_immutable()
536
+ True
537
+ sage: CorrelationGraph(data, 0.9, True, immutable=True).is_immutable()
538
+ True
440
539
  """
441
540
  from numpy import corrcoef
442
541
  from sage.matrix.constructor import Matrix
@@ -453,10 +552,11 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation):
453
552
  adjacency_matrix = Matrix(boolean_adjacency_matrix.astype(int))
454
553
 
455
554
  # call graph constructor
456
- return Graph(adjacency_matrix, format='adjacency_matrix', name="Correlation Graph")
555
+ return Graph(adjacency_matrix, format='adjacency_matrix',
556
+ immutable=immutable, name="Correlation Graph")
457
557
 
458
558
 
459
- def CompleteBipartiteGraph(p, q, set_position=True):
559
+ def CompleteBipartiteGraph(p, q, set_position=True, immutable=False, name=None):
460
560
  r"""
461
561
  Return a Complete Bipartite Graph on `p + q` vertices.
462
562
 
@@ -472,6 +572,12 @@ def CompleteBipartiteGraph(p, q, set_position=True):
472
572
  assign positions to the vertices so that the set of cardinality `p` is
473
573
  on the line `y=1` and the set of cardinality `q` is on the line `y=0`.
474
574
 
575
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
576
+ immutable or a mutable graph
577
+
578
+ - ``name`` -- string (default: ``None``); used as the name of the returned
579
+ graph when set
580
+
475
581
  PLOTTING: Upon construction, the position dictionary is filled to override
476
582
  the spring-layout algorithm. By convention, each complete bipartite graph
477
583
  will be displayed with the first `p` nodes on the top row (at `y=1`) from
@@ -567,12 +673,24 @@ def CompleteBipartiteGraph(p, q, set_position=True):
567
673
  Traceback (most recent call last):
568
674
  ...
569
675
  ValueError: the arguments p(=1) and q(=-1) must be positive integers
676
+
677
+ Check the behavior of parameter ``immutable``::
678
+
679
+ sage: graphs.CompleteBipartiteGraph(1, 2, immutable=True).is_immutable()
680
+ True
681
+
682
+ Check the behavior of parameter ``name``::
683
+
684
+ sage: graphs.CompleteBipartiteGraph(1, 2, name='foo')
685
+ foo: Graph on 3 vertices
570
686
  """
571
687
  if p < 0 or q < 0:
572
688
  raise ValueError('the arguments p(={}) and q(={}) must be positive integers'.format(p, q))
573
689
 
574
- G = Graph(p + q, name="Complete bipartite graph of order {}+{}".format(p, q))
575
- G.add_edges((i, j) for i in range(p) for j in range(p, p + q))
690
+ name = f"Complete bipartite graph of order {p}+{q}" if name is None else name
691
+ edges = ((i, j) for i in range(p) for j in range(p, p + q))
692
+ G = Graph([range(p + q), edges], format='vertices_and_edges',
693
+ immutable=immutable, name=name)
576
694
 
577
695
  # We now assign positions to vertices:
578
696
  # - vertices 0,..,p-1 are placed on the line (0, 1) to (max(p, q), 1)
@@ -586,7 +704,7 @@ def CompleteBipartiteGraph(p, q, set_position=True):
586
704
  return G
587
705
 
588
706
 
589
- def CompleteMultipartiteGraph(L):
707
+ def CompleteMultipartiteGraph(L, immutable=False):
590
708
  r"""
591
709
  Return a complete multipartite graph.
592
710
 
@@ -594,6 +712,9 @@ def CompleteMultipartiteGraph(L):
594
712
 
595
713
  - ``L`` -- list of integers; the respective sizes of the components
596
714
 
715
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
716
+ immutable or a mutable graph
717
+
597
718
  PLOTTING: Produce a layout of the vertices so that vertices in the same
598
719
  vertex set are adjacent and clearly separated from vertices in other vertex
599
720
  sets.
@@ -617,53 +738,74 @@ def CompleteMultipartiteGraph(L):
617
738
 
618
739
  sage: g.chromatic_number() # needs cliquer
619
740
  3
741
+
742
+ TESTS:
743
+
744
+ Prevent negative dimensions::
745
+
746
+ sage: graphs.CompleteMultipartiteGraph([1, -1, 2])
747
+ Traceback (most recent call last):
748
+ ...
749
+ ValueError: the sizes of the components must be positive integers
750
+
751
+ Check the bahavior of parameter ``immutable``::
752
+
753
+ sage: graphs.CompleteMultipartiteGraph([1], immutable=True).is_immutable()
754
+ True
755
+ sage: graphs.CompleteMultipartiteGraph([1, 2], immutable=True).is_immutable()
756
+ True
757
+ sage: graphs.CompleteMultipartiteGraph([1, 2, 3], immutable=True).is_immutable()
758
+ True
620
759
  """
760
+ if any(p < 0 for p in L):
761
+ raise ValueError("the sizes of the components must be positive integers")
762
+
621
763
  r = len(L) # getting the number of partitions
622
764
  name = "Multipartite Graph with set sizes {}".format(L)
623
765
 
624
766
  if not r:
625
- g = Graph()
626
- elif r == 1:
627
- g = Graph(L[0])
767
+ return Graph(name=name, immutable=immutable)
768
+ if r == 1:
769
+ g = Graph(L[0], immutable=immutable, name=name)
628
770
  g._line_embedding(range(L[0]), first=(0, 0), last=(L[0], 0))
629
- elif r == 2:
630
- g = CompleteBipartiteGraph(L[0], L[1])
631
- g.name(name)
632
- else:
633
- # This position code gives bad results on bipartite or isolated graphs
634
- points = [(cos(2 * pi * i / r), sin(2 * pi * i / r)) for i in range(r)]
635
- slopes = [(points[(i + 1) % r][0] - points[i % r][0],
636
- points[(i + 1) % r][1] - points[i % r][1]) for i in range(r)]
637
-
638
- counter = 0
639
- positions = {}
640
- for i in range(r):
641
- vertex_set_size = L[i] + 1
642
- for j in range(1, vertex_set_size):
643
- x = points[i][0] + slopes[i][0] * j / vertex_set_size
644
- y = points[i][1] + slopes[i][1] * j / vertex_set_size
645
- positions[counter] = (x, y)
646
- counter += 1
647
-
648
- g = Graph(sum(L))
649
- s = 0
650
- for i in L:
651
- g.add_clique(range(s, s + i))
652
- s += i
653
-
654
- g = g.complement()
655
- g.set_pos(positions)
771
+ return g
772
+ if r == 2:
773
+ return CompleteBipartiteGraph(L[0], L[1], immutable=immutable, name=name)
774
+
775
+ # This position code gives bad results on bipartite or isolated graphs
776
+ points = [(cos(2 * pi * i / r), sin(2 * pi * i / r)) for i in range(r)]
777
+ slopes = [(points[(i + 1) % r][0] - points[i % r][0],
778
+ points[(i + 1) % r][1] - points[i % r][1]) for i in range(r)]
779
+
780
+ counter = 0
781
+ parts = []
782
+ positions = {}
783
+ for i, size in enumerate(L):
784
+ parts.append(list(range(counter, counter + size)))
785
+ vertex_set_size = size + 1
786
+ for j in range(1, vertex_set_size):
787
+ x = points[i][0] + slopes[i][0] * j / vertex_set_size
788
+ y = points[i][1] + slopes[i][1] * j / vertex_set_size
789
+ positions[counter] = (x, y)
790
+ counter += 1
656
791
 
657
- g.name(name)
658
- return g
792
+ from itertools import combinations
793
+ edges = ((a, b) for A, B in combinations(parts, 2) for a in A for b in B)
794
+ return Graph([range(counter), edges], format='vertices_and_edges',
795
+ immutable=immutable, pos=positions, name=name)
659
796
 
660
797
 
661
- def DiamondGraph():
798
+ def DiamondGraph(immutable=False):
662
799
  """
663
800
  Return a diamond graph with 4 nodes.
664
801
 
665
802
  A diamond graph is a square with one pair of diagonal nodes connected.
666
803
 
804
+ INPUT:
805
+
806
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
807
+ immutable or a mutable graph
808
+
667
809
  PLOTTING: Upon construction, the position dictionary is filled to override
668
810
  the spring-layout algorithm. By convention, the diamond graph is drawn as a
669
811
  diamond, with the first node on top, second on the left, third on the right,
@@ -675,18 +817,31 @@ def DiamondGraph():
675
817
 
676
818
  sage: g = graphs.DiamondGraph()
677
819
  sage: g.show() # long time # needs sage.plot
820
+
821
+ TESTS:
822
+
823
+ Check the behavior of parameter ``immutable``::
824
+
825
+ sage: graphs.DiamondGraph(immutable=True).is_immutable()
826
+ True
678
827
  """
679
828
  pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1)}
680
829
  edges = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)]
681
- return Graph(edges, pos=pos_dict, name="Diamond Graph")
830
+ return Graph([range(4), edges], format='vertices_and_edges',
831
+ immutable=immutable, pos=pos_dict, name="Diamond Graph")
682
832
 
683
833
 
684
- def GemGraph():
834
+ def GemGraph(immutable=False):
685
835
  """
686
836
  Return a gem graph with 5 nodes.
687
837
 
688
838
  A gem graph is a fan graph (4,1).
689
839
 
840
+ INPUT:
841
+
842
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
843
+ immutable or a mutable graph
844
+
690
845
  PLOTTING: Upon construction, the position dictionary is filled to override
691
846
  the spring-layout algorithm. By convention, the gem graph is drawn as a gem,
692
847
  with the sharp part on the bottom.
@@ -697,18 +852,31 @@ def GemGraph():
697
852
 
698
853
  sage: g = graphs.GemGraph()
699
854
  sage: g.show() # long time # needs sage.plot
855
+
856
+ TESTS:
857
+
858
+ Check the behavior of parameter ``immutable``::
859
+
860
+ sage: graphs.GemGraph(immutable=True).is_immutable()
861
+ True
700
862
  """
701
863
  pos_dict = {0: (0.5, 0), 1: (0, 0.75), 2: (0.25, 1), 3: (0.75, 1), 4: (1, 0.75)}
702
864
  edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (2, 3), (3, 4)]
703
- return Graph(edges, pos=pos_dict, name="Gem Graph")
865
+ return Graph([range(5), edges], format='vertices_and_edges',
866
+ immutable=immutable, pos=pos_dict, name="Gem Graph")
704
867
 
705
868
 
706
- def ForkGraph():
869
+ def ForkGraph(immutable=False):
707
870
  """
708
871
  Return a fork graph with 5 nodes.
709
872
 
710
873
  A fork graph, sometimes also called chair graph, is 5 vertex tree.
711
874
 
875
+ INPUT:
876
+
877
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
878
+ immutable or a mutable graph
879
+
712
880
  PLOTTING: Upon construction, the position dictionary is filled to override
713
881
  the spring-layout algorithm. By convention, the fork graph is drawn as a
714
882
  fork, with the sharp part on the bottom.
@@ -719,16 +887,29 @@ def ForkGraph():
719
887
 
720
888
  sage: g = graphs.ForkGraph()
721
889
  sage: g.show() # long time # needs sage.plot
890
+
891
+ TESTS:
892
+
893
+ Check the behavior of parameter ``immutable``::
894
+
895
+ sage: graphs.ForkGraph(immutable=True).is_immutable()
896
+ True
722
897
  """
723
898
  pos_dict = {0: (0, 0), 1: (1, 0), 2: (0, 1), 3: (1, 1), 4: (0, 2)}
724
899
  edges = [(0, 2), (2, 3), (3, 1), (2, 4)]
725
- return Graph(edges, pos=pos_dict, name="Fork Graph")
900
+ return Graph([range(5), edges], format='vertices_and_edges',
901
+ immutable=immutable, pos=pos_dict, name="Fork Graph")
726
902
 
727
903
 
728
- def DartGraph():
904
+ def DartGraph(immutable=False):
729
905
  """
730
906
  Return a dart graph with 5 nodes.
731
907
 
908
+ INPUT:
909
+
910
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
911
+ immutable or a mutable graph
912
+
732
913
  PLOTTING: Upon construction, the position dictionary is filled to override
733
914
  the spring-layout algorithm. By convention, the dart graph is drawn as a
734
915
  dart, with the sharp part on the bottom.
@@ -739,19 +920,32 @@ def DartGraph():
739
920
 
740
921
  sage: g = graphs.DartGraph()
741
922
  sage: g.show() # long time # needs sage.plot
923
+
924
+ TESTS:
925
+
926
+ Check the behavior of parameter ``immutable``::
927
+
928
+ sage: graphs.DartGraph(immutable=True).is_immutable()
929
+ True
742
930
  """
743
931
  pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1), 4: (0, 0)}
744
932
  edges = [(0, 1), (0, 2), (1, 4), (2, 4), (0, 4), (3, 4)]
745
- return Graph(edges, pos=pos_dict, name="Dart Graph")
933
+ return Graph([range(5), edges], format='vertices_and_edges',
934
+ immutable=immutable, pos=pos_dict, name="Dart Graph")
746
935
 
747
936
 
748
- def EmptyGraph():
937
+ def EmptyGraph(immutable=False):
749
938
  """
750
939
  Return an empty graph (0 nodes and 0 edges).
751
940
 
752
941
  This is useful for constructing graphs by adding edges and vertices
753
942
  individually or in a loop.
754
943
 
944
+ INPUT:
945
+
946
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
947
+ immutable or a mutable graph
948
+
755
949
  PLOTTING: When plotting, this graph will use the default
756
950
  spring-layout algorithm, unless a position dictionary is
757
951
  specified.
@@ -780,11 +974,18 @@ def EmptyGraph():
780
974
  sage: for i in range(1, 4):
781
975
  ....: empty2.add_edge(4,i) # add edges {[1:4],[2:4],[3:4]}
782
976
  sage: empty2.show() # long time # needs sage.plot
977
+
978
+ TESTS:
979
+
980
+ Check the behavior of parameter ``immutable``::
981
+
982
+ sage: graphs.EmptyGraph(immutable=True).is_immutable()
983
+ True
783
984
  """
784
- return Graph(sparse=True)
985
+ return Graph(sparse=True, immutable=immutable)
785
986
 
786
987
 
787
- def ToroidalGrid2dGraph(p, q):
988
+ def ToroidalGrid2dGraph(p, q, immutable=False):
788
989
  r"""
789
990
  Return a toroidal 2-dimensional grid graph with `p \times q` nodes (`p` rows
790
991
  and `q` columns).
@@ -793,6 +994,13 @@ def ToroidalGrid2dGraph(p, q):
793
994
  grid graph with identical parameters to which are added the edges
794
995
  `((i, 0), (i, q - 1))` and `((0, i), (p - 1, i))`.
795
996
 
997
+ INPUT:
998
+
999
+ - ``p, q`` -- nonnegative integers; the sides of the toroidal grid
1000
+
1001
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1002
+ immutable or a mutable graph
1003
+
796
1004
  EXAMPLES:
797
1005
 
798
1006
  The toroidal 2-dimensional grid is a regular graph, while the usual
@@ -806,14 +1014,21 @@ def ToroidalGrid2dGraph(p, q):
806
1014
  False
807
1015
  sage: tgrid.is_regular()
808
1016
  True
1017
+
1018
+ TESTS:
1019
+
1020
+ Check the behavior of parameter ``immutable``::
1021
+
1022
+ sage: graphs.ToroidalGrid2dGraph(2, 3, immutable=True).is_immutable()
1023
+ True
809
1024
  """
810
- g = Grid2dGraph(p, q, set_positions=True)
1025
+ name = f"Toroidal 2D Grid Graph with parameters {p},{q}"
1026
+ g = Grid2dGraph(p, q, set_positions=True, immutable=False)
1027
+ g.name(name)
811
1028
 
812
1029
  g.add_edges([((i, 0), (i, q - 1)) for i in range(p)])
813
1030
  g.add_edges([((0, i), (p - 1, i)) for i in range(q)])
814
1031
 
815
- g.name("Toroidal 2D Grid Graph with parameters {},{}".format(p, q))
816
-
817
1032
  pos = g._pos
818
1033
  p += 0.
819
1034
  q += 0.
@@ -825,10 +1040,12 @@ def ToroidalGrid2dGraph(p, q):
825
1040
  y += 0.25 * (1.0 + v * (v - q + 1) / vf)
826
1041
  pos[u, v] = (x, y)
827
1042
 
1043
+ if immutable:
1044
+ return Graph(g, immutable=True, pos=g.get_pos(), name=name)
828
1045
  return g
829
1046
 
830
1047
 
831
- def Toroidal6RegularGrid2dGraph(p, q):
1048
+ def Toroidal6RegularGrid2dGraph(p, q, immutable=False):
832
1049
  r"""
833
1050
  Return a toroidal 6-regular grid.
834
1051
 
@@ -843,6 +1060,9 @@ def Toroidal6RegularGrid2dGraph(p, q):
843
1060
 
844
1061
  - ``p``, ``q`` -- integers
845
1062
 
1063
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1064
+ immutable or a mutable graph
1065
+
846
1066
  EXAMPLES:
847
1067
 
848
1068
  The toroidal 6-regular grid on `25` elements::
@@ -871,19 +1091,27 @@ def Toroidal6RegularGrid2dGraph(p, q):
871
1091
  Traceback (most recent call last):
872
1092
  ...
873
1093
  ValueError: parameters p and q must be integers larger than 3
1094
+
1095
+ Check the behavior of parameter ``immutable``::
1096
+
1097
+ sage: graphs.Toroidal6RegularGrid2dGraph(4, 4, immutable=True).is_immutable()
1098
+ True
874
1099
  """
875
1100
  if p <= 3 or q <= 3:
876
1101
  raise ValueError("parameters p and q must be integers larger than 3")
877
1102
 
878
- g = ToroidalGrid2dGraph(p, q)
1103
+ g = ToroidalGrid2dGraph(p, q, immutable=False)
879
1104
  for u, v in g:
880
1105
  g.add_edge((u, v), ((u + 1) % p, (v + 1) % q))
881
1106
 
882
- g.name("Toroidal Hexagonal Grid graph on {}x{} elements".format(p, q))
1107
+ name = f"Toroidal Hexagonal Grid graph on {p}x{q} elements"
1108
+ if immutable:
1109
+ return Graph(g, immutable=True, pos=g.get_pos(), name=name)
1110
+ g.name(name)
883
1111
  return g
884
1112
 
885
1113
 
886
- def Grid2dGraph(p, q, set_positions=True):
1114
+ def Grid2dGraph(p, q, set_positions=True, immutable=False, name=None):
887
1115
  r"""
888
1116
  Return a `2`-dimensional grid graph with `p \times q` nodes (`p` rows and
889
1117
  `q` columns).
@@ -899,6 +1127,12 @@ def Grid2dGraph(p, q, set_positions=True):
899
1127
  - ``set_positions`` -- boolean (default: ``True``); whether to set the
900
1128
  position of the nodes
901
1129
 
1130
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1131
+ immutable or a mutable graph
1132
+
1133
+ - ``name`` -- string (default: ``None``); used as the name of the returned
1134
+ graph when set
1135
+
902
1136
  PLOTTING: Upon construction, the position dictionary is filled to override
903
1137
  the spring-layout algorithm. By convention, nodes are labelled in (row,
904
1138
  column) pairs with `(0, 0)` in the top left corner. Edges will always be
@@ -930,26 +1164,33 @@ def Grid2dGraph(p, q, set_positions=True):
930
1164
  sage: g = graphs.Grid2dGraph(5,7)
931
1165
  sage: g.name()
932
1166
  '2D Grid Graph for [5, 7]'
1167
+
1168
+ Check the behavior of parameter ``ìmmutable``::
1169
+
1170
+ sage: graphs.Grid2dGraph(2, 3, immutable=True).is_immutable()
1171
+ True
1172
+
1173
+ Check the behavior of parameter ``name``::
1174
+
1175
+ sage: graphs.Grid2dGraph(2, 3, name='foo')
1176
+ foo: Graph on 6 vertices
933
1177
  """
934
1178
  if p <= 0 or q <= 0:
935
1179
  raise ValueError("parameters p and q must be positive integers")
936
1180
 
937
- pos_dict = {}
1181
+ vertices = ((i, j) for i in range(p) for j in range(q))
1182
+ from itertools import chain
1183
+ edges = chain((((i, j), (i + 1, j)) for i in range(p - 1) for j in range(q)),
1184
+ (((i, j), (i, j + 1)) for i in range(p) for j in range(q - 1)))
1185
+ pos_dict = None
938
1186
  if set_positions:
939
- for i in range(p):
940
- y = -i
941
- for j in range(q):
942
- x = j
943
- pos_dict[i, j] = (x, y)
1187
+ pos_dict = {(i, j): (j, -i) for i in range(p) for j in range(q)}
1188
+ return Graph([vertices, edges], format='vertices_and_edges',
1189
+ immutable=immutable, pos=pos_dict,
1190
+ name=f"2D Grid Graph for [{p}, {q}]" if name is None else name)
944
1191
 
945
- G = Graph(pos=pos_dict, name="2D Grid Graph for [{}, {}]".format(p, q))
946
- G.add_vertices((i, j) for i in range(p) for j in range(q))
947
- G.add_edges(((i, j), (i + 1, j)) for i in range(p - 1) for j in range(q))
948
- G.add_edges(((i, j), (i, j + 1)) for i in range(p) for j in range(q - 1))
949
- return G
950
1192
 
951
-
952
- def GridGraph(dim_list):
1193
+ def GridGraph(dim_list, immutable=False):
953
1194
  r"""
954
1195
  Return an `n`-dimensional grid graph.
955
1196
 
@@ -958,6 +1199,9 @@ def GridGraph(dim_list):
958
1199
  - ``dim_list`` -- list of integers representing the number of nodes to
959
1200
  extend in each dimension
960
1201
 
1202
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1203
+ immutable or a mutable graph
1204
+
961
1205
  PLOTTING: When plotting, this graph will use the default spring-layout
962
1206
  algorithm, unless a position dictionary is specified.
963
1207
 
@@ -1029,36 +1273,52 @@ def GridGraph(dim_list):
1029
1273
  Traceback (most recent call last):
1030
1274
  ...
1031
1275
  ValueError: all dimensions must be positive integers
1276
+
1277
+ Check the behavior of parameter ``ìmmutable``::
1278
+
1279
+ sage: graphs.GridGraph([], immutable=True).is_immutable()
1280
+ True
1281
+ sage: graphs.GridGraph([2], immutable=True).is_immutable()
1282
+ True
1283
+ sage: graphs.GridGraph([2, 2], immutable=True).is_immutable()
1284
+ True
1285
+ sage: graphs.GridGraph([2, 2, 2], immutable=True).is_immutable()
1286
+ True
1032
1287
  """
1033
1288
  dim = [int(a) for a in dim_list]
1034
1289
  if any(a <= 0 for a in dim):
1035
1290
  raise ValueError("all dimensions must be positive integers")
1036
1291
 
1037
- g = Graph()
1292
+ name = "Grid Graph for {}".format(dim)
1038
1293
  n_dim = len(dim)
1294
+ if not n_dim:
1295
+ return Graph(name=name, immutable=immutable)
1039
1296
  if n_dim == 1:
1040
1297
  # Vertices are labeled from 0 to dim[0]-1
1041
- g = PathGraph(dim[0])
1042
- elif n_dim == 2:
1298
+ return PathGraph(dim[0], immutable=immutable, name=name)
1299
+ if n_dim == 2:
1043
1300
  # We use the Grid2dGraph generator to also get the positions
1044
- g = Grid2dGraph(*dim)
1045
- elif n_dim > 2:
1046
- # Vertices are tuples of dimension n_dim, and the graph contains at
1047
- # least vertex (0, 0, ..., 0)
1048
- g.add_vertex(tuple([0] * n_dim))
1049
- import itertools
1050
- for u in itertools.product(*[range(d) for d in dim]):
1301
+ return Grid2dGraph(*dim, immutable=immutable, name=name)
1302
+
1303
+ # Now, n_dim > 2 and we don't set positions
1304
+ # Vertices are tuples of dimension n_dim, and the graph contains at
1305
+ # least vertex (0, 0, ..., 0)
1306
+ V = [tuple([0] * n_dim)]
1307
+
1308
+ def edges():
1309
+ from itertools import product
1310
+ for u in product(*[range(d) for d in dim]):
1051
1311
  for i in range(n_dim):
1052
1312
  if u[i] + 1 < dim[i]:
1053
1313
  v = list(u)
1054
1314
  v[i] = u[i] + 1
1055
- g.add_edge(u, tuple(v))
1315
+ yield (u, tuple(v))
1056
1316
 
1057
- g.name("Grid Graph for {}".format(dim))
1058
- return g
1317
+ return Graph([V, edges()], format='vertices_and_edges',
1318
+ immutable=immutable, name=name)
1059
1319
 
1060
1320
 
1061
- def HouseGraph():
1321
+ def HouseGraph(immutable=False):
1062
1322
  """
1063
1323
  Return a house graph with 5 nodes.
1064
1324
 
@@ -1073,19 +1333,32 @@ def HouseGraph():
1073
1333
  connecting the roof to the wall. The fifth node is the top of the roof,
1074
1334
  connected only to the third and fourth.
1075
1335
 
1336
+ INPUT:
1337
+
1338
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1339
+ immutable or a mutable graph
1340
+
1076
1341
  EXAMPLES:
1077
1342
 
1078
1343
  Construct and show a house graph::
1079
1344
 
1080
1345
  sage: g = graphs.HouseGraph()
1081
1346
  sage: g.show() # long time # needs sage.plot
1347
+
1348
+ TESTS:
1349
+
1350
+ Check the behavior of parameter ``immutable``::
1351
+
1352
+ sage: graphs.HouseGraph(immutable=True).is_immutable()
1353
+ True
1082
1354
  """
1083
1355
  pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)}
1084
1356
  edges = [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
1085
- return Graph(edges, pos=pos_dict, name="House Graph")
1357
+ return Graph([range(5), edges], format='vertices_and_edges',
1358
+ immutable=immutable, pos=pos_dict, name="House Graph")
1086
1359
 
1087
1360
 
1088
- def HouseXGraph():
1361
+ def HouseXGraph(immutable=False):
1089
1362
  """
1090
1363
  Return a house X graph with 5 nodes.
1091
1364
 
@@ -1101,19 +1374,32 @@ def HouseXGraph():
1101
1374
  connecting the roof to the wall. The fifth node is the top of the roof,
1102
1375
  connected only to the third and fourth.
1103
1376
 
1377
+ INPUT:
1378
+
1379
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1380
+ immutable or a mutable graph
1381
+
1104
1382
  EXAMPLES:
1105
1383
 
1106
1384
  Construct and show a house X graph::
1107
1385
 
1108
1386
  sage: g = graphs.HouseXGraph()
1109
1387
  sage: g.show() # long time # needs sage.plot
1388
+
1389
+ TESTS:
1390
+
1391
+ Check the behavior of parameter ``immutable``::
1392
+
1393
+ sage: graphs.HouseXGraph(immutable=True).is_immutable()
1394
+ True
1110
1395
  """
1111
1396
  pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)}
1112
1397
  edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
1113
- return Graph(edges, pos=pos_dict, name="House Graph")
1398
+ return Graph([range(5), edges], format='vertices_and_edges',
1399
+ immutable=immutable, pos=pos_dict, name="House Graph")
1114
1400
 
1115
1401
 
1116
- def LadderGraph(n):
1402
+ def LadderGraph(n, immutable=False):
1117
1403
  r"""
1118
1404
  Return a ladder graph with `2 * n` nodes.
1119
1405
 
@@ -1125,6 +1411,13 @@ def LadderGraph(n):
1125
1411
  displayed horizontally, with the first n nodes displayed left to right on
1126
1412
  the top horizontal line.
1127
1413
 
1414
+ INPUT:
1415
+
1416
+ - ``n`` -- a nonnegative integer; number of nodes is `2n`
1417
+
1418
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1419
+ immutable or a mutable graph
1420
+
1128
1421
  EXAMPLES:
1129
1422
 
1130
1423
  Construct and show a ladder graph with 14 nodes::
@@ -1147,21 +1440,28 @@ def LadderGraph(n):
1147
1440
  ....: j.append(n)
1148
1441
  sage: G = graphics_array(j)
1149
1442
  sage: G.show() # long time
1443
+
1444
+ TESTS:
1445
+
1446
+ Check the behavior of parameter ``immutable``::
1447
+
1448
+ sage: graphs.LadderGraph(4, immutable=True).is_immutable()
1449
+ True
1150
1450
  """
1151
- pos_dict = {}
1152
- for i in range(n):
1153
- pos_dict[i] = (i, 1)
1451
+ pos_dict = {i: (i, 1) for i in range(n)}
1154
1452
  for i in range(n, 2 * n):
1155
1453
  x = i - n
1156
1454
  pos_dict[i] = (x, 0)
1157
- G = Graph(2 * n, pos=pos_dict, name="Ladder graph")
1158
- G.add_path(list(range(n)))
1159
- G.add_path(list(range(n, 2 * n)))
1160
- G.add_edges((i, i + n) for i in range(n))
1161
- return G
1455
+ from itertools import chain
1456
+ edges_1 = zip(range(n), range(1, n))
1457
+ edges_2 = zip(range(n, 2 * n), range(n + 1, 2 * n))
1458
+ edges_3 = ((i, i + n) for i in range(n))
1459
+ return Graph([range(2 * n), chain(edges_1, edges_2, edges_3)],
1460
+ format='vertices_and_edges', immutable=immutable,
1461
+ pos=pos_dict, name="Ladder graph")
1162
1462
 
1163
1463
 
1164
- def MoebiusLadderGraph(n):
1464
+ def MoebiusLadderGraph(n, immutable=False):
1165
1465
  r"""
1166
1466
  Return a Möbius ladder graph with `2n` nodes
1167
1467
 
@@ -1185,6 +1485,9 @@ def MoebiusLadderGraph(n):
1185
1485
 
1186
1486
  - ``n`` -- a nonnegative integer; number of nodes is `2n`
1187
1487
 
1488
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1489
+ immutable or a mutable graph
1490
+
1188
1491
  OUTPUT:
1189
1492
 
1190
1493
  - ``G`` -- a Möbius ladder graph of order `2n`; note that a
@@ -1222,6 +1525,11 @@ def MoebiusLadderGraph(n):
1222
1525
  ...
1223
1526
  ValueError: parameter n must be a nonnegative integer
1224
1527
 
1528
+ Check the behavior of parameter ``immutable``::
1529
+
1530
+ sage: graphs.MoebiusLadderGraph(4, immutable=True).is_immutable()
1531
+ True
1532
+
1225
1533
  REFERENCES:
1226
1534
 
1227
1535
  - :wikipedia:`Möbius_ladder`
@@ -1238,14 +1546,17 @@ def MoebiusLadderGraph(n):
1238
1546
  if n < 0:
1239
1547
  raise ValueError("parameter n must be a nonnegative integer")
1240
1548
 
1241
- G = Graph(2 * n, name="Moebius ladder graph")
1549
+ from itertools import chain
1550
+ edges_1 = zip(range(2 * n), chain(range(1, 2 * n), (0,)))
1551
+ edges_2 = ((i, i + n) for i in range(n))
1552
+ G = Graph([range(2 * n), chain(edges_1, edges_2)],
1553
+ format='vertices_and_edges', immutable=immutable,
1554
+ name="Moebius ladder graph")
1242
1555
  G._circle_embedding(list(range(2 * n)), angle=pi/2)
1243
- G.add_cycle(list(range(2 * n)))
1244
- G.add_edges((i, i + n) for i in range(n))
1245
1556
  return G
1246
1557
 
1247
1558
 
1248
- def PathGraph(n, pos=None):
1559
+ def PathGraph(n, pos=None, immutable=False, name=None):
1249
1560
  r"""
1250
1561
  Return a path graph with `n` nodes.
1251
1562
 
@@ -1255,12 +1566,18 @@ def PathGraph(n, pos=None):
1255
1566
 
1256
1567
  INPUT:
1257
1568
 
1258
- - ``n`` -- number of nodes of the path graph
1569
+ - ``n`` -- nonnegative integer; number of nodes of the path graph
1259
1570
 
1260
1571
  - ``pos`` -- string (default: ``None``); indicates the embedding to use
1261
1572
  between 'circle', 'line' or the default algorithm. See the plotting
1262
1573
  section below for more detail.
1263
1574
 
1575
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1576
+ immutable or a mutable graph
1577
+
1578
+ - ``name`` -- string (default: ``None``); used as the name of the returned
1579
+ graph when set
1580
+
1264
1581
  PLOTTING: Upon construction, the position dictionary is filled to override
1265
1582
  the spring-layout algorithm. By convention, the graph may be drawn in one of
1266
1583
  two ways: The 'line' argument will draw the graph in a horizontal line (left
@@ -1272,23 +1589,19 @@ def PathGraph(n, pos=None):
1272
1589
  argument) the graph will be drawn as a 'circle' if `10 < n < 41` and as a
1273
1590
  'line' for all other `n`.
1274
1591
 
1275
- EXAMPLES: Show default drawing by size: 'line': `n \leq 10`
1592
+ EXAMPLES:
1276
1593
 
1277
- ::
1594
+ Show default drawing by size: 'line': `n \leq 10`::
1278
1595
 
1279
1596
  sage: p = graphs.PathGraph(10)
1280
1597
  sage: p.show() # long time # needs sage.plot
1281
1598
 
1282
- 'circle': `10 < n < 41`
1283
-
1284
- ::
1599
+ 'circle': `10 < n < 41`::
1285
1600
 
1286
1601
  sage: q = graphs.PathGraph(25)
1287
1602
  sage: q.show() # long time # needs sage.plot
1288
1603
 
1289
- 'line': `n \geq 41`
1290
-
1291
- ::
1604
+ 'line': `n \geq 41`::
1292
1605
 
1293
1606
  sage: r = graphs.PathGraph(55)
1294
1607
  sage: r.show() # long time # needs sage.plot
@@ -1297,8 +1610,22 @@ def PathGraph(n, pos=None):
1297
1610
 
1298
1611
  sage: s = graphs.PathGraph(5,'circle')
1299
1612
  sage: s.show() # long time # needs sage.plot
1613
+
1614
+ TESTS:
1615
+
1616
+ Check the behavior of parameter ``immutable``::
1617
+
1618
+ sage: graphs.PathGraph(4, immutable=True).is_immutable()
1619
+ True
1620
+
1621
+ Check the behavior of parameter ``name``::
1622
+
1623
+ sage: graphs.PathGraph(4, name='foo')
1624
+ foo: Graph on 4 vertices
1300
1625
  """
1301
- G = Graph(n, name="Path graph")
1626
+ edges = ((i, i + 1) for i in range(n - 1))
1627
+ G = Graph([range(n), edges], format='vertices_and_edges',
1628
+ immutable=immutable, name="Path graph" if name is None else name)
1302
1629
 
1303
1630
  pos_dict = {}
1304
1631
 
@@ -1348,17 +1675,23 @@ def PathGraph(n, pos=None):
1348
1675
  counter += 1
1349
1676
  G.set_pos(pos_dict)
1350
1677
 
1351
- G.add_edges((i, i + 1) for i in range(n - 1))
1352
1678
  return G
1353
1679
 
1354
1680
 
1355
- def StarGraph(n):
1681
+ def StarGraph(n, immutable=False):
1356
1682
  r"""
1357
1683
  Return a star graph with `n + 1` nodes.
1358
1684
 
1359
1685
  A Star graph is a basic structure where one node is connected to all other
1360
1686
  nodes.
1361
1687
 
1688
+ INPUT:
1689
+
1690
+ - ``n`` -- a nonnegative integer; number of nodes is `n + 1`
1691
+
1692
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1693
+ immutable or a mutable graph
1694
+
1362
1695
  PLOTTING: Upon construction, the position dictionary is filled to override
1363
1696
  the spring-layout algorithm. By convention, each star graph will be
1364
1697
  displayed with the first (0) node in the center, the second node (1) at the
@@ -1421,8 +1754,16 @@ def StarGraph(n):
1421
1754
  ....: j.append(n)
1422
1755
  sage: G = graphics_array(j)
1423
1756
  sage: G.show() # long time
1757
+
1758
+ TESTS:
1759
+
1760
+ Check the behavior of parameter ``immutable``::
1761
+
1762
+ sage: graphs.StarGraph(4, immutable=True).is_immutable()
1763
+ True
1424
1764
  """
1425
- G = Graph({0: list(range(1, n + 1))}, name="Star graph", format='dict_of_lists')
1765
+ G = Graph({0: list(range(1, n + 1))}, format='dict_of_lists',
1766
+ immutable=immutable, name="Star graph")
1426
1767
  G.set_pos({0: (0, 0)})
1427
1768
  G._circle_embedding(list(range(1, n + 1)), angle=pi/2)
1428
1769
  return G