passagemath-graphs 10.5.43__cp312-cp312-macosx_14_0_arm64.whl → 10.6.1rc2__cp312-cp312-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.1rc2.dist-info}/METADATA +5 -6
  2. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.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-312-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-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-312-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-312-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-312-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-312-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-312-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-312-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-312-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-312-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-312-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-312-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-312-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-312-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-312-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-312-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-312-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-312-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-312-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-312-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-312-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-312-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-312-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-312-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-312-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-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.1rc2.dist-info}/WHEEL +0 -0
  132. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/top_level.txt +0 -0
@@ -26,6 +26,8 @@ from libc.stdint cimport uint32_t
26
26
  from cysignals.signals cimport sig_on, sig_off, sig_check
27
27
  from memory_allocator cimport MemoryAllocator
28
28
 
29
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
30
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
29
31
  from sage.graphs.base.static_sparse_graph cimport short_digraph
30
32
  from sage.graphs.base.static_sparse_graph cimport init_short_digraph
31
33
  from sage.graphs.base.static_sparse_graph cimport free_short_digraph
@@ -414,6 +416,17 @@ def atoms_and_clique_separators(G, tree=False, rooted_tree=False, separators=Fal
414
416
  {1} _{}_
415
417
  / /
416
418
  {3} {2}
419
+
420
+ Immutable graphs::
421
+
422
+ sage: G = graphs.RandomGNP(10, .7)
423
+ sage: G._backend
424
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
425
+ sage: H = Graph(G, immutable=True)
426
+ sage: H._backend
427
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
428
+ sage: G.atoms_and_clique_separators() == H.atoms_and_clique_separators()
429
+ True
417
430
  """
418
431
  cdef list A = [] # atoms
419
432
  cdef list Sh = [] # separators
@@ -453,13 +466,20 @@ def atoms_and_clique_separators(G, tree=False, rooted_tree=False, separators=Fal
453
466
  return A, Sc
454
467
 
455
468
  cdef int N = G.order()
456
- cdef list int_to_vertex = list(G)
457
469
 
458
470
  # Copying the whole graph to obtain the list of neighbors quicker than by
459
471
  # calling out_neighbors. This data structure is well documented in the
460
472
  # module sage.graphs.base.static_sparse_graph
473
+ cdef list int_to_vertex
474
+ cdef StaticSparseCGraph cg
461
475
  cdef short_digraph sd
462
- init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
476
+ if isinstance(G, StaticSparseBackend):
477
+ cg = <StaticSparseCGraph> G._cg
478
+ sd = <short_digraph> cg.g
479
+ int_to_vertex = cg._vertex_to_labels
480
+ else:
481
+ int_to_vertex = list(G)
482
+ init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
463
483
 
464
484
  # variables for the manipulation of the short digraph
465
485
  cdef uint32_t** p_vertices = sd.neighbors
@@ -575,7 +595,8 @@ def atoms_and_clique_separators(G, tree=False, rooted_tree=False, separators=Fal
575
595
  for u in Cint:
576
596
  active[u] = False
577
597
 
578
- free_short_digraph(sd)
598
+ if not isinstance(G, StaticSparseBackend):
599
+ free_short_digraph(sd)
579
600
  H.clear()
580
601
 
581
602
  # We add the last atom
@@ -91,7 +91,7 @@ cdef class FastDigraph:
91
91
 
92
92
  def print_adjacency_matrix(self):
93
93
  r"""
94
- Displays the adjacency matrix of ``self``.
94
+ Display the adjacency matrix of ``self``.
95
95
 
96
96
  EXAMPLES::
97
97
 
@@ -132,7 +132,7 @@ Methods
132
132
  # ****************************************************************************
133
133
 
134
134
 
135
- def is_cartesian_product(g, certificate=False, relabeling=False):
135
+ def is_cartesian_product(g, certificate=False, relabeling=False, immutable=None):
136
136
  r"""
137
137
  Test whether the graph is a Cartesian product.
138
138
 
@@ -149,6 +149,10 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
149
149
  product graph. If `g` is not a Cartesian product, ``None`` is returned
150
150
  instead.
151
151
 
152
+ - ``immutable`` -- boolean (default: ``None``); whether to create a
153
+ mutable/immutable graph. ``immutable=None`` (default) means that the
154
+ graph and its factors will behave the same way.
155
+
152
156
  .. SEEALSO::
153
157
 
154
158
  - :meth:`sage.graphs.generic_graph.GenericGraph.cartesian_product`
@@ -217,6 +221,19 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
217
221
  False
218
222
  sage: Graph({0:[]}).is_cartesian_product()
219
223
  False
224
+
225
+ Check the behaviour of parameter ``immutable``::
226
+
227
+ sage: G = graphs.Grid2dGraph(3, 3)
228
+ sage: any(f.is_immutable() for f in G.is_cartesian_product(certificate=True))
229
+ False
230
+ sage: all(f.is_immutable() for f in G.is_cartesian_product(certificate=True, immutable=True))
231
+ True
232
+ sage: G = G.copy(immutable=True)
233
+ sage: all(f.is_immutable() for f in G.is_cartesian_product(certificate=True))
234
+ True
235
+ sage: any(f.is_immutable() for f in G.is_cartesian_product(certificate=True, immutable=False))
236
+ False
220
237
  """
221
238
  g._scream_if_not_simple()
222
239
  if g.is_directed():
@@ -316,11 +333,13 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
316
333
  if len(edges) == 1:
317
334
  return (False, None) if relabeling else False
318
335
 
336
+ if immutable is None:
337
+ immutable = g.is_immutable()
338
+
319
339
  # Building the list of factors
320
340
  cdef list factors = []
321
341
  for cc in edges:
322
- tmp = Graph()
323
- tmp.add_edges(cc)
342
+ tmp = Graph(cc, format='list_of_edges', immutable=immutable)
324
343
  factors.append(tmp.subgraph(vertices=tmp.connected_components(sort=False)[0]))
325
344
 
326
345
  # Computing the product of these graphs
@@ -338,11 +357,10 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
338
357
  return isiso, dictt
339
358
  if certificate:
340
359
  return factors
341
- else:
342
- return True
360
+ return True
343
361
 
344
362
 
345
- def rooted_product(G, H, root=None):
363
+ def rooted_product(G, H, root=None, immutable=None):
346
364
  r"""
347
365
  Return the rooted product of `G` and `H`.
348
366
 
@@ -369,6 +387,15 @@ def rooted_product(G, H, root=None):
369
387
  - :mod:`~sage.graphs.graph_decompositions.graph_products`
370
388
  -- a module on graph products
371
389
 
390
+ INPUT:
391
+
392
+ - ``G, H`` -- two (di)graphs
393
+
394
+ - ``immutable`` -- boolean (default: ``None``); whether to create a
395
+ mutable/immutable (di)graph. When ``immutable=None`` (default) the rooted
396
+ product will be mutable if one of ``G`` or ``H`` is mutable and immutable
397
+ otherwise.
398
+
372
399
  EXAMPLES:
373
400
 
374
401
  The rooted product of two trees is a tree::
@@ -433,30 +460,49 @@ def rooted_product(G, H, root=None):
433
460
  Traceback (most recent call last):
434
461
  ...
435
462
  TypeError: the graphs should be both directed or both undirected
463
+
464
+ Check the behaviour of parameter ``immutable``::
465
+
466
+ sage: G = graphs.CycleGraph(4)
467
+ sage: H = graphs.PathGraph(3)
468
+ sage: G.rooted_product(H).is_immutable()
469
+ False
470
+ sage: G.rooted_product(H, immutable=True).is_immutable()
471
+ True
472
+ sage: G = G.copy(immutable=True)
473
+ sage: G.rooted_product(H).is_immutable()
474
+ False
475
+ sage: G.rooted_product(H, immutable=True).is_immutable()
476
+ True
477
+ sage: H = H.copy(immutable=True)
478
+ sage: G.rooted_product(H).is_immutable()
479
+ True
480
+ sage: G.rooted_product(H, immutable=False).is_immutable()
481
+ False
436
482
  """
437
483
  G._scream_if_not_simple(allow_loops=True)
438
- if G._directed and H._directed:
439
- from sage.graphs.digraph import DiGraph
440
- R = DiGraph(loops=(G.has_loops() or H.has_loops()))
441
- elif (not G._directed) and (not H._directed):
442
- from sage.graphs.graph import Graph
443
- R = Graph(loops=(G.has_loops() or H.has_loops()))
444
- else:
484
+ if G._directed is not H._directed:
445
485
  raise TypeError('the graphs should be both directed or both undirected')
446
486
 
447
- R.name(f'Rooted product of {G} and {H}')
487
+ loops = G.has_loops() or H.has_loops()
488
+ name = f'Rooted product of {G} and {H}'
489
+ if immutable is None:
490
+ immutable = G.is_immutable() and H.is_immutable()
448
491
 
449
492
  if not G or not H:
450
- return R
493
+ return G.parent()(loops=loops, name=name, immutable=immutable)
451
494
  if root is None:
452
495
  root = next(H.vertex_iterator())
453
496
  elif root not in H:
454
497
  raise ValueError("the specified root is not a vertex of H")
455
498
 
456
- R.add_vertices((u, x) for u in G for x in H)
457
- for u, v in G.edge_iterator(labels=False):
458
- R.add_edge((u, root), (v, root))
459
- for x, y in H.edge_iterator(labels=False):
460
- R.add_edges(((u, x), (u, y)) for u in G)
499
+ vertices = ((u, x) for u in G for x in H)
500
+
501
+ def edges():
502
+ for u, v in G.edge_iterator(labels=False):
503
+ yield ((u, root), (v, root))
504
+ for x, y in H.edge_iterator(labels=False):
505
+ yield from (((u, x), (u, y)) for u in G)
461
506
 
462
- return R
507
+ return G.parent()([vertices, edges()], format='vertices_and_edges',
508
+ name=name, loops=loops, immutable=immutable)
@@ -28,6 +28,7 @@ AUTHORS:
28
28
  # ****************************************************************************
29
29
 
30
30
  from libcpp.algorithm cimport swap
31
+ from cysignals.signals cimport sig_on, sig_off
31
32
  from cython.operator cimport dereference as deref
32
33
 
33
34
  from sage.graphs.base.c_graph cimport CGraphBackend
@@ -156,6 +157,19 @@ cdef void extended_lex_BFS(
156
157
  [0[1[2]] [3] [4]]
157
158
  sage: G.lex_BFS(algorithm="fast")
158
159
  [0, 1, 2, 3, 4]
160
+
161
+ Check that :issue:`39934` is fixed::
162
+
163
+ sage: G = Graph(graphs.HouseGraph(), immutable=True)
164
+ sage: G.slice_decomposition()
165
+ [0[1[2]] [3] [4]]
166
+ sage: G.lex_BFS(algorithm="fast")
167
+ [0, 1, 2, 3, 4]
168
+ sage: G = Graph(graphs.HouseGraph(), sparse=False)
169
+ sage: G.slice_decomposition()
170
+ [0[1[2]] [3] [4]]
171
+ sage: G.lex_BFS(algorithm="fast")
172
+ [0, 1, 2, 3, 4]
159
173
  """
160
174
  cdef int n = <int> cg.num_verts
161
175
  # Variables for the partition refinement algorithm
@@ -182,6 +196,7 @@ cdef void extended_lex_BFS(
182
196
  deref(xslice_len).resize(n)
183
197
  part_len.resize(max_nparts)
184
198
  if lex_label != NULL:
199
+ deref(lex_label).clear()
185
200
  deref(lex_label).resize(n)
186
201
 
187
202
  # Initialize the position of vertices in sigma (and compute max_degree)
@@ -197,7 +212,7 @@ cdef void extended_lex_BFS(
197
212
  sigma[i] = v_int
198
213
  deref(sigma_inv)[v_int] = i
199
214
  i = i + 1
200
- max_degree = max(max_degree, cg.out_degrees[v_int])
215
+ max_degree = max(max_degree, cg.out_degree(v_int))
201
216
 
202
217
  # Variables needed to iterate over neighbors of a vertex
203
218
  cdef int nneighbors
@@ -226,7 +241,7 @@ cdef void extended_lex_BFS(
226
241
  v_int = sigma[i]
227
242
 
228
243
  # Iterate over the neighbors of v
229
- nneighbors = cg.out_neighbors_unsafe (v_int, neighbors.data(), max_degree)
244
+ nneighbors = cg.out_neighbors_unsafe(v_int, neighbors.data(), max_degree)
230
245
  for k in range(nneighbors):
231
246
  u_int = neighbors[k]
232
247
  j = deref(sigma_inv)[u_int] # get the position of u
@@ -234,7 +249,7 @@ cdef void extended_lex_BFS(
234
249
  continue # already taken care of
235
250
 
236
251
  if lex_label != NULL:
237
- deref(lex_label)[j].push_back (v_int)
252
+ deref(lex_label)[j].push_back(v_int)
238
253
 
239
254
  p = part_of[j] # get the part of u
240
255
  l = part_head[p] # get the beginning of the part containing u
@@ -339,6 +354,14 @@ def slice_decomposition(G, initial_vertex=None):
339
354
  Traceback (most recent call last):
340
355
  ...
341
356
  ValueError: parameter G must be an undirected graph
357
+
358
+ TESTS:
359
+
360
+ Check that :issue:`39934` is fixed::
361
+
362
+ sage: G = Graph(graphs.HouseGraph(), immutable=True)
363
+ sage: G.slice_decomposition()
364
+ [0[1[2]] [3] [4]]
342
365
  """
343
366
  return SliceDecomposition(G, initial_vertex=initial_vertex)
344
367
 
@@ -410,14 +433,17 @@ cdef class SliceDecomposition(SageObject):
410
433
  cdef vector[vector[int]] lex_label
411
434
 
412
435
  # Compute the slice decomposition using the extended lexBFS algorithm
436
+ sig_on()
413
437
  extended_lex_BFS(cg, sigma, NULL, initial_v_int, NULL,
414
438
  &(self.xslice_len), &lex_label)
439
+ sig_off()
415
440
 
416
441
  # Translate the results with the actual vertices of the graph
417
442
  self.sigma = tuple(Gbackend.vertex_label(v_int) for v_int in sigma)
418
- self.sigma_inv = {v: i for i, v in enumerate(self.sigma)}
419
- self.lex_label = {i: tuple(Gbackend.vertex_label(v_int) for v_int in lli)
420
- for i, lli in enumerate(lex_label)}
443
+ self.sigma_inv = {v: i for i, v in enumerate(self.sigma)}
444
+ self.lex_label = {i: tuple(Gbackend.vertex_label(v_int)
445
+ for v_int in lli)
446
+ for i, lli in enumerate(lex_label)}
421
447
 
422
448
  def __eq__(self, other):
423
449
  """
@@ -480,7 +506,7 @@ cdef class SliceDecomposition(SageObject):
480
506
 
481
507
  OUTPUT:
482
508
 
483
- A dictionnary with the keys:
509
+ A dictionary with the keys:
484
510
 
485
511
  * ``"pivot"`` -- the vertex `v` given as parameter
486
512
 
@@ -523,7 +549,7 @@ cdef class SliceDecomposition(SageObject):
523
549
  'sequence': [['u'], ['y', 'z']],
524
550
  'slice': ['u', 'y', 'z']}
525
551
 
526
- Some values of the returned dictionnary can be obtained via other
552
+ Some values of the returned dictionary can be obtained via other
527
553
  methods (:meth:`~slice`, :meth:`~xslice_sequence`,
528
554
  :meth:`~active_edges`, :meth:`~lexicographic_label`)::
529
555
 
@@ -36,11 +36,11 @@ def __append_to_doc(methods):
36
36
  " :widths: 33, 33, 33\n"
37
37
  " :delim: |\n\n")
38
38
 
39
- h = (len(methods)+2)//3
39
+ h = (len(methods) + 2) // 3
40
40
  # Reorders the list of methods for horizontal reading, the only one Sphinx understands
41
- reordered_methods = [0]*3*h
41
+ reordered_methods = [0] * (3 * h)
42
42
  for i, m in enumerate(methods):
43
- reordered_methods[3*(i % h) + (i//h)] = m
43
+ reordered_methods[3 * (i % h) + (i // h)] = m
44
44
  methods = reordered_methods
45
45
 
46
46
  # Adding the list to the __doc__ string
@@ -845,7 +845,7 @@ class GraphGenerators:
845
845
  if vertices is None:
846
846
  raise NotImplementedError
847
847
  if (len(degree_sequence) != vertices or sum(degree_sequence) % 2
848
- or sum(degree_sequence) > vertices*(vertices - 1)):
848
+ or sum(degree_sequence) > vertices * (vertices - 1)):
849
849
  raise ValueError("Invalid degree sequence.")
850
850
  degree_sequence = sorted(degree_sequence)
851
851
  if augment == 'edges':
@@ -1126,7 +1126,7 @@ class GraphGenerators:
1126
1126
 
1127
1127
  EXAMPLES:
1128
1128
 
1129
- The generator can be used to construct biparrtite graphs for testing,
1129
+ The generator can be used to construct bipartite graphs for testing,
1130
1130
  one at a time (usually inside a loop). Or it can be used to
1131
1131
  create an entire list all at once if there is sufficient memory
1132
1132
  to contain it::
@@ -1510,7 +1510,7 @@ class GraphGenerators:
1510
1510
  def _read_planar_code(self, code_input, immutable=False):
1511
1511
  r"""
1512
1512
  Return a generator for the plane graphs in planar code format in
1513
- the file code_input (see [BM2016]_).
1513
+ the binary file ``code_input`` (see [BM2016]_).
1514
1514
 
1515
1515
  A file with planar code starts with a header ``>>planar_code<<``.
1516
1516
  After the header each graph is stored in the following way :
@@ -1524,7 +1524,7 @@ class GraphGenerators:
1524
1524
 
1525
1525
  INPUT:
1526
1526
 
1527
- - ``code_input`` -- a file containing valid planar code data
1527
+ - ``code_input`` -- a binary file containing valid planar code data
1528
1528
 
1529
1529
  - ``immutable`` -- boolean (default: ``False``); whether to return
1530
1530
  immutable or mutable graphs
@@ -1544,18 +1544,17 @@ class GraphGenerators:
1544
1544
 
1545
1545
  EXAMPLES:
1546
1546
 
1547
- The following example creates a small planar code file in memory and
1548
- reads it using the ``_read_planar_code`` method::
1547
+ The following example creates a small planar code binary
1548
+ file in memory and reads it using the ``_read_planar_code`` method::
1549
1549
 
1550
- sage: from io import StringIO
1551
- sage: code_input = StringIO('>>planar_code<<')
1552
- sage: _ = code_input.write('>>planar_code<<')
1550
+ sage: from io import BytesIO
1551
+ sage: code_input = BytesIO()
1552
+ sage: n = code_input.write(b'>>planar_code<<')
1553
1553
  sage: for c in [4,2,3,4,0,1,4,3,0,1,2,4,0,1,3,2,0]:
1554
- ....: _ = code_input.write('{:c}'.format(c))
1555
- sage: _ = code_input.seek(0)
1554
+ ....: n = code_input.write(bytes('{:c}'.format(c),'ascii'))
1555
+ sage: n = code_input.seek(0)
1556
1556
  sage: gen = graphs._read_planar_code(code_input)
1557
- sage: l = list(gen)
1558
- sage: l
1557
+ sage: l = list(gen); l
1559
1558
  [Graph on 4 vertices]
1560
1559
  sage: l[0].is_isomorphic(graphs.CompleteGraph(4))
1561
1560
  True
@@ -1564,10 +1563,33 @@ class GraphGenerators:
1564
1563
  2: [1, 4, 3],
1565
1564
  3: [1, 2, 4],
1566
1565
  4: [1, 3, 2]}
1566
+
1567
+ TESTS::
1568
+
1569
+ sage: from io import StringIO
1570
+ sage: code_input = StringIO()
1571
+ sage: n = code_input.write('>>planar_code<<')
1572
+ sage: n = code_input.seek(0)
1573
+ sage: list(graphs._read_planar_code(code_input))
1574
+ Traceback (most recent call last):
1575
+ ...
1576
+ TypeError: not a binary file
1577
+
1578
+ sage: from io import BytesIO
1579
+ sage: code_input = BytesIO()
1580
+ sage: n = code_input.write(b'>>wrong header<<')
1581
+ sage: n = code_input.seek(0)
1582
+ sage: list(graphs._read_planar_code(code_input))
1583
+ Traceback (most recent call last):
1584
+ ...
1585
+ TypeError: file has no valid planar code header
1567
1586
  """
1568
1587
  # start of code to read planar code
1569
1588
  header = code_input.read(15)
1570
- assert header == '>>planar_code<<', 'Not a valid planar code header'
1589
+ if not isinstance(header, bytes):
1590
+ raise TypeError('not a binary file')
1591
+ if header != b'>>planar_code<<':
1592
+ raise TypeError('file has no valid planar code header')
1571
1593
 
1572
1594
  # read graph per graph
1573
1595
  while True:
@@ -1720,10 +1742,7 @@ class GraphGenerators:
1720
1742
 
1721
1743
  sp = subprocess.Popen(command, shell=True,
1722
1744
  stdin=subprocess.PIPE, stdout=subprocess.PIPE,
1723
- stderr=subprocess.PIPE, close_fds=True,
1724
- encoding='latin-1')
1725
-
1726
- sp.stdout.reconfigure(newline='')
1745
+ stderr=subprocess.PIPE, close_fds=True)
1727
1746
 
1728
1747
  yield from graphs._read_planar_code(sp.stdout, immutable=immutable)
1729
1748
 
@@ -1811,10 +1830,7 @@ class GraphGenerators:
1811
1830
 
1812
1831
  sp = subprocess.Popen(command, shell=True,
1813
1832
  stdin=subprocess.PIPE, stdout=subprocess.PIPE,
1814
- stderr=subprocess.PIPE, close_fds=True,
1815
- encoding='latin-1')
1816
-
1817
- sp.stdout.reconfigure(newline='')
1833
+ stderr=subprocess.PIPE, close_fds=True)
1818
1834
 
1819
1835
  yield from graphs._read_planar_code(sp.stdout, immutable=immutable)
1820
1836
 
@@ -1999,14 +2015,11 @@ class GraphGenerators:
1999
2015
  options)
2000
2016
  sp = subprocess.Popen(command, shell=True,
2001
2017
  stdin=subprocess.PIPE, stdout=subprocess.PIPE,
2002
- stderr=subprocess.PIPE, close_fds=True,
2003
- encoding='latin-1')
2004
-
2005
- sp.stdout.reconfigure(newline='')
2018
+ stderr=subprocess.PIPE, close_fds=True)
2006
2019
 
2007
2020
  try:
2008
2021
  yield from graphs._read_planar_code(sp.stdout, immutable=immutable)
2009
- except AssertionError:
2022
+ except (TypeError, AssertionError):
2010
2023
  raise AttributeError("invalid options '{}'".format(options))
2011
2024
 
2012
2025
  def planar_graphs(self, order, minimum_degree=None,
@@ -2209,7 +2222,7 @@ class GraphGenerators:
2209
2222
  raise ValueError("the number of edges cannot be less than order - 1")
2210
2223
  edges = '-e:{}'.format(maximum_edges)
2211
2224
  else:
2212
- if minimum_edges > 3*order - 6:
2225
+ if minimum_edges > 3 * order - 6:
2213
2226
  raise ValueError("the number of edges cannot be more than 3*order - 6")
2214
2227
  if maximum_edges is None:
2215
2228
  edges = '-e{}:'.format(minimum_edges)
@@ -2970,7 +2983,7 @@ def canaug_traverse_vert(g, aut_gens, max_verts, property, dig=False, loops=Fals
2970
2983
  # in the case of graphs, there are n possibilities,
2971
2984
  # and in the case of digraphs, there are 2*n.
2972
2985
  if dig:
2973
- possibilities = 2*n
2986
+ possibilities = 2 * n
2974
2987
  else:
2975
2988
  possibilities = n
2976
2989
  num_roots = 2**possibilities
@@ -18,7 +18,8 @@ from sage.misc.randstate cimport random
18
18
  from sage.misc.randstate import set_random_seed
19
19
 
20
20
 
21
- def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None):
21
+ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None,
22
+ immutable=False):
22
23
  r"""
23
24
  Return a random graph or a digraph on `n` nodes.
24
25
 
@@ -39,6 +40,9 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None):
39
40
  - ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the random
40
41
  number generator (default: ``None``)
41
42
 
43
+ - ``immutable`` -- boolean (default: ``False``); whether to return an
44
+ immutable or mutable (di)graph.
45
+
42
46
  REFERENCES:
43
47
 
44
48
  - [ER1959]_
@@ -52,7 +56,8 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None):
52
56
  sage: D.num_verts()
53
57
  10
54
58
  sage: D.edges(sort=True, labels=False)
55
- [(0, 2), (0, 5), (1, 5), (1, 7), (4, 1), (4, 2), (4, 9), (5, 0), (5, 2), (5, 3), (5, 7), (6, 5), (7, 1), (8, 2), (8, 6), (9, 4)]
59
+ [(0, 3), (0, 6), (1, 7), (1, 9), (4, 6), (4, 7), (5, 4), (5, 6),
60
+ (5, 8), (5, 9), (6, 3), (7, 2), (7, 9), (8, 5), (9, 1), (9, 5)]
56
61
 
57
62
  TESTS::
58
63
 
@@ -73,23 +78,18 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None):
73
78
  cdef int pp = int(round(float(p * RAND_MAX_f)))
74
79
 
75
80
  if directed:
76
- from sage.graphs.digraph import DiGraph
77
- G = DiGraph(loops=loops)
81
+ from sage.graphs.digraph import DiGraph as GT
78
82
  else:
79
- from sage.graphs.graph import Graph
80
- G = Graph()
81
83
  if loops:
82
84
  raise ValueError("parameter 'loops' can be set to True only when 'directed' is True")
83
- G.name('Random' + ('Directed' if directed else '') + 'GNP(%s,%s)' % (n, p))
85
+ from sage.graphs.graph import Graph as GT
84
86
 
85
- G.add_vertices(range(n))
87
+ name = 'Random' + ('Directed' if directed else '') + 'GNP(%s,%s)' % (n, p)
86
88
 
87
- # Standard random GNP generator for Graph and DiGraph
88
89
  cdef int i, j
89
- for i in range(n):
90
- for j in range((0 if directed else i + 1), n):
91
- if random() < pp:
92
- if i != j or loops:
93
- G.add_edge(i, j)
90
+ edges = ((i, j) for i in range(n)
91
+ for j in range((0 if directed else i + 1), n)
92
+ if (i != j or loops) and random() < pp)
94
93
 
95
- return G
94
+ return GT([range(n), edges], format='vertices_and_edges',
95
+ loops=directed and loops, name=name, immutable=immutable)
@@ -430,7 +430,7 @@ Visit 'https://www.ctan.org/pkg/tkz-berge'.
430
430
  """)
431
431
 
432
432
 
433
- def have_tkz_graph():
433
+ def have_tkz_graph() -> bool:
434
434
  r"""
435
435
  Return ``True`` if the proper LaTeX packages for the ``tikzpicture``
436
436
  environment are installed in the user's environment, namely ``tikz``,