From abb96f00c675bac61ac12ca8033b3d1940c97c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 5 May 2024 16:43:05 +0200 Subject: [PATCH 1/4] various ruff fixes in combinat --- .../combinat/cluster_algebra_quiver/quiver.py | 5 +- src/sage/combinat/nu_dyck_word.py | 88 +++++------ src/sage/combinat/partition.py | 143 ++++++++---------- src/sage/combinat/permutation.py | 35 ++--- src/sage/combinat/words/finite_word.py | 25 ++- src/sage/combinat/words/morphism.py | 24 ++- src/sage/combinat/words/paths.py | 16 +- src/sage/combinat/words/suffix_trees.py | 4 +- src/sage/combinat/yang_baxter_graph.py | 30 ++-- 9 files changed, 174 insertions(+), 196 deletions(-) diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver.py b/src/sage/combinat/cluster_algebra_quiver/quiver.py index 3fc3499ef67..37103b623f4 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver.py @@ -787,9 +787,8 @@ def qmu_save(self, filename=None): string.append('1') string.append('//Matrix') string.append(str(m) + ' ' + str(m)) - for i in range(m): - string.append(' '.join(str(M[i, j]) - for j in range(m))) + string.extend(' '.join(str(M[i, j]) for j in range(m)) + for i in range(m)) string.append('//Points') for i in range(m): diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index ddc54a03612..bbf43361a25 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -829,7 +829,7 @@ def _latex_(self): if latex_options['show_grid']: grid = [((0, 0), (self.width(), self.height()))] for v1, v2 in grid: - res += " \\draw[dotted] %s grid %s;" % (str(v1), str(v2)) + res += f" \\draw[dotted] {str(v1)} grid {str(v2)};" res += "\n" # Add points if wanted @@ -838,8 +838,8 @@ def _latex_(self): radius = 0.15 + .03 * latex_options['line width'] for v in self.points(): res += " \\draw[line width=2," - res += "color=%s,fill=%s]" % (pt_color, pt_color) - res += "%s circle (%s);" % (str(v), str(radius)) + res += f"color={pt_color},fill={pt_color}]" + res += f"{str(v)} circle ({str(radius)});" res += "\n" # Add nu if wanted @@ -853,7 +853,7 @@ def _latex_(self): res += ";\n" # setup Path - res += " \\draw[rounded corners=1, color=%s, line width=%s]" % ( + res += " \\draw[rounded corners=1, color={}, line width={}]".format( latex_options['color'], str(latex_options['line width']) ) @@ -1210,46 +1210,46 @@ class options(GlobalOptions): """ NAME = 'NuDyckWords' module = 'sage.combinat.nu_dyck_path' - display = dict(default="list", - description='Specifies how nu Dyck words should be printed', - values=dict(list='displayed as a list', - lattice='displayed on the lattice defined by ``diagram_style``'), - case_sensitive=False) - ascii_art = dict(default="pretty_output", - description='Specifies how the ascii art of nu Dyck words should be printed', - values=dict(pretty_output="Using pretty printing"), - alias=dict(pretty_print="pretty_output",), - case_sensitive=False) - diagram_style = dict(default="grid", - values=dict( - grid='printing as paths on a grid using N and E steps',), - alias={'N-E': 'grid'}, - case_sensitive=False) - latex_tikz_scale = dict(default=1, - description='The default value for the tikz scale when latexed', - checker=lambda x: True) # More trouble than it's worth to check - latex_line_width_scalar = dict(default=2, - description='The default value for the line width as a ' - 'multiple of the tikz scale when latexed', - checker=lambda x: True) # More trouble than it's worth to check - latex_color = dict(default="black", - description='The default value for the color when latexed', - checker=lambda x: isinstance(x, str)) - latex_show_points = dict(default=False, - description='The default value for showing points', - checker=lambda x: isinstance(x, bool)) - latex_points_color = dict(default='black', - description='The default value for path color.', - checker=lambda x: isinstance(x, str)) - latex_show_grid = dict(default=True, - description='The default value for showing grid', - checker=lambda x: isinstance(x, bool)) - latex_show_nu = dict(default=True, - description='The default value for showing nu', - checker=lambda x: isinstance(x, bool)) - latex_nu_options = dict(default='rounded corners=1, color=red, line width=1', - description='The default value for options for nu path', - checker=lambda x: isinstance(x, str)) + display = {'default': "list", + 'description': 'Specifies how nu Dyck words should be printed', + 'values': {'list': 'displayed as a list', + 'lattice': 'displayed on the lattice defined by ``diagram_style``'}, + 'case_sensitive': False} + ascii_art = {'default': "pretty_output", + 'description': 'Specifies how the ascii art of nu Dyck words should be printed', + 'values': {'pretty_output': "Using pretty printing"}, + 'alias': {'pretty_print': "pretty_output"}, + 'case_sensitive': False} + diagram_style = {'default': "grid", + 'values': { + 'grid': 'printing as paths on a grid using N and E steps'}, + 'alias': {'N-E': 'grid'}, + 'case_sensitive': False} + latex_tikz_scale = {'default': 1, + 'description': 'The default value for the tikz scale when latexed', + 'checker': lambda x: True} # More trouble than it's worth to check + latex_line_width_scalar = {'default': 2, + 'description': 'The default value for the line width as a ' + 'multiple of the tikz scale when latexed', + 'checker': lambda x: True} # More trouble than it's worth to check + latex_color = {'default': "black", + 'description': 'The default value for the color when latexed', + 'checker': lambda x: isinstance(x, str)} + latex_show_points = {'default': False, + 'description': 'The default value for showing points', + 'checker': lambda x: isinstance(x, bool)} + latex_points_color = {'default': 'black', + 'description': 'The default value for path color.', + 'checker': lambda x: isinstance(x, str)} + latex_show_grid = {'default': True, + 'description': 'The default value for showing grid', + 'checker': lambda x: isinstance(x, bool)} + latex_show_nu = {'default': True, + 'description': 'The default value for showing nu', + 'checker': lambda x: isinstance(x, bool)} + latex_nu_options = {'default': 'rounded corners=1, color=red, line width=1', + 'description': 'The default value for options for nu path', + 'checker': lambda x: isinstance(x, str)} def _element_constructor_(self, word): """ diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index da521bd7822..09333182485 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -713,7 +713,7 @@ def _repr_exp_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ', '.join('%s%s' % (m+1, '' if e == 1 else '^%s' % e) + return '%s' % ', '.join('{}{}'.format(m+1, '' if e == 1 else '^%s' % e) for (m,e) in enumerate(exp) if e > 0) def _repr_exp_high(self): @@ -733,7 +733,7 @@ def _repr_exp_high(self): return '-' exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return ', '.join('%s%s' % (M - m, '' if e == 1 else '^%s' % e) + return ', '.join('{}{}'.format(M - m, '' if e == 1 else '^%s' % e) for m, e in enumerate(exp) if e > 0) def _repr_compact_low(self): @@ -751,7 +751,7 @@ def _repr_compact_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ','.join('%s%s' % (m+1, '' if e == 1 else '^%s' % e) + return '%s' % ','.join('{}{}'.format(m+1, '' if e == 1 else '^%s' % e) for (m,e) in enumerate(exp) if e > 0) def _repr_compact_high(self): @@ -770,7 +770,7 @@ def _repr_compact_high(self): return '-' exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return '%s' % ','.join('%s%s' % (M-m, '' if e == 1 else '^%s' % e) + return '%s' % ','.join('{}{}'.format(M-m, '' if e == 1 else '^%s' % e) for (m,e) in enumerate(exp) if e > 0) def _repr_diagram(self): @@ -945,7 +945,7 @@ def _latex_exp_low(self): if not self._list: return "{\\emptyset}" exp = self.to_exp() - return '%s' % ','.join('%s%s' % (m+1, '' if e == 1 else '^{%s}' % e) + return '%s' % ','.join('{}{}'.format(m+1, '' if e == 1 else '^{%s}' % e) for (m,e) in enumerate(exp) if e > 0) def _latex_exp_high(self): @@ -963,7 +963,7 @@ def _latex_exp_high(self): return "{\\emptyset}" exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return '%s' % ','.join('%s%s' % (M-m, '' if e == 1 else '^{%s}' % e) + return '%s' % ','.join('{}{}'.format(M-m, '' if e == 1 else '^{%s}' % e) for (m,e) in enumerate(exp) if e > 0) def ferrers_diagram(self): @@ -2339,11 +2339,7 @@ def cells(self): sage: Partition([3,2]).cells() [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1)] """ - res = [] - for i in range(len(self)): - for j in range(self[i]): - res.append( (i,j) ) - return res + return [(i, j) for i, si in enumerate(self) for j in range(si)] def generalized_pochhammer_symbol(self, a, alpha): r""" @@ -2925,7 +2921,7 @@ def top_garnir_tableau(self,e,cell): """ (row,col) = cell if row+1 >= len(self) or col >= self[row+1]: - raise ValueError('(%s,%s)=(row+1,col) must be inside the diagram' % (row+1,col)) + raise ValueError(f'({row+1},{col})=(row+1,col) must be inside the diagram') g = self.garnir_tableau(cell) # start with the Garnir tableau and modify @@ -3336,16 +3332,16 @@ def attacking_pairs(self): attacking_pairs = [] for i, r in enumerate(self): for j in range(r): - #c is in position (i,j) - #Find the d that satisfy condition 1 - for k in range(j+1, r): - attacking_pairs.append( ((i,j),(i,k)) ) + # c is in position (i,j) + # Find the d that satisfy condition 1 + attacking_pairs.extend(((i, j), (i, k)) + for k in range(j + 1, r)) - #Find the d that satisfy condition 2 + # Find the d that satisfy condition 2 if i == 0: continue - for k in range(j): - attacking_pairs.append( ((i,j),(i-1,k)) ) + attacking_pairs.extend(((i, j), (i - 1, k)) + for k in range(j)) return attacking_pairs @@ -4017,7 +4013,7 @@ def is_restricted(self, e, multicharge=(0,)): return (not self or ( self[-1] < e and all(self[r]-self[r+1] < e for r in range(len(self)-1)) )) - def is_regular(self, e, multicharge=(0,)): + def is_regular(self, e, multicharge=(0,)) -> bool: """ Return ``True`` is this is an ``e``-regular partition. @@ -4049,9 +4045,9 @@ def conjugacy_class_size(self): sage: Partition([2,1,1]).conjugacy_class_size() 6 """ - return factorial(sum(self))/self.centralizer_size() + return factorial(sum(self)) / self.centralizer_size() - def corners(self): + def corners(self) -> list: r""" Return a list of the corners of the partition ``self``. @@ -4224,9 +4220,8 @@ def rim(self): p = self res = [] prevLen = 1 - for i in range(len(p)-1, -1, -1): - for c in range(prevLen-1, p[i]): - res.append((i,c)) + for i in range(len(p) - 1, -1, -1): + res.extend((i, c) for c in range(prevLen-1, p[i])) prevLen = p[i] return res @@ -4263,9 +4258,8 @@ def outer_rim(self): p = self res = [] prevLen = 0 - for i in range(len(p)-1, -1, -1): - for c in range(prevLen, p[i]+1): - res.append((i+1,c)) + for i in range(len(p) - 1, -1, -1): + res.extend((i + 1, c) for c in range(prevLen, p[i] + 1)) prevLen = p[i] res.append((0, prevLen)) return res @@ -4316,7 +4310,7 @@ def zero_one_sequence(self): sage: all(Partitions().from_zero_one(mu.zero_one_sequence()) == mu for n in range(10) for mu in Partitions(n)) True """ - tmp = set(self[i] - i for i in range(len(self))) + tmp = {si - i for i, si in enumerate(self)} return [Integer(i not in tmp) for i in range(-len(self) + 1, self.get_part(0) + 1)] @@ -4958,7 +4952,7 @@ def horizontal_border_strip_cells(self, k): [(3, 0), (3, 1)]] """ if k == 0: - return list() + return [] L = self._list shelf = [k] # the number of boxes which will fit in a row @@ -5099,11 +5093,8 @@ def atom(self): sage: Partition([3,2,1]).atom() [[[1, 2, 3, 6], [4, 5]], [[1, 2, 3], [4, 5], [6]]] """ - res = [] - for tab in tableau.StandardTableaux_size(self.size()): - if tab.atom() == self: - res.append(tab) - return res + return [tab for tab in tableau.StandardTableaux_size(self.size()) + if tab.atom() == self] def k_atom(self, k): r""" @@ -6059,7 +6050,7 @@ def __classcall_private__(cls, n=None, **kwargs): return RestrictedPartitions_n(n, kwargs['restricted']) # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute - kwargs['name'] = "Partitions of the integer %s satisfying constraints %s" % (n, ", ".join( ["%s=%s" % (key, kwargs[key]) for key in sorted(kwargs)] )) + kwargs['name'] = "Partitions of the integer {} satisfying constraints {}".format(n, ", ".join( ["{}={}".format(key, kwargs[key]) for key in sorted(kwargs)] )) # min_part is at least 1, and it is 1 by default kwargs['min_part'] = max(1, kwargs.get('min_part', 1)) @@ -6195,34 +6186,34 @@ class options(GlobalOptions): """ NAME = 'Partitions' module = 'sage.combinat.partition' - display = dict(default="list", - description='Specifies how partitions should be printed', - values=dict(list='displayed as a list', - exp_low='in exponential form (lowest first)', - exp_high='in exponential form (highest first)', - diagram='as a Ferrers diagram', - compact_low='compact form of ``exp_low``', - compact_high='compact form of ``exp_high``'), - alias=dict(exp="exp_low", compact="compact_low", array="diagram", - ferrers_diagram="diagram", young_diagram="diagram"), - case_sensitive=False) - latex = dict(default="young_diagram", - description='Specifies how partitions should be latexed', - values=dict(diagram='latex as a Ferrers diagram', - young_diagram='latex as a Young diagram', - list='latex as a list', - exp_high='latex as a list in exponential notation (highest first)', - exp_low='as a list latex in exponential notation (lowest first)'), - alias=dict(exp="exp_low", array="diagram", ferrers_diagram="diagram"), - case_sensitive=False) - diagram_str = dict(default="*", - description='The character used for the cells when printing Ferrers diagrams', - checker=lambda char: isinstance(char,str)) - latex_diagram_str = dict(default="\\ast", - description='The character used for the cells when latexing Ferrers diagrams', - checker=lambda char: isinstance(char,str)) - convention = dict(link_to=(tableau.Tableaux.options,'convention')) - notation = dict(alt_name='convention') + display = {'default': "list", + 'description': 'Specifies how partitions should be printed', + 'values': {'list': 'displayed as a list', + 'exp_low': 'in exponential form (lowest first)', + 'exp_high': 'in exponential form (highest first)', + 'diagram': 'as a Ferrers diagram', + 'compact_low': 'compact form of ``exp_low``', + 'compact_high': 'compact form of ``exp_high``'}, + 'alias': {'exp': "exp_low", 'compact': "compact_low", 'array': "diagram", + 'ferrers_diagram': "diagram", 'young_diagram': "diagram"}, + 'case_sensitive': False} + latex = {'default': "young_diagram", + 'description': 'Specifies how partitions should be latexed', + 'values': {'diagram': 'latex as a Ferrers diagram', + 'young_diagram': 'latex as a Young diagram', + 'list': 'latex as a list', + 'exp_high': 'latex as a list in exponential notation (highest first)', + 'exp_low': 'as a list latex in exponential notation (lowest first)'}, + 'alias': {'exp': "exp_low", 'array': "diagram", 'ferrers_diagram': "diagram"}, + 'case_sensitive': False} + diagram_str = {'default': "*", + 'description': 'The character used for the cells when printing Ferrers diagrams', + 'checker': lambda char: isinstance(char,str)} + latex_diagram_str = {'default': "\\ast", + 'description': 'The character used for the cells when latexing Ferrers diagrams', + 'checker': lambda char: isinstance(char,str)} + convention = {'link_to': (tableau.Tableaux.options,'convention')} + notation = {'alt_name': 'convention'} def __reversed__(self): """ @@ -6282,7 +6273,7 @@ def _element_constructor_(self, lst): # trailing zeros are removed in Partition.__init__ return self.element_class(self, lst) - raise ValueError('%s is not an element of %s' % (lst, self)) + raise ValueError(f'{lst} is not an element of {self}') def __contains__(self, x): """ @@ -7122,7 +7113,7 @@ def _repr_(self): sage: Partitions(5, length=2) # indirect doctest Partitions of the integer 5 of length 2 """ - return "Partitions of the integer {} of length {}".format(self.n, self.k) + return f"Partitions of the integer {self.n} of length {self.k}" def _an_element_(self): """ @@ -7344,7 +7335,7 @@ def _repr_(self): sage: Partitions(5, parts_in=[1,2,3]) # indirect doctest Partitions of the integer 5 with parts in [1, 2, 3] """ - return "Partitions of the integer %s with parts in %s" % (self.n, self.parts) + return f"Partitions of the integer {self.n} with parts in {self.parts}" def cardinality(self): r""" @@ -7877,7 +7868,7 @@ def _repr_(self): sage: PartitionsInBox(2,2) # indirect doctest Integer partitions which fit in a 2 x 2 box """ - return "Integer partitions which fit in a %s x %s box" % (self.h, self.w) + return f"Integer partitions which fit in a {self.h} x {self.w} box" def __contains__(self, x): """ @@ -8161,7 +8152,7 @@ def _repr_(self): sage: RegularPartitions_all(3) 3-Regular Partitions """ - return "{}-Regular Partitions".format(self._ell) + return f"{self._ell}-Regular Partitions" def __iter__(self): """ @@ -8251,7 +8242,7 @@ def _repr_(self): sage: RegularPartitions_truncated(4, 3) 4-Regular Partitions with max length 3 """ - return "{}-Regular Partitions with max length {}".format(self._ell, self._max_len) + return f"{self._ell}-Regular Partitions with max length {self._max_len}" def __iter__(self): """ @@ -8369,7 +8360,7 @@ def _repr_(self): sage: RegularPartitions_bounded(4, 3) 4-Regular 3-Bounded Partitions """ - return "{}-Regular {}-Bounded Partitions".format(self._ell, self.k) + return f"{self._ell}-Regular {self.k}-Bounded Partitions" def __iter__(self): """ @@ -8432,7 +8423,7 @@ def _repr_(self): sage: RegularPartitions_n(3, 5) 5-Regular Partitions of the integer 3 """ - return "{}-Regular Partitions of the integer {}".format(self._ell, self.n) + return f"{self._ell}-Regular Partitions of the integer {self.n}" def __contains__(self, x): """ @@ -8724,7 +8715,7 @@ def _repr_(self): sage: PartitionsGreatestLE(10, 2) # indirect doctest Partitions of 10 having parts less than or equal to 2 """ - return "Partitions of %s having parts less than or equal to %s" % (self.n, self.k) + return f"Partitions of {self.n} having parts less than or equal to {self.k}" def cardinality(self): """ @@ -8814,7 +8805,7 @@ def _repr_(self): sage: PartitionsGreatestEQ(10, 2) # indirect doctest Partitions of 10 having greatest part equal to 2 """ - return "Partitions of %s having greatest part equal to %s" % (self.n, self.k) + return f"Partitions of {self.n} having greatest part equal to {self.k}" def cardinality(self): """ @@ -8996,7 +8987,7 @@ def _repr_(self): sage: RestrictedPartitions_all(3) 3-Restricted Partitions """ - return "{}-Restricted Partitions".format(self._ell) + return f"{self._ell}-Restricted Partitions" def __iter__(self): """ @@ -9051,7 +9042,7 @@ def _repr_(self): sage: RestrictedPartitions_n(3, 5) 5-Restricted Partitions of the integer 3 """ - return "{}-Restricted Partitions of the integer {}".format(self._ell, self.n) + return f"{self._ell}-Restricted Partitions of the integer {self.n}" def __contains__(self, x): """ diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 3919d9866da..d1ef95abf50 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -239,7 +239,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** from __future__ import annotations -from typing import Iterator +from collections.abc import Iterator import itertools import operator @@ -680,9 +680,9 @@ def _latex_(self): redword = self.reduced_word() if not redword: return self.parent().options.latex_empty_str - return " ".join("%s_{%s}" % (let, i) for i in redword) + return " ".join(f"{let}_{{{i}}}" for i in redword) if display == "twoline": - return "\\begin{pmatrix} %s \\\\ %s \\end{pmatrix}" % ( + return "\\begin{{pmatrix}} {} \\\\ {} \\end{{pmatrix}}".format( " & ".join("%s" % i for i in range(1, len(self._list)+1)), " & ".join("%s" % i for i in self._list)) if display == "list": @@ -1406,7 +1406,7 @@ def __call__(self, i): """ if isinstance(i, (int, Integer)) and 1 <= i <= len(self): return self[i - 1] - raise TypeError("i (= %s) must be between 1 and %s" % (i, len(self))) + raise TypeError(f"i (= {i}) must be between 1 and {len(self)}") ######## # Rank # @@ -2780,7 +2780,7 @@ def destandardize(self, weight, ordered_alphabet=None): for a in weight: partial.append(partial[-1]+a) if not set(ides).issubset(set(partial)): - raise ValueError("Standardization with weight {} is not possible!".format(weight)) + raise ValueError(f"Standardization with weight {weight} is not possible!") if ordered_alphabet is None: ordered_alphabet = list(range(1,len(weight)+1)) else: @@ -4221,7 +4221,7 @@ def right_permutohedron_interval_iterator(self, other): [2, 1, 5, 4, 3], [2, 5, 1, 4, 3], [2, 5, 4, 1, 3]] """ if len(self) != len(other): - raise ValueError("len({}) and len({}) must be equal".format(self, other)) + raise ValueError(f"len({self}) and len({other}) must be equal") if not self.permutohedron_lequal(other): raise ValueError("{} must be lower or equal than {} for the right permutohedron order".format(self, other)) d = DiGraph() @@ -6079,7 +6079,7 @@ def _repr_(self) -> str: sage: Permutations(3,2) Permutations of {1,...,3} of length 2 """ - return "Permutations of {1,...,%s} of length %s" % (self.n, self._k) + return f"Permutations of {{1,...,{self.n}}} of length {self._k}" def __iter__(self) -> Iterator[Permutation]: """ @@ -6710,7 +6710,7 @@ def _repr_(self): sage: Permutations([1,2,2], 2) Permutations of the multi-set [1, 2, 2] of length 2 """ - return "Permutations of the multi-set %s of length %s" % (list(self.mset), self._k) + return f"Permutations of the multi-set {list(self.mset)} of length {self._k}" def cardinality(self): """ @@ -6797,8 +6797,7 @@ def _repr_(self): sage: repr(Permutations([1,2,4],2)) 'Permutations of the set [1, 2, 4] of length 2' """ - return "Permutations of the set %s of length %s" % (list(self._set), - self._k) + return f"Permutations of the set {list(self._set)} of length {self._k}" def __iter__(self): """ @@ -6914,7 +6913,7 @@ def _repr_(self): sage: Arrangements([1,2,2],2) Arrangements of the multi-set [1, 2, 2] of length 2 """ - return "Arrangements of the multi-set %s of length %s" % (list(self.mset), self._k) + return f"Arrangements of the multi-set {list(self.mset)} of length {self._k}" class Arrangements_setk(Arrangements, Permutations_setk): @@ -6929,8 +6928,7 @@ def _repr_(self): sage: Arrangements([1,2,3],2) Arrangements of the set [1, 2, 3] of length 2 """ - return "Arrangements of the set %s of length %s" % (list(self._set), - self._k) + return f"Arrangements of the set {list(self._set)} of length {self._k}" ############################################################### # Standard permutations @@ -7420,8 +7418,8 @@ def element_in_conjugacy_classes(self, nu): from sage.combinat.partition import Partition nu = Partition(nu) if nu.size() > self.n: - raise ValueError("the size of the partition (=%s) should be at most" - " the size of the permutations (=%s)" % (nu.size(), self.n)) + raise ValueError("the size of the partition (={}) should be at most" + " the size of the permutations (={})".format(nu.size(), self.n)) l = [] i = 0 for nui in nu: @@ -8307,7 +8305,7 @@ def _repr_(self): sage: Permutations(descents=([1,0,4,8],12)) Standard permutations of 12 with descents [0, 1, 4, 8] """ - return "Standard permutations of %s with descents %s" % (self.n, list(self._d)) + return f"Standard permutations of {self.n} with descents {list(self._d)}" def cardinality(self): """ @@ -9239,8 +9237,7 @@ def _repr_(self): sage: CyclicPermutationsOfPartition([[1,2,3,4],[5,6,7]]) Cyclic permutations of partition [[1, 2, 3, 4], [5, 6, 7]] """ - return "Cyclic permutations of partition {}".format( - [list(_) for _ in self.partition]) + return f"Cyclic permutations of partition {[list(_) for _ in self.partition]}" def __iter__(self, distinct=False): """ @@ -9498,7 +9495,7 @@ def _repr_(self): sage: Permutations(3, avoiding=[[2, 1, 3],[1,2,3]]) Standard permutations of 3 avoiding [[2, 1, 3], [1, 2, 3]] """ - return "Standard permutations of %s avoiding %s" % (self.n, list(self._a)) + return f"Standard permutations of {self.n} avoiding {list(self._a)}" def __iter__(self): """ diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index 1bdd38e92c7..1b5dcb3b03e 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -293,7 +293,7 @@ def _repr_(self): if word_options['old_repr']: if word_options['truncate'] and \ self.length() > word_options['truncate_length']: - return "Finite word of length %s over %s" % (self.length(), str(self.parent().alphabet())[17:]) + return "Finite word of length {} over {}".format(self.length(), str(self.parent().alphabet())[17:]) return word_options['identifier'] + self.string_rep() def coerce(self, other): @@ -331,7 +331,7 @@ def coerce(self, other): self = other.parent()(self) self.parent()._check(self, length=None) except Exception: - raise TypeError("no coercion rule between %r and %r" % (self.parent(), other.parent())) + raise TypeError("no coercion rule between {!r} and {!r}".format(self.parent(), other.parent())) return self, other def __hash__(self): @@ -1261,7 +1261,7 @@ def number_of_factors(self, n=None, algorithm='suffix tree'): elif algorithm == 'naive': return ZZ(len(self.factor_set(n, algorithm='naive'))) else: - raise ValueError('Unknown algorithm (={})'.format(algorithm)) + raise ValueError(f'Unknown algorithm (={algorithm})') def factor_iterator(self, n=None): r""" @@ -1437,7 +1437,7 @@ def factor_set(self, n=None, algorithm='suffix tree'): S.add(self[i:i+n]) return Set(S) else: - raise ValueError('Unknown algorithm (={})'.format(algorithm)) + raise ValueError(f'Unknown algorithm (={algorithm})') def topological_entropy(self, n): r""" @@ -2067,8 +2067,7 @@ def _conjugates_list(self): [word: a] """ S = [self] - for i in range(1, self.length()): - S.append(self.conjugate(i)) + S.extend(self.conjugate(i) for i in range(1, self.length())) return S def conjugates_iterator(self): @@ -2853,9 +2852,9 @@ def length_maximal_palindrome(self, j, m=None, f=None): # Initialize the next (left) position to check i = (jj - m - 1) / 2 if not i.is_integer(): - raise ValueError("(2*j-m-1)/2(={}) must be an integer, i.e., " - "2*j(={}) and m(={}) can't " - "have the same parity".format(i, jj, m)) + raise ValueError(f"(2*j-m-1)/2(={i}) must be an integer, i.e., " + f"2*j(={jj}) and m(={m}) can't " + "have the same parity") i = Integer(i) # Compute @@ -2970,8 +2969,7 @@ def lps_lengths(self, f=None): for j in range(1, 2 * len(self) + 1): Nj = j + LPC[j] if Nj > Nk: - for i in range(Nk + 2 - (Nk % 2), Nj + 1, 2): - LPS.append(i - j) + LPS.extend(i - j for i in range(Nk + 2 - (Nk % 2), Nj + 1, 2)) Nk = Nj return LPS @@ -3858,8 +3856,7 @@ def subword_complementaries(self, other): if len(m) == 1: temp.append([j]+m[0]) if len(m) > 1: - for sw in m: - temp.append([j]+sw) + temp.extend([j] + sw for sw in m) Mpos[i][j] = temp # Create the list of positions for occurrences of `self` as a subword @@ -3875,7 +3872,7 @@ def subword_complementaries(self, other): comp_words.append(Word([other[i] for i in comp_pos])) return comp_words - def is_lyndon(self): + def is_lyndon(self) -> bool: r""" Return ``True`` if ``self`` is a Lyndon word, and ``False`` otherwise. diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index 9424a3370b7..46207beab1c 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -883,18 +883,15 @@ def _latex_(self): A = self.domain().alphabet() latex_layout = self.latex_layout() if latex_layout == 'oneliner': - L = [r"%s \mapsto %s" % (a, self.image(a)) for a in A] - return LatexExpr(r','.join(L)) - elif latex_layout == 'array': + lines = (fr"{a} \mapsto {self.image(a)}" for a in A) + return LatexExpr(r','.join(lines)) + if latex_layout == 'array': s = r"\begin{array}{l}" + '\n' - lines = [] - for a in A: - lines.append(r"%s \mapsto %s" % (a, self.image(a))) + lines = (fr"{a} \mapsto {self.image(a)}" for a in A) s += '\\\\\n'.join(lines) s += '\n' + r"\end{array}" return LatexExpr(s) - else: - raise ValueError('unknown latex_layout(=%s)' % latex_layout) + raise ValueError('unknown latex_layout(=%s)' % latex_layout) def __mul__(self, other): r""" @@ -1693,8 +1690,7 @@ def is_prolongable(self, letter): TypeError: codomain of self must be an instance of Words """ if letter not in self.domain().alphabet(): - raise TypeError("letter (=%s) is not in the domain alphabet (=%s)" - % (letter, self.domain().alphabet())) + raise TypeError("letter (={}) is not in the domain alphabet (={})".format(letter, self.domain().alphabet())) image = self.image(letter) return not image.is_empty() and letter == image[0] @@ -1893,11 +1889,9 @@ def fixed_points(self): [] """ - L = [] - for letter in self.domain().alphabet(): - if self.is_prolongable(letter=letter): - L.append(self.fixed_point(letter=letter)) - return L + return [self.fixed_point(letter=letter) + for letter in self.domain().alphabet() + if self.is_prolongable(letter=letter)] def periodic_point(self, letter): r""" diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py index f5506152d44..21709124f64 100644 --- a/src/sage/combinat/words/paths.py +++ b/src/sage/combinat/words/paths.py @@ -1489,11 +1489,11 @@ def is_tangent(self): class FiniteWordPath_2d(FiniteWordPath_all): - def plot(self, pathoptions=dict(rgbcolor='red', thickness=3), - fill=True, filloptions=dict(rgbcolor='red', alpha=0.2), - startpoint=True, startoptions=dict(rgbcolor='red', pointsize=100), - endarrow=True, arrowoptions=dict(rgbcolor='red', arrowsize=20, width=3), - gridlines=False, gridoptions=dict()): + def plot(self, pathoptions={"rgbcolor": 'red', "thickness": 3}, + fill=True, filloptions={"rgbcolor": 'red', "alpha": 0.2}, + startpoint=True, startoptions={"rgbcolor": 'red', "pointsize": 100}, + endarrow=True, arrowoptions={"rgbcolor": 'red', "arrowsize": 20, "width": 3}, + gridlines=False, gridoptions={}): r""" Return a 2d Graphics illustrating the path. @@ -1698,7 +1698,7 @@ def animate(self): return animate(images, **kwds) - def plot_directive_vector(self, options=dict(rgbcolor='blue')): + def plot_directive_vector(self, options={"rgbcolor": 'blue'}): r""" Return an arrow 2d graphics that goes from the start of the path to the end. @@ -2003,8 +2003,8 @@ def ymax(self): class FiniteWordPath_3d(FiniteWordPath_all): - def plot(self, pathoptions=dict(rgbcolor='red', arrow_head=True, thickness=3), - startpoint=True, startoptions=dict(rgbcolor='red', size=10)): + def plot(self, pathoptions={"rgbcolor": 'red', "arrow_head": True, "thickness": 3}, + startpoint=True, startoptions={"rgbcolor": 'red', "size": 10}): r""" INPUT: diff --git a/src/sage/combinat/words/suffix_trees.py b/src/sage/combinat/words/suffix_trees.py index 8c56ba3d4b3..c2bda4caf96 100644 --- a/src/sage/combinat/words/suffix_trees.py +++ b/src/sage/combinat/words/suffix_trees.py @@ -1740,7 +1740,7 @@ def treat_node(current_node, parent): D = self.transition_function_dictionary() string_depth = {0: 0} n = len(self.word()) - labeling = dict() + labeling = {} treat_node(0, None) return labeling @@ -1827,7 +1827,7 @@ def treat_node(current_node, i, j): walk_chain(current_node, child, l, square_start) prelabeling = self._partial_labeling() - labeling = dict() + labeling = {} D = self.transition_function_dictionary() treat_node(0, 0, 0) return labeling diff --git a/src/sage/combinat/yang_baxter_graph.py b/src/sage/combinat/yang_baxter_graph.py index f2fdb7a5a47..6b7684e077a 100644 --- a/src/sage/combinat/yang_baxter_graph.py +++ b/src/sage/combinat/yang_baxter_graph.py @@ -166,7 +166,7 @@ def _successors(self, u): if v != u: yield (v, op) - def __repr__(self): + def __repr__(self) -> str: r""" EXAMPLES:: @@ -176,7 +176,7 @@ def __repr__(self): sage: Y.__repr__() 'Yang-Baxter graph with root vertex (1, 2, 3)' """ - return "Yang-Baxter graph with root vertex %s" % (self._root,) + return f"Yang-Baxter graph with root vertex {self._root}" @lazy_attribute def _digraph(self): @@ -216,7 +216,7 @@ def __hash__(self): # used in containers but are mutable. return hash(self._digraph.copy(immutable=True)) - def __eq__(self, other): + def __eq__(self, other) -> bool: r""" EXAMPLES:: @@ -238,7 +238,7 @@ def __eq__(self, other): """ return type(self) is type(other) and self._digraph == other._digraph - def __ne__(self, other): + def __ne__(self, other) -> bool: r""" Test non-equality. @@ -369,7 +369,7 @@ def root(self): """ return self._root - def successors(self, v): + def successors(self, v) -> list: r""" Return the successors of the vertex ``v``. @@ -405,7 +405,7 @@ def plot(self, *args, **kwds): kwds["vertex_labels"] = True return self._digraph.plot(*args, **kwds) - def vertices(self, sort=False): + def vertices(self, sort=False) -> list: r""" Return the vertices of ``self``. @@ -439,7 +439,7 @@ def edges(self): """ return self._digraph.edges(sort=True) - def vertex_relabelling_dict(self, v, relabel_operator): + def vertex_relabelling_dict(self, v, relabel_operator) -> dict: r""" Return a dictionary pairing vertices ``u`` of ``self`` with the object obtained from ``v`` by applying the @@ -590,7 +590,7 @@ def __init__(self, partition): for i in range(sum(partition) - 1)] super().__init__(root, operators) - def __repr__(self): + def __repr__(self) -> str: r""" EXAMPLES:: @@ -598,7 +598,7 @@ def __repr__(self): sage: Y.__repr__() # needs sage.combinat 'Yang-Baxter graph of [3, 2], with top vertex (1, 0, 2, 1, 0)' """ - return "Yang-Baxter graph of %s, with top vertex %s" % (self._partition, self._root) + return f"Yang-Baxter graph of {self._partition}, with top vertex {self._root}" def __copy__(self): r""" @@ -695,7 +695,7 @@ def _swap_operator(self, operator, u): """ return operator(u) - def vertex_relabelling_dict(self, v): + def vertex_relabelling_dict(self, v) -> dict: r""" Return a dictionary pairing vertices ``u`` of ``self`` with the object obtained from ``v`` by applying transpositions corresponding to the @@ -792,7 +792,7 @@ def __hash__(self): """ return hash(self._position) - def __eq__(self, other): + def __eq__(self, other) -> bool: r""" Compare two swap operators. @@ -811,7 +811,7 @@ def __eq__(self, other): return False return self._position == other._position - def __ne__(self, other): + def __ne__(self, other) -> bool: """ Check whether ``self`` is not equal to ``other``. @@ -826,7 +826,7 @@ def __ne__(self, other): """ return not (self == other) - def __repr__(self): + def __repr__(self) -> str: r""" Representation string. @@ -840,7 +840,7 @@ def __repr__(self): pos = self._position return f"Swap positions {pos} and {pos + 1}" - def __str__(self): + def __str__(self) -> str: r""" A short str representation (used, for example, in labelling edges of graphs). @@ -889,7 +889,7 @@ def position(self): class SwapIncreasingOperator(SwapOperator): - def __repr__(self): + def __repr__(self) -> str: r""" Representation string. From eca4ca6c2a0e16f379d965c55e7c6f44f2c282d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 7 May 2024 20:04:52 +0200 Subject: [PATCH 2/4] fix some indentation --- src/sage/combinat/partition.py | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 09333182485..146aa6f6c9d 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -6187,31 +6187,31 @@ class options(GlobalOptions): NAME = 'Partitions' module = 'sage.combinat.partition' display = {'default': "list", - 'description': 'Specifies how partitions should be printed', - 'values': {'list': 'displayed as a list', - 'exp_low': 'in exponential form (lowest first)', - 'exp_high': 'in exponential form (highest first)', - 'diagram': 'as a Ferrers diagram', - 'compact_low': 'compact form of ``exp_low``', - 'compact_high': 'compact form of ``exp_high``'}, - 'alias': {'exp': "exp_low", 'compact': "compact_low", 'array': "diagram", - 'ferrers_diagram': "diagram", 'young_diagram': "diagram"}, - 'case_sensitive': False} - latex = {'default': "young_diagram", - 'description': 'Specifies how partitions should be latexed', - 'values': {'diagram': 'latex as a Ferrers diagram', - 'young_diagram': 'latex as a Young diagram', - 'list': 'latex as a list', - 'exp_high': 'latex as a list in exponential notation (highest first)', - 'exp_low': 'as a list latex in exponential notation (lowest first)'}, - 'alias': {'exp': "exp_low", 'array': "diagram", 'ferrers_diagram': "diagram"}, + 'description': 'Specifies how partitions should be printed', + 'values': {'list': 'displayed as a list', + 'exp_low': 'in exponential form (lowest first)', + 'exp_high': 'in exponential form (highest first)', + 'diagram': 'as a Ferrers diagram', + 'compact_low': 'compact form of ``exp_low``', + 'compact_high': 'compact form of ``exp_high``'}, + 'alias': {'exp': "exp_low", 'compact': "compact_low", 'array': "diagram", + 'ferrers_diagram': "diagram", 'young_diagram': "diagram"}, 'case_sensitive': False} + latex = {'default': "young_diagram", + 'description': 'Specifies how partitions should be latexed', + 'values': {'diagram': 'latex as a Ferrers diagram', + 'young_diagram': 'latex as a Young diagram', + 'list': 'latex as a list', + 'exp_high': 'latex as a list in exponential notation (highest first)', + 'exp_low': 'as a list latex in exponential notation (lowest first)'}, + 'alias': {'exp': "exp_low", 'array': "diagram", 'ferrers_diagram': "diagram"}, + 'case_sensitive': False} diagram_str = {'default': "*", - 'description': 'The character used for the cells when printing Ferrers diagrams', - 'checker': lambda char: isinstance(char,str)} + 'description': 'The character used for the cells when printing Ferrers diagrams', + 'checker': lambda char: isinstance(char,str)} latex_diagram_str = {'default': "\\ast", - 'description': 'The character used for the cells when latexing Ferrers diagrams', - 'checker': lambda char: isinstance(char,str)} + 'description': 'The character used for the cells when latexing Ferrers diagrams', + 'checker': lambda char: isinstance(char,str)} convention = {'link_to': (tableau.Tableaux.options,'convention')} notation = {'alt_name': 'convention'} From 0a1292a6d413acc1e9cab5a0783fe65dacdf30b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 9 May 2024 07:50:17 +0200 Subject: [PATCH 3/4] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit details in formatted strings Co-authored-by: Matthias Köppe --- src/sage/combinat/nu_dyck_word.py | 4 ++-- src/sage/combinat/permutation.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index bbf43361a25..bdc2c0f6e3a 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -829,7 +829,7 @@ def _latex_(self): if latex_options['show_grid']: grid = [((0, 0), (self.width(), self.height()))] for v1, v2 in grid: - res += f" \\draw[dotted] {str(v1)} grid {str(v2)};" + res += f" \\draw[dotted] {v1} grid {v2};" res += "\n" # Add points if wanted @@ -839,7 +839,7 @@ def _latex_(self): for v in self.points(): res += " \\draw[line width=2," res += f"color={pt_color},fill={pt_color}]" - res += f"{str(v)} circle ({str(radius)});" + res += f"{v} circle ({radius});" res += "\n" # Add nu if wanted diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index d1ef95abf50..0ec9451a9a9 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -682,7 +682,7 @@ def _latex_(self): return self.parent().options.latex_empty_str return " ".join(f"{let}_{{{i}}}" for i in redword) if display == "twoline": - return "\\begin{{pmatrix}} {} \\\\ {} \\end{{pmatrix}}".format( + return r"\begin{{pmatrix}} {} \\ {} \end{{pmatrix}}".format( " & ".join("%s" % i for i in range(1, len(self._list)+1)), " & ".join("%s" % i for i in self._list)) if display == "list": From 300fa326182d21208bbeddcda5b9428eda4da86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 9 May 2024 20:05:18 +0200 Subject: [PATCH 4/4] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit about code formatting Co-authored-by: Matthias Köppe --- src/sage/combinat/partition.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 146aa6f6c9d..6264548aa23 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -713,8 +713,8 @@ def _repr_exp_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ', '.join('{}{}'.format(m+1, '' if e == 1 else '^%s' % e) - for (m,e) in enumerate(exp) if e > 0) + return '%s' % ', '.join('{}{}'.format(m + 1, '' if e == 1 else '^%s' % e) + for (m,e) in enumerate(exp) if e > 0) def _repr_exp_high(self): """ @@ -751,8 +751,8 @@ def _repr_compact_low(self): if not self._list: return '-' exp = self.to_exp() - return '%s' % ','.join('{}{}'.format(m+1, '' if e == 1 else '^%s' % e) - for (m,e) in enumerate(exp) if e > 0) + return '%s' % ','.join('{}{}'.format(m + 1, '' if e == 1 else '^%s' % e) + for (m,e) in enumerate(exp) if e > 0) def _repr_compact_high(self): """ @@ -770,8 +770,8 @@ def _repr_compact_high(self): return '-' exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return '%s' % ','.join('{}{}'.format(M-m, '' if e == 1 else '^%s' % e) - for (m,e) in enumerate(exp) if e > 0) + return '%s' % ','.join('{}{}'.format(M - m, '' if e == 1 else '^%s' % e) + for (m,e) in enumerate(exp) if e > 0) def _repr_diagram(self): r""" @@ -945,8 +945,8 @@ def _latex_exp_low(self): if not self._list: return "{\\emptyset}" exp = self.to_exp() - return '%s' % ','.join('{}{}'.format(m+1, '' if e == 1 else '^{%s}' % e) - for (m,e) in enumerate(exp) if e > 0) + return '%s' % ','.join('{}{}'.format(m + 1, '' if e == 1 else '^{%s}' % e) + for (m,e) in enumerate(exp) if e > 0) def _latex_exp_high(self): r""" @@ -963,8 +963,8 @@ def _latex_exp_high(self): return "{\\emptyset}" exp = self.to_exp()[::-1] # reversed list of exponents M = max(self) - return '%s' % ','.join('{}{}'.format(M-m, '' if e == 1 else '^{%s}' % e) - for (m,e) in enumerate(exp) if e > 0) + return '%s' % ','.join('{}{}'.format(M - m, '' if e == 1 else '^{%s}' % e) + for (m,e) in enumerate(exp) if e > 0) def ferrers_diagram(self): r""" @@ -4221,7 +4221,7 @@ def rim(self): res = [] prevLen = 1 for i in range(len(p) - 1, -1, -1): - res.extend((i, c) for c in range(prevLen-1, p[i])) + res.extend((i, c) for c in range(prevLen - 1, p[i])) prevLen = p[i] return res