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.
- {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/METADATA +126 -30
- passagemath_graphs-10.5.43.dist-info/RECORD +256 -0
- {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/WHEEL +2 -1
- passagemath_graphs.dylibs/libgmp.10.dylib +0 -0
- sage/all__sagemath_graphs.py +5 -0
- sage/combinat/abstract_tree.py +1 -1
- sage/combinat/binary_tree.py +1 -1
- sage/combinat/cluster_algebra_quiver/all.py +1 -1
- sage/combinat/cluster_algebra_quiver/cluster_seed.py +28 -24
- sage/combinat/cluster_algebra_quiver/interact.py +4 -0
- sage/combinat/designs/MOLS_handbook_data.py +5 -5
- sage/combinat/designs/bibd.py +10 -9
- sage/combinat/designs/covering_array.py +3 -3
- sage/combinat/designs/covering_design.py +2 -1
- sage/combinat/designs/database.py +11 -10
- sage/combinat/designs/designs_pyx.cpython-39-darwin.so +0 -0
- sage/combinat/designs/designs_pyx.pyx +13 -45
- sage/combinat/designs/difference_family.py +6 -6
- sage/combinat/designs/difference_matrices.py +1 -1
- sage/combinat/designs/evenly_distributed_sets.cpython-39-darwin.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +15 -22
- sage/combinat/designs/ext_rep.py +9 -14
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-39-darwin.so +0 -0
- sage/combinat/designs/gen_quadrangles_with_spread.pyx +1 -1
- sage/combinat/designs/group_divisible_designs.py +1 -1
- sage/combinat/designs/incidence_structures.py +8 -8
- sage/combinat/designs/latin_squares.py +1 -1
- sage/combinat/designs/orthogonal_arrays_build_recursive.py +8 -7
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-39-darwin.so +0 -0
- sage/combinat/designs/resolvable_bibd.py +1 -1
- sage/combinat/designs/steiner_quadruple_systems.py +1 -1
- sage/combinat/designs/subhypergraph_search.cpython-39-darwin.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +9 -9
- sage/combinat/finite_state_machine_generators.py +2 -2
- sage/combinat/graph_path.py +3 -3
- sage/combinat/interval_posets.py +10 -10
- sage/combinat/ordered_tree.py +1 -1
- sage/combinat/posets/cartesian_product.py +1 -1
- sage/combinat/posets/d_complete.py +1 -1
- sage/combinat/posets/forest.py +1 -1
- sage/combinat/posets/hasse_cython.cpython-39-darwin.so +0 -0
- sage/combinat/posets/hasse_diagram.py +8 -6
- sage/combinat/posets/incidence_algebras.py +8 -8
- sage/combinat/posets/lattices.py +28 -4
- sage/combinat/posets/linear_extension_iterator.cpython-39-darwin.so +0 -0
- sage/combinat/posets/linear_extension_iterator.pyx +2 -0
- sage/combinat/posets/linear_extensions.py +7 -16
- sage/combinat/posets/moebius_algebra.py +1 -1
- sage/combinat/posets/poset_examples.py +1 -1
- sage/combinat/posets/posets.py +54 -56
- sage/combinat/rooted_tree.py +3 -3
- sage/combinat/tamari_lattices.py +1 -1
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/graphs/asteroidal_triples.cpython-39-darwin.so +0 -0
- sage/graphs/base/boost_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/boost_graph.pxd +1 -1
- sage/graphs/base/boost_graph.pyx +1 -1
- sage/graphs/base/c_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/c_graph.pxd +4 -4
- sage/graphs/base/c_graph.pyx +270 -184
- sage/graphs/base/dense_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/graph_backends.cpython-39-darwin.so +0 -0
- sage/graphs/base/sparse_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_dense_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.pyx +93 -6
- sage/graphs/base/static_sparse_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_sparse_graph.pyx +1 -1
- sage/graphs/bipartite_graph.py +0 -1
- sage/graphs/centrality.cpython-39-darwin.so +0 -0
- sage/graphs/centrality.pyx +0 -0
- sage/graphs/comparability.cpython-39-darwin.so +0 -0
- sage/graphs/comparability.pyx +172 -138
- sage/graphs/connectivity.cpython-39-darwin.so +0 -0
- sage/graphs/connectivity.pyx +194 -18
- sage/graphs/convexity_properties.cpython-39-darwin.so +0 -0
- sage/graphs/digraph_generators.py +118 -74
- sage/graphs/distances_all_pairs.cpython-39-darwin.so +0 -0
- sage/graphs/distances_all_pairs.pyx +145 -27
- sage/graphs/edge_connectivity.cpython-39-darwin.so +0 -0
- sage/graphs/generators/basic.py +471 -130
- sage/graphs/generators/distance_regular.cpython-39-darwin.so +0 -0
- sage/graphs/generators/distance_regular.pyx +12 -12
- sage/graphs/generators/families.py +2 -2
- sage/graphs/generators/random.py +8 -13
- sage/graphs/generators/smallgraphs.py +12 -11
- sage/graphs/generic_graph.py +687 -265
- sage/graphs/generic_graph_pyx.cpython-39-darwin.so +0 -0
- sage/graphs/genus.cpython-39-darwin.so +0 -0
- sage/graphs/graph.py +12 -46
- sage/graphs/graph_coloring.cpython-39-darwin.so +0 -0
- sage/graphs/graph_database.py +1 -1
- sage/graphs/graph_decompositions/bandwidth.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/cutwidth.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/graph_products.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/modular_decomposition.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/tree_decomposition.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-39-darwin.so +0 -0
- sage/graphs/graph_generators.py +110 -55
- sage/graphs/graph_generators_pyx.cpython-39-darwin.so +0 -0
- sage/graphs/graph_latex.py +1 -1
- sage/graphs/graph_list.py +2 -3
- sage/graphs/graph_plot.py +225 -30
- sage/graphs/hyperbolicity.cpython-39-darwin.so +0 -0
- sage/graphs/independent_sets.cpython-39-darwin.so +0 -0
- sage/graphs/isgci.py +3 -8
- sage/graphs/isoperimetric_inequalities.cpython-39-darwin.so +0 -0
- sage/graphs/line_graph.cpython-39-darwin.so +0 -0
- sage/graphs/matching.py +14 -25
- sage/graphs/matching_covered_graph.py +871 -60
- sage/graphs/orientations.py +190 -134
- sage/graphs/path_enumeration.cpython-39-darwin.so +0 -0
- sage/graphs/path_enumeration.pyx +25 -25
- sage/graphs/spanning_tree.cpython-39-darwin.so +0 -0
- sage/graphs/strongly_regular_db.cpython-39-darwin.so +0 -0
- sage/graphs/strongly_regular_db.pyx +54 -52
- sage/graphs/traversals.cpython-39-darwin.so +0 -0
- sage/graphs/traversals.pyx +114 -46
- sage/graphs/trees.cpython-39-darwin.so +0 -0
- sage/graphs/views.cpython-39-darwin.so +0 -0
- sage/graphs/weakly_chordal.cpython-39-darwin.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-39-darwin.so +0 -0
- sage/knots/free_knotinfo_monoid.py +2 -3
- sage/knots/knot.py +1 -1
- sage/knots/knotinfo.py +4 -4
- sage/knots/link.py +58 -57
- sage/sandpiles/sandpile.py +2 -3
- sage/topology/cell_complex.py +1 -1
- sage/topology/cubical_complex.py +7 -7
- sage/topology/delta_complex.py +4 -4
- sage/topology/simplicial_complex.py +7 -22
- passagemath_graphs-10.5.10.dist-info/RECORD +0 -251
- {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/top_level.txt +0 -0
sage/graphs/connectivity.pyx
CHANGED
@@ -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
|
-
|
135
|
-
|
136
|
-
|
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)
|
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
|
-
- ``
|
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,
|
Binary file
|