@@ -58,6 +58,18 @@ Methods
58
58
-------
59
59
"""
60
60
61
+ # ****************************************************************************
62
+ #
63
+ # Copyright (C) 2023 David Coudert <[email protected] >
64
+ #
65
+ # This program is free software: you can redistribute it and/or modify
66
+ # it under the terms of the GNU General Public License as published by
67
+ # the Free Software Foundation, either version 2 of the License, or
68
+ # (at your option) any later version.
69
+ # https://www.gnu.org/licenses/
70
+ # ****************************************************************************
71
+
72
+ from sage.misc.superseded import deprecation
61
73
62
74
def is_connected (G ):
63
75
"""
@@ -119,7 +131,7 @@ def is_connected(G):
119
131
return len (conn_verts) == G.num_verts()
120
132
121
133
122
- def connected_components (G , sort = False ):
134
+ def connected_components (G , sort = None , key = None ):
123
135
"""
124
136
Return the list of connected components.
125
137
@@ -130,8 +142,16 @@ def connected_components(G, sort=False):
130
142
131
143
- ``G`` -- the input graph
132
144
133
- - ``sort`` -- boolean (default: ``False``); whether to sort vertices inside
134
- each component
145
+ - ``sort`` -- boolean (default: ``None``); if ``True``, vertices inside each
146
+ component are sorted according to the default ordering
147
+
148
+ As of :trac:`35889`, this argument must be explicitly specified (unless a
149
+ ``key`` is given); otherwise a warning is printed and ``sort=True`` is
150
+ used. The default will eventually be changed to ``False``.
151
+
152
+ - ``key`` -- a function (default: ``None``); a function that takes a
153
+ vertex as its one argument and returns a value that can be used for
154
+ comparisons in the sorting algorithm (we must have ``sort=True``)
135
155
136
156
EXAMPLES::
137
157
@@ -142,8 +162,10 @@ def connected_components(G, sort=False):
142
162
sage: G.connected_components(sort=True)
143
163
[[0, 1, 2, 3], [4, 5, 6]]
144
164
sage: D = DiGraph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]})
145
- sage: connected_components(D, True)
165
+ sage: connected_components(D, sort= True)
146
166
[[0, 1, 2, 3], [4, 5, 6]]
167
+ sage: connected_components(D, sort=True, key=lambda x: -x)
168
+ [[3, 2, 1, 0], [6, 5, 4]]
147
169
148
170
TESTS:
149
171
@@ -154,16 +176,40 @@ def connected_components(G, sort=False):
154
176
Traceback (most recent call last):
155
177
...
156
178
TypeError: the input must be a Sage graph
179
+
180
+ When parameter ``key`` is set, parameter ``sort`` must be ``True``::
181
+
182
+ sage: G = Graph(2)
183
+ sage: G.connected_components(sort=False, key=lambda x: x)
184
+ Traceback (most recent call last):
185
+ ...
186
+ ValueError: sort keyword is False, yet a key function is given
187
+
188
+ Deprecation warning for ``sort=None`` (:trac:`35889`)::
189
+
190
+ sage: G = graphs.HouseGraph()
191
+ sage: G.connected_components()
192
+ doctest:...: DeprecationWarning: parameter 'sort' will be set to False by default in the future
193
+ See https://github.com/sagemath/sage/issues/35889 for details.
194
+ [[0, 1, 2, 3, 4]]
157
195
"""
158
196
from sage.graphs.generic_graph import GenericGraph
159
197
if not isinstance (G, GenericGraph):
160
198
raise TypeError (" the input must be a Sage graph" )
161
199
200
+ if sort is None :
201
+ if key is None :
202
+ deprecation(35889 , " parameter 'sort' will be set to False by default in the future" )
203
+ sort = True
204
+
205
+ if (not sort) and key:
206
+ raise ValueError (' sort keyword is False, yet a key function is given' )
207
+
162
208
cdef set seen = set ()
163
209
cdef list components = []
164
210
for v in G:
165
211
if v not in seen:
166
- c = connected_component_containing_vertex(G, v, sort = sort)
212
+ c = connected_component_containing_vertex(G, v, sort = sort, key = key )
167
213
seen.update(c)
168
214
components.append(c)
169
215
components.sort(key = lambda comp : - len (comp))
@@ -236,7 +282,7 @@ def connected_components_subgraphs(G):
236
282
return [G.subgraph(c, inplace = False ) for c in connected_components(G, sort = False )]
237
283
238
284
239
- def connected_component_containing_vertex (G , vertex , sort = False ):
285
+ def connected_component_containing_vertex (G , vertex , sort = None , key = None ):
240
286
"""
241
287
Return a list of the vertices connected to vertex.
242
288
@@ -246,8 +292,16 @@ def connected_component_containing_vertex(G, vertex, sort=False):
246
292
247
293
- ``v`` -- the vertex to search for
248
294
249
- - ``sort`` -- boolean (default: ``False``); whether to sort vertices inside
250
- the component
295
+ - ``sort`` -- boolean (default: ``None``); if ``True``, vertices inside the
296
+ component are sorted according to the default ordering
297
+
298
+ As of :trac:`35889`, this argument must be explicitly specified (unless a
299
+ ``key`` is given); otherwise a warning is printed and ``sort=True`` is
300
+ used. The default will eventually be changed to ``False``.
301
+
302
+ - ``key`` -- a function (default: ``None``); a function that takes a
303
+ vertex as its one argument and returns a value that can be used for
304
+ comparisons in the sorting algorithm (we must have ``sort=True``)
251
305
252
306
EXAMPLES::
253
307
@@ -260,6 +314,8 @@ def connected_component_containing_vertex(G, vertex, sort=False):
260
314
sage: D = DiGraph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]})
261
315
sage: connected_component_containing_vertex(D, 0, sort=True)
262
316
[0, 1, 2, 3]
317
+ sage: connected_component_containing_vertex(D, 0, sort=True, key=lambda x: -x)
318
+ [3, 2, 1, 0]
263
319
264
320
TESTS:
265
321
@@ -274,24 +330,48 @@ def connected_component_containing_vertex(G, vertex, sort=False):
274
330
:trac:`35889` is fixed::
275
331
276
332
sage: G = Graph([('A', 1)])
277
- sage: G.connected_component_containing_vertex(1)
333
+ sage: G.connected_component_containing_vertex(1, sort=False )
278
334
[1, 'A']
279
335
sage: G.connected_component_containing_vertex(1, sort=True)
280
336
Traceback (most recent call last):
281
337
...
282
338
TypeError: '<' not supported between instances of 'str' and 'int'
339
+
340
+ When parameter ``key`` is set, parameter ``sort`` must be ``True``::
341
+
342
+ sage: G = Graph(2)
343
+ sage: G.connected_component_containing_vertex(1, sort=False, key=lambda x: x)
344
+ Traceback (most recent call last):
345
+ ...
346
+ ValueError: sort keyword is False, yet a key function is given
347
+
348
+ Deprecation warning for ``sort=None`` (:trac:`35889`)::
349
+
350
+ sage: G = graphs.HouseGraph()
351
+ sage: G.connected_component_containing_vertex(1)
352
+ doctest:...: DeprecationWarning: parameter 'sort' will be set to False by default in the future
353
+ See https://github.com/sagemath/sage/issues/35889 for details.
354
+ [0, 1, 2, 3, 4]
283
355
"""
284
356
from sage.graphs.generic_graph import GenericGraph
285
357
if not isinstance (G, GenericGraph):
286
358
raise TypeError (" the input must be a Sage graph" )
287
359
360
+ if sort is None :
361
+ if key is None :
362
+ deprecation(35889 , " parameter 'sort' will be set to False by default in the future" )
363
+ sort = True
364
+
365
+ if (not sort) and key:
366
+ raise ValueError (' sort keyword is False, yet a key function is given' )
367
+
288
368
try :
289
369
c = list (G._backend.depth_first_search(vertex, ignore_direction = True ))
290
370
except AttributeError :
291
371
c = list (G.depth_first_search(vertex, ignore_direction = True ))
292
372
293
373
if sort:
294
- c.sort( )
374
+ return sorted (c, key = key )
295
375
return c
296
376
297
377
@@ -335,7 +415,7 @@ def connected_components_sizes(G):
335
415
return [len (cc) for cc in connected_components(G, sort = False )]
336
416
337
417
338
- def blocks_and_cut_vertices (G , algorithm = " Tarjan_Boost" , sort = False ):
418
+ def blocks_and_cut_vertices (G , algorithm = " Tarjan_Boost" , sort = False , key = None ):
339
419
"""
340
420
Return the blocks and cut vertices of the graph.
341
421
@@ -361,6 +441,10 @@ def blocks_and_cut_vertices(G, algorithm="Tarjan_Boost", sort=False):
361
441
the components and the list of cut vertices
362
442
**currently only available for ``"Tarjan_Sage"``**
363
443
444
+ - ``key`` -- a function (default: ``None``); a function that takes a
445
+ vertex as its one argument and returns a value that can be used for
446
+ comparisons in the sorting algorithm (we must have ``sort=True``)
447
+
364
448
OUTPUT: ``(B, C)``, where ``B`` is a list of blocks - each is a list of
365
449
vertices and the blocks are the corresponding induced subgraphs - and
366
450
``C`` is a list of cut vertices.
@@ -449,6 +533,9 @@ def blocks_and_cut_vertices(G, algorithm="Tarjan_Boost", sort=False):
449
533
raise NotImplementedError (" blocks and cut vertices algorithm '%s ' is not implemented" % algorithm)
450
534
451
535
# If algorithm is "Tarjan_Sage"
536
+ if (not sort) and key:
537
+ raise ValueError (' sort keyword is False, yet a key function is given' )
538
+
452
539
blocks = []
453
540
cut_vertices = set ()
454
541
@@ -541,7 +628,7 @@ def blocks_and_cut_vertices(G, algorithm="Tarjan_Boost", sort=False):
541
628
u1, u2 = edge_stack.pop()
542
629
new_block.add(u1)
543
630
if sort:
544
- this_block = sorted (new_block)
631
+ this_block = sorted (new_block, key = key )
545
632
else :
546
633
this_block = list (new_block)
547
634
blocks.append(this_block)
@@ -556,9 +643,8 @@ def blocks_and_cut_vertices(G, algorithm="Tarjan_Boost", sort=False):
556
643
start_already_seen = True
557
644
558
645
if sort:
559
- return blocks, sorted (cut_vertices)
560
- else :
561
- return blocks, list (cut_vertices)
646
+ return blocks, sorted (cut_vertices, key = key)
647
+ return blocks, list (cut_vertices)
562
648
563
649
564
650
def blocks_and_cuts_tree (G ):
@@ -1113,9 +1199,9 @@ def edge_connectivity(G,
1113
1199
b = set (H).difference(a)
1114
1200
val.append([a, b])
1115
1201
else :
1116
- val.append(connected_components(H) )
1202
+ val.append([ set (c) for c in connected_components(H, sort = False )] )
1117
1203
elif vertices:
1118
- val.append([set (c) for c in connected_components(G)])
1204
+ val.append([set (c) for c in connected_components(G, sort = False )])
1119
1205
1120
1206
return val
1121
1207
@@ -2137,7 +2223,7 @@ def cleave(G, cut_vertices=None, virtual_edges=True, solver=None, verbose=0,
2137
2223
2138
2224
H = G.copy(immutable = False )
2139
2225
H.delete_vertices(cut_vertices)
2140
- CC = H.connected_components()
2226
+ CC = H.connected_components(sort = False )
2141
2227
if len (CC) == 1 :
2142
2228
raise ValueError (" the set cut_vertices is not a vertex cut of the graph" )
2143
2229
0 commit comments