passagemath-graphs 10.5.43__cp313-cp313-macosx_14_0_arm64.whl → 10.6.1rc1__cp313-cp313-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 (132) hide show
  1. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/METADATA +5 -6
  2. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/RECORD +132 -130
  3. sage/combinat/abstract_tree.py +188 -17
  4. sage/combinat/cluster_algebra_quiver/interact.py +1 -2
  5. sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
  6. sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
  7. sage/combinat/designs/covering_design.py +2 -6
  8. sage/combinat/designs/database.py +11 -10
  9. sage/combinat/designs/designs_pyx.cpython-313-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-313-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-313-darwin.so +0 -0
  14. sage/combinat/designs/latin_squares.py +53 -20
  15. sage/combinat/designs/orthogonal_arrays.py +2 -1
  16. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-313-darwin.so +0 -0
  17. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
  18. sage/combinat/designs/resolvable_bibd.py +191 -157
  19. sage/combinat/designs/subhypergraph_search.cpython-313-darwin.so +0 -0
  20. sage/combinat/designs/subhypergraph_search.pyx +4 -4
  21. sage/combinat/designs/twographs.py +2 -2
  22. sage/combinat/finite_state_machine.py +6 -6
  23. sage/combinat/posets/bubble_shuffle.py +247 -0
  24. sage/combinat/posets/d_complete.py +3 -3
  25. sage/combinat/posets/elements.py +3 -3
  26. sage/combinat/posets/hasse_cython.cpython-313-darwin.so +0 -0
  27. sage/combinat/posets/hasse_cython.pyx +1 -1
  28. sage/combinat/posets/hasse_diagram.py +16 -22
  29. sage/combinat/posets/hochschild_lattice.py +158 -0
  30. sage/combinat/posets/incidence_algebras.py +14 -16
  31. sage/combinat/posets/lattices.py +51 -53
  32. sage/combinat/posets/linear_extension_iterator.cpython-313-darwin.so +0 -0
  33. sage/combinat/posets/linear_extensions.py +10 -12
  34. sage/combinat/posets/moebius_algebra.py +4 -4
  35. sage/combinat/posets/poset_examples.py +70 -23
  36. sage/combinat/posets/posets.py +294 -103
  37. sage/databases/knotinfo_db.py +2 -1
  38. sage/graphs/asteroidal_triples.cpython-313-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-313-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-313-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-313-darwin.so +0 -0
  45. sage/graphs/base/dense_graph.pxd +5 -3
  46. sage/graphs/base/dense_graph.pyx +44 -0
  47. sage/graphs/base/graph_backends.cpython-313-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-313-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-313-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-313-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-313-darwin.so +0 -0
  53. sage/graphs/base/static_sparse_graph.pyx +86 -15
  54. sage/graphs/bipartite_graph.py +59 -36
  55. sage/graphs/centrality.cpython-313-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-313-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-313-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-313-darwin.so +0 -0
  62. sage/graphs/convexity_properties.pyx +52 -9
  63. sage/graphs/digraph.py +439 -95
  64. sage/graphs/digraph_generators.py +174 -102
  65. sage/graphs/distances_all_pairs.cpython-313-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-313-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-313-darwin.so +0 -0
  70. sage/graphs/generators/distance_regular.pyx +1 -1
  71. sage/graphs/generators/families.py +37 -27
  72. sage/graphs/generators/random.py +2 -2
  73. sage/graphs/generators/smallgraphs.py +3 -3
  74. sage/graphs/generic_graph.py +558 -86
  75. sage/graphs/generic_graph_pyx.cpython-313-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-313-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-313-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-313-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-313-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-313-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-313-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-313-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-313-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-313-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-313-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-313-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-313-darwin.so +0 -0
  97. sage/graphs/graph_generators_pyx.pyx +15 -15
  98. sage/graphs/graph_latex.py +1 -1
  99. sage/graphs/graph_list.py +52 -9
  100. sage/graphs/graph_plot.py +7 -0
  101. sage/graphs/hyperbolicity.cpython-313-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-313-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-313-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-313-darwin.so +0 -0
  107. sage/graphs/line_graph.pyx +153 -37
  108. sage/graphs/matching_covered_graph.py +84 -60
  109. sage/graphs/orientations.py +3 -18
  110. sage/graphs/path_enumeration.cpython-313-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-313-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-313-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-313-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-313-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-313-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-313-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-313-darwin.so +0 -0
  123. sage/knots/free_knotinfo_monoid.py +3 -3
  124. sage/knots/knotinfo.py +102 -82
  125. sage/knots/link.py +72 -39
  126. sage/topology/cubical_complex.py +4 -5
  127. sage/topology/delta_complex.py +4 -4
  128. sage/topology/simplicial_complex.py +0 -1
  129. sage/topology/simplicial_complex_catalog.py +6 -0
  130. sage/topology/simplicial_complex_examples.py +4 -16
  131. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/WHEEL +0 -0
  132. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/top_level.txt +0 -0
@@ -151,6 +151,21 @@ class DiGraphGenerators:
151
151
  dense data structure. See the documentation of
152
152
  :class:`~sage.graphs.graph.Graph`.
153
153
 
154
+ - ``copy`` -- boolean (default: ``True``); whether to make copies of the
155
+ digraphs before returning them. If set to ``False`` the method returns the
156
+ digraph it is working on. The second alternative is faster, but modifying
157
+ any of the digraph instances returned by the method may break the
158
+ function's behaviour, as it is using these digraphs to compute the next
159
+ ones: only use ``copy = False`` when you stick to *reading* the digraphs
160
+ returned.
161
+
162
+ This parameter is ignored when ``immutable`` is set to ``True``, in which
163
+ case returned graphs are always copies.
164
+
165
+ - ``immutable`` -- boolean (default: ``False``); whether to return immutable
166
+ or mutable digraphs. When set to ``True``, this parameter implies
167
+ ``copy=True``.
168
+
154
169
  EXAMPLES:
155
170
 
156
171
  Print digraphs on 2 or less vertices::
@@ -225,7 +240,7 @@ class DiGraphGenerators:
225
240
  (``vertices='vectors'``)
226
241
 
227
242
  - ``immutable`` -- boolean (default: ``False``); whether to return
228
- an immutable or mutable digraph.
243
+ an immutable or mutable digraph
229
244
 
230
245
  EXAMPLES::
231
246
 
@@ -339,7 +354,7 @@ class DiGraphGenerators:
339
354
  - ``n`` -- integer; number of vertices in the path
340
355
 
341
356
  - ``immutable`` -- boolean (default: ``False``); whether to return
342
- an immutable or mutable digraph.
357
+ an immutable or mutable digraph
343
358
 
344
359
  EXAMPLES::
345
360
 
@@ -369,7 +384,7 @@ class DiGraphGenerators:
369
384
  - ``n`` -- integer; the number of vertices of the digraph
370
385
 
371
386
  - ``immutable`` -- boolean (default: ``False``); whether to return
372
- an immutable or mutable digraph.
387
+ an immutable or mutable digraph
373
388
 
374
389
  .. SEEALSO::
375
390
 
@@ -421,7 +436,7 @@ class DiGraphGenerators:
421
436
  - ``q`` -- integer; the number of vertices of the digraph
422
437
 
423
438
  - ``immutable`` -- boolean (default: ``False``); whether to return
424
- an immutable or mutable digraph.
439
+ an immutable or mutable digraph
425
440
 
426
441
  .. SEEALSO::
427
442
 
@@ -483,7 +498,7 @@ class DiGraphGenerators:
483
498
  - ``n`` -- integer; number of vertices in the tournament
484
499
 
485
500
  - ``immutable`` -- boolean (default: ``False``); whether to return
486
- an immutable or mutable digraph.
501
+ an immutable or mutable digraph
487
502
 
488
503
  EXAMPLES::
489
504
 
@@ -532,7 +547,7 @@ class DiGraphGenerators:
532
547
  - ``n`` -- integer; number of vertices
533
548
 
534
549
  - ``immutable`` -- boolean (default: ``False``); whether to return
535
- an immutable or mutable digraph.
550
+ an immutable or mutable digraph
536
551
 
537
552
  EXAMPLES::
538
553
 
@@ -597,7 +612,7 @@ class DiGraphGenerators:
597
612
  `<https://pallini.di.uniroma1.it>`_.
598
613
 
599
614
  - ``immutable`` -- boolean (default: ``False``); whether to return
600
- immutable or mutable digraphs.
615
+ immutable or mutable digraphs
601
616
 
602
617
  EXAMPLES::
603
618
 
@@ -697,7 +712,7 @@ class DiGraphGenerators:
697
712
  standard error and standard output are displayed
698
713
 
699
714
  - ``immutable`` -- boolean (default: ``False``); whether to return
700
- immutable or mutable digraphs.
715
+ immutable or mutable digraphs
701
716
 
702
717
  EXAMPLES::
703
718
 
@@ -816,7 +831,7 @@ class DiGraphGenerators:
816
831
  beginning with ">E" indicates an error with the input.
817
832
 
818
833
  - ``immutable`` -- boolean (default: ``False``); whether to return
819
- immutable or mutable posets.
834
+ immutable or mutable posets
820
835
 
821
836
  The possible options, obtained as output of ``genposetg --help``::
822
837
 
@@ -865,7 +880,7 @@ class DiGraphGenerators:
865
880
  not, i.e., edges from `u` to itself
866
881
 
867
882
  - ``immutable`` -- boolean (default: ``False``); whether to return
868
- an immutable or mutable digraph.
883
+ an immutable or mutable digraph
869
884
 
870
885
  .. SEEALSO::
871
886
 
@@ -913,7 +928,7 @@ class DiGraphGenerators:
913
928
  - ``n`` -- integer; number of vertices
914
929
 
915
930
  - ``immutable`` -- boolean (default: ``False``); whether to return
916
- an immutable or mutable digraph.
931
+ an immutable or mutable digraph
917
932
 
918
933
  EXAMPLES:
919
934
 
@@ -952,7 +967,7 @@ class DiGraphGenerators:
952
967
  is an integer
953
968
 
954
969
  - ``immutable`` -- boolean (default: ``False``); whether to return
955
- an immutable or mutable digraph.
970
+ an immutable or mutable digraph
956
971
 
957
972
  EXAMPLES:
958
973
 
@@ -999,7 +1014,7 @@ class DiGraphGenerators:
999
1014
  G._circle_embedding(list(range(n)))
1000
1015
  return G
1001
1016
 
1002
- def DeBruijn(self, k, n, vertices='strings'):
1017
+ def DeBruijn(self, k, n, vertices='strings', immutable=False):
1003
1018
  r"""
1004
1019
  Return the De Bruijn digraph with parameters `k,n`.
1005
1020
 
@@ -1026,6 +1041,9 @@ class DiGraphGenerators:
1026
1041
  are words over an alphabet (default) or integers
1027
1042
  (``vertices='string'``)
1028
1043
 
1044
+ - ``immutable`` -- boolean (default: ``False``); whether to return
1045
+ an immutable or mutable digraph
1046
+
1029
1047
  EXAMPLES:
1030
1048
 
1031
1049
  de Bruijn digraph of degree 2 and diameter 2::
@@ -1079,40 +1097,48 @@ class DiGraphGenerators:
1079
1097
  """
1080
1098
  from sage.rings.integer import Integer
1081
1099
 
1100
+ name = f"De Bruijn digraph (k={k}, n={n})"
1082
1101
  if vertices == 'strings':
1083
1102
  from sage.combinat.words.words import Words
1084
1103
 
1085
1104
  W = Words(list(range(k)) if isinstance(k, Integer) else k, n)
1086
1105
  A = Words(list(range(k)) if isinstance(k, Integer) else k, 1)
1087
- g = DiGraph(loops=True)
1088
1106
 
1089
1107
  if not n:
1090
- g.allow_multiple_edges(True)
1091
- v = W[0]
1092
- vs = v.string_rep()
1093
- for a in A:
1094
- g.add_edge(vs, vs, a.string_rep())
1108
+ multiedges = True
1109
+
1110
+ def edges():
1111
+ v = W[0]
1112
+ vs = v.string_rep()
1113
+ return ((vs, vs, a.string_rep()) for a in A)
1114
+
1095
1115
  else:
1096
- for w in W:
1097
- ww = w[1:]
1098
- ws = w.string_rep()
1099
- for a in A:
1100
- g.add_edge(ws, (ww * a).string_rep(), a.string_rep())
1116
+ multiedges = False
1117
+
1118
+ def edges():
1119
+ for w in W:
1120
+ ww = w[1:]
1121
+ ws = w.string_rep()
1122
+ yield from ((ws, (ww * a).string_rep(), a.string_rep())
1123
+ for a in A)
1124
+
1125
+ return DiGraph(edges(), format='list_of_edges', name=name,
1126
+ loops=True, multiedges=multiedges,
1127
+ immutable=immutable)
1101
1128
 
1102
1129
  elif vertices == 'integers':
1103
1130
  d = k if isinstance(k, Integer) else len(list(k))
1104
1131
  if not d:
1105
- g = DiGraph(loops=True, multiedges=True)
1106
- else:
1107
- g = digraphs.GeneralizedDeBruijn(d ** n, d)
1132
+ return DiGraph(loops=True, multiedges=True, name=name,
1133
+ immutable=immutable)
1134
+
1135
+ return digraphs.GeneralizedDeBruijn(d ** n, d, immutable=immutable,
1136
+ name=name)
1108
1137
 
1109
1138
  else:
1110
1139
  raise ValueError('unknown type for vertices')
1111
1140
 
1112
- g.name("De Bruijn digraph (k={}, n={})".format(k, n))
1113
- return g
1114
-
1115
- def GeneralizedDeBruijn(self, n, d):
1141
+ def GeneralizedDeBruijn(self, n, d, immutable=False, name=None):
1116
1142
  r"""
1117
1143
  Return the generalized de Bruijn digraph of order `n` and degree `d`.
1118
1144
 
@@ -1131,6 +1157,12 @@ class DiGraphGenerators:
1131
1157
 
1132
1158
  - ``d`` -- integer; degree of the digraph (must be at least one)
1133
1159
 
1160
+ - ``immutable`` -- boolean (default: ``False``); whether to return
1161
+ an immutable or mutable digraph
1162
+
1163
+ - ``name`` -- string (default: ``None``); when set, the specified name
1164
+ is used instead of the default one
1165
+
1134
1166
  .. SEEALSO::
1135
1167
 
1136
1168
  * :meth:`sage.graphs.generic_graph.GenericGraph.is_circulant` --
@@ -1164,15 +1196,15 @@ class DiGraphGenerators:
1164
1196
  raise ValueError("order must be greater than or equal to one")
1165
1197
  if d < 1:
1166
1198
  raise ValueError("degree must be greater than or equal to one")
1199
+ if name is None:
1200
+ name = f"Generalized de Bruijn digraph (n={n}, d={d})"
1167
1201
 
1168
- GB = DiGraph(n, loops=True, multiedges=True,
1169
- name="Generalized de Bruijn digraph (n={}, d={})".format(n, d))
1170
- for u in range(n):
1171
- for a in range(u * d, u * d + d):
1172
- GB.add_edge(u, a % n)
1173
- return GB
1202
+ edges = ((u, a % n) for u in range(n) for a in range(u * d, u * d + d))
1203
+ return DiGraph([range(n), edges], format='vertices_and_edges',
1204
+ loops=True, multiedges=True, immutable=immutable,
1205
+ name=name)
1174
1206
 
1175
- def ImaseItoh(self, n, d):
1207
+ def ImaseItoh(self, n, d, immutable=False, name=None):
1176
1208
  r"""
1177
1209
  Return the Imase-Itoh digraph of order `n` and degree `d`.
1178
1210
 
@@ -1194,6 +1226,12 @@ class DiGraphGenerators:
1194
1226
  - ``d`` -- integer; degree of the digraph (must be greater than or
1195
1227
  equal to one)
1196
1228
 
1229
+ - ``immutable`` -- boolean (default: ``False``); whether to return
1230
+ an immutable or mutable digraph
1231
+
1232
+ - ``name`` -- string (default: ``None``); when set, the specified name
1233
+ is used instead of the default one
1234
+
1197
1235
  EXAMPLES::
1198
1236
 
1199
1237
  sage: II = digraphs.ImaseItoh(8, 2)
@@ -1230,15 +1268,15 @@ class DiGraphGenerators:
1230
1268
  raise ValueError("order must be greater than or equal to two")
1231
1269
  if d < 1:
1232
1270
  raise ValueError("degree must be greater than or equal to one")
1271
+ if name is None:
1272
+ name = f"Imase and Itoh digraph (n={n}, d={d})"
1233
1273
 
1234
- II = DiGraph(n, loops=True, multiedges=True,
1235
- name="Imase and Itoh digraph (n={}, d={})".format(n, d))
1236
- for u in range(n):
1237
- for a in range(-u * d - d, -u * d):
1238
- II.add_edge(u, a % n)
1239
- return II
1274
+ edges = ((u, a % n) for u in range(n) for a in range(-u * d - d, -u * d))
1275
+ return DiGraph([range(n), edges], format='vertices_and_edges',
1276
+ loops=True, multiedges=True, immutable=immutable,
1277
+ name=name)
1240
1278
 
1241
- def Kautz(self, k, D, vertices='strings'):
1279
+ def Kautz(self, k, D, vertices='strings', immutable=False):
1242
1280
  r"""
1243
1281
  Return the Kautz digraph of degree `d` and diameter `D`.
1244
1282
 
@@ -1273,6 +1311,9 @@ class DiGraphGenerators:
1273
1311
  are words over an alphabet (default) or integers
1274
1312
  (``vertices='strings'``)
1275
1313
 
1314
+ - ``immutable`` -- boolean (default: ``False``); whether to return
1315
+ an immutable or mutable digraph
1316
+
1276
1317
  EXAMPLES::
1277
1318
 
1278
1319
  sage: # needs sage.combinat
@@ -1347,6 +1388,8 @@ class DiGraphGenerators:
1347
1388
 
1348
1389
  from sage.rings.integer import Integer
1349
1390
 
1391
+ name = f"Kautz digraph (k={k}, D={D})"
1392
+
1350
1393
  if vertices == 'strings':
1351
1394
  from sage.combinat.words.words import Words
1352
1395
 
@@ -1364,27 +1407,26 @@ class DiGraphGenerators:
1364
1407
  V = VV
1365
1408
 
1366
1409
  # We now build the set of arcs
1367
- G = DiGraph()
1368
- for u in V:
1369
- us = u.string_rep()
1370
- for a in my_alphabet:
1371
- if not u.has_suffix(a):
1372
- G.add_edge(us, (u[1:] * a).string_rep(),
1373
- a.string_rep())
1410
+ def edges():
1411
+ for u in V:
1412
+ us = u.string_rep()
1413
+ yield from ((us, (u[1:] * a).string_rep(), a.string_rep())
1414
+ for a in my_alphabet if not u.has_suffix(a))
1415
+
1416
+ return DiGraph(edges(), format='list_of_edges',
1417
+ name=name, immutable=immutable)
1374
1418
 
1375
1419
  elif vertices == 'integers':
1376
1420
  d = k if isinstance(k, Integer) else (len(list(k)) - 1)
1377
1421
  if d < 1:
1378
1422
  raise ValueError("degree must be greater than or equal to one")
1379
- G = digraphs.ImaseItoh((d + 1) * (d ** (D - 1)), d)
1423
+ return digraphs.ImaseItoh((d + 1) * (d ** (D - 1)), d,
1424
+ name=name, immutable=immutable)
1380
1425
 
1381
1426
  else:
1382
1427
  raise ValueError('unknown type for vertices')
1383
1428
 
1384
- G.name("Kautz digraph (k={}, D={})".format(k, D))
1385
- return G
1386
-
1387
- def RandomDirectedAcyclicGraph(self, n, p, weight_max=None):
1429
+ def RandomDirectedAcyclicGraph(self, n, p, weight_max=None, immutable=False):
1388
1430
  r"""
1389
1431
  Return a random (weighted) directed acyclic graph of order `n`.
1390
1432
 
@@ -1404,6 +1446,9 @@ class DiGraphGenerators:
1404
1446
  unweighted. When ``weight_max`` is set to a positive integer, edges
1405
1447
  are assigned a random integer weight between ``1`` and ``weight_max``.
1406
1448
 
1449
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1450
+ immutable or mutable digraph
1451
+
1407
1452
  EXAMPLES::
1408
1453
 
1409
1454
  sage: D = digraphs.RandomDirectedAcyclicGraph(5, .5); D
@@ -1454,21 +1499,22 @@ class DiGraphGenerators:
1454
1499
  pp = int(round(float(p * RAND_MAX_f)))
1455
1500
 
1456
1501
  if weight_max is None:
1457
- D = DiGraph(n, name=f"RandomDAG({n}, {p})")
1458
- D.add_edges((i, j) for i in range(n) for j in range(i) if random() < pp)
1502
+ name = f"RandomDAG({n}, {p})"
1503
+ edges = ((i, j) for i in range(n) for j in range(i) if random() < pp)
1459
1504
 
1460
1505
  else:
1461
1506
  from sage.rings.integer_ring import ZZ
1462
1507
  if weight_max in ZZ and weight_max < 1:
1463
1508
  raise ValueError("parameter weight_max must be a positive integer")
1464
1509
 
1465
- D = DiGraph(n, name=f"RandomWeightedDAG({n}, {p}, {weight_max})")
1466
- D.add_edges((i, j, randint(1, weight_max))
1467
- for i in range(n) for j in range(i) if random() < pp)
1510
+ name = f"RandomWeightedDAG({n}, {p}, {weight_max})"
1511
+ edges = ((i, j, randint(1, weight_max))
1512
+ for i in range(n) for j in range(i) if random() < pp)
1468
1513
 
1469
- return D
1514
+ return DiGraph([range(n), edges], format='vertices_and_edges',
1515
+ name=name, immutable=immutable)
1470
1516
 
1471
- def RandomDirectedGN(self, n, kernel=None, seed=None):
1517
+ def RandomDirectedGN(self, n, kernel=None, seed=None, immutable=False):
1472
1518
  r"""
1473
1519
  Return a random growing network (GN) digraph with `n` vertices.
1474
1520
 
@@ -1488,6 +1534,9 @@ class DiGraphGenerators:
1488
1534
  - ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the
1489
1535
  random number generator (default: ``None``)
1490
1536
 
1537
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1538
+ immutable or mutable digraph
1539
+
1491
1540
  EXAMPLES::
1492
1541
 
1493
1542
  sage: # needs networkx
@@ -1507,9 +1556,10 @@ class DiGraphGenerators:
1507
1556
  if seed is None:
1508
1557
  seed = int(current_randstate().long_seed() % sys.maxsize)
1509
1558
  import networkx
1510
- return DiGraph(networkx.gn_graph(n, kernel, seed=seed))
1559
+ return DiGraph(networkx.gn_graph(n, kernel, seed=seed),
1560
+ immutable=immutable)
1511
1561
 
1512
- def RandomDirectedGNC(self, n, seed=None):
1562
+ def RandomDirectedGNC(self, n, seed=None, immutable=False):
1513
1563
  r"""
1514
1564
  Return a random growing network with copying (GNC) digraph with `n`
1515
1565
  vertices.
@@ -1527,6 +1577,9 @@ class DiGraphGenerators:
1527
1577
  - ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the
1528
1578
  random number generator (default: ``None``)
1529
1579
 
1580
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1581
+ immutable or mutable digraph
1582
+
1530
1583
  EXAMPLES::
1531
1584
 
1532
1585
  sage: # needs networkx
@@ -1540,9 +1593,9 @@ class DiGraphGenerators:
1540
1593
  if seed is None:
1541
1594
  seed = int(current_randstate().long_seed() % sys.maxsize)
1542
1595
  import networkx
1543
- return DiGraph(networkx.gnc_graph(n, seed=seed))
1596
+ return DiGraph(networkx.gnc_graph(n, seed=seed), immutable=immutable)
1544
1597
 
1545
- def RandomDirectedGNP(self, n, p, loops=False, seed=None):
1598
+ def RandomDirectedGNP(self, n, p, loops=False, seed=None, immutable=False):
1546
1599
  r"""
1547
1600
  Return a random digraph on `n` nodes.
1548
1601
 
@@ -1561,6 +1614,9 @@ class DiGraphGenerators:
1561
1614
  - ``seed`` -- integer (default: ``None``); seed for random number
1562
1615
  generator
1563
1616
 
1617
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1618
+ immutable or mutable digraph
1619
+
1564
1620
  PLOTTING: When plotting, this graph will use the default spring-layout
1565
1621
  algorithm, unless a position dictionary is specified.
1566
1622
 
@@ -1579,9 +1635,10 @@ class DiGraphGenerators:
1579
1635
  if seed is None:
1580
1636
  seed = current_randstate().long_seed()
1581
1637
 
1582
- return RandomGNP(n, p, directed=True, loops=loops, seed=seed)
1638
+ return RandomGNP(n, p, directed=True, loops=loops, seed=seed,
1639
+ immutable=immutable)
1583
1640
 
1584
- def RandomDirectedGNM(self, n, m, loops=False):
1641
+ def RandomDirectedGNM(self, n, m, loops=False, immutable=False):
1585
1642
  r"""
1586
1643
  Return a random labelled digraph on `n` nodes and `m` arcs.
1587
1644
 
@@ -1593,6 +1650,9 @@ class DiGraphGenerators:
1593
1650
 
1594
1651
  - ``loops`` -- boolean (default: ``False``); whether to allow loops
1595
1652
 
1653
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1654
+ immutable or mutable digraph
1655
+
1596
1656
  PLOTTING: When plotting, this graph will use the default spring-layout
1597
1657
  algorithm, unless a position dictionary is specified.
1598
1658
 
@@ -1635,10 +1695,6 @@ class DiGraphGenerators:
1635
1695
  # When the graph is dense, we actually compute its complement. This will
1636
1696
  # prevent us from drawing the same pair u,v too many times.
1637
1697
 
1638
- from sage.misc.prandom import _pyrand
1639
- rand = _pyrand()
1640
- D = DiGraph(n, loops=loops)
1641
-
1642
1698
  # Ensuring the parameters n,m make sense.
1643
1699
  #
1644
1700
  # If the graph is dense, we actually want to build its complement. We
@@ -1679,9 +1735,10 @@ class DiGraphGenerators:
1679
1735
 
1680
1736
  adj = {i: dict() for i in range(n)}
1681
1737
 
1682
- # We fill the dictionary structure, but add the corresponding edge in
1683
- # the graph only if is_dense is False. If it is true, we will add the
1684
- # edges in a second phase.
1738
+ # We fill the dictionary structure.
1739
+
1740
+ from sage.misc.prandom import _pyrand
1741
+ rand = _pyrand()
1685
1742
 
1686
1743
  while m > 0:
1687
1744
 
@@ -1697,21 +1754,19 @@ class DiGraphGenerators:
1697
1754
  if (u != v or loops) and (v not in adj[u]):
1698
1755
  adj[u][v] = 1
1699
1756
  m -= 1
1700
- if not is_dense:
1701
- D.add_edge(u, v)
1702
1757
 
1703
- # If is_dense is True, it means the graph has not been built. We fill D
1704
- # with the complement of the edges stored in the adj dictionary
1758
+ # If is_dense is True, we fill the digraph with the complement of the
1759
+ # edges stored in the adj dictionary
1705
1760
 
1706
1761
  if is_dense:
1707
- for u in range(n):
1708
- for v in range(n):
1709
- if ((u != v) or loops) and (v not in adj[u]):
1710
- D.add_edge(u, v)
1762
+ edges = ((u, v) for u in range(n) for v in range(n)
1763
+ if (u != v or loops) and v not in adj[u])
1764
+ return DiGraph([range(n), edges], format='vertices_and_edges',
1765
+ loops=loops, immutable=immutable)
1711
1766
 
1712
- return D
1767
+ return DiGraph(adj, format='dict_of_lists', loops=loops)
1713
1768
 
1714
- def RandomDirectedGNR(self, n, p, seed=None):
1769
+ def RandomDirectedGNR(self, n, p, seed=None, immutable=False):
1715
1770
  r"""
1716
1771
  Return a random growing network with redirection (GNR) digraph
1717
1772
  with `n` vertices and redirection probability `p`.
@@ -1731,6 +1786,9 @@ class DiGraphGenerators:
1731
1786
  - ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the
1732
1787
  random number generator (default: ``None``)
1733
1788
 
1789
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1790
+ immutable or mutable digraph
1791
+
1734
1792
  EXAMPLES::
1735
1793
 
1736
1794
  sage: # needs networkx
@@ -1744,9 +1802,9 @@ class DiGraphGenerators:
1744
1802
  if seed is None:
1745
1803
  seed = int(current_randstate().long_seed() % sys.maxsize)
1746
1804
  import networkx
1747
- return DiGraph(networkx.gnr_graph(n, p, seed=seed))
1805
+ return DiGraph(networkx.gnr_graph(n, p, seed=seed), immutable=immutable)
1748
1806
 
1749
- def RandomSemiComplete(self, n):
1807
+ def RandomSemiComplete(self, n, immutable=False):
1750
1808
  r"""
1751
1809
  Return a random semi-complete digraph on `n` vertices.
1752
1810
 
@@ -1766,6 +1824,9 @@ class DiGraphGenerators:
1766
1824
 
1767
1825
  - ``n`` -- integer; the number of nodes
1768
1826
 
1827
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
1828
+ immutable or mutable digraph
1829
+
1769
1830
  .. SEEALSO::
1770
1831
 
1771
1832
  - :meth:`~sage.graphs.digraph_generators.DiGraphGenerators.Complete`
@@ -1783,22 +1844,26 @@ class DiGraphGenerators:
1783
1844
  ...
1784
1845
  ValueError: the number of vertices cannot be strictly negative
1785
1846
  """
1786
- G = DiGraph(n, name="Random Semi-Complete digraph")
1847
+ if n < 0:
1848
+ raise ValueError('the number of vertices cannot be strictly negative')
1787
1849
 
1788
1850
  # For each pair u,v we choose a random number ``coin`` in [1,3].
1789
1851
  # We select edge `(u,v)` if `coin==1` or `coin==2`.
1790
1852
  # We select edge `(v,u)` if `coin==2` or `coin==3`.
1791
1853
  import itertools
1792
1854
  from sage.misc.prandom import randint
1793
- for u, v in itertools.combinations(range(n), 2):
1794
- coin = randint(1, 3)
1795
- if coin <= 2:
1796
- G.add_edge(u, v)
1797
- if coin >= 2:
1798
- G.add_edge(v, u)
1799
1855
 
1800
- G._circle_embedding(list(range(n)))
1856
+ def edges():
1857
+ for u, v in itertools.combinations(range(n), 2):
1858
+ coin = randint(1, 3)
1859
+ if coin <= 2:
1860
+ yield (u, v)
1861
+ if coin >= 2:
1862
+ yield (v, u)
1801
1863
 
1864
+ G = DiGraph([range(n), edges()], format='vertices_and_edges',
1865
+ immutable=immutable, name="Random Semi-Complete digraph")
1866
+ G._circle_embedding(list(range(n)))
1802
1867
  return G
1803
1868
 
1804
1869
  # ##############################################################################
@@ -1806,7 +1871,7 @@ class DiGraphGenerators:
1806
1871
  # ##############################################################################
1807
1872
 
1808
1873
  def __call__(self, vertices=None, property=lambda x: True, augment='edges',
1809
- size=None, sparse=True, copy=True):
1874
+ size=None, sparse=True, copy=True, immutable=False):
1810
1875
  """
1811
1876
  Access the generator of isomorphism class representatives [McK1998]_.
1812
1877
  Iterates over distinct, exhaustive representatives.
@@ -1850,6 +1915,13 @@ class DiGraphGenerators:
1850
1915
  compute the next ones: only use ``copy = False`` when you stick to
1851
1916
  *reading* the digraphs returned.
1852
1917
 
1918
+ This parameter is ignored when ``immutable`` is set to ``True``, in
1919
+ which case returned graphs are always copies.
1920
+
1921
+ - ``immutable`` -- boolean (default: ``False``); whether to return
1922
+ immutable or mutable digraphs. When set to ``True``, this parameter
1923
+ implies ``copy=True``.
1924
+
1853
1925
  EXAMPLES:
1854
1926
 
1855
1927
  Print digraphs on 2 or less vertices::
@@ -1876,7 +1948,6 @@ class DiGraphGenerators:
1876
1948
 
1877
1949
  sage: digraphs? # not tested
1878
1950
  """
1879
- from copy import copy as copyfun
1880
1951
  if size is not None:
1881
1952
  def extra_property(x):
1882
1953
  return x.size() == size
@@ -1891,14 +1962,15 @@ class DiGraphGenerators:
1891
1962
  g = DiGraph(sparse=sparse)
1892
1963
  for gg in canaug_traverse_vert(g, [], vertices, property, dig=True, sparse=sparse):
1893
1964
  if extra_property(gg):
1894
- yield copyfun(gg) if copy else gg
1965
+ yield gg.copy(immutable=immutable) if copy or immutable else gg
1895
1966
 
1896
1967
  elif augment == 'edges':
1897
1968
 
1898
1969
  if vertices is None:
1899
1970
  vertices = 0
1900
1971
  while True:
1901
- yield from self(vertices, sparse=sparse, copy=copy)
1972
+ yield from self(vertices, sparse=sparse, copy=copy,
1973
+ immutable=immutable)
1902
1974
  vertices += 1
1903
1975
 
1904
1976
  from sage.graphs.graph_generators import canaug_traverse_edge
@@ -1912,7 +1984,7 @@ class DiGraphGenerators:
1912
1984
  gens.append(gen)
1913
1985
  for gg in canaug_traverse_edge(g, gens, property, dig=True, sparse=sparse):
1914
1986
  if extra_property(gg):
1915
- yield copyfun(gg) if copy else gg
1987
+ yield gg.copy(immutable=immutable) if copy or immutable else gg
1916
1988
  else:
1917
1989
  raise NotImplementedError()
1918
1990
 
@@ -15,7 +15,7 @@ from sage.misc.cachefunc import cached_function
15
15
 
16
16
 
17
17
  @cached_function
18
- def have_dot2tex():
18
+ def have_dot2tex() -> bool:
19
19
  """
20
20
  Return whether ``dot2tex`` >= 2.8.7 and graphviz are installed
21
21
  and functional.
@@ -748,7 +748,7 @@ def CompleteMultipartiteGraph(L, immutable=False):
748
748
  ...
749
749
  ValueError: the sizes of the components must be positive integers
750
750
 
751
- Check the bahavior of parameter ``immutable``::
751
+ Check the behaviour of parameter ``immutable``::
752
752
 
753
753
  sage: graphs.CompleteMultipartiteGraph([1], immutable=True).is_immutable()
754
754
  True
@@ -856,7 +856,7 @@ def HermitianFormsGraph(const int n, const int r):
856
856
  sage: G.is_distance_regular(True)
857
857
  ([5, 4, None], [None, 1, 2])
858
858
  sage: G = graphs.HermitianFormsGraph(3, 3) # not tested (2 min)
859
- sage: G.order() # not tested (bacuase of the above)
859
+ sage: G.order() # not tested (because of the above)
860
860
  19683
861
861
 
862
862
  REFERENCES: