Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
trac #15428: cell_poset methods on partitions and skew partitions
Browse files Browse the repository at this point in the history
  • Loading branch information
darijgr committed Dec 27, 2013
1 parent 036984d commit 6812b87
Show file tree
Hide file tree
Showing 2 changed files with 321 additions and 1 deletion.
193 changes: 192 additions & 1 deletion src/sage/combinat/partition.py
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,197 @@ def down_list(self):
"""
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
Expand Down Expand Up @@ -5171,7 +5362,7 @@ def random_element_uniform(self):
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:
Expand Down
129 changes: 129 additions & 0 deletions src/sage/combinat/skew_partition.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,135 @@ def inner_corners(self):
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``.
Expand Down

0 comments on commit 6812b87

Please sign in to comment.