| 1406 | def cell_poset(self, orientation="SE"): |
| 1407 | """ |
| 1408 | Return the Young diagram of ``self`` as a poset. The optional |
| 1409 | keyword variable ``orientation`` determines the order relation |
| 1410 | of the poset. |
| 1411 | |
| 1412 | The poset always uses the set of cells of the Young diagram |
| 1413 | of ``self`` as its ground set. The order relation of the poset |
| 1414 | depends on the ``orientation`` variable (which defaults to |
| 1415 | ``"SE"``). Concretely, ``orientation`` has to be specified to |
| 1416 | one of the strings ``"NW"``, ``"NE"``, ``"SW"``, and ``"SE"``, |
| 1417 | standing for "northwest", "northeast", "southwest" and |
| 1418 | "southeast", respectively. If ``orientation`` is ``"SE"``, then |
| 1419 | the order relation of the poset is such that a cell `u` is |
| 1420 | greater or equal to a cell `v` in the poset if and only if `u` |
| 1421 | lies weakly southeast of `v` (this means that `u` can be |
| 1422 | reached from `v` by a sequence of south and east steps; the |
| 1423 | sequence is allowed to consist of south steps only, or of east |
| 1424 | steps only, or even be empty). Similarly the order relation is |
| 1425 | defined for the other three orientations. The Young diagram is |
| 1426 | supposed to be drawn in English notation. |
| 1427 | |
| 1428 | The elements of the poset are the cells of the Young diagram |
| 1429 | of ``self``, written as tuples of zero-based coordinates (so |
| 1430 | that `(3, 7)` stands for the `8`-th cell of the `4`-th row, |
| 1431 | etc.). |
| 1432 | |
| 1433 | EXAMPLES:: |
| 1434 | |
| 1435 | sage: p = Partition([3,3,1]) |
| 1436 | sage: Q = p.cell_poset(); Q |
| 1437 | Finite poset containing 7 elements |
| 1438 | sage: sorted(Q) |
| 1439 | [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0)] |
| 1440 | sage: sorted(Q.maximal_elements()) |
| 1441 | [(1, 2), (2, 0)] |
| 1442 | sage: Q.minimal_elements() |
| 1443 | [(0, 0)] |
| 1444 | sage: sorted(Q.upper_covers((1, 0))) |
| 1445 | [(1, 1), (2, 0)] |
| 1446 | sage: Q.upper_covers((1, 1)) |
| 1447 | [(1, 2)] |
| 1448 | |
| 1449 | sage: P = p.cell_poset(orientation="NW"); P |
| 1450 | Finite poset containing 7 elements |
| 1451 | sage: sorted(P) |
| 1452 | [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0)] |
| 1453 | sage: sorted(P.minimal_elements()) |
| 1454 | [(1, 2), (2, 0)] |
| 1455 | sage: P.maximal_elements() |
| 1456 | [(0, 0)] |
| 1457 | sage: P.upper_covers((2, 0)) |
| 1458 | [(1, 0)] |
| 1459 | sage: sorted(P.upper_covers((1, 2))) |
| 1460 | [(0, 2), (1, 1)] |
| 1461 | sage: sorted(P.upper_covers((1, 1))) |
| 1462 | [(0, 1), (1, 0)] |
| 1463 | sage: sorted([len(P.upper_covers(v)) for v in P]) |
| 1464 | [0, 1, 1, 1, 1, 2, 2] |
| 1465 | |
| 1466 | sage: R = p.cell_poset(orientation="NE"); R |
| 1467 | Finite poset containing 7 elements |
| 1468 | sage: sorted(R) |
| 1469 | [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0)] |
| 1470 | sage: R.maximal_elements() |
| 1471 | [(0, 2)] |
| 1472 | sage: R.minimal_elements() |
| 1473 | [(2, 0)] |
| 1474 | sage: sorted([len(R.upper_covers(v)) for v in R]) |
| 1475 | [0, 1, 1, 1, 1, 2, 2] |
| 1476 | sage: R.is_isomorphic(P) |
| 1477 | False |
| 1478 | sage: R.is_isomorphic(P.dual()) |
| 1479 | False |
| 1480 | |
| 1481 | Linear extensions of ``p.cell_poset()`` are in 1-to-1 correspondence |
| 1482 | with standard Young tableaux of shape `p`:: |
| 1483 | |
| 1484 | sage: all( len(p.cell_poset().linear_extensions()) |
| 1485 | ....: == len(p.standard_tableaux()) |
| 1486 | ....: for n in range(8) for p in Partitions(n) ) |
| 1487 | True |
| 1488 | |
| 1489 | This is not the case for northeast orientation:: |
| 1490 | |
| 1491 | sage: q = Partition([3, 1]) |
| 1492 | sage: q.cell_poset(orientation="NE").is_chain() |
| 1493 | True |
| 1494 | |
| 1495 | TESTS: |
| 1496 | |
| 1497 | We check that the posets are really what they should be for size |
| 1498 | up to `7`:: |
| 1499 | |
| 1500 | sage: def check_NW(n): |
| 1501 | ....: for p in Partitions(n): |
| 1502 | ....: P = p.cell_poset(orientation="NW") |
| 1503 | ....: for c in p.cells(): |
| 1504 | ....: for d in p.cells(): |
| 1505 | ....: if P.le(c, d) != (c[0] >= d[0] |
| 1506 | ....: and c[1] >= d[1]): |
| 1507 | ....: return False |
| 1508 | ....: return True |
| 1509 | sage: all( check_NW(n) for n in range(8) ) |
| 1510 | True |
| 1511 | |
| 1512 | sage: def check_NE(n): |
| 1513 | ....: for p in Partitions(n): |
| 1514 | ....: P = p.cell_poset(orientation="NE") |
| 1515 | ....: for c in p.cells(): |
| 1516 | ....: for d in p.cells(): |
| 1517 | ....: if P.le(c, d) != (c[0] >= d[0] |
| 1518 | ....: and c[1] <= d[1]): |
| 1519 | ....: return False |
| 1520 | ....: return True |
| 1521 | sage: all( check_NE(n) for n in range(8) ) |
| 1522 | True |
| 1523 | |
| 1524 | sage: def test_duality(n, ori1, ori2): |
| 1525 | ....: for p in Partitions(n): |
| 1526 | ....: P = p.cell_poset(orientation=ori1) |
| 1527 | ....: Q = p.cell_poset(orientation=ori2) |
| 1528 | ....: for c in p.cells(): |
| 1529 | ....: for d in p.cells(): |
| 1530 | ....: if P.lt(c, d) != Q.lt(d, c): |
| 1531 | ....: return False |
| 1532 | ....: return True |
| 1533 | sage: all( test_duality(n, "NW", "SE") for n in range(8) ) |
| 1534 | True |
| 1535 | sage: all( test_duality(n, "NE", "SW") for n in range(8) ) |
| 1536 | True |
| 1537 | sage: all( test_duality(n, "NE", "SE") for n in range(4) ) |
| 1538 | False |
| 1539 | """ |
| 1540 | from sage.combinat.posets.posets import Poset |
| 1541 | covers = {} |
| 1542 | if orientation == "NW": |
| 1543 | for i, row in enumerate(self): |
| 1544 | if i == 0: |
| 1545 | covers[(0, 0)] = [] |
| 1546 | for j in range(1, row): |
| 1547 | covers[(0, j)] = [(0, j - 1)] |
| 1548 | else: |
| 1549 | covers[(i, 0)] = [(i - 1, 0)] |
| 1550 | for j in range(1, row): |
| 1551 | covers[(i, j)] = [(i - 1, j), (i, j - 1)] |
| 1552 | elif orientation == "NE": |
| 1553 | for i, row in enumerate(self): |
| 1554 | if i == 0: |
| 1555 | covers[(0, row - 1)] = [] |
| 1556 | for j in range(row - 1): |
| 1557 | covers[(0, j)] = [(0, j + 1)] |
| 1558 | else: |
| 1559 | covers[(i, row - 1)] = [(i - 1, row - 1)] |
| 1560 | for j in range(row - 1): |
| 1561 | covers[(i, j)] = [(i - 1, j), (i, j + 1)] |
| 1562 | elif orientation == "SE": |
| 1563 | l = len(self) - 1 |
| 1564 | for i, row in enumerate(self): |
| 1565 | if i == l: |
| 1566 | covers[(i, row - 1)] = [] |
| 1567 | for j in range(row - 1): |
| 1568 | covers[(i, j)] = [(i, j + 1)] |
| 1569 | else: |
| 1570 | next_row = self[i + 1] |
| 1571 | if row == next_row: |
| 1572 | covers[(i, row - 1)] = [(i + 1, row - 1)] |
| 1573 | for j in range(row - 1): |
| 1574 | covers[(i, j)] = [(i + 1, j), (i, j + 1)] |
| 1575 | else: |
| 1576 | covers[(i, row - 1)] = [] |
| 1577 | for j in range(next_row): |
| 1578 | covers[(i, j)] = [(i + 1, j), (i, j + 1)] |
| 1579 | for j in range(next_row, row - 1): |
| 1580 | covers[(i, j)] = [(i, j + 1)] |
| 1581 | elif orientation == "SW": |
| 1582 | l = len(self) - 1 |
| 1583 | for i, row in enumerate(self): |
| 1584 | if i == l: |
| 1585 | covers[(i, 0)] = [] |
| 1586 | for j in range(1, row): |
| 1587 | covers[(i, j)] = [(i, j - 1)] |
| 1588 | else: |
| 1589 | covers[(i, 0)] = [(i + 1, 0)] |
| 1590 | next_row = self[i + 1] |
| 1591 | for j in range(1, next_row): |
| 1592 | covers[(i, j)] = [(i + 1, j), (i, j - 1)] |
| 1593 | for j in range(next_row, row): |
| 1594 | covers[(i, j)] = [(i, j - 1)] |
| 1595 | return Poset(covers) |
| 1596 | |