Ticket #15428: trac_15428-partition-posets-dg.patch

File trac_15428-partition-posets-dg.patch, 14.8 KB (added by darij, 7 years ago)

updated version

• sage/combinat/partition.py

```# HG changeset patch
# User darij grinberg <darijgrinberg@gmail.com>
# Date 1386341511 28800
# Node ID ea57dc7a6a8d01de503b8de2e4e763e8fed9068a
# Parent  d54cbe14f5be80106485d1c7cae772f65efb1f26
trac #15428: partitions to posets

diff --git a/sage/combinat/partition.py b/sage/combinat/partition.py```
 a class Partition(CombinatorialObject, Ele """ return [p for p in self.down()] def cell_poset(self, orientation="SE"): """ Return the Young diagram of ``self`` as a poset. The optional keyword variable ``orientation`` determines the order relation of the poset. The poset always uses the set of cells of the Young diagram of ``self`` as its ground set. The order relation of the poset depends on the ``orientation`` variable (which defaults to ``"SE"``). Concretely, ``orientation`` has to be specified to one of the strings ``"NW"``, ``"NE"``, ``"SW"``, and ``"SE"``, standing for "northwest", "northeast", "southwest" and "southeast", respectively. If ``orientation`` is ``"SE"``, then the order relation of the poset is such that a cell `u` is greater or equal to a cell `v` in the poset if and only if `u` lies weakly southeast of `v` (this means that `u` can be reached from `v` by a sequence of south and east steps; the sequence is allowed to consist of south steps only, or of east steps only, or even be empty). Similarly the order relation is defined for the other three orientations. The Young diagram is supposed to be drawn in English notation. The elements of the poset are the cells of the Young diagram of ``self``, written as tuples of zero-based coordinates (so that `(3, 7)` stands for the `8`-th cell of the `4`-th row, etc.). EXAMPLES:: sage: p = Partition([3,3,1]) sage: Q = p.cell_poset(); Q Finite poset containing 7 elements sage: sorted(Q) [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0)] sage: sorted(Q.maximal_elements()) [(1, 2), (2, 0)] sage: Q.minimal_elements() [(0, 0)] sage: sorted(Q.upper_covers((1, 0))) [(1, 1), (2, 0)] sage: Q.upper_covers((1, 1)) [(1, 2)] sage: P = p.cell_poset(orientation="NW"); P Finite poset containing 7 elements sage: sorted(P) [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0)] sage: sorted(P.minimal_elements()) [(1, 2), (2, 0)] sage: P.maximal_elements() [(0, 0)] sage: P.upper_covers((2, 0)) [(1, 0)] sage: sorted(P.upper_covers((1, 2))) [(0, 2), (1, 1)] sage: sorted(P.upper_covers((1, 1))) [(0, 1), (1, 0)] sage: sorted([len(P.upper_covers(v)) for v in P]) [0, 1, 1, 1, 1, 2, 2] sage: R = p.cell_poset(orientation="NE"); R Finite poset containing 7 elements sage: sorted(R) [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0)] sage: R.maximal_elements() [(0, 2)] sage: R.minimal_elements() [(2, 0)] sage: sorted([len(R.upper_covers(v)) for v in R]) [0, 1, 1, 1, 1, 2, 2] sage: R.is_isomorphic(P) False sage: R.is_isomorphic(P.dual()) False Linear extensions of ``p.cell_poset()`` are in 1-to-1 correspondence with standard Young tableaux of shape `p`:: sage: all( len(p.cell_poset().linear_extensions()) ....:      == len(p.standard_tableaux()) ....:      for n in range(8) for p in Partitions(n) ) True This is not the case for northeast orientation:: sage: q = Partition([3, 1]) sage: q.cell_poset(orientation="NE").is_chain() True TESTS: We check that the posets are really what they should be for size up to `7`:: sage: def check_NW(n): ....:     for p in Partitions(n): ....:         P = p.cell_poset(orientation="NW") ....:         for c in p.cells(): ....:             for d in p.cells(): ....:                 if P.le(c, d) != (c[0] >= d[0] ....:                                   and c[1] >= d[1]): ....:                     return False ....:     return True sage: all( check_NW(n) for n in range(8) ) True sage: def check_NE(n): ....:     for p in Partitions(n): ....:         P = p.cell_poset(orientation="NE") ....:         for c in p.cells(): ....:             for d in p.cells(): ....:                 if P.le(c, d) != (c[0] >= d[0] ....:                                   and c[1] <= d[1]): ....:                     return False ....:     return True sage: all( check_NE(n) for n in range(8) ) True sage: def test_duality(n, ori1, ori2): ....:     for p in Partitions(n): ....:         P = p.cell_poset(orientation=ori1) ....:         Q = p.cell_poset(orientation=ori2) ....:         for c in p.cells(): ....:             for d in p.cells(): ....:                 if P.lt(c, d) != Q.lt(d, c): ....:                     return False ....:     return True sage: all( test_duality(n, "NW", "SE") for n in range(8) ) True sage: all( test_duality(n, "NE", "SW") for n in range(8) ) True sage: all( test_duality(n, "NE", "SE") for n in range(4) ) False """ from sage.combinat.posets.posets import Poset covers = {} if orientation == "NW": for i, row in enumerate(self): if i == 0: covers[(0, 0)] = [] for j in range(1, row): covers[(0, j)] = [(0, j - 1)] else: covers[(i, 0)] = [(i - 1, 0)] for j in range(1, row): covers[(i, j)] = [(i - 1, j), (i, j - 1)] elif orientation == "NE": for i, row in enumerate(self): if i == 0: covers[(0, row - 1)] = [] for j in range(row - 1): covers[(0, j)] = [(0, j + 1)] else: covers[(i, row - 1)] = [(i - 1, row - 1)] for j in range(row - 1): covers[(i, j)] = [(i - 1, j), (i, j + 1)] elif orientation == "SE": l = len(self) - 1 for i, row in enumerate(self): if i == l: covers[(i, row - 1)] = [] for j in range(row - 1): covers[(i, j)] = [(i, j + 1)] else: next_row = self[i + 1] if row == next_row: covers[(i, row - 1)] = [(i + 1, row - 1)] for j in range(row - 1): covers[(i, j)] = [(i + 1, j), (i, j + 1)] else: covers[(i, row - 1)] = [] for j in range(next_row): covers[(i, j)] = [(i + 1, j), (i, j + 1)] for j in range(next_row, row - 1): covers[(i, j)] = [(i, j + 1)] elif orientation == "SW": l = len(self) - 1 for i, row in enumerate(self): if i == l: covers[(i, 0)] = [] for j in range(1, row): covers[(i, j)] = [(i, j - 1)] else: covers[(i, 0)] = [(i + 1, 0)] next_row = self[i + 1] for j in range(1, next_row): covers[(i, j)] = [(i + 1, j), (i, j - 1)] for j in range(next_row, row): covers[(i, j)] = [(i, j - 1)] return Poset(covers) def frobenius_coordinates(self): """ Return a pair of sequences of Frobenius coordinates aka beta numbers class Partitions_n(Partitions): TESTS:: sage: all(Part.random_element_uniform() in Part ...       for Part in map(Partitions, range(10))) ....:     for Part in map(Partitions, range(10))) True ALGORITHM:
• sage/combinat/skew_partition.py

`diff --git a/sage/combinat/skew_partition.py b/sage/combinat/skew_partition.py`
 a class SkewPartition(CombinatorialObject, icorners += [(nn, 0)] return icorners def cell_poset(self, orientation="SE"): """ Return the Young diagram of ``self`` as a poset. The optional keyword variable ``orientation`` determines the order relation of the poset. The poset always uses the set of cells of the Young diagram of ``self`` as its ground set. The order relation of the poset depends on the ``orientation`` variable (which defaults to ``"SE"``). Concretely, ``orientation`` has to be specified to one of the strings ``"NW"``, ``"NE"``, ``"SW"``, and ``"SE"``, standing for "northwest", "northeast", "southwest" and "southeast", respectively. If ``orientation`` is ``"SE"``, then the order relation of the poset is such that a cell `u` is greater or equal to a cell `v` in the poset if and only if `u` lies weakly southeast of `v` (this means that `u` can be reached from `v` by a sequence of south and east steps; the sequence is allowed to consist of south steps only, or of east steps only, or even be empty). Similarly the order relation is defined for the other three orientations. The Young diagram is supposed to be drawn in English notation. The elements of the poset are the cells of the Young diagram of ``self``, written as tuples of zero-based coordinates (so that `(3, 7)` stands for the `8`-th cell of the `4`-th row, etc.). EXAMPLES:: sage: p = SkewPartition([[3,3,1], [2,1]]) sage: Q = p.cell_poset(); Q Finite poset containing 4 elements sage: sorted(Q) [(0, 2), (1, 1), (1, 2), (2, 0)] sage: sorted(Q.maximal_elements()) [(1, 2), (2, 0)] sage: sorted(Q.minimal_elements()) [(0, 2), (1, 1), (2, 0)] sage: sorted(Q.upper_covers((1, 1))) [(1, 2)] sage: sorted(Q.upper_covers((0, 2))) [(1, 2)] sage: P = p.cell_poset(orientation="NW"); P Finite poset containing 4 elements sage: sorted(P) [(0, 2), (1, 1), (1, 2), (2, 0)] sage: sorted(P.minimal_elements()) [(1, 2), (2, 0)] sage: sorted(P.maximal_elements()) [(0, 2), (1, 1), (2, 0)] sage: sorted(P.upper_covers((1, 2))) [(0, 2), (1, 1)] sage: R = p.cell_poset(orientation="NE"); R Finite poset containing 4 elements sage: sorted(R) [(0, 2), (1, 1), (1, 2), (2, 0)] sage: R.maximal_elements() [(0, 2)] sage: R.minimal_elements() [(2, 0)] sage: R.upper_covers((2, 0)) [(1, 1)] sage: sorted([len(R.upper_covers(v)) for v in R]) [0, 1, 1, 1] TESTS: We check that the posets are really what they should be for size up to `6`:: sage: def check_NW(n): ....:     for p in SkewPartitions(n): ....:         P = p.cell_poset(orientation="NW") ....:         for c in p.cells(): ....:             for d in p.cells(): ....:                 if P.le(c, d) != (c[0] >= d[0] ....:                                   and c[1] >= d[1]): ....:                     return False ....:     return True sage: all( check_NW(n) for n in range(7) ) True sage: def check_NE(n): ....:     for p in SkewPartitions(n): ....:         P = p.cell_poset(orientation="NE") ....:         for c in p.cells(): ....:             for d in p.cells(): ....:                 if P.le(c, d) != (c[0] >= d[0] ....:                                   and c[1] <= d[1]): ....:                     return False ....:     return True sage: all( check_NE(n) for n in range(7) ) True sage: def test_duality(n, ori1, ori2): ....:     for p in SkewPartitions(n): ....:         P = p.cell_poset(orientation=ori1) ....:         Q = p.cell_poset(orientation=ori2) ....:         for c in p.cells(): ....:             for d in p.cells(): ....:                 if P.lt(c, d) != Q.lt(d, c): ....:                     return False ....:     return True sage: all( test_duality(n, "NW", "SE") for n in range(7) ) True sage: all( test_duality(n, "NE", "SW") for n in range(7) ) True sage: all( test_duality(n, "NE", "SE") for n in range(4) ) False """ from sage.combinat.posets.posets import Poset # Getting the cover relations seems hard, so let's just compute # the comparison function. if orientation == "NW": def poset_le(u, v): return u[0] >= v[0] and u[1] >= v[1] elif orientation == "NE": def poset_le(u, v): return u[0] >= v[0] and u[1] <= v[1] elif orientation == "SE": def poset_le(u, v): return u[0] <= v[0] and u[1] <= v[1] elif orientation == "SW": def poset_le(u, v): return u[0] <= v[0] and u[1] >= v[1] return Poset((self.cells(), poset_le)) def frobenius_rank(self): r""" Return the Frobenius rank of the skew partition ``self``.