diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 1f1cd007290..351e7397d51 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -130,6 +130,10 @@ REFERENCES: and T. Yalcin, *Block ciphers - focus on the linear layer (feat. PRIDE)*; in CRYPTO, (2014), pp. 57-76. +.. [ADMNT2025] Ilani Axelrod-Freed, Colin Defant, Hanna Mularczyk, + Son Nguyen and Katherine Tung, *Chute Move Posets are + Lattices*. :arXiv:`2507.13214` + .. [ABBS2013] \J.-C Aval, A. Boussicault, M. Bouvel, M. Silimbani, *Combinatorics of non-ambiguous trees*, :arxiv:`1305.3716` @@ -487,6 +491,10 @@ REFERENCES: :arxiv:`1110.4275`, :doi:`10.1007/s13366-011-0084-0`. +.. [BB1993] Nantel Bergeron and Sara Billey, *RC-graphs and Schubert + polynomials*. Experiment. Math. **2** (1993), no. 4, + 257-269. + .. [BB1997] Mladen Bestvina and Noel Brady. *Morse theory and finiteness properties of groups*. Invent. Math. **129** (1997). No. 3, @@ -584,6 +592,10 @@ REFERENCES: Electronic Journal of Combinatorics 18(2), 2011. :doi:`10.37236/2027` +.. [BMM2025] Sara Billey, Connor McCausland and Clare Minnerath, *A + Proof of Rubey's Lattice Conjecture*. + :arXiv:`2507.18852`. + .. [BPPSST2017] Banik, Pandey, Peyrin, Sasaki, Sim, and Todo, GIFT : A Small Present Towards Reaching the Limit of Lightweight Encryption. *Cryptographic Hardware and Embedded Systems - CHES 2017*, @@ -2426,8 +2438,8 @@ REFERENCES: .. [DP2011] \B. Deconinck and M. S. Patterson, *Computing with plane algebraic curves and Riemann surfaces: The algorithms of the Maple package - "Algcurves"*, In: A. Bobenko and C. Klein (eds) Computational - approach to Riemann surfaces. Lecture Notes in Mathematics 2013. + "Algcurves"*, In: A. Bobenko and C. Klein (eds) Computational + approach to Riemann surfaces. Lecture Notes in Mathematics 2013. Springer, Berlin, Heidelberg. (2011). :doi:`10.1007/978-3-642-17413-1_2` @@ -2584,7 +2596,7 @@ REFERENCES: .. [Eh2013] Ehrhardt, Wolfgang. *The AMath and DAMath Special Functions: Reference Manual and Implementation Notes*, - Version 1.3. 2013. + Version 1.3. 2013. https://web.archive.org/web/20131210061646/http://www.wolfgang-ehrhardt.de/specialfunctions.pdf. .. [EL2002] Ekedahl, Torsten & Laksov, Dan. (2002). *Splitting algebras, Symmetric functions and @@ -5257,7 +5269,7 @@ REFERENCES: Inventiones Mathematicae **84**, (1986), 1-48. .. [MT2001] B. Mojar and C. Thomassen. *Graphs on Surfaces*. - Johns Hopkins University Press, (2001). ISBN 9780801866890. + Johns Hopkins University Press, (2001). ISBN 9780801866890. .. [Mu1997] Murty, M. Ram. *Congruences between modular forms*. In "Analytic Number Theory" (ed. Y. Motohashi), London Math. Soc. Lecture Notes @@ -5270,7 +5282,7 @@ REFERENCES: .. [Mur1983] \G. E. Murphy. *The idempotents of the symmetric group and Nakayama's conjecture*. J. Algebra **81** (1983). 258-265. -.. [Mus2023] Yossef Musleh. *Algorithms for Drinfeld Modules*. +.. [Mus2023] Yossef Musleh. *Algorithms for Drinfeld Modules*. PhD thesis, University of Waterloo, 2023. .. [Muth2019] Robert Muth. *Super RSK correspondence with symmetry*. @@ -5945,6 +5957,11 @@ REFERENCES: imaginary quadratic fields. Invent. Math. 103 (1991), no. 1, 25--68. +.. [Rub2011] Martin Rubey, *Maximal 0–1-fillings of moon polyominoes + with restricted chain lengths and RC-graphs*. Adv. in + Appl. Math. **48** (2012), no. 2, + 290-305. :arXiv:`1009.3919` + .. [RS2010] RUBIN, K., & SILVERBERG, A. (2010). CHOOSING THE CORRECT ELLIPTIC CURVE IN THE CM METHOD. Mathematics of Computation, 79(269), 545-561. :doi:`10.1090/S0025-5718-09-02266-2` diff --git a/src/sage/combinat/posets/chute_move.py b/src/sage/combinat/posets/chute_move.py new file mode 100644 index 00000000000..9c528552420 --- /dev/null +++ b/src/sage/combinat/posets/chute_move.py @@ -0,0 +1,169 @@ +r""" +Chute move lattices + +Chute move posets were defined by Rubey in [Rub2011]_ as a +generalization of the chute and ladder posets of Bergeron and Billey +[BB1993]_. They were shown to be lattices independently by Sara +Billey, Connor McCausland and Clare Minnerath in [BMM2025]_ and by +Ilani Axelrod-Freed, Colin Defant, Hanna Mularczyk, Son Nguyen and +Katherine Tung in [ADMNT2025]_. +""" +from sage.categories.finite_lattice_posets import FiniteLatticePosets +from sage.combinat.permutation import Permutation +from sage.combinat.posets.lattices import LatticePoset +from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet +from sage.structure.sage_object import SageObject + + +def intervals_to_polyomino(intervals): + M = set() + for x, interval in enumerate(intervals, 1): + low, high = interval + assert low <= high, f"interval={interval} is not a proper interval" + M.update((x, y) for y in range(low, high + 1)) + return sorted(M) + + +class PolyominoFilling(SageObject): + def __init__(self, P, F): + self._P = tuple(sorted(P)) + self._F = tuple(sorted(F)) + + def __hash__(self): + return hash((self._P, self._F)) + + def __eq__(self, other): + return self._P == other._P and self._F == other._F + + def _repr_(self): + return f"shape={self._P}, filling={self._F}" + + def _latex_(self): + draw_grid_lines = True, + stroke_width = "" # very thin" + bullet_tex = r"\bullet" + cell_size = 0.5 + + from sage.misc.latex import latex + latex.add_package_to_preamble_if_available("tikz") + + # bounding box + xs = [x for x,_ in self._P] + ys = [y for _,y in self._P] + minx, maxx = min(xs), max(xs) + miny, maxy = min(ys), max(ys) + + # shift so lower-left is (0,0) + shift_x = -minx + shift_y = -miny + width = maxx - minx + 1 + height = maxy - miny + 1 + + # Build TikZ code + tikz_lines = [] + tikz_lines.append(r"\begin{tikzpicture}[x=%scm,y=%scm]" % (cell_size, cell_size)) + tikz_lines.append(r" \path[use as bounding box] (0,0) rectangle (%d,%d);" % (width, height)) + # Draw each cell as a unit square at shifted coordinates + if draw_grid_lines: + for (x, y) in self._P: + sx, sy = x + shift_x, y + shift_y + tikz_lines.append(f" \\draw[{stroke_width}] ({sx},{sy}) rectangle ({sx+1},{sy+1});") + else: + for (x, y) in self._P: + sx, sy = x + shift_x, y + shift_y + tikz_lines.append(f" \\fill[white] ({sx},{sy}) rectangle ({sx+1},{sy+1});") + + for (x, y) in self._F: + sx, sy = x + shift_x, y + shift_y + tikz_lines.append(f" \\node at ({sx+0.5},{sy+0.5}) {{${bullet_tex}$}};") + + tikz_lines.append(r"\end{tikzpicture}") + return "\n".join(tikz_lines) + + +def ChuteMoveLattice(M, n=None): + r""" + Return the chute move lattice. + + INPUT: + + - ``M`` -- a permutation, or an L-convex polyomino + - ``n`` -- a positive integer, if ``M`` is a polyomino, or ``None`` + + EXAMPLES:: + + sage: from sage.combinat.posets.chute_move import intervals_to_polyomino + sage: M = intervals_to_polyomino([(1,4),(1,3),(1,2),(1,1)]) + sage: L = posets.ChuteMoveLattice(M, 1); L + Finite lattice containing 5 elements + + sage: from sage.combinat.tamari_lattices import GeneralizedTamariLattice + sage: b = 4; m = 2; T = GeneralizedTamariLattice(m*b+1,b,m=2) + sage: C = posets.ChuteMoveLattice(Permutation([1,8,6,4,2,3,5,7])) + sage: C.is_isomorphic(T) + True + """ + from sage.groups.perm_gps.permgroup_element import SymmetricGroupElement + if isinstance(M, SymmetricGroupElement): + M = Permutation(M) + + if isinstance(M, Permutation): + n = len(M) + Minv = M.inverse() + + def above_left(j): + return sum(M(i) > j for i in range(1, Minv(j))) + + top = tuple([(j, c) + for j in range(1, n + 1) + for c in range(1 + above_left(j), n + 2 - j)]) + M = intervals_to_polyomino([(1, n - i) for i in range(n)]) + else: + boundary_cells = [(x, y) for x, y in M + if (x-1, y) not in M or (x, y+1) not in M or (x-1, y+1) not in M] + top = tuple(sorted(set((cx, cy) + for x, y in boundary_cells + for cx in range(x, x + n) + for cy in range(y - n + 1, y + 1) + if (cx, cy) in M))) + + def chutable(i, l): + # Return the other coordinate, if ``l[i]`` is a chutable + # coordinate and the result is in ``M``, otherwise ``False``. + + # the rectangle is given (in Cartesian coordinates) by + # a,d - c,d + # | | + # a,b - c,b + # with a < c and d < b + a, b = l[i] + # (a, b) must not be the first or last element of l + # the predecessor (a, d) of (a, b) must have same x coordinate + i -= 1 + a1, d = l[i] + if a1 != a: + return + + # the first element within the rectangle must be (c, b) + i += 2 + c, b1 = l[i] + while i + 1 < len(l) and (c == a or b1 < d or b1 > b): + i += 1 + c, b1 = l[i] + + if i >= len(l) or b1 != b or (c, d) not in M: + return + + return c, d + + def children(l): + return [tuple(sorted(l[:i] + (c,) + l[i+1:])) + for i in range(1, len(l)-1) + if (c := chutable(i, l)) is not None] + + S = RecursivelyEnumeratedSet([top], children, + structure=None, enumeration="naive") + d = {PolyominoFilling(M, f): [PolyominoFilling(M, g) for g in children(f)] + for f in S} + cat = FiniteLatticePosets().CongruenceUniform() + return LatticePoset(d, category=cat) diff --git a/src/sage/combinat/posets/meson.build b/src/sage/combinat/posets/meson.build index 32c323c9dd0..51dce3e59eb 100644 --- a/src/sage/combinat/posets/meson.build +++ b/src/sage/combinat/posets/meson.build @@ -2,6 +2,7 @@ py.install_sources( '__init__.py', 'all.py', 'bubble_shuffle.py', + 'chute_move.py', 'cartesian_product.py', 'd_complete.py', 'elements.py', diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index d8bb880d360..73546040488 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -102,7 +102,7 @@ import sage.categories.posets from sage.combinat.permutation import Permutations, Permutation, to_standard from sage.combinat.posets.posets import Poset, FinitePoset, FinitePosets_n -from sage.combinat.posets import bubble_shuffle, hochschild_lattice +from sage.combinat.posets import bubble_shuffle, hochschild_lattice, chute_move from sage.combinat.posets.d_complete import DCompletePoset from sage.combinat.posets.mobile import MobilePoset as Mobile from sage.combinat.posets.lattices import (LatticePoset, MeetSemilattice, @@ -290,6 +290,8 @@ def BooleanLattice(n, facade=None, use_subsets=False): HochschildLattice = staticmethod(hochschild_lattice.hochschild_lattice) + ChuteMoveLattice = staticmethod(chute_move.ChuteMoveLattice) + @staticmethod def ChainPoset(n, facade=None): r"""