Skip to content

Commit 273073b

Browse files
author
Release Manager
committed
gh-40719: implement the method "is_left_modular" for lattices extracted from #37601 ### 📝 Checklist - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. URL: #40719 Reported by: Frédéric Chapoton Reviewer(s): Martin Rubey
2 parents 8aed6f7 + fd7eab7 commit 273073b

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

src/sage/combinat/posets/lattices.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
:meth:`~FiniteLatticePoset.is_planar` | Return ``True`` if the lattice has an upward planar drawing.
6363
:meth:`~FiniteLatticePoset.is_dismantlable` | Return ``True`` if the lattice is dismantlable.
6464
:meth:`~FiniteLatticePoset.is_interval_dismantlable` | Return ``True`` if the lattice is interval dismantlable.
65+
:meth:`~FiniteLatticePoset.is_left_modular` | Return ``True`` if the lattice is left_modular.
6566
:meth:`~FiniteLatticePoset.is_sublattice_dismantlable` | Return ``True`` if the lattice is sublattice dismantlable.
6667
:meth:`~FiniteLatticePoset.is_stone` | Return ``True`` if the lattice is a Stone lattice.
6768
:meth:`~FiniteLatticePoset.is_trim` | Return ``True`` if the lattice is a trim lattice.
@@ -1557,9 +1558,24 @@ def is_trim(self, certificate=False) -> bool | tuple:
15571558
sage: LatticePoset({1:[]}).is_trim(True)
15581559
(True, [1])
15591560
1561+
Testing a trim lattice ::
1562+
1563+
sage: L = LatticePoset(([1,2,3,4,5,6],
1564+
....: [[1,2],[1,3],[3,4],[4,5],[2,5],[2,6],[6,5],[2,4]]))
1565+
sage: L.is_trim(True)
1566+
(True, [1, 2, 6, 5])
1567+
1568+
Testing a lattice which is not trim ::
1569+
1570+
sage: L = LatticePoset(([1,2,3,4,5,6],
1571+
....: [[1,2],[1,3],[3,4],[4,5],[2,5],[2,6],[6,5]]))
1572+
sage: L.is_trim(True)
1573+
(False, None)
1574+
15601575
.. SEEALSO::
15611576
15621577
- Weaker properties: :meth:`is_extremal`
1578+
- Weaker properties: :meth:`is_left_modular`
15631579
- Stronger properties: :meth:`is_distributive`
15641580
15651581
REFERENCES:
@@ -1577,6 +1593,72 @@ def is_trim(self, certificate=False) -> bool | tuple:
15771593
return (True, chain) if certificate else True
15781594
return (False, None) if certificate else False
15791595

1596+
def is_left_modular(self, H=None, certificate=False) -> bool | tuple:
1597+
r"""
1598+
Return whether ``self`` is a left-modular lattice.
1599+
1600+
INPUT:
1601+
1602+
- ``H`` -- subset of elements; full ``self`` if no ``H`` is given
1603+
1604+
- ``certificate`` -- boolean (default: ``False``); whether to return
1605+
a failure
1606+
1607+
OUTPUT:
1608+
1609+
if ``certificate == True``, this returns either ``(True, None)``
1610+
or ``(False, (y, x, z))`` where the tuple `(y, x, z)`
1611+
fails left-modularity.
1612+
1613+
if ``certificate == False``, this returns ``False`` if any
1614+
`x \in H` fails to be left-modular and ``True`` otherwise.
1615+
1616+
ALGORITHM:
1617+
1618+
Given a lattice `L` and a subset of elements `H`,
1619+
an element `x \in H` is left-modular
1620+
if for every `y,z \in L, y \leq z`
1621+
we have `(y \vee x) \wedge z = y \vee (x \wedge z)`.
1622+
1623+
.. SEEALSO::
1624+
1625+
- Stronger properties: :meth:`is_trim`
1626+
1627+
- :meth:`is_left_modular_element`
1628+
1629+
EXAMPLES:
1630+
1631+
A lattice that is not left-modular::
1632+
1633+
sage: L = LatticePoset(([1,2,3,4,5],
1634+
....: [[1,2],[1,3],[3,4],[4,5],[2,5]]))
1635+
sage: L.is_left_modular()
1636+
False
1637+
1638+
A left-modular lattice::
1639+
1640+
sage: L = LatticePoset(([1,2,3,4,5,6],
1641+
....: [[1,2],[1,3],[3,4],[4,5],[2,5],[2,6],[6,5],[2,4]]))
1642+
sage: L.is_left_modular()
1643+
True
1644+
1645+
TESTS::
1646+
1647+
sage: L = LatticePoset(([1,2,3,4,5],
1648+
....: [[1,2],[1,3],[3,4],[4,5],[2,5]]))
1649+
sage: L.is_left_modular(certificate=True)
1650+
(False, (3, 2, 4))
1651+
"""
1652+
if H is None:
1653+
H = self
1654+
for x in H:
1655+
for z in self:
1656+
mxz = self.meet(x, z)
1657+
for y in self.lower_covers_iterator(z):
1658+
if self.join(y, mxz) != self.meet(self.join(y, x), z):
1659+
return False if not certificate else (False, (y, x, z))
1660+
return (True, None) if certificate else True
1661+
15801662
def is_complemented(self, certificate=False) -> bool | tuple:
15811663
r"""
15821664
Return ``True`` if the lattice is complemented, and
@@ -2716,6 +2798,8 @@ def is_left_modular_element(self, x) -> bool:
27162798
.. SEEALSO::
27172799
27182800
- Stronger properties: :meth:`is_modular_element`
2801+
2802+
- :meth:`is_left_modular`
27192803
"""
27202804
return all(self.meet(self.join(y, x), z) ==
27212805
self.join(y, self.meet(x, z))

0 commit comments

Comments
 (0)