From 9ba3ea3e0fb495c2a8deea509ffc3e965bbdf265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 9 Apr 2024 09:36:45 +0200 Subject: [PATCH 1/3] some C4 fixes in combinat folder --- .../algebras/quatalg/quaternion_algebra.py | 9 +++-- src/sage/combinat/sloane_functions.py | 2 +- .../combinat/species/partition_species.py | 2 +- src/sage/combinat/subset.py | 3 +- src/sage/combinat/subword_complex.py | 12 +++---- src/sage/combinat/superpartition.py | 2 +- src/sage/combinat/tableau_residues.py | 4 +-- src/sage/combinat/tableau_tuple.py | 9 +++-- src/sage/combinat/tamari_lattices.py | 8 ++--- src/sage/combinat/tiling.py | 33 +++++++++---------- src/sage/combinat/tuple.py | 4 +-- src/sage/combinat/words/finite_word.py | 6 ++-- src/sage/combinat/words/morphism.py | 24 +++++++------- src/sage/combinat/yang_baxter_graph.py | 4 +-- 14 files changed, 63 insertions(+), 59 deletions(-) diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 02d0ccf0326..c5860eec5a1 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -1190,9 +1190,12 @@ def ramified_primes(self): if not is_RationalField(self.base_ring()): raise ValueError("base field must be the rational numbers") - return sorted([p for p in set([2]).union(prime_divisors(self._a.numerator()), - prime_divisors(self._a.denominator()), prime_divisors(self._b.numerator()), - prime_divisors(self._b.denominator())) if hilbert_symbol(self._a, self._b, p) == -1]) + a, b = self._a, self._b + return sorted(p for p in {2}.union(prime_divisors(a.numerator()), + prime_divisors(a.denominator()), + prime_divisors(b.numerator()), + prime_divisors(b.denominator())) + if hilbert_symbol(self._a, self._b, p) == -1) def is_isomorphic(self, A) -> bool: """ diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index e9911d47506..808bcfd849d 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -859,7 +859,7 @@ def _eval(self, n): sage: [sloane.A003418._eval(n) for n in range(1,11)] [1, 2, 6, 12, 60, 60, 420, 840, 2520, 2520] """ - return arith.lcm([i for i in range(1, n+1)]) + return arith.lcm(list(range(1, n + 1))) class A007318(SloaneSequence): diff --git a/src/sage/combinat/species/partition_species.py b/src/sage/combinat/species/partition_species.py index dea38378a7a..8d9a83d1e00 100644 --- a/src/sage/combinat/species/partition_species.py +++ b/src/sage/combinat/species/partition_species.py @@ -182,7 +182,7 @@ def _structures(self, structure_class, labels): yield structure_class(self, labels, []) return - u = [i for i in reversed(range(1, n + 1))] + u = list(range(n, 0, -1)) s0 = u.pop() # Reconstruct the set partitions from diff --git a/src/sage/combinat/subset.py b/src/sage/combinat/subset.py index 822420d6514..4d036ad6c93 100644 --- a/src/sage/combinat/subset.py +++ b/src/sage/combinat/subset.py @@ -741,7 +741,8 @@ def last(self): if self._k > self._s.cardinality(): raise EmptySetError - return self.element_class([i for i in itertools.islice(reversed(self._s), int(self._k))]) + return self.element_class(list(itertools.islice(reversed(self._s), + int(self._k)))) def _fast_iterator(self): r""" diff --git a/src/sage/combinat/subword_complex.py b/src/sage/combinat/subword_complex.py index 0439d7f72f0..f280a5901f3 100644 --- a/src/sage/combinat/subword_complex.py +++ b/src/sage/combinat/subword_complex.py @@ -1854,8 +1854,8 @@ def cover_relations(self, label=False): """ N = len(self.group().long_element(as_word=True)) F = self.greedy_facet(side="positive") - Fs = set([F]) - seen = set([F]) + Fs = {F} + seen = {F} covers = [] while Fs: F = Fs.pop() @@ -1895,7 +1895,7 @@ def increasing_flip_graph(self, label=True): from sage.graphs.digraph import DiGraph return DiGraph(self.cover_relations(label=label)) - def interval(self, I, J): + def interval(self, I, J) -> set: """ Return the interval [I,J] in the increasing flip graph subword complex. @@ -1924,7 +1924,7 @@ def interval(self, I, J): """ G = self.increasing_flip_graph() paths = G.all_paths(I, J) - return set(K for path in paths for K in path) + return {K for path in paths for K in path} def increasing_flip_poset(self): """ @@ -2125,8 +2125,8 @@ def _greedy_flip_algorithm(Q, w): flip_to_ancestors.append(j) next_index = i + 1 has_new_child = True - facet_list.append([x for x in F]) - extended_root_conf_indices_list.append([x for x in R]) + facet_list.append(list(F)) + extended_root_conf_indices_list.append(list(R)) if not has_new_child: i = flip_to_ancestors.pop() if i != -1: diff --git a/src/sage/combinat/superpartition.py b/src/sage/combinat/superpartition.py index a2e77f8a5b1..e16e87fa9f0 100644 --- a/src/sage/combinat/superpartition.py +++ b/src/sage/combinat/superpartition.py @@ -691,7 +691,7 @@ def add_horizontal_border_strip_star(self, h) -> list: # TODO: Check that this is not supposed to be # a tuple of size 1 + [(i) for i in circ_list if row_changed[i[0]] == 0]] - if len(set([k for (j, k) in new_sp[1]])) == len(new_sp[1]): + if len({k for j, k in new_sp[1]}) == len(new_sp[1]): out += [SuperPartition.from_circled_diagram(*new_sp)] return out diff --git a/src/sage/combinat/tableau_residues.py b/src/sage/combinat/tableau_residues.py index ae3f65e7196..db94461f6ef 100644 --- a/src/sage/combinat/tableau_residues.py +++ b/src/sage/combinat/tableau_residues.py @@ -340,7 +340,7 @@ def __getitem__(self, k): except (IndexError, KeyError): raise IndexError('k must be in the range 1, 2, ..., {}'.format(len(self))) - def residues(self): + def residues(self) -> list: r""" Return a list of the residue sequence. @@ -350,7 +350,7 @@ def residues(self): sage: ResidueSequence(3,(0,0,1),[0,0,1,1,2,2,3,3]).residues() [0, 0, 1, 1, 2, 2, 0, 0] """ - return [r for r in self] + return list(self) def restrict(self, m): r""" diff --git a/src/sage/combinat/tableau_tuple.py b/src/sage/combinat/tableau_tuple.py index 1568175325e..511b98d3e1b 100644 --- a/src/sage/combinat/tableau_tuple.py +++ b/src/sage/combinat/tableau_tuple.py @@ -597,7 +597,7 @@ def components(self): 6 7 8 9 """ - return [t for t in self] + return list(self) def to_list(self): """ @@ -2371,9 +2371,8 @@ def list(self): ([[3, 5], [4]], [[1, 2]])] """ if self.is_finite(): - return [y for y in self] - else: - raise NotImplementedError('this is an infinite set of tableaux') + return list(self) + raise NotImplementedError('this is an infinite set of tableaux') class TableauTuples_all(TableauTuples): @@ -2666,7 +2665,7 @@ def an_element(self): if self.size() == 0: return self.element_class(self, [[] for _ in range(self.level())]) - tab = [[[m for m in range(1, self.size() + 1)]]] + tab = [[list(range(1, self.size() + 1))]] for _ in range(self.level() - 1): tab.append([]) return self.element_class(self, tab) diff --git a/src/sage/combinat/tamari_lattices.py b/src/sage/combinat/tamari_lattices.py index b84b587e1b3..f3e4de13a28 100644 --- a/src/sage/combinat/tamari_lattices.py +++ b/src/sage/combinat/tamari_lattices.py @@ -92,11 +92,11 @@ def paths_in_triangle(i, j, a, b) -> list[tuple[int, ...]]: return [tuple([1] * j)] if (j - 1) * a >= (i) * b: - result = [u + tuple([1]) for u in paths_in_triangle(i, j - 1, a, b)] - result += [u + tuple([0]) for u in paths_in_triangle(i - 1, j, a, b)] + result = [u + (1,) for u in paths_in_triangle(i, j - 1, a, b)] + result += [u + (0,) for u in paths_in_triangle(i - 1, j, a, b)] return result - return [u + tuple([0]) for u in paths_in_triangle(i - 1, j, a, b)] + return [u + (0,) for u in paths_in_triangle(i - 1, j, a, b)] def swap(p, i, m=1) -> tuple[int, ...]: @@ -156,7 +156,7 @@ def swap(p, i, m=1) -> tuple[int, ...]: height -= 1 if height <= 0: found = True - q = [k for k in p] + q = list(p) for k in range(i, j): q[k] = p[k + 1] q[j] = 0 diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index a6284b83e1b..2190c5b2119 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -991,12 +991,13 @@ def canonical_isometric_copies(self, orientation_preserving=True, """ if mod_box_isometries: L = ncube_isometry_group_cosets(self._dimension, orientation_preserving) - P_cosets = set(frozenset((m * self).canonical() for m in coset) for coset in L) + P_cosets = {frozenset((m * self).canonical() for m in coset) + for coset in L} P_cosets_representents = [min(s, key=lambda a: a.sorted_list()) for s in P_cosets] - return sorted(P_cosets_representents, key=lambda a:a.sorted_list()) + return sorted(P_cosets_representents, key=lambda a: a.sorted_list()) else: L = ncube_isometry_group(self._dimension, orientation_preserving) - P_images = set((m * self).canonical() for m in L) + P_images = {(m * self).canonical() for m in L} return sorted(P_images, key=lambda a: a.sorted_list()) def translated_copies(self, box): @@ -1222,8 +1223,8 @@ def isometric_copies(self, box, orientation_preserving=True, raise ValueError("Dimension of input box must match the " "dimension of the polyomino") box_min_coords, box_max_coords = box.bounding_box() - if mod_box_isometries and len(set(b-a for (a,b) in zip(box_min_coords, - box_max_coords))) < box._dimension: + if mod_box_isometries and len({b - a for a, b in zip(box_min_coords, + box_max_coords)}) < box._dimension: raise NotImplementedError("The code below assumes that the" " sizes of the box (={}) are all distinct when" " argument `mod_box_isometries` is True.".format(box)) @@ -1267,8 +1268,8 @@ def isometric_copies_intersection(self, box, orientation_preserving=True): """ all_distinct_cano = self.canonical_isometric_copies(orientation_preserving, mod_box_isometries=False) - return set([t for cano in all_distinct_cano - for t in cano.translated_copies_intersection(box=box)]) + return {t for cano in all_distinct_cano + for t in cano.translated_copies_intersection(box=box)} def neighbor_edges(self): r""" @@ -1766,11 +1767,10 @@ def coord_to_int_dict(self): ((2, 0), 4), ((2, 1), 5)] """ if self._reusable: - return dict((c, i) for i, c in enumerate(self.space())) - else: - number_of_pieces = len(self._pieces) - return dict((c, i+number_of_pieces) - for i, c in enumerate(self.space())) + return {c: i for i, c in enumerate(self.space())} + + number_of_pieces = len(self._pieces) + return {c: i + number_of_pieces for i, c in enumerate(self.space())} @cached_method def int_to_coord_dict(self): @@ -1814,11 +1814,10 @@ def int_to_coord_dict(self): """ if self._reusable: - return dict((i, c) for i, c in enumerate(self.space())) - else: - number_of_pieces = len(self._pieces) - return dict((i+number_of_pieces, c) - for i, c in enumerate(self.space())) + return dict(enumerate(self.space())) + + number_of_pieces = len(self._pieces) + return {i + number_of_pieces: c for i, c in enumerate(self.space())} @cached_method def rows_for_piece(self, i, mod_box_isometries=False): diff --git a/src/sage/combinat/tuple.py b/src/sage/combinat/tuple.py index 54d1caf9181..196d869769d 100644 --- a/src/sage/combinat/tuple.py +++ b/src/sage/combinat/tuple.py @@ -77,7 +77,7 @@ def __init__(self, S, k): """ self.S = S self.k = k - self._index_list = list(set(S.index(s) for s in S)) + self._index_list = list({S.index(s) for s in S}) category = FiniteEnumeratedSets() Parent.__init__(self, category=category) @@ -168,7 +168,7 @@ def __init__(self, S, k): """ self.S = S self.k = k - self._index_list = list(set(S.index(s) for s in S)) + self._index_list = list({S.index(s) for s in S}) category = FiniteEnumeratedSets() Parent.__init__(self, category=category) diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index b596f87e56d..1bdd38e92c7 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -1426,7 +1426,7 @@ def factor_set(self, n=None, algorithm='suffix tree'): return Set(self.factor_iterator(n)) elif algorithm == 'naive': if n is None: - S = set([self[0:0]]) + S = {self[0:0]} for n in range(1, self.length()+1): for i in range(self.length()-n+1): S.add(self[i:i+n]) @@ -3006,7 +3006,7 @@ def palindromes(self, f=None): [word: , word: ab, word: abbabaab, word: ba, word: baba, word: bbabaa] """ LPS = self.lps_lengths(f) - return set(self[i - LPS[i]: i] for i in range(len(self) + 1)) + return {self[i - LPS[i]: i] for i in range(len(self) + 1)} def palindromic_complexity(self, n): r""" @@ -6415,7 +6415,7 @@ def delta(self): return Words()([]) ss = self[0] c = 0 - v = list() + v = [] max_c = 0 for s in self: if s == ss: diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index f490ac96cd0..abd66da0650 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -401,7 +401,7 @@ def __init__(self, data, domain=None, codomain=None): self._morph = {} - dom_alph = list() + dom_alph = [] for key, val in data.items(): dom_alph.append(key) if val in codomain.alphabet(): @@ -950,7 +950,8 @@ def __mul__(self, other): sage: m * WordMorphism('') WordMorphism: """ - return WordMorphism(dict((key, self(w)) for key, w in other._morph.items()), codomain=self.codomain()) + return WordMorphism({key: self(w) for key, w in other._morph.items()}, + codomain=self.codomain()) def __pow__(self, exp): r""" @@ -1090,7 +1091,8 @@ def restrict_domain(self, alphabet): ... TypeError: 'sage.rings.integer.Integer' object is not iterable """ - return WordMorphism(dict((a, self(a)) for a in alphabet if a in self.domain().alphabet())) + return WordMorphism({a: self(a) for a in alphabet + if a in self.domain().alphabet()}) def _matrix_(self, R=None): r""" @@ -1276,7 +1278,7 @@ def image(self, letter): """ return self._morph[letter] - def images(self): + def images(self) -> list: r""" Return the list of all the images of the letters of the alphabet under ``self``. @@ -1727,9 +1729,8 @@ def is_uniform(self, k=None): True """ if k is None: - return len(set(w.length() for w in self.images())) == 1 - else: - return all(w.length() == k for w in self.images()) + k = self.images()[0].length() + return all(w.length() == k for w in self.images()) def fixed_point(self, letter): r""" @@ -1980,7 +1981,7 @@ def periodic_points(self): raise NotImplementedError("f should be non erasing") A = self.domain().alphabet() - d = dict((letter, self(letter)[0]) for letter in A) + d = {letter: self(letter)[0] for letter in A} G = set(self.growing_letters()) res = [] @@ -2173,7 +2174,8 @@ def conjugate(self, pos): sage: m.conjugate(2) WordMorphism: a->cdeab, b->zxy """ - return WordMorphism(dict((key, w.conjugate(pos)) for (key, w) in self._morph.items())) + return WordMorphism({key: w.conjugate(pos) + for (key, w) in self._morph.items()}) def has_left_conjugate(self): r""" @@ -3785,7 +3787,7 @@ def try_create_h(f, k): h = {letter: [letter] if image else [] for letter, image in f.items()} elif len(Y) < len(X): # Trivial case #2. k = {x: [y] for x, y in zip(X, Y)} - k_inverse = {y: x for y, x in zip(Y, X)} + k_inverse = dict(zip(Y, X)) h = {x: [k_inverse[y] for y in image] for x, image in f.items()} elif not self.is_injective(): # Non-trivial but a fast case. k = dict(f) @@ -3822,7 +3824,7 @@ def try_create_h(f, k): for comb in combinations(factors, len(X) - 1): if any(x.is_proper_prefix(y) for x in comb for y in comb): continue - k = {x: image for x, image in zip(X, comb)} + k = dict(zip(X, comb)) h = try_create_h(f, k) if h: break diff --git a/src/sage/combinat/yang_baxter_graph.py b/src/sage/combinat/yang_baxter_graph.py index bcfac20fdb3..f2fdb7a5a47 100644 --- a/src/sage/combinat/yang_baxter_graph.py +++ b/src/sage/combinat/yang_baxter_graph.py @@ -335,7 +335,7 @@ def _edges_in_bfs(self): seen[self._root] = True while queue: u = queue.pop() - l = sorted(list(digraph.neighbor_out_iterator(u))) + l = sorted(digraph.neighbor_out_iterator(u)) for w in l: if w not in seen: seen[w] = True @@ -585,7 +585,7 @@ def __init__(self, partition): """ self._partition = partition beta = sorted(self._partition, reverse=True) - root = sum([tuple(range(b)) for b in beta], tuple())[::-1] + root = sum((tuple(range(b)) for b in beta), ())[::-1] operators = [SwapIncreasingOperator(i) for i in range(sum(partition) - 1)] super().__init__(root, operators) From 6e73c11e5f6e4de90b141d7d01dc6f143e2ce088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 Apr 2024 09:30:10 +0200 Subject: [PATCH 2/3] fix suggestions --- src/sage/arith/functions.pyx | 4 ++-- src/sage/combinat/sloane_functions.py | 2 +- src/sage/combinat/tiling.py | 5 +---- src/sage/combinat/words/morphism.py | 11 ++++++++++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/sage/arith/functions.pyx b/src/sage/arith/functions.pyx index f0c7c03220e..a3a9c4ae216 100644 --- a/src/sage/arith/functions.pyx +++ b/src/sage/arith/functions.pyx @@ -30,7 +30,7 @@ def lcm(a, b=None): - ``a,b`` -- two elements of a ring with lcm or - - ``a`` -- a list or tuple of elements of a ring with lcm + - ``a`` -- a list, tuple or iterable of elements of a ring with lcm OUTPUT: @@ -135,7 +135,7 @@ cpdef LCM_list(v): INPUT: - - ``v`` -- an iterable + - ``v`` -- an iterable OUTPUT: integer diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index 808bcfd849d..76a05d6dc18 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -859,7 +859,7 @@ def _eval(self, n): sage: [sloane.A003418._eval(n) for n in range(1,11)] [1, 2, 6, 12, 60, 60, 420, 840, 2520, 2520] """ - return arith.lcm(list(range(1, n + 1))) + return arith.lcm(range(1, n + 1)) class A007318(SloaneSequence): diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index 2190c5b2119..43c7817f13a 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -1811,13 +1811,10 @@ def int_to_coord_dict(self): True sage: all(B[A[i]] == i for i in A) True - """ if self._reusable: return dict(enumerate(self.space())) - - number_of_pieces = len(self._pieces) - return {i + number_of_pieces: c for i, c in enumerate(self.space())} + return dict(enumerate(self.space(), start=len(self._pieces))) @cached_method def rows_for_piece(self, i, mod_box_isometries=False): diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index abd66da0650..24f22dad7e4 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -1727,9 +1727,18 @@ def is_uniform(self, k=None): False sage: tau.is_uniform(k=2) True + + TESTS: + + sage: phi = WordMorphism('') + sage: phi.is_uniform() + False """ if k is None: - k = self.images()[0].length() + try: + k = self.images()[0].length() + except IndexError: + return False return all(w.length() == k for w in self.images()) def fixed_point(self, letter): From b9ae35b104c07b046ab1a4b12f2a1f1a9b797ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 Apr 2024 20:10:18 +0200 Subject: [PATCH 3/3] fix suggested details --- src/sage/combinat/words/morphism.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index 24f22dad7e4..9424a3370b7 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -1700,7 +1700,7 @@ def is_prolongable(self, letter): def is_uniform(self, k=None): r""" - Return True if self is a `k`-uniform morphism. + Return ``True`` if ``self`` is a `k`-uniform morphism. Let `k` be a positive integer. A morphism `\phi` is called `k`-uniform if for every letter `\alpha`, we have `|\phi(\alpha)| = k`. In other @@ -1709,9 +1709,10 @@ def is_uniform(self, k=None): INPUT: - - ``k`` - a positive integer or None. If set to a positive integer, - then the function return True if self is `k`-uniform. If set to - None, then the function return True if self is uniform. + - ``k`` - a positive integer or ``None``. If set to a positive integer, + then the function return ``True`` if ``self`` is `k`-uniform. + If set to ``None``, then the function return ``True`` if ``self`` + is uniform. EXAMPLES:: @@ -1728,17 +1729,17 @@ def is_uniform(self, k=None): sage: tau.is_uniform(k=2) True - TESTS: + TESTS:: sage: phi = WordMorphism('') sage: phi.is_uniform() - False + True """ if k is None: try: k = self.images()[0].length() except IndexError: - return False + return True return all(w.length() == k for w in self.images()) def fixed_point(self, letter):