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
@@ -56,6 +56,7 @@ Here is what the module can do:
56
56
  :meth:`is_triconnected` | Check whether the graph is triconnected.
57
57
  :meth:`spqr_tree` | Return a SPQR-tree representing the triconnected components of the graph.
58
58
  :meth:`spqr_tree_to_graph` | Return the graph represented by the SPQR-tree `T`.
59
+ :meth:`minimal_separators` | Return an iterator over the minimal separators of ``G``.
59
60
 
60
61
  Methods
61
62
  -------
@@ -76,7 +77,7 @@ from sage.misc.superseded import deprecation
76
77
  from sage.sets.disjoint_set cimport DisjointSet
77
78
 
78
79
 
79
- def is_connected(G):
80
+ def is_connected(G, forbidden_vertices=None):
80
81
  """
81
82
  Check whether the (di)graph is connected.
82
83
 
@@ -86,6 +87,9 @@ def is_connected(G):
86
87
 
87
88
  - ``G`` -- the input graph
88
89
 
90
+ - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to
91
+ avoid during the search
92
+
89
93
  .. SEEALSO::
90
94
 
91
95
  - :meth:`~Graph.is_biconnected`
@@ -101,6 +105,10 @@ def is_connected(G):
101
105
  sage: G.add_edge(0,3)
102
106
  sage: is_connected(G)
103
107
  True
108
+ sage: is_connected(G, forbidden_vertices=[3])
109
+ False
110
+ sage: is_connected(G, forbidden_vertices=[1])
111
+ True
104
112
  sage: D = DiGraph({0: [1, 2], 1: [2], 3: [4, 5], 4: [5]})
105
113
  sage: is_connected(D)
106
114
  False
@@ -128,15 +136,30 @@ def is_connected(G):
128
136
  if not G.order():
129
137
  return True
130
138
 
139
+ forbidden = None if forbidden_vertices is None else set(forbidden_vertices)
140
+
131
141
  try:
132
- return G._backend.is_connected()
142
+ return G._backend.is_connected(forbidden_vertices=forbidden)
133
143
  except AttributeError:
134
- v = next(G.vertex_iterator())
135
- conn_verts = list(G.depth_first_search(v, ignore_direction=True))
136
- return len(conn_verts) == G.num_verts()
144
+ # Search for a vertex in G that is not forbidden
145
+ if forbidden:
146
+ for v in G:
147
+ if v not in forbidden:
148
+ break
149
+ else:
150
+ # The empty graph is connected, so the graph with only forbidden
151
+ # vertices is also connected
152
+ return True
153
+ else:
154
+ v = next(G.vertex_iterator())
155
+ n = len(forbidden)
156
+ for _ in G.depth_first_search(v, ignore_direction=True,
157
+ forbidden_vertices=forbidden):
158
+ n += 1
159
+ return n == G.num_verts()
137
160
 
138
161
 
139
- def connected_components(G, sort=None, key=None):
162
+ def connected_components(G, sort=None, key=None, forbidden_vertices=None):
140
163
  """
141
164
  Return the list of connected components.
142
165
 
@@ -158,6 +181,9 @@ def connected_components(G, sort=None, key=None):
158
181
  vertex as its one argument and returns a value that can be used for
159
182
  comparisons in the sorting algorithm (we must have ``sort=True``)
160
183
 
184
+ - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to
185
+ avoid during the search
186
+
161
187
  EXAMPLES::
162
188
 
163
189
  sage: from sage.graphs.connectivity import connected_components
@@ -172,6 +198,15 @@ def connected_components(G, sort=None, key=None):
172
198
  sage: connected_components(D, sort=True, key=lambda x: -x)
173
199
  [[3, 2, 1, 0], [6, 5, 4]]
174
200
 
201
+ Connected components in a graph with forbidden vertices::
202
+
203
+ sage: G = graphs.PathGraph(5)
204
+ sage: connected_components(G, sort=True, forbidden_vertices=[2])
205
+ [[0, 1], [3, 4]]
206
+ sage: connected_components(G, sort=True,
207
+ ....: forbidden_vertices=G.neighbor_iterator(2, closed=True))
208
+ [[0], [4]]
209
+
175
210
  TESTS:
176
211
 
177
212
  If ``G`` is not a Sage graph, an error is raised::
@@ -210,18 +245,19 @@ def connected_components(G, sort=None, key=None):
210
245
  if (not sort) and key:
211
246
  raise ValueError('sort keyword is False, yet a key function is given')
212
247
 
213
- cdef set seen = set()
248
+ cdef set seen = set(forbidden_vertices) if forbidden_vertices else set()
214
249
  cdef list components = []
215
250
  for v in G:
216
251
  if v not in seen:
217
- c = connected_component_containing_vertex(G, v, sort=sort, key=key)
252
+ c = connected_component_containing_vertex(G, v, sort=sort, key=key,
253
+ forbidden_vertices=seen)
218
254
  seen.update(c)
219
255
  components.append(c)
220
256
  components.sort(key=lambda comp: -len(comp))
221
257
  return components
222
258
 
223
259
 
224
- def connected_components_number(G):
260
+ def connected_components_number(G, forbidden_vertices=None):
225
261
  """
226
262
  Return the number of connected components.
227
263
 
@@ -229,6 +265,9 @@ def connected_components_number(G):
229
265
 
230
266
  - ``G`` -- the input graph
231
267
 
268
+ - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to
269
+ avoid during the search
270
+
232
271
  EXAMPLES::
233
272
 
234
273
  sage: from sage.graphs.connectivity import connected_components_number
@@ -240,6 +279,8 @@ def connected_components_number(G):
240
279
  sage: D = DiGraph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]})
241
280
  sage: connected_components_number(D)
242
281
  2
282
+ sage: connected_components_number(D, forbidden_vertices=[1, 3])
283
+ 3
243
284
 
244
285
  TESTS:
245
286
 
@@ -251,19 +292,29 @@ def connected_components_number(G):
251
292
  ...
252
293
  TypeError: the input must be a Sage graph
253
294
  """
254
- return len(connected_components(G, sort=False))
295
+ return len(connected_components(G, sort=False,
296
+ forbidden_vertices=forbidden_vertices))
255
297
 
256
298
 
257
- def connected_components_subgraphs(G):
299
+ def connected_components_subgraphs(G, forbidden_vertices=None):
258
300
  """
259
301
  Return a list of connected components as graph objects.
260
302
 
303
+ INPUT:
304
+
305
+ - ``G`` -- the input graph
306
+
307
+ - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to
308
+ avoid during the search
309
+
261
310
  EXAMPLES::
262
311
 
263
312
  sage: from sage.graphs.connectivity import connected_components_subgraphs
264
313
  sage: G = Graph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]})
265
314
  sage: L = connected_components_subgraphs(G)
266
315
  sage: graphs_list.show_graphs(L) # needs sage.plot
316
+ sage: L = connected_components_subgraphs(G, forbidden_vertices=[1, 3])
317
+ sage: graphs_list.show_graphs(L) # needs sage.plot
267
318
  sage: D = DiGraph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]})
268
319
  sage: L = connected_components_subgraphs(D)
269
320
  sage: graphs_list.show_graphs(L) # needs sage.plot
@@ -284,10 +335,13 @@ def connected_components_subgraphs(G):
284
335
  if not isinstance(G, GenericGraph):
285
336
  raise TypeError("the input must be a Sage graph")
286
337
 
287
- return [G.subgraph(c, inplace=False) for c in connected_components(G, sort=False)]
338
+ return [G.subgraph(c, inplace=False)
339
+ for c in connected_components(G, sort=False,
340
+ forbidden_vertices=forbidden_vertices)]
288
341
 
289
342
 
290
- def connected_component_containing_vertex(G, vertex, sort=None, key=None):
343
+ def connected_component_containing_vertex(G, vertex, sort=None, key=None,
344
+ forbidden_vertices=None):
291
345
  """
292
346
  Return a list of the vertices connected to vertex.
293
347
 
@@ -295,7 +349,7 @@ def connected_component_containing_vertex(G, vertex, sort=None, key=None):
295
349
 
296
350
  - ``G`` -- the input graph
297
351
 
298
- - ``v`` -- the vertex to search for
352
+ - ``vertex`` -- the vertex to search for
299
353
 
300
354
  - ``sort`` -- boolean (default: ``None``); if ``True``, vertices inside the
301
355
  component are sorted according to the default ordering
@@ -308,6 +362,9 @@ def connected_component_containing_vertex(G, vertex, sort=None, key=None):
308
362
  vertex as its one argument and returns a value that can be used for
309
363
  comparisons in the sorting algorithm (we must have ``sort=True``)
310
364
 
365
+ - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to
366
+ avoid during the search. The start ``vertex`` cannot be in this set.
367
+
311
368
  EXAMPLES::
312
369
 
313
370
  sage: from sage.graphs.connectivity import connected_component_containing_vertex
@@ -316,6 +373,8 @@ def connected_component_containing_vertex(G, vertex, sort=None, key=None):
316
373
  [0, 1, 2, 3]
317
374
  sage: G.connected_component_containing_vertex(0, sort=True)
318
375
  [0, 1, 2, 3]
376
+ sage: G.connected_component_containing_vertex(0, sort=True, forbidden_vertices=[1, 3])
377
+ [0]
319
378
  sage: D = DiGraph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]})
320
379
  sage: connected_component_containing_vertex(D, 0, sort=True)
321
380
  [0, 1, 2, 3]
@@ -370,22 +429,33 @@ def connected_component_containing_vertex(G, vertex, sort=None, key=None):
370
429
  if (not sort) and key:
371
430
  raise ValueError('sort keyword is False, yet a key function is given')
372
431
 
432
+ forbidden = None if forbidden_vertices is None else list(forbidden_vertices)
433
+
373
434
  try:
374
- c = list(G._backend.depth_first_search(vertex, ignore_direction=True))
435
+ c = list(G._backend.depth_first_search(vertex, ignore_direction=True,
436
+ forbidden_vertices=forbidden))
375
437
  except AttributeError:
376
- c = list(G.depth_first_search(vertex, ignore_direction=True))
438
+ c = list(G.depth_first_search(vertex, ignore_direction=True,
439
+ forbidden_vertices=forbidden))
377
440
 
378
441
  if sort:
379
442
  return sorted(c, key=key)
380
443
  return c
381
444
 
382
445
 
383
- def connected_components_sizes(G):
446
+ def connected_components_sizes(G, forbidden_vertices=None):
384
447
  """
385
448
  Return the sizes of the connected components as a list.
386
449
 
387
450
  The list is sorted from largest to lower values.
388
451
 
452
+ INPUT:
453
+
454
+ - ``G`` -- the input graph
455
+
456
+ - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to
457
+ avoid during the search
458
+
389
459
  EXAMPLES::
390
460
 
391
461
  sage: from sage.graphs.connectivity import connected_components_sizes
@@ -401,6 +471,13 @@ def connected_components_sizes(G):
401
471
  [2, 1]
402
472
  [3]
403
473
  [3]
474
+ sage: G = graphs.PathGraph(5)
475
+ sage: G.connected_components_sizes()
476
+ [5]
477
+ sage: G.connected_components_sizes(forbidden_vertices=[1])
478
+ [3, 1]
479
+ sage: G.connected_components_sizes(forbidden_vertices=[1, 3])
480
+ [1, 1, 1]
404
481
 
405
482
  TESTS:
406
483
 
@@ -417,7 +494,8 @@ def connected_components_sizes(G):
417
494
  raise TypeError("the input must be a Sage graph")
418
495
 
419
496
  # connected components are sorted from largest to smallest
420
- return [len(cc) for cc in connected_components(G, sort=False)]
497
+ return [len(cc) for cc in connected_components(G, sort=False,
498
+ forbidden_vertices=forbidden_vertices)]
421
499
 
422
500
 
423
501
  def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None):
@@ -1186,6 +1264,104 @@ def is_cut_vertex(G, u, weak=False):
1186
1264
  return is_vertex_cut(G, [u], weak=weak)
1187
1265
 
1188
1266
 
1267
+ def minimal_separators(G, forbidden_vertices=None):
1268
+ r"""
1269
+ Return an iterator over the minimal separators of ``G``.
1270
+
1271
+ A separator in a graph is a set of vertices whose removal increases the
1272
+ number of connected components. In other words, a separator is a vertex
1273
+ cut. This method implements the algorithm proposed in [BBC2000]_.
1274
+ It computes the set `S` of minimal separators of a graph in `O(n^3)` time
1275
+ per separator, and so overall in `O(n^3 |S|)` time.
1276
+
1277
+ .. WARNING::
1278
+
1279
+ Note that all separators are recorded during the execution of the
1280
+ algorithm and so the memory consumption of this method might be huge.
1281
+
1282
+ INPUT:
1283
+
1284
+ - ``G`` -- an undirected graph
1285
+
1286
+ - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to
1287
+ avoid during the search
1288
+
1289
+ EXAMPLES::
1290
+
1291
+ sage: P = graphs.PathGraph(5)
1292
+ sage: sorted(sorted(sep) for sep in P.minimal_separators())
1293
+ [[1], [2], [3]]
1294
+ sage: C = graphs.CycleGraph(6)
1295
+ sage: sorted(sorted(sep) for sep in C.minimal_separators())
1296
+ [[0, 2], [0, 3], [0, 4], [1, 3], [1, 4], [1, 5], [2, 4], [2, 5], [3, 5]]
1297
+ sage: sorted(sorted(sep) for sep in C.minimal_separators(forbidden_vertices=[0]))
1298
+ [[2], [3], [4]]
1299
+ sage: sorted(sorted(sep) for sep in (P + C).minimal_separators())
1300
+ [[1], [2], [3], [5, 7], [5, 8], [5, 9], [6, 8],
1301
+ [6, 9], [6, 10], [7, 9], [7, 10], [8, 10]]
1302
+ sage: sorted(sorted(sep) for sep in (P + C).minimal_separators(forbidden_vertices=[10]))
1303
+ [[1], [2], [3], [6], [7], [8]]
1304
+
1305
+ sage: G = graphs.RandomGNP(10, .3)
1306
+ sage: all(G.is_vertex_cut(sep) for sep in G.minimal_separators())
1307
+ True
1308
+
1309
+ TESTS::
1310
+
1311
+ sage: list(Graph().minimal_separators())
1312
+ []
1313
+ sage: list(Graph(1).minimal_separators())
1314
+ []
1315
+ sage: list(Graph(2).minimal_separators())
1316
+ []
1317
+ sage: from sage.graphs.connectivity import minimal_separators
1318
+ sage: list(minimal_separators(DiGraph()))
1319
+ Traceback (most recent call last):
1320
+ ...
1321
+ ValueError: the input must be an undirected graph
1322
+ """
1323
+ from sage.graphs.graph import Graph
1324
+ if not isinstance(G, Graph):
1325
+ raise ValueError("the input must be an undirected graph")
1326
+
1327
+ if forbidden_vertices is not None and G.order() >= 3:
1328
+ # Build the subgraph with active vertices
1329
+ G = G.subgraph(set(G).difference(forbidden_vertices), immutable=True)
1330
+
1331
+ if G.order() < 3:
1332
+ return
1333
+ if not G.is_connected():
1334
+ for cc in G.connected_components(sort=False):
1335
+ if len(cc) > 2:
1336
+ yield from minimal_separators(G.subgraph(cc))
1337
+ return
1338
+
1339
+ # Initialization - identify separators needing further inspection
1340
+ cdef list to_explore = []
1341
+ for v in G:
1342
+ # iterate over the connected components of G \ N[v]
1343
+ for comp in G.connected_components(sort=False, forbidden_vertices=G.neighbor_iterator(v, closed=True)):
1344
+ # The vertex boundary of comp in G is a separator
1345
+ nh = G.vertex_boundary(comp)
1346
+ if nh:
1347
+ to_explore.append(frozenset(nh))
1348
+
1349
+ # Generation of all minimal separators
1350
+ cdef set separators = set()
1351
+ while to_explore:
1352
+ sep = to_explore.pop()
1353
+ if sep in separators:
1354
+ continue
1355
+ yield set(sep)
1356
+ separators.add(sep)
1357
+ for v in sep:
1358
+ # iterate over the connected components of G \ sep \ N(v)
1359
+ for comp in G.connected_components(sort=False, forbidden_vertices=sep.union(G.neighbor_iterator(v))):
1360
+ nh = G.vertex_boundary(comp)
1361
+ if nh:
1362
+ to_explore.append(frozenset(nh))
1363
+
1364
+
1189
1365
  def edge_connectivity(G,
1190
1366
  value_only=True,
1191
1367
  implementation=None,