Skip to content

Commit

Permalink
gh-35891: Deprecate sorting by default in connected component methods…
Browse files Browse the repository at this point in the history
… for graphs

    
Fixes #35889.

### 📚 Description

We deprecate sorting by default in `connected_components` and
`connected_component_containing_vertex`.  The default value of parameter
`sort` was `True`. We change it to `None` to identify calls when a
deprecation warning is necessary. We also add parameter `key` so that
users can define home made sorting rules.

This deprecation is needed to avoid type errors when vertices have
labels of incomparable type.

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x
]`. -->

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.

### ⌛ Dependencies
    
URL: #35891
Reported by: David Coudert
Reviewer(s): Dima Pasechnik
  • Loading branch information
Release Manager committed Jul 29, 2023
2 parents 8b3883d + efcf6f0 commit a48b7b8
Show file tree
Hide file tree
Showing 39 changed files with 208 additions and 103 deletions.
6 changes: 3 additions & 3 deletions src/sage/algebras/fusion_rings/f_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -1726,11 +1726,11 @@ def _partition_eqns(self, eqns=None, verbose=True):
if eqns is None:
eqns = self.ideal_basis
graph = self.equations_graph(eqns)
partition = {tuple(c): [] for c in graph.connected_components()}
partition = {tuple(c): [] for c in graph.connected_components(sort=True)}
for eq_tup in eqns:
partition[tuple(graph.connected_component_containing_vertex(variables(eq_tup)[0]))].append(eq_tup)
partition[tuple(graph.connected_component_containing_vertex(variables(eq_tup)[0], sort=True))].append(eq_tup)
if verbose:
print("Partitioned {} equations into {} components of size:".format(len(eqns), len(graph.connected_components())))
print("Partitioned {} equations into {} components of size:".format(len(eqns), graph.connected_components_number()))
print(graph.connected_components_sizes())
return partition

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ def irreducible_component_index_sets(self):
for i,j in itertools.combinations(I,2)
if s[i]*s[j] != s[j]*s[i] ]],
format="vertices_and_edges")
return G.connected_components()
return G.connected_components(sort=False)

@abstract_method(optional=True)
def irreducible_components(self):
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/loop_crystals.py
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ def one_dimensional_configuration_sum(self, q=None, group_components=True):
B = P0.algebra(q.parent())
if group_components:
G = self.digraph(index_set=self.cartan_type().classical().index_set())
C = G.connected_components()
C = G.connected_components(sort=False)
return B.sum(q**(c[0].energy_function())*B.sum(B(P0(b.weight())) for b in c)
for c in C)
return B.sum(q**(b.energy_function())*B(P0(b.weight())) for b in self)
Expand Down
8 changes: 4 additions & 4 deletions src/sage/combinat/cluster_algebra_quiver/mutation_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False):
dg_tmp = DiGraph( dg )
dg_tmp.delete_vertices( c1 )

components = dg_tmp.connected_components()
components = dg_tmp.connected_components(sort=False)
# if not len(components) == 2:
if len(components) != 2:
return _false_return(4)
Expand Down Expand Up @@ -938,7 +938,7 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False):
else:
c2.reverse()
dg_tmp.delete_edge( tuple( c2 ) )
components = dg_tmp.connected_components()
components = dg_tmp.connected_components(sort=False)
if len(components) != 2:
return _false_return(7)
else:
Expand Down Expand Up @@ -1190,7 +1190,7 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False):
edge = long_cycle[0][0]
sg = DiGraph( dg )
sg. delete_vertices(edge)
connected_components = sg.connected_components()
connected_components = sg.connected_components(sort=False)
cycle = []
if connected_components:
cycle.append( ( edge[0], edge[1], len( connected_components[0] ) + 1 ) )
Expand All @@ -1200,7 +1200,7 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False):
for edge in tmp:
sg = DiGraph( dg )
sg. delete_vertices(edge)
connected_components = sg.connected_components()
connected_components = sg.connected_components(sort=False)
if len( connected_components ) == 2:
#if len( list_intersection( [ connected_components[0], list_substract( long_cycle[0], [edge] )[0] ] ) ) > 0:
if len( set(connected_components[0]).intersection( set(long_cycle[0]).difference([edge]).pop() ) ) > 0:
Expand Down
4 changes: 2 additions & 2 deletions src/sage/combinat/cluster_algebra_quiver/quiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ def mutation_type(self):

# checking the type for each connected component
mutation_type = []
connected_components = sorted(dg.connected_components())
connected_components = sorted(dg.connected_components(sort=False))
for component in connected_components:
# constructing the digraph for this component
dg_component = dg.subgraph( component )
Expand Down Expand Up @@ -1157,7 +1157,7 @@ def canonical_label(self, certificate=False):
if dg.is_connected():
Q._mutation_type = self._mutation_type
else:
CC = sorted( self._digraph.connected_components() )
CC = sorted(self._digraph.connected_components(sort=False))
CC_new = sorted(zip([sorted(iso[i] for i in L) for L in CC],
range(len(CC))))
comp_iso = [L[1] for L in CC_new]
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/constellation.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ def connected_components(self):
G.add_vertices(list(range(self.degree())))
for p in self._g:
G.add_edges(enumerate(p.domain()), loops=False)
m = G.connected_components()
m = G.connected_components(sort=False)
if len(m) == 1:
return [self]
for mm in m:
Expand Down
12 changes: 6 additions & 6 deletions src/sage/combinat/crystals/littelmann_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ def weight(x):
return P0.sum(int(c)*P0.basis()[i] for i,c in w if i in P0.index_set())
if group_components:
G = self.digraph(index_set=self.cartan_type().classical().index_set())
C = G.connected_components()
C = G.connected_components(sort=False)
return sum(q**(c[0].energy_function())*B.sum(B(weight(b)) for b in c) for c in C)
return B.sum(q**(b.energy_function())*B(weight(b)) for b in self)

Expand Down Expand Up @@ -1081,7 +1081,7 @@ def energy_function(self):
sage: La = R.weight_space().basis()
sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]+La[2])
sage: G = LS.digraph(index_set=[1,2])
sage: C = G.connected_components()
sage: C = G.connected_components(sort=False)
sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C]
[True, True, True, True]
Expand All @@ -1093,15 +1093,15 @@ def energy_function(self):
sage: [(x.weight(), x.energy_function()) for x in hw]
[(-2*Lambda[0] + Lambda[2], 0), (-2*Lambda[0] + Lambda[1], 1), (0, 2)]
sage: G = LS.digraph(index_set=J)
sage: C = G.connected_components()
sage: C = G.connected_components(sort=False)
sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C]
[True, True, True]
sage: R = RootSystem(CartanType(['G',2,1]).dual())
sage: La = R.weight_space().basis()
sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1]+La[2])
sage: G = LS.digraph(index_set=[1,2])
sage: C = G.connected_components()
sage: C = G.connected_components(sort=False)
sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C] # long time
[True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
Expand All @@ -1110,15 +1110,15 @@ def energy_function(self):
sage: La = R.weight_space().basis()
sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]+La[2])
sage: G = LS.digraph(index_set=R.cartan_type().classical().index_set())
sage: C = G.connected_components()
sage: C = G.connected_components(sort=False)
sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C] # long time
[True, True, True, True, True, True, True, True, True, True, True]
sage: R = RootSystem(['BC',2,2])
sage: La = R.weight_space().basis()
sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]+La[2])
sage: G = LS.digraph(index_set=R.cartan_type().classical().index_set())
sage: C = G.connected_components()
sage: C = G.connected_components(sort=False)
sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C] # long time
[True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/partition_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -1974,7 +1974,7 @@ def set_partition_composition(sp1, sp2):
True
"""
g = pair_to_graph(sp1, sp2)
connected_components = g.connected_components()
connected_components = g.connected_components(sort=False)

res = []
total_removed = 0
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/posets/mobile.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def _is_valid_ribbon(self, ribbon):
continue

G_un.delete_edge(lc, r)
P = Poset(G.subgraph(G_un.connected_component_containing_vertex(lc)))
P = Poset(G.subgraph(G_un.connected_component_containing_vertex(lc, sort=False)))
if P.top() != lc or not P.is_d_complete():
return False
G_un.add_edge(lc, r)
Expand Down
8 changes: 4 additions & 4 deletions src/sage/combinat/posets/posets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1368,11 +1368,11 @@ def _latex_(self):
EXAMPLES::
sage: P = Poset(([1,2], [[1,2]]), cover_relations = True)
sage: print(P._latex_()) #optional - dot2tex graphviz
sage: print(P._latex_()) # optional - dot2tex graphviz
\begin{tikzpicture}[>=latex,line join=bevel,]
%%
\node (node_...) at (6.0...bp,...bp) [draw,draw=none] {$...$};
\node (node_...) at (6.0...bp,...bp) [draw,draw=none] {$...$};
\node (node_...) at (5...bp,...bp) [draw,draw=none] {$...$};
\node (node_...) at (5...bp,...bp) [draw,draw=none] {$...$};
\draw [black,->] (node_...) ..controls (...bp,...bp) and (...bp,...bp) .. (node_...);
%
\end{tikzpicture}
Expand Down Expand Up @@ -5330,7 +5330,7 @@ def edge_color(va, vb):

fusion = fusion.transitive_closure()
resu = []
for s in fusion.connected_components():
for s in fusion.connected_components(sort=False):
subg = [x for x in prod_dg if all(x[i] == v0[i] for i in factors_range
if i not in s)]
resu.append(Poset(prod_dg.subgraph(subg)))
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/root_system/ambient_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def _test_norm_of_simple_roots(self, **options):
T = self.cartan_type()
D = T.symmetrizer()
alpha = self.simple_roots()
for C in T.dynkin_diagram().connected_components():
for C in T.dynkin_diagram().connected_components(sort=False):
tester.assertEqual(len( set( alpha[i].scalar(alpha[i]) / D[i] for i in C ) ), 1)

# FIXME: attribute or method?
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/root_system/cartan_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -1739,7 +1739,7 @@ def symmetrizer(self):
M[i, n * i + j] = m[i,j]
M[j, n * i + j] -= m[j,i]
kern = M.integer_kernel()
c = len(self.dynkin_diagram().connected_components())
c = len(self.dynkin_diagram().connected_components(sort=False))
if kern.dimension() < c:
# the Cartan matrix is not symmetrizable
return None
Expand Down
4 changes: 2 additions & 2 deletions src/sage/geometry/polyhedral_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1234,7 +1234,7 @@ def connected_component(self, cell=None):
if v not in g:
raise ValueError(
"the polyhedral complex does not contain the given cell")
vertices = g.connected_component_containing_vertex(v)
vertices = g.connected_component_containing_vertex(v, sort=False)
facets = [f for f in self.maximal_cell_iterator()
if any(vf in f.vertices_matrix().columns()
for vf in vertices)]
Expand All @@ -1243,7 +1243,7 @@ def connected_component(self, cell=None):
if cell not in g:
raise ValueError(
"the polyhedral complex does not contain the given cell")
faces = g.connected_component_containing_vertex(cell)
faces = g.connected_component_containing_vertex(cell, sort=False)
facets = [f for f in self.maximal_cell_iterator()
if f in faces]
return PolyhedralComplex(facets, maximality_check=False,
Expand Down
4 changes: 2 additions & 2 deletions src/sage/geometry/polyhedron/base_QQ.py
Original file line number Diff line number Diff line change
Expand Up @@ -1180,7 +1180,7 @@ class functions of the acting group. A character `\rho` is effective if
True
sage: Hstar = p3.Hstar_function(S3) # optional - pynormaliz
sage: Hlin = p3.Hstar_function(S3, # optional - pynormaliz
....: output='Hstar_as_lin_comb')]
....: output='Hstar_as_lin_comb')
sage: p3.is_effective(Hstar, Hlin) # optional - pynormaliz
True
Expand Down Expand Up @@ -1242,7 +1242,7 @@ class functions of the acting group. A character `\rho` is effective if
sage: p2 = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz
....: backend='normaliz')
sage: Hstar = p2.Hstar_function() # optional - pynormaliz
sage: Hstarlin = p2.Hstar_function(output='Hstar_as_lin_comb')] # optional - pynormaliz
sage: Hstarlin = p2.Hstar_function(output='Hstar_as_lin_comb') # optional - pynormaliz
sage: p1._is_effective_normaliz(Hstar, Hstarlin) # optional - pynormaliz
Traceback (most recent call last):
...
Expand Down
2 changes: 1 addition & 1 deletion src/sage/graphs/base/c_graph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4819,7 +4819,7 @@ cdef class Search_iterator:
Immutable graphs (see :trac:`16019`)::
sage: DiGraph([[1,2]], immutable=True).connected_components()
sage: DiGraph([(1, 2)], immutable=True).connected_components(sort=True)
[[1, 2]]
"""
Expand Down
2 changes: 1 addition & 1 deletion src/sage/graphs/base/static_sparse_graph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ def tarjan_strongly_connected_components(G):
sage: tarjan_strongly_connected_components(digraphs.Path(3))
[[2], [1], [0]]
sage: D = DiGraph( { 0 : [1, 3], 1 : [2], 2 : [3], 4 : [5, 6], 5 : [6] } )
sage: D.connected_components()
sage: D.connected_components(sort=True)
[[0, 1, 2, 3], [4, 5, 6]]
sage: D = DiGraph( { 0 : [1, 3], 1 : [2], 2 : [3], 4 : [5, 6], 5 : [6] } )
sage: D.strongly_connected_components()
Expand Down
2 changes: 1 addition & 1 deletion src/sage/graphs/bipartite_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@ def _check_bipartition_for_add_edges(self, edges):
vertex_in_left[v] = False

# Map each vertex to the connected component it belongs to
vertex_to_component = {v: comp for comp in self.connected_components()
vertex_to_component = {v: comp for comp in self.connected_components(sort=False)
for v in comp}

for e in edges:
Expand Down
4 changes: 2 additions & 2 deletions src/sage/graphs/comparability.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def greedy_is_comparability(g, no_certificate=False, equivalence_class=False):
# Each vertex can partition its neighbors into equivalence classes
equivalence_classes = {}
for v in g:
equivalence_classes[v] = g.subgraph(vertices=g.neighbors(v)).complement().connected_components()
equivalence_classes[v] = g.subgraph(vertices=g.neighbors(v)).complement().connected_components(sort=False)
# We build a graph h with one vertex per (vertex of g + equivalence class)
from sage.graphs.graph import Graph
Expand Down Expand Up @@ -288,7 +288,7 @@ def greedy_is_comparability(g, no_certificate=False, equivalence_class=False):
if equivalence_class:
# Returning the largest equivalence class
cc = sorted(h.connected_components(), key=len)[-1]
cc = sorted(h.connected_components(sort=False), key=len)[-1]
edges = []
for v, sid in cc:
Expand Down
Loading

0 comments on commit a48b7b8

Please sign in to comment.