From bc8a4040467f4e2dbc1fc46cb41fc8b5034d5c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 22 Jan 2024 16:09:49 +0100 Subject: [PATCH 1/4] some changes in posets (ruff UP and PERF) --- src/sage/combinat/posets/cartesian_product.py | 2 +- src/sage/combinat/posets/hasse_diagram.py | 25 ++++---- src/sage/combinat/posets/lattices.py | 17 +++--- src/sage/combinat/posets/linear_extensions.py | 4 +- src/sage/combinat/posets/moebius_algebra.py | 6 +- src/sage/combinat/posets/poset_examples.py | 57 +++++++++---------- src/sage/combinat/posets/posets.py | 50 ++++++++-------- 7 files changed, 80 insertions(+), 81 deletions(-) diff --git a/src/sage/combinat/posets/cartesian_product.py b/src/sage/combinat/posets/cartesian_product.py index abf2ec94b4d..42c23732df9 100644 --- a/src/sage/combinat/posets/cartesian_product.py +++ b/src/sage/combinat/posets/cartesian_product.py @@ -102,7 +102,7 @@ def __init__(self, sets, category, order=None, **kwargs): try: self._le_ = getattr(self, 'le_' + order) except AttributeError: - raise ValueError("no order '%s' known" % (order,)) + raise ValueError(f"no order '{order}' known") else: self._le_ = order diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 1c61cee4760..f91bd993d6f 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -67,7 +67,7 @@ def __str__(self): sage: error.__str__() 'no meet for 15 and 18' """ - return "no {} for {} and {}".format(self.fail, self.x, self.y) + return f"no {self.fail} for {self.x} and {self.y}" class HasseDiagram(DiGraph): @@ -792,8 +792,8 @@ def _rank(self): while not_found: y = not_found.pop() rank[y] = 0 # We set some vertex to have rank 0 - component = set([y]) - queue = set([y]) + component = {y} + queue = {y} while queue: # look at the neighbors of y and set the ranks; # then look at the neighbors of the neighbors ... @@ -1286,7 +1286,7 @@ def _leq_storage(self): [{0, 1, 2, 3, 4, 5, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6}] """ n = self.order() - greater_than = [set([i]) for i in range(n)] + greater_than = [{i} for i in range(n)] for i in range(n - 1, -1, -1): gt = greater_than[i] for j in self.neighbor_out_iterator(i): @@ -2481,7 +2481,7 @@ def is_linear_interval(self, t_min, t_max) -> bool: return True return False - def diamonds(self): + def diamonds(self) -> tuple: r""" Return the list of diamonds of ``self``. @@ -2525,8 +2525,7 @@ def diamonds(self): zs = self.common_upper_covers([x, y]) if len(zs) != 1: all_diamonds_completed = False - for z in zs: - diamonds.append((w, x, y, z)) + diamonds.extend((w, x, y, z) for z in zs) return (diamonds, all_diamonds_completed) def common_upper_covers(self, vertices): @@ -2651,7 +2650,7 @@ def sublattices_iterator(self, elms, min_e): if e in elms: continue current_set = set(elms) - gens = set([e]) + gens = {e} while gens: g = gens.pop() if g < e and g not in elms: @@ -2684,7 +2683,7 @@ def sublattice(elms, e): Helper function to get sublattice generated by list of elements. """ - gens_remaining = set([e]) + gens_remaining = {e} current_set = set(elms) while gens_remaining: @@ -2700,7 +2699,7 @@ def sublattice(elms, e): N = self.cardinality() elms = [0] - sublats = [set([0])] + sublats = [{0}] result = [] skip = -1 @@ -2981,7 +2980,7 @@ def neutral_elements(self): return set(range(n)) todo = set(range(1, n - 1)) - neutrals = set([0, n - 1]) + neutrals = {0, n - 1} notneutrals = set() all_elements = set(range(n)) @@ -3242,7 +3241,7 @@ def fill_to_interval(S): for v in fill_to_interval(c): cong.union(r, v) - todo = set(cong.find(e) for part in parts for e in part) + todo = {cong.find(e) for part in parts for e in part} while todo: @@ -3307,7 +3306,7 @@ def fill_to_interval(S): d = jn[d, m] # This removes duplicates from todo. - todo = set(cong.find(x) for x in todo) + todo = {cong.find(x) for x in todo} return cong diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 6af274fd18a..75a3af11e3b 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -3089,11 +3089,10 @@ def vertical_decomposition(self, elements_only=False): self._hasse_diagram.vertical_decomposition(return_list=True) + [self.cardinality() - 1]) n = len(elms) - result = [] - for i in range(n - 1): - result.append(LatticePoset( - self.subposet([self[e] for e in range(elms[i], elms[i + 1] + 1)]))) - return result + return [LatticePoset(self.subposet([self[e] + for e in range(elms[i], + elms[i + 1] + 1)])) + for i in range(n - 1)] def is_vertically_decomposable(self, certificate=False): r""" @@ -3461,8 +3460,8 @@ def frattini_sublattice(self): sage: sorted(L.frattini_sublattice().list()) [1, 2, 4, 10, 19, 22, 33] """ - return LatticePoset(self.subposet([self[x] for x in - self._hasse_diagram.frattini_sublattice()])) + return LatticePoset(self.subposet([self[x] + for x in self._hasse_diagram.frattini_sublattice()])) def moebius_algebra(self, R): """ @@ -3634,9 +3633,9 @@ def adjunct(self, other, a, b): if not isinstance(other, FiniteLatticePoset): raise ValueError("other is not a finite lattice") if not self.is_greater_than(b, a): - raise ValueError("element %s is not greater than %s in the lattice" % (b, a)) + raise ValueError(f"element {b} is not greater than {a} in the lattice") if self.covers(a, b): - raise ValueError("element %s covers element %s in the lattice" % (b, a)) + raise ValueError(f"element {b} covers element {a} in the lattice") if other.cardinality() == 0: return self.relabel(lambda e: (0, e)) diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index cca9b098d4a..736562802f5 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -141,7 +141,7 @@ def check(self): """ P = self.parent().poset() if not P.is_linear_extension(self): - raise ValueError("%s is not a linear extension of %s" % (self, P)) + raise ValueError(f"{self} is not a linear extension of {P}") def poset(self): r""" @@ -625,7 +625,7 @@ def cardinality(self): while K[j]: K.append([b for a in K[j] for b in Jup[a]]) j += 1 - K = sorted(set(item for sublist in K for item in sublist)) + K = sorted({item for sublist in K for item in sublist}) for j in range(len(K)): i = m + j + 1 Jup[i] = [m + K.index(a) + 1 for a in Jup[K[j]]] diff --git a/src/sage/combinat/posets/moebius_algebra.py b/src/sage/combinat/posets/moebius_algebra.py index 00691051587..5a4380e643f 100644 --- a/src/sage/combinat/posets/moebius_algebra.py +++ b/src/sage/combinat/posets/moebius_algebra.py @@ -123,7 +123,7 @@ def _repr_(self): sage: L.moebius_algebra(QQ) Moebius algebra of Finite lattice containing 16 elements over Rational Field """ - return "Moebius algebra of {} over {}".format(self._lattice, self.base_ring()) + return f"Moebius algebra of {self._lattice} over {self.base_ring()}" def a_realization(self): r""" @@ -705,7 +705,7 @@ def _repr_(self): Category of bases of Moebius algebra of Finite lattice containing 16 elements over Rational Field """ - return "Category of bases of {}".format(self.base()) + return f"Category of bases of {self.base()}" def super_categories(self): r""" @@ -738,7 +738,7 @@ def _repr_(self): Moebius algebra of Finite lattice containing 16 elements over Rational Field in the idempotent basis """ - return "{} in the {} basis".format(self.realization_of(), self._basis_name) + return f"{self.realization_of()} in the {self._basis_name} basis" def product_on_basis(self, x, y): """ diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index e166e87b141..0b4a949c27b 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -426,7 +426,7 @@ def DiamondPoset(n, facade=None): """ n = check_int(n, 3) c = [[n - 1] for x in range(n)] - c[0] = [x for x in range(1, n - 1)] + c[0] = list(range(1, n - 1)) c[n - 1] = [] D = DiGraph({v: c[v] for v in range(n)}, format='dict_of_lists') return FiniteLatticePoset(hasse_diagram=D, @@ -719,9 +719,9 @@ def ProductOfChains(chain_lengths, facade=None): try: l = [Integer(x) for x in chain_lengths] except TypeError: - raise TypeError("parameter chain_lengths must be a list of integers, not {0}".format(chain_lengths)) + raise TypeError("parameter chain_lengths must be a list of integers, not {}".format(chain_lengths)) if any(x < 0 for x in l): - raise TypeError("parameter chain_lengths must be a list of nonnegative integers, not {0}".format(l)) + raise TypeError("parameter chain_lengths must be a list of nonnegative integers, not {}".format(l)) # given the empty list, we expect the empty poset. if not chain_lengths: @@ -781,9 +781,9 @@ def RandomPoset(n, p): try: p = float(p) except (TypeError, ValueError): - raise TypeError("probability must be a real number, not {0}".format(p)) + raise TypeError(f"probability must be a real number, not {p}") if p < 0 or p > 1: - raise ValueError("probability must be between 0 and 1, not {0}".format(p)) + raise ValueError(f"probability must be between 0 and 1, not {p}") D = DiGraph(loops=False, multiedges=False) D.add_vertices(range(n)) @@ -867,9 +867,9 @@ def RandomLattice(n, p, properties=None): try: p = float(p) except Exception: - raise TypeError("probability must be a real number, not {0}".format(p)) + raise TypeError(f"probability must be a real number, not {p}") if p < 0 or p >= 1: - raise ValueError("probability must be a positive real number and below 1, not {0}".format(p)) + raise ValueError("probability must be a positive real number and below 1, not {}".format(p)) if properties is None: # Basic case, no special properties for lattice asked. @@ -882,11 +882,11 @@ def RandomLattice(n, p, properties=None): return LatticePoset(D, cover_relations=True) if isinstance(properties, str): - properties = set([properties]) + properties = {properties} else: properties = set(properties) - known_properties = set(['planar', 'dismantlable', 'distributive', 'stone']) + known_properties = {'planar', 'dismantlable', 'distributive', 'stone'} errors = properties.difference(known_properties) if errors: raise ValueError("unknown value %s for 'properties'" % errors.pop()) @@ -907,22 +907,22 @@ def RandomLattice(n, p, properties=None): if 'stone' in properties and len(properties) > 1: raise NotImplementedError("combining 'stone' with other properties is not implemented") - if properties == set(['planar']): + if properties == {'planar'}: D = _random_planar_lattice(n) D.relabel([i - 1 for i in Permutations(n).random_element()]) return LatticePoset(D) - if properties == set(['dismantlable']): + if properties == {'dismantlable'}: D = _random_dismantlable_lattice(n) D.relabel([i - 1 for i in Permutations(n).random_element()]) return LatticePoset(D) - if properties == set(['stone']): + if properties == {'stone'}: D = _random_stone_lattice(n) D.relabel([i - 1 for i in Permutations(n).random_element()]) return LatticePoset(D) - if properties == set(['distributive']): + if properties == {'distributive'}: tmp = Poset(_random_distributive_lattice(n)).order_ideals_lattice(as_ideals=False) D = copy(tmp._hasse_diagram) D.relabel([i - 1 for i in Permutations(n).random_element()]) @@ -1106,18 +1106,17 @@ def SymmetricGroupBruhatIntervalPoset(start, end): start = Permutation(start) end = Permutation(end) if len(start) != len(end): - raise TypeError("start (%s) and end (%s) must have same length" % (start, end)) + raise TypeError(f"start ({start}) and end ({end}) must have same length") if not start.bruhat_lequal(end): - raise TypeError("must have start (%s) <= end (%s) in Bruhat order" % (start, end)) + raise TypeError(f"must have start ({start}) <= end ({end}) in Bruhat order") unseen = [start] nodes = {} while unseen: perm = unseen.pop(0) nodes[perm] = [succ_perm for succ_perm in perm.bruhat_succ() if succ_perm.bruhat_lequal(end)] - for succ_perm in nodes[perm]: - if succ_perm not in nodes: - unseen.append(succ_perm) + unseen.extend(succ_perm for succ_perm in nodes[perm] + if succ_perm not in nodes) return Poset(nodes) @staticmethod @@ -1393,9 +1392,9 @@ def UpDownPoset(n, m=1): try: m = Integer(m) except TypeError: - raise TypeError("parameter m must be an integer, not {0}".format(m)) + raise TypeError(f"parameter m must be an integer, not {m}") if m < 1: - raise ValueError("parameter m must be positive, not {0}".format(m)) + raise ValueError(f"parameter m must be positive, not {m}") covers = [[i, i + 1] if (i + 1) % (m + 1) else [i + 1, i] for i in range(n - 1)] @@ -1681,7 +1680,7 @@ def PermutationPatternInterval(bottom, top): top = P(top) bottom = P(bottom) if not top.has_pattern(bottom): - raise ValueError("{} doesn't contain {} as a pattern".format(top, bottom)) + raise ValueError(f"{top} doesn't contain {bottom} as a pattern") # Make a list of lists of elements in the interval divided by rank. # List will be flattened at the end elem = [[top]] @@ -1833,19 +1832,17 @@ def MobilePoset(ribbon, hangers, anchor=None): elements.extend(ribbon._elements) if anchor: - for cr in anchor[2].cover_relations(): - cover_relations.append(((anchor[0], cr[0]), (anchor[0], cr[1]))) + cover_relations.extend(((anchor[0], cr[0]), (anchor[0], cr[1])) + for cr in anchor[2].cover_relations()) cover_relations.append((anchor[0], (anchor[0], anchor[1]))) - for elmt in anchor[2]._elements: - elements.append((anchor[0], elmt)) + elements.extend((anchor[0], elmt) for elmt in anchor[2]._elements) for r, hangs in hangers.items(): for i, h in enumerate(hangs): - for v in h._elements: - elements.append((r, i, v)) - for cr in h.cover_relations(): - cover_relations.append(((r, i, cr[0]), (r, i, cr[1]))) + elements.extend((r, i, v) for v in h._elements) + cover_relations.extend(((r, i, cr[0]), (r, i, cr[1])) + for cr in h.cover_relations()) cover_relations.append(((r, i, h.top()), r)) return Mobile(DiGraph([elements, cover_relations])) @@ -1896,7 +1893,7 @@ def _random_lattice(n, p): n = n - 1 meets = [[None] * n for _ in range(n)] meets[0][0] = 0 - maxs = set([0]) + maxs = {0} lc_all = [[]] # No lower covers for the bottom element. for i in range(1, n): diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 0a8352274ee..3a8252983e3 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -677,6 +677,13 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio ... ValueError: the provided list of elements is not a linear extension for the poset as it contains duplicate elements + + TESTS:: + + sage: Poset([("a","b","c"),(["a","b","c"])]) + Traceback (most recent call last): + ... + TypeError: not a list of relations """ # Avoiding some errors from the user when data should be a pair if not (element_labels is None or isinstance(element_labels, (dict, list))): @@ -716,17 +723,14 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio else: # type 1 elements, relations = data # check that relations are relations - for r in relations: - try: - u, v = r - except ValueError: - raise TypeError("not a list of relations") + if not all(len(r) == 2 for r in relations): + raise TypeError("not a list of relations") D = DiGraph() D.add_vertices(elements) D.add_edges(relations, loops=False) elif len(data) > 2: # type 3, list/tuple of upper covers - vertices = sorted(set(x for item in data for x in item)) + vertices = sorted({x for item in data for x in item}) if len(vertices) != len(data): # by default, assuming vertices are the range 0..n vertices = range(len(data)) @@ -987,10 +991,10 @@ def __classcall__(cls, hasse_diagram, elements=None, category=None, facade=None, if facade is None: facade = poset in Sets().Facade() if elements is None: - relabel = {i: x for i, x in enumerate(poset._elements)} + relabel = dict(enumerate(poset._elements)) else: elements = tuple(elements) - relabel = {i: x for i, x in enumerate(elements)} + relabel = dict(enumerate(elements)) hasse_diagram = poset._hasse_diagram.relabel(relabel, inplace=False) hasse_diagram = hasse_diagram.copy(immutable=True) else: @@ -2179,7 +2183,7 @@ def cover_relations(self): sage: P.cover_relations() [[1, 2], [0, 2], [2, 3], [3, 4]] """ - return [c for c in self.cover_relations_iterator()] + return list(self.cover_relations_iterator()) @combinatorial_map(name="cover_relations_graph") def cover_relations_graph(self): @@ -4124,7 +4128,7 @@ def upper_covers(self, x): .. SEEALSO:: :meth:`lower_covers` """ - return [e for e in self.upper_covers_iterator(x)] + return list(self.upper_covers_iterator(x)) def lower_covers_iterator(self, x): """ @@ -4159,7 +4163,7 @@ def lower_covers(self, x): .. SEEALSO:: :meth:`upper_covers` """ - return [e for e in self.lower_covers_iterator(x)] + return list(self.lower_covers_iterator(x)) def cardinality(self): """ @@ -4708,7 +4712,7 @@ def isomorphic_subposets(self, other): L = self._hasse_diagram.transitive_closure().subgraph_search_iterator(other._hasse_diagram.transitive_closure(), induced=True, return_graphs=False) # Since subgraph_search_iterator returns labelled copies, we # remove duplicates. - return [self.subposet([self._list[i] for i in x]) for x in sorted(set(frozenset(y) for y in L))] + return [self.subposet([self._list[i] for i in x]) for x in sorted({frozenset(y) for y in L})] # Caveat: list is overridden by the method list above!!! def antichains(self, element_constructor=type([])): @@ -5842,7 +5846,7 @@ def dual(self): elements = reversed(self._elements) else: elements = None - H = self._hasse_diagram.relabel({i: x for i, x in enumerate(self._elements)}, + H = self._hasse_diagram.relabel(dict(enumerate(self._elements)), inplace=False) return self._dual_class(H.reverse(), elements=elements, @@ -6388,7 +6392,7 @@ def subposet(self, elements): TypeError: 'sage.rings.integer.Integer' object is not iterable """ H = self._hasse_diagram - elms = sorted(set(self._element_to_vertex(e) for e in elements)) + elms = sorted({self._element_to_vertex(e) for e in elements}) if not elms: return Poset() @@ -6401,7 +6405,7 @@ def subposet(self, elements): lt[i].update(lt[low]) if i in elms: relations += [(x, i) for x in lt[i]] - lt[i] = set([i]) + lt[i] = {i} g = DiGraph([elms, relations], format='vertices_and_edges') if self._is_facade: @@ -6425,20 +6429,20 @@ def random_subposet(self, p): TESTS:: - sage: P = posets.IntegerPartitions(4) # needs sage.combinat + sage: P = posets.IntegerPartitions(3) # needs sage.combinat sage: P.random_subposet(1) == P # needs sage.combinat True + sage: P.random_subposet(1.41) == P # needs sage.combinat + Traceback (most recent call last): + ... + ValueError: probability p must be in [0..1] """ from sage.misc.randstate import current_randstate random = current_randstate().python_random().random - elements = [] p = float(p) if p < 0 or p > 1: raise ValueError("probability p must be in [0..1]") - for v in self: - if random() <= p: - elements.append(v) - return self.subposet(elements) + return self.subposet([v for v in self if random() <= p]) def random_order_ideal(self, direction='down'): """ @@ -7120,7 +7124,7 @@ def order_complex(self, on_ints=False): from sage.topology.simplicial_complex import SimplicialComplex L = self.list() if on_ints: - iso = dict([(L[i], i) for i in range(len(L))]) + iso = {L[i]: i for i in range(len(L))} facets = [] for f in self.maximal_chains_iterator(): @@ -7129,7 +7133,7 @@ def order_complex(self, on_ints=False): if on_ints: facets.append([iso[a] for a in f]) elif self._is_facade: - facets.append([a for a in f]) + facets.append(list(f)) else: facets.append([a.element for a in f]) From b34ac5f9b0396b5de22e239b5edb5d984486c75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 22 Jan 2024 16:10:33 +0100 Subject: [PATCH 2/4] auto-annotation by ruff --- src/sage/combinat/posets/cartesian_product.py | 2 +- src/sage/combinat/posets/elements.py | 2 +- src/sage/combinat/posets/hasse_diagram.py | 4 ++-- src/sage/combinat/posets/incidence_algebras.py | 4 ++-- src/sage/combinat/posets/linear_extensions.py | 4 ++-- src/sage/combinat/posets/mobile.py | 2 +- src/sage/combinat/posets/moebius_algebra.py | 14 +++++++------- src/sage/combinat/posets/posets.py | 8 ++++---- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sage/combinat/posets/cartesian_product.py b/src/sage/combinat/posets/cartesian_product.py index 42c23732df9..24d763d5831 100644 --- a/src/sage/combinat/posets/cartesian_product.py +++ b/src/sage/combinat/posets/cartesian_product.py @@ -81,7 +81,7 @@ class CartesianProductPoset(CartesianProduct): :class:`CartesianProduct` """ - def __init__(self, sets, category, order=None, **kwargs): + def __init__(self, sets, category, order=None, **kwargs) -> None: r""" See :class:`CartesianProductPoset` for details. diff --git a/src/sage/combinat/posets/elements.py b/src/sage/combinat/posets/elements.py index 4cfb0b28ae0..a15bae281e3 100644 --- a/src/sage/combinat/posets/elements.py +++ b/src/sage/combinat/posets/elements.py @@ -23,7 +23,7 @@ class PosetElement(Element): - def __init__(self, poset, element, vertex): + def __init__(self, poset, element, vertex) -> None: r""" Establish the parent-child relationship between ``poset`` and ``element``, where ``element`` is associated to the diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index f91bd993d6f..7f25f19ce4f 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -40,7 +40,7 @@ class LatticeError(ValueError): a and b" instead of "No meet for 1 and 2". """ - def __init__(self, fail, x, y): + def __init__(self, fail, x, y) -> None: """ Initialize the exception. @@ -56,7 +56,7 @@ def __init__(self, fail, x, y): self.x = x self.y = y - def __str__(self): + def __str__(self) -> str: """ Return string representation of the exception. diff --git a/src/sage/combinat/posets/incidence_algebras.py b/src/sage/combinat/posets/incidence_algebras.py index 943fb69fde9..3fc3f2a0b76 100644 --- a/src/sage/combinat/posets/incidence_algebras.py +++ b/src/sage/combinat/posets/incidence_algebras.py @@ -52,7 +52,7 @@ class IncidenceAlgebra(CombinatorialFreeModule): - :wikipedia:`Incidence_algebra` """ - def __init__(self, R, P, prefix='I'): + def __init__(self, R, P, prefix='I') -> None: """ Initialize ``self``. @@ -438,7 +438,7 @@ class ReducedIncidenceAlgebra(CombinatorialFreeModule): `[x, y]` is isomorphic to `[x', y']` as posets. Thus the delta, Möbius, and zeta functions are all elements of `R_P`. """ - def __init__(self, I, prefix='R'): + def __init__(self, I, prefix='R') -> None: """ Initialize ``self``. diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 736562802f5..8c430e03d41 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -513,7 +513,7 @@ def __classcall_private__(cls, poset, facade=False): """ return super().__classcall__(cls, poset, facade=facade) - def __init__(self, poset, facade): + def __init__(self, poset, facade) -> None: """ TESTS:: @@ -671,7 +671,7 @@ def __iter__(self): for lin_ext in linear_extension_iterator(self._poset._hasse_diagram): yield self._element_constructor_([vertex_to_element(_) for _ in lin_ext]) - def __contains__(self, obj): + def __contains__(self, obj) -> bool: """ Membership testing diff --git a/src/sage/combinat/posets/mobile.py b/src/sage/combinat/posets/mobile.py index 321942a0fd7..5e18f5c4856 100644 --- a/src/sage/combinat/posets/mobile.py +++ b/src/sage/combinat/posets/mobile.py @@ -64,7 +64,7 @@ class MobilePoset(FinitePoset): _lin_ext_type = LinearExtensionsOfMobile _desc = 'Finite mobile poset' - def __init__(self, hasse_diagram, elements, category, facade, key, ribbon=None, check=True): + def __init__(self, hasse_diagram, elements, category, facade, key, ribbon=None, check=True) -> None: r""" Initialize ``self``. diff --git a/src/sage/combinat/posets/moebius_algebra.py b/src/sage/combinat/posets/moebius_algebra.py index 5a4380e643f..5a8074c3272 100644 --- a/src/sage/combinat/posets/moebius_algebra.py +++ b/src/sage/combinat/posets/moebius_algebra.py @@ -96,7 +96,7 @@ class MoebiusAlgebra(Parent, UniqueRepresentation): European Journal of Combinatorics, **19**, 1998. :doi:`10.1006/eujc.1998.0227`. """ - def __init__(self, R, L): + def __init__(self, R, L) -> None: """ Initialize ``self``. @@ -161,7 +161,7 @@ class E(BasisAbstract): Let `E_x` and `E_y` be basis elements of `M_L` for some lattice `L`. Multiplication is given by `E_x E_y = E_{x \vee y}`. """ - def __init__(self, M, prefix='E'): + def __init__(self, M, prefix='E') -> None: """ Initialize ``self``. @@ -242,7 +242,7 @@ class I(BasisAbstract): Multiplication is given by `I_x I_y = \delta_{xy} I_x` where `\delta_{xy}` is the Kronecker delta. """ - def __init__(self, M, prefix='I'): + def __init__(self, M, prefix='I') -> None: """ Initialize ``self``. @@ -381,7 +381,7 @@ class QuantumMoebiusAlgebra(Parent, UniqueRepresentation): \operatorname{rank} L - \operatorname{rank}` a). At `q = 1`, this reduces to the multiplication formula originally given by Solomon. """ - def __init__(self, L, q=None): + def __init__(self, L, q=None) -> None: """ Initialize ``self``. @@ -471,7 +471,7 @@ class E(BasisAbstract): is the corank function (i.e., `\operatorname{crk} a = \operatorname{rank} L - \operatorname{rank}` a). """ - def __init__(self, M, prefix='E'): + def __init__(self, M, prefix='E') -> None: """ Initialize ``self``. @@ -547,7 +547,7 @@ class C(BasisAbstract): filter of `x` and `P(F^x; q)` is the characteristic polynomial of the (sub)poset `F^x`. """ - def __init__(self, M, prefix='C'): + def __init__(self, M, prefix='C') -> None: """ Initialize ``self``. @@ -626,7 +626,7 @@ class KL(BasisAbstract): sage: KL[4] * KL[10] (q+3*q^2+3*q^3+q^4)*KL[14] + (1+4*q+6*q^2+4*q^3+q^4)*KL[15] """ - def __init__(self, M, prefix='KL'): + def __init__(self, M, prefix='KL') -> None: """ Initialize ``self``. diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 3a8252983e3..45142e54423 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -1013,7 +1013,7 @@ def __classcall__(cls, hasse_diagram, elements=None, category=None, facade=None, category=category, facade=facade, key=key) - def __init__(self, hasse_diagram, elements, category, facade, key): + def __init__(self, hasse_diagram, elements, category, facade, key) -> None: r""" EXAMPLES:: @@ -1230,7 +1230,7 @@ def unwrap(self, element): else: return element.element - def __contains__(self, x): + def __contains__(self, x) -> bool: r""" Return ``True`` if ``x`` is an element of the poset. @@ -8909,7 +8909,7 @@ class FinitePosets_n(UniqueRepresentation, Parent): [[1, 2], [0, 2]] """ - def __init__(self, n): + def __init__(self, n) -> None: r""" EXAMPLES:: @@ -8934,7 +8934,7 @@ def _repr_(self): """ return "Posets containing %s elements" % self._n - def __contains__(self, P): + def __contains__(self, P) -> bool: """ EXAMPLES:: From 2266a35ad43768c1d52d82f50878155964e57488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 22 Jan 2024 16:20:53 +0100 Subject: [PATCH 3/4] further details in posets --- src/sage/combinat/posets/hasse_diagram.py | 25 ++++++++++++---------- src/sage/combinat/posets/lattices.py | 2 +- src/sage/combinat/posets/poset_examples.py | 2 +- src/sage/combinat/posets/posets.py | 10 +++++++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 7f25f19ce4f..9fc250802b8 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -1109,11 +1109,11 @@ def moebius_function_matrix(self, algorithm='cython'): m[(i, k)] = -ZZ.sum(m[(j, k)] for j in available if k in greater_than[j]) - M = matrix(ZZ, n, n, m, sparse=True) + M = matrix(ZZ, n, n, m, sparse=True) # noqa: F821 elif algorithm == "matrix": M = self.lequal_matrix().inverse_of_unit() elif algorithm == "cython": - M = moebius_matrix_fast(self._leq_storage) + M = moebius_matrix_fast(self._leq_storage) # noqa: F821 else: raise ValueError("unknown algorithm") self._moebius_function_matrix = M @@ -1187,7 +1187,7 @@ def coxeter_transformation(self, algorithm='cython'): if algorithm == 'matrix': return - self.lequal_matrix() * self.moebius_function_matrix().transpose() elif algorithm == 'cython': - return coxeter_matrix_fast(self._leq_storage) + return coxeter_matrix_fast(self._leq_storage) # noqa: F821 else: raise ValueError("unknown algorithm") @@ -1324,11 +1324,11 @@ def _leq_matrix_boolean(self): Finite Field of size 2 """ n = self.order() - R = GF(2) + R = GF(2) # noqa: F821 one = R.one() greater_than = self._leq_storage D = {(i, j): one for i in range(n) for j in greater_than[i]} - M = matrix(R, n, n, D, sparse=True) + M = matrix(R, n, n, D, sparse=True) # noqa: F821 M.set_immutable() return M @@ -1359,7 +1359,7 @@ def _leq_matrix(self): n = self.order() greater_than = self._leq_storage D = {(i, j): 1 for i in range(n) for j in greater_than[i]} - return matrix(ZZ, n, n, D, sparse=True, immutable=True) + return matrix(ZZ, n, n, D, sparse=True, immutable=True) # noqa: F821 def lequal_matrix(self, boolean=False): r""" @@ -1544,7 +1544,7 @@ def _meet(self): self._meet_semilattice_failure = () n = self.cardinality() if n == 0: - return matrix(0) + return matrix(0) # noqa: F821 meet = [[-1 for x in range(n)] for x in range(n)] lc = [self.neighbors_in(x) for x in range(n)] # Lc = lower covers @@ -1564,7 +1564,7 @@ def _meet(self): meet[y][x] = q if q == -1: self._meet_semilattice_failure += ((x, y),) - return matrix(ZZ, meet) + return matrix(ZZ, meet) # noqa: F821 def meet_matrix(self): r""" @@ -1708,7 +1708,7 @@ def _join(self): self._join_semilattice_failure = () n = self.cardinality() if n == 0: - return matrix(0) + return matrix(0) # noqa: F821 join = [[-1 for x in range(n)] for x in range(n)] uc = [self.neighbors_out(x) for x in range(n)] # uc = upper covers @@ -1729,7 +1729,7 @@ def _join(self): if q == -1: self._join_semilattice_failure += ((x, y),) - return matrix(ZZ, join) + return matrix(ZZ, join) # noqa: F821 def join_matrix(self): r""" @@ -3143,7 +3143,7 @@ def atoms_of_congruence_lattice(self): return min_congruences - def congruence(self, parts, start=None, stop_pairs=[]): + def congruence(self, parts, start=None, stop_pairs=None): """ Return the congruence ``start`` "extended" by ``parts``. @@ -3207,6 +3207,9 @@ def congruence(self, parts, start=None, stop_pairs=[]): from sage.sets.disjoint_set import DisjointSet from copy import copy + if stop_pairs is None: + stop_pairs = [] + n = self.order() mt = self.meet_matrix() jn = self.join_matrix() diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 75a3af11e3b..10f1746e5e1 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -2003,7 +2003,7 @@ def join(L): return (B, [self._vertex_to_element(e) for e in A]) else: return B - assert False, "BUG: breadth() in lattices.py have an error." + raise RuntimeError("BUG: breadth() in lattices.py have an error") def complements(self, element=None): r""" diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 0b4a949c27b..6a0e57a8887 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1550,7 +1550,7 @@ def YoungFibonacci(n): covers = [] current_level = [''] - for i in range(1, n + 1): + for _ in range(1, n + 1): new_level = set() for low in current_level: ind = low.find('1') diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 45142e54423..36f4d1eee10 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -4715,7 +4715,7 @@ def isomorphic_subposets(self, other): return [self.subposet([self._list[i] for i in x]) for x in sorted({frozenset(y) for y in L})] # Caveat: list is overridden by the method list above!!! - def antichains(self, element_constructor=type([])): + def antichains(self, element_constructor=None): """ Return the antichains of the poset. @@ -4779,6 +4779,9 @@ def antichains(self, element_constructor=type([])): """ vertex_to_element = self._vertex_to_element + if element_constructor is None: + element_constructor = list + def f(antichain): return element_constructor(vertex_to_element(x) for x in antichain) result = self._hasse_diagram.antichains(element_class=f) @@ -4921,7 +4924,7 @@ def dilworth_decomposition(self): chains.append(chain) return chains - def chains(self, element_constructor=type([]), exclude=None): + def chains(self, element_constructor=None, exclude=None): """ Return the chains of the poset. @@ -4969,6 +4972,9 @@ def chains(self, element_constructor=type([]), exclude=None): .. SEEALSO:: :meth:`maximal_chains`, :meth:`antichains` """ + if element_constructor is None: + element_constructor = list + if exclude is not None: exclude = [self._element_to_vertex(x) for x in exclude] result = self._hasse_diagram.chains(element_class=element_constructor, From b41465df81a467dd6cb4a17f842dc18199830835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 26 Jan 2024 10:36:41 +0100 Subject: [PATCH 4/4] a few more details in posets --- src/sage/combinat/posets/hasse_diagram.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 9fc250802b8..9f46877aa0e 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -1857,9 +1857,8 @@ def find_nonsemidistributive_elements(self, meet_or_join): for x in range(n): u = M1[e, x] for y in range(x): - if u == M1[e, y]: - if u != M1[e, M2[x, y]]: - return (u, e, x, y) + if u == M1[e, y] and u != M1[e, M2[x, y]]: + return (u, e, x, y) return None @@ -2151,9 +2150,8 @@ def recursive_fit(orthocomplements, unbinded): # Every element might have one possible orthocomplement, # but so that they don't fit together. Must check that. for lc in self.lower_covers_iterator(e): - if start[lc] is not None: - if not self.has_edge(e_, start[lc]): - return + if not (start[lc] is None or self.has_edge(e_, start[lc])): + return if start[e_] is None: start[e] = e_ start[e_] = e @@ -2191,10 +2189,7 @@ def find_nonsemimodular_pair(self, upper): sage: H_.find_nonsemimodular_pair(upper=False) is None True """ - if upper: - neighbors = self.neighbors_out - else: - neighbors = self.neighbors_in + neighbors = self.neighbors_out if upper else self.neighbors_in n = self.order() for e in range(n):