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,65 @@ 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 | list :
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 list of failures
1606+
1607+ OUTPUT:
1608+
1609+ if ``certificate == True``, this outputs a list of tuples
1610+ `(y, x, z)` which fail left-modularity.
1611+
1612+ if ``certificate == False``, this outputs ``False``
1613+ if any `x \in H` fails to be left-modular and ``True`` otherwise.
1614+
1615+ ALGORITHM:
1616+
1617+ Given a lattice `L` and a subset of elements `H`,
1618+ an element `x \in H` is left-modular
1619+ if for every `y,z \in L, y \leq z`
1620+ the equality `(y \vee x) \wedge z = y \vee (x \wedge z)`.
1621+
1622+ .. SEEALSO::
1623+
1624+ - Stronger properties: :meth:`is_trim`
1625+
1626+ EXAMPLES:
1627+
1628+ A lattice that is not left-modular::
1629+
1630+ sage: L = LatticePoset(([1,2,3,4,5],
1631+ ....: [[1,2],[1,3],[3,4],[4,5],[2,5]]))
1632+ sage: L.is_left_modular()
1633+ False
1634+
1635+ A left-modular lattice::
1636+
1637+ sage: L = LatticePoset(([1,2,3,4,5,6],
1638+ ....: [[1,2],[1,3],[3,4],[4,5],[2,5],[2,6],[6,5],[2,4]]))
1639+ sage: L.is_left_modular()
1640+ True
1641+ """
1642+ if H is None :
1643+ H = self
1644+ out = []
1645+ for x in H :
1646+ for z in self :
1647+ mxz = self .meet (x , z )
1648+ for y in self .principal_lower_set (z ):
1649+ if self .join (y , mxz ) != self .meet (self .join (y , x ), z ):
1650+ if not certificate :
1651+ return False
1652+ out .append ((y , x , z ))
1653+ return out if certificate else True
1654+
15801655 def is_complemented (self , certificate = False ) -> bool | tuple :
15811656 r"""
15821657 Return ``True`` if the lattice is complemented, and
0 commit comments