예제 #1
0
    def BooleanLattice(n, facade=None):
        """
        Return the Boolean lattice containing `2^n` elements.

        - ``n`` (an integer) -- number of elements will be `2^n`
        - ``facade`` (boolean) -- whether to make the returned poset a
          facade poset (see :mod:`sage.categories.facade_sets`); the
          default behaviour is the same as the default behaviour of
          the :func:`~sage.combinat.posets.posets.Poset` constructor

        EXAMPLES::

            sage: Posets.BooleanLattice(5)
            Finite lattice containing 32 elements
        """
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError(
                "number of elements must be non-negative, not {0}".format(n))
        if n == 0:
            return LatticePoset(([0], []))
        if n == 1:
            return LatticePoset(([0, 1], [[0, 1]]))
        return LatticePoset(
            [[Integer(x | (1 << y)) for y in range(0, n) if x & (1 << y) == 0]
             for x in range(0, 2**n)],
            facade=facade)
예제 #2
0
        def order_ideals_lattice(self, as_ideals=True):
            r"""
            Returns the lattice of order ideals of a poset `P`,
            ordered by inclusion. The usual notation is `J(P)`.

            The underlying set is by default the set of order ideals
            of `P`. It can be alternatively chosen to be the set of
            antichains of `P`.

            INPUT:

            - ``as_ideals`` -- Boolean, if ``True`` (default) returns
              a poset on the set of order ideals, otherwise on the set
              of antichains

            EXAMPLES::

                sage: P = Posets.PentagonPoset(facade = True)
                sage: P.cover_relations()
                [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]]
                sage: J = P.order_ideals_lattice(); J
                Finite lattice containing 8 elements
                sage: list(J)
                [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}]

            As a lattice on antichains::

                sage: J2 = P.order_ideals_lattice(False); J2
                Finite lattice containing 8 elements
                sage: list(J2)
                [(0,), (1, 2), (1, 3), (1,), (2,), (3,), (4,), ()]

            TESTS::

                sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J
                Finite lattice containing 6 elements
                sage: list(J)
                [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}]
                sage: J.cover_relations()
                [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]]

            .. NOTE:: we use facade posets in the examples above just
               to ensure a nicer ordering in the output.
            """
            from sage.combinat.posets.lattices import LatticePoset
            if as_ideals:
                from sage.misc.misc import attrcall
                from sage.sets.set import Set
                ideals = [Set( self.order_ideal(antichain) ) for antichain in self.antichains()]
                return LatticePoset((ideals,attrcall("issubset")))
            else:
                from sage.misc.cachefunc import cached_function
                antichains = [tuple(a) for a in self.antichains()]
                @cached_function
                def is_above(a,xb):
                    return any(self.is_lequal(xa,xb) for xa in a)
                def cmp(a,b):
                    return all(is_above(a,xb) for xb in b)
                return LatticePoset((antichains,cmp))
예제 #3
0
        def order_ideals_lattice(self):
            r"""
            Returns the lattice of order ideals of a poset `P`,
            ordered by inclusion. The usual notation is `J(P)`.

            EXAMPLES::

                sage: P = Posets.PentagonPoset(facade = True)
                sage: P.cover_relations()
                [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]]
                sage: J = P.order_ideals_lattice(); J
                Finite lattice containing 8 elements
                sage: list(J)
                [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}]

            TESTS::

                sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J
                Finite lattice containing 6 elements
                sage: list(J)
                [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}]
                sage: J.cover_relations()
                [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]]

            .. note:: we use facade posets in the examples above just
               to ensure a nicer ordering in the output.
            """
            from sage.misc.misc import attrcall
            from sage.sets.set import Set
            from sage.combinat.posets.lattices import LatticePoset
            ideals = [
                Set(self.order_ideal(antichain))
                for antichain in self.antichains()
            ]
            return LatticePoset((ideals, attrcall("issubset")))
예제 #4
0
    def ChainPoset(n):
        """
        Returns a chain (a totally ordered poset) containing ``n`` elements.

        EXAMPLES::

            sage: C = Posets.ChainPoset(6); C
            Finite lattice containing 6 elements
            sage: C.linear_extension()
            [0, 1, 2, 3, 4, 5]
            sage: for i in range(5):
            ...       for j in range(5):
            ...           if C.covers(C(i),C(j)) and j != i+1:
            ...              print "TEST FAILED"

        TESTS:

        Check that #8422 is solved::

            sage: Posets.ChainPoset(0)
            Finite lattice containing 0 elements
            sage: C = Posets.ChainPoset(1); C
            Finite lattice containing 1 elements
            sage: C.cover_relations()
            []
            sage: C = Posets.ChainPoset(2); C
            Finite lattice containing 2 elements
            sage: C.cover_relations()
            [[0, 1]]
        """
        return LatticePoset((range(n), [[x,x+1] for x in range(n-1)]))
예제 #5
0
    def PentagonPoset(facade=False):
        """
        Returns the "pentagon poset".

        EXAMPLES::

            sage: P = Posets.PentagonPoset(); P
            Finite lattice containing 5 elements
            sage: P.cover_relations()
            [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]]

        This lattice and the diamond poset on 5 elements are the two
        smallest lattices which are not distributive::

            sage: P.is_distributive()
            False
            sage: Posets.DiamondPoset(5).is_distributive()
            False
        """
        p = LatticePoset([[1, 2], [4], [3], [4], []], facade=facade)
        p.hasse_diagram()._pos = {
            0: [2, 0],
            1: [0, 2],
            2: [3, 1],
            3: [3, 3],
            4: [2, 4]
        }
        return p
예제 #6
0
    def DiamondPoset(n, facade=None):
        """
        Return the lattice of rank two containing ``n`` elements.

        INPUT:

        - ``n`` - number of vertices, an integer at least 3.

        - ``facade`` (boolean) -- whether to make the returned poset a
          facade poset (see :mod:`sage.categories.facade_sets`). The
          default behaviour is the same as the default behaviour of
          the :func:`~sage.combinat.posets.posets.Poset` constructor).

        EXAMPLES::

            sage: Posets.DiamondPoset(7)
            Finite lattice containing 7 elements
        """
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n <= 2:
            raise ValueError("n must be an integer at least 3")
        c = [[n - 1] for x in range(n)]
        c[0] = [x for x in range(1, n - 1)]
        c[n - 1] = []
        return LatticePoset(c, facade=facade)
예제 #7
0
        def face_lattice(self, facade=False):
            r"""
            Returns the (big) face lattice.

            The *(big) face lattice* is the (big) face poset with a top element
            added.

            EXAMPLES::

                sage: from oriented_matroids import OrientedMatroid
                sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1],
                ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0],
                ....: [0,0,0]]
                sage: M = OrientedMatroid(C, key='covector')
                sage: M.face_lattice()
                Finite lattice containing 14 elements
            """
            from sage.combinat.posets.lattices import LatticePoset
            els = self.covectors()
            rels = [
                (Y, X) for X in els for Y in els
                if Y.is_conformal_with(X) and Y.support().issubset(X.support())
            ]

            # Add top element
            for i in els:
                rels.append((i, 1))
            els.append(1)
            return LatticePoset((els, rels),
                                cover_relations=False,
                                facade=facade)
예제 #8
0
    def PentagonPoset(facade = None):
        """
        Returns the Pentagon poset.

        INPUT:

        - ``facade`` (boolean) -- whether to make the returned poset a
          facade poset (see :mod:`sage.categories.facade_sets`). The
          default behaviour is the same as the default behaviour of
          the :func:`~sage.combinat.posets.posets.Poset` constructor).

        EXAMPLES::

            sage: P = Posets.PentagonPoset(); P
            Finite lattice containing 5 elements
            sage: P.cover_relations()
            [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]]

        This is smallest lattice that is not modular::

            sage: P.is_modular()
            False

        This poset and the :meth:`DiamondPoset` are the two smallest
        lattices which are not distributive::

            sage: P.is_distributive()
            False
            sage: Posets.DiamondPoset(5).is_distributive()
            False
        """
        p = LatticePoset([[1,2],[4],[3],[4],[]], facade = facade)
        p.hasse_diagram()._pos = {0:[2,0],1:[0,2],2:[3,1],3:[3,3],4:[2,4]}
        return p
예제 #9
0
        def shard_poset(self, side='right'):
            """
            Return the shard intersection order attached to `W`.

            This is a lattice structure on `W`, introduced in [Reading]_. It
            contains the noncrossing partition lattice, as the induced lattice
            on the subset of `c`-sortable elements.

            The partial order is given by simultaneous inclusion of inversion sets
            and subgroups attached to every element.

            The precise description used here can be found in [StThWi]_.

            Another implementation for the symmetric groups is
            available as :func:`~sage.combinat.shard_order.shard_poset`.

            .. SEEALSO::

                :meth:`bhz_poset`, :meth:`bruhat_poset`, :meth:`weak_poset`

            EXAMPLES::

                sage: W = CoxeterGroup(['A',3], base_ring=ZZ)
                sage: SH = W.shard_poset(); SH
                Finite lattice containing 24 elements
                sage: SH.is_graded()
                True
                sage: SH.characteristic_polynomial()
                q^3 - 11*q^2 + 23*q - 13
                sage: SH.f_polynomial()
                34*q^3 + 22*q^2 + q

            REFERENCES:

            .. [Reading] Nathan Reading, *Noncrossing partitions and the shard
               intersection order*, DMTCS Proceedings of FPSAC 2009, 745--756

            .. [StThWi] Christian Stump, Hugh Thomas and Nathan Williams,
               *Cataland: why the fuss?*, :arxiv:`1503.00710`
            """
            from sage.combinat.posets.lattices import LatticePoset
            data = {
                w:
                (frozenset(u.lift() for u in w.covered_reflections_subgroup()),
                 frozenset((~w).inversions_as_reflections()))
                for w in self
            }

            def shard_comparison(u, v):
                Gu, Nu = data[u]
                Gv, Nv = data[v]
                return Gu.issubset(Gv) and Nu.issubset(Nv)

            return LatticePoset([self, shard_comparison])
예제 #10
0
    def BooleanLattice(n):
        """
        Returns the Boolean lattice containing `2^n` elements.

        EXAMPLES::

            sage: Posets.BooleanLattice(5)
            Finite lattice containing 32 elements
        """
        return LatticePoset([[Integer(x|(1<<y)) for y in range(0,n) if x&(1<<y)==0] for
            x in range(0,2**n)])
예제 #11
0
    def lattice(self):
        r"""
        Return the lattice of the monotone triangles with `n` rows.

        EXAMPLES::

            sage: M = MonotoneTriangles(3)
            sage: P = M.lattice()
            sage: P
            Finite lattice containing 7 elements

        """
        return LatticePoset(self._lattice_initializer(), cover_relations=True)
예제 #12
0
    def lattice(self):
        r"""
        Return the lattice of the alternating sign matrices of size
        `n`, created by ``LatticePoset``.

        EXAMPLES::

            sage: A = AlternatingSignMatrices(3)
            sage: L = A.lattice()
            sage: L
            Finite lattice containing 7 elements

        """
        return LatticePoset(self._lattice_initializer(), cover_relations=True)
예제 #13
0
            def test_composition_series_poset(self):
                """
                Sanity checks for a for regular left/right class

                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ); M
                    Free module generated by Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication over Rational Field
                    sage: M.test_composition_series_poset()
                """
                S = self.semigroup()
                R = self.basis().keys()
                composition_series_poset = self.composition_series_poset()
                assert composition_series_poset.is_meet_semilattice()
                #annihilator_poset = self.annihilator_poset()
                #annihilator_poset_dual = annihilator_poset.dual()
                #f = lambda J: annihilator_poset_dual(self.annihilator_with_apex(J))
                #assert composition_series_poset.is_poset_isomorphism(f, annihilator_poset_dual)

                # Dimension checks
                for J in self.composition_series():
                    assert self.annihilator_with_apex(J).dimension() == S.lr_regular_class(J, side=R.side()).cardinality()

                assert self.dimension() == sum(S.simple_module_dimension(J) for J in self.composition_series())

                # That can't work with the current definition of annihilator_module_with_apex.
                # j_poset = S.j_poset_on_regular_classes()
                # f = lambda J: composition_series_poset(self.annihilator_module_with_apex(J).apex())
                # assert j_poset.is_poset_morphism(f, composition_series_poset)

                return

                assert composition_series_poset.is_lattice()
                from sage.combinat.posets.lattices import LatticePoset
                composition_lattice = LatticePoset(composition_series_poset)
                # annihilator_poset = LatticePoset(annihilator_poset)

                # Check that self.annihilator_module_with_apex is a
                # lattice morphism from the composition poset to the
                # lattice of submodules of self. This is similar to
                # the above isomorphism test with the
                # annihilator_poset, except that we enforce that the
                # meet on submodules is given by intersection.

                f = lambda J: self.annihilator_module_with_apex(J)
                L = composition_lattice
                for J1 in self.composition_series():
                    for J2 in self.composition_series():
                        assert f(J1).intersection(f(J2)) == f( L.join(L(J1), L(J2)) )
예제 #14
0
    def BooleanLattice(n):
        """
        Returns the Boolean lattice containing `2^n` elements.

        EXAMPLES::

            sage: Posets.BooleanLattice(5)
            Finite lattice containing 32 elements
        """
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError(
                "number of elements must be non-negative, not {0}".format(n))
        if n == 0:
            return LatticePoset(([0], []))
        if n == 1:
            return LatticePoset(([0, 1], [[0, 1]]))
        return LatticePoset(
            [[Integer(x | (1 << y)) for y in range(0, n) if x & (1 << y) == 0]
             for x in range(0, 2**n)])
예제 #15
0
    def DiamondPoset(n, facade=False):
        """
        Returns the lattice of rank two containing ``n`` elements.

        EXAMPLES::

            sage: Posets.DiamondPoset(7)
            Finite lattice containing 7 elements
        """
        c = [[n - 1] for x in range(n)]
        c[0] = [x for x in range(1, n - 1)]
        c[n - 1] = []
        if n > 2:
            return LatticePoset(c, facade=facade)
        else:
            return Poset(c, facade=facade)
예제 #16
0
    def ChainPoset(n, facade=None):
        """
        Return a chain (a totally ordered poset) containing ``n`` elements.

        - ``n`` (an integer) -- number of elements.
        - ``facade`` (boolean) -- whether to make the returned poset a
          facade poset (see :mod:`sage.categories.facade_sets`); the
          default behaviour is the same as the default behaviour of
          the :func:`~sage.combinat.posets.posets.Poset` constructor

        EXAMPLES::

            sage: C = Posets.ChainPoset(6); C
            Finite lattice containing 6 elements
            sage: C.linear_extension()
            [0, 1, 2, 3, 4, 5]

        TESTS::

            sage: for i in range(5):
            ....:     for j in range(5):
            ....:         if C.covers(C(i),C(j)) and j != i+1:
            ....:             print("TEST FAILED")

        Check that :trac:`8422` is solved::

            sage: Posets.ChainPoset(0)
            Finite lattice containing 0 elements
            sage: C = Posets.ChainPoset(1); C
            Finite lattice containing 1 elements
            sage: C.cover_relations()
            []
            sage: C = Posets.ChainPoset(2); C
            Finite lattice containing 2 elements
            sage: C.cover_relations()
            [[0, 1]]
        """
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError(
                "number of elements must be non-negative, not {0}".format(n))
        return LatticePoset((range(n), [[x, x + 1] for x in range(n - 1)]),
                            facade=facade)
예제 #17
0
    def YoungsLatticePrincipalOrderIdeal(lam):
        """
        Return the principal order ideal of the
        partition `lam` in Young's Lattice.

        INPUT:

        - ``lam`` -- a partition

        EXAMPLES::

            sage: P = Posets.YoungsLatticePrincipalOrderIdeal(Partition([2,2]))
            sage: P
            Finite lattice containing 6 elements
            sage: P.cover_relations()
            [[[], [1]],
             [[1], [1, 1]],
             [[1], [2]],
             [[1, 1], [2, 1]],
             [[2], [2, 1]],
             [[2, 1], [2, 2]]]
        """
        from sage.misc.flatten import flatten
        from sage.combinat.partition import Partition

        def lower_covers(l):
            """
            Nested function returning those partitions obtained
            from the partition `l` by removing
            a single cell.
            """
            return [l.remove_cell(c[0], c[1]) for c in l.removable_cells()]

        def contained_partitions(l):
            """
            Nested function returning those partitions contained in
            the partition `l`
            """
            if l == Partition([]):
                return l
            return flatten(
                [l, [contained_partitions(m) for m in lower_covers(l)]])

        ideal = list(set(contained_partitions(lam)))
        H = DiGraph(dict([[p, lower_covers(p)] for p in ideal]))
        return LatticePoset(H.reverse())
예제 #18
0
    def __classcall_private__(cls, R, L):
        """
        Normalize input to ensure a unique representation.

        TESTS::

            sage: L1 = posets.BooleanLattice(4)
            sage: L2 = posets.BooleanLattice(4, facade=False)
            sage: L1 is L2
            False
            sage: M1 = L1.moebius_algebra(QQ)
            sage: M2 = L2.moebius_algebra(QQ)
            sage: M1 is M2
            True
        """
        # We force the lattice to not be a facade in order to guarantee
        #   that the ordering of the poset is used (see #21054).
        L = LatticePoset(L, facade=False)
        return super(MoebiusAlgebra, cls).__classcall__(cls, R, L)
예제 #19
0
    def SetPartitions(n):
        r"""
        Return the lattice of set partitions of the set `\{1,\ldots,n\}`
        ordered by refinement.

        INPUT:

        - ``n`` -- a positive integer

        EXAMPLES::

            sage: Posets.SetPartitions(4)
            Finite lattice containing 15 elements
        """
        from sage.rings.semirings.non_negative_integer_semiring import NN
        if n not in NN:
            raise ValueError('n must be an integer')
        from sage.combinat.set_partition import SetPartitions
        S = SetPartitions(n)
        return LatticePoset((S, S.is_less_than))
예제 #20
0
    def DivisorLattice(n, facade=None):
        """
        Return the divisor lattice of an integer.

        Elements of the lattice are divisors of `n` and
        `x < y` in the lattice if `x` divides `y`.

        INPUT:

        - ``n`` -- an integer
        - ``facade`` (boolean) -- whether to make the returned poset a
          facade poset (see :mod:`sage.categories.facade_sets`); the
          default behaviour is the same as the default behaviour of
          the :func:`~sage.combinat.posets.posets.Poset` constructor

        EXAMPLES::

            sage: P = Posets.DivisorLattice(12)
            sage: sorted(P.cover_relations())
            [[1, 2], [1, 3], [2, 4], [2, 6], [3, 6], [4, 12], [6, 12]]

            sage: P = Posets.DivisorLattice(10, facade=False)
            sage: P(2) < P(5)
            False

        TESTS::

            sage: Posets.DivisorLattice(1)
            Finite lattice containing 1 elements
        """
        from sage.arith.misc import divisors
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n <= 0:
            raise ValueError("n must be a positive integer")
        return LatticePoset((divisors(n), lambda x, y: y % x == 0),
                            facade=facade,
                            linear_extension=True)
예제 #21
0
    def ChainPoset(n):
        """
        Returns a chain (a totally ordered poset) containing ``n`` elements.

        EXAMPLES::

            sage: C = Posets.ChainPoset(6); C
            Finite lattice containing 6 elements
            sage: C.linear_extension()
            [0, 1, 2, 3, 4, 5]

        TESTS::

            sage: for i in range(5):
            ....:     for j in range(5):
            ....:         if C.covers(C(i),C(j)) and j != i+1:
            ....:             print "TEST FAILED"

        Check that :trac:`8422` is solved::

            sage: Posets.ChainPoset(0)
            Finite lattice containing 0 elements
            sage: C = Posets.ChainPoset(1); C
            Finite lattice containing 1 elements
            sage: C.cover_relations()
            []
            sage: C = Posets.ChainPoset(2); C
            Finite lattice containing 2 elements
            sage: C.cover_relations()
            [[0, 1]]
        """
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError(
                "number of elements must be non-negative, not {0}".format(n))
        return LatticePoset((range(n), [[x, x + 1] for x in range(n - 1)]))
예제 #22
0
    def IntegerPartitionsDominanceOrder(n):
        r"""
        Return the poset of integer partitions on the integer `n`
        ordered by dominance.

        That is, if `p=(p_1,\ldots,p_i)` and `q=(q_1,\ldots,q_j)` are
        integer partitions of `n`, then `p` is greater than `q` if and
        only if `p_1+\cdots+p_k > q_1+\cdots+q_k` for all `k`.

        INPUT:

        - ``n`` -- a positive integer

        EXAMPLES::

            sage: P = Posets.IntegerPartitionsDominanceOrder(6); P
            Finite lattice containing 11 elements
            sage: P.cover_relations()
            [[[1, 1, 1, 1, 1, 1], [2, 1, 1, 1, 1]],
             [[2, 1, 1, 1, 1], [2, 2, 1, 1]],
             [[2, 2, 1, 1], [2, 2, 2]],
             [[2, 2, 1, 1], [3, 1, 1, 1]],
             [[2, 2, 2], [3, 2, 1]],
             [[3, 1, 1, 1], [3, 2, 1]],
             [[3, 2, 1], [3, 3]],
             [[3, 2, 1], [4, 1, 1]],
             [[3, 3], [4, 2]],
             [[4, 1, 1], [4, 2]],
             [[4, 2], [5, 1]],
             [[5, 1], [6]]]
        """
        from sage.rings.semirings.non_negative_integer_semiring import NN
        if n not in NN:
            raise ValueError('n must be an integer')
        from sage.combinat.partition import Partitions, Partition
        return LatticePoset((Partitions(n), Partition.dominates)).dual()
예제 #23
0
 def support_lattice(self):
     from sage.combinat.posets.lattices import LatticePoset
     return LatticePoset(self.j_poset())
예제 #24
0
        def weak_poset(self, side = "right", facade = False):
            """
            INPUT:

            - ``side`` -- "left", "right", or "twosided" (default: "right")
            - ``facade`` -- a boolean (default: ``False``)

            Returns the left (resp. right) poset for weak order.  In
            this poset, `u` is smaller than `v` if some reduced word
            of `u` is a right (resp. left) factor of some reduced word
            of `v`.

            EXAMPLES::

                sage: W = WeylGroup(["A", 2])
                sage: P = W.weak_poset()
                sage: P
                Finite lattice containing 6 elements
                sage: P.show()

            This poset is in fact a lattice::

                sage: W = WeylGroup(["B", 3])
                sage: P = W.weak_poset(side = "left")
                sage: P.is_lattice()
                True

            so this method has an alias :meth:`weak_lattice`::

                sage: W.weak_lattice(side = "left") is W.weak_poset(side = "left")
                True

            As a bonus feature, one can create the left-right weak
            poset::

                sage: W = WeylGroup(["A",2])
                sage: P = W.weak_poset(side = "twosided")
                sage: P.show()
                sage: len(P.hasse_diagram().edges())
                8

            This is the transitive closure of the union of left and
            right order. In this poset, `u` is smaller than `v` if
            some reduced word of `u` is a factor of some reduced word
            of `v`. Note that this is not a lattice::

                sage: P.is_lattice()
                False

            By default, the elements of `P` are aware of that they
            belong to `P`::

                sage: P.an_element().parent()
                Finite poset containing 6 elements

            If instead one wants the elements to be plain elements of
            the Coxeter group, one can use the ``facade`` option::

                sage: P = W.weak_poset(facade = True)
                sage: P.an_element().parent()
                Weyl Group of type ['A', 2] (as a matrix group acting on the ambient space)

            .. see also:: :func:`Poset` for more on posets and facade posets.

            TESTS::

                sage: [len(WeylGroup(["A", n]).weak_poset(side = "right").cover_relations()) for n in [1,2,3]]
                [1, 6, 36]
                sage: [len(WeylGroup(["A", n]).weak_poset(side = "left" ).cover_relations()) for n in [1,2,3]]
                [1, 6, 36]

            .. todo::

                - Use the symmetric group in the examples (for nicer
                  output), and print the edges for a stronger test.
                - The constructed poset should be lazy, in order to
                  handle large / infinite Coxeter groups.
            """
            from sage.combinat.posets.posets import Poset
            from sage.combinat.posets.lattices import LatticePoset
            if side == "twosided":
                covers = tuple([u, v] for u in self for v in u.upper_covers(side="left")+u.upper_covers(side="right") )
                return Poset((self, covers), cover_relations = True, facade = facade)
            else:
                covers = tuple([u, v] for u in self for v in u.upper_covers(side=side) )
                return LatticePoset((self, covers), cover_relations = True, facade = facade)
예제 #25
0
def test_finite_lattice(L):
    """
    Test several functions on a given finite lattice.

    The function contains tests of different kinds:

    - Implications of Boolean properties. Examples: a distributive lattice is modular,
      a dismantlable and distributive lattice is planar, a simple lattice can not be
      constructible by Day's doublings.
    - Dual and self-dual properties. Examples: Dual of a modular lattice is modular,
      dual of an atomic lattice is co-atomic.
    - Certificate tests. Example: certificate for a non-complemented lattice must be
      an element without a complement.
    - Verification of some property by known property or by a random test.
      Examples: A lattice is distributive iff join-primes are exactly
      join-irreducibles and an interval of a relatively complemented
      lattice is complemented.
    - Set inclusions. Example: Every co-atom must be meet-irreducible.
    - And several other tests. Example: The skeleton of a pseudocomplemented
      lattice must be Boolean.

    EXAMPLES::

        sage: from sage.tests.finite_poset import test_finite_lattice
        sage: L = posets.RandomLattice(10, 0.98)
        sage: test_finite_lattice(L) is None  # Long time
        True
    """
    from sage.combinat.posets.lattices import LatticePoset

    from sage.sets.set import Set
    from sage.combinat.subset import Subsets

    from sage.misc.prandom import randint
    from sage.misc.flatten import flatten
    from sage.misc.misc import attrcall

    from sage.misc.sageinspect import sage_getargspec

    if L.cardinality() < 4:
        # Special cases should be tested in specific TESTS-sections.
        return None

    all_props = set(list(implications) + flatten(implications.values()))
    P = {x: test_attrcall('is_' + x, L) for x in all_props}

    ### Relations between boolean-valued properties ###

    # Direct one-property implications
    for prop1 in implications:
        if P[prop1]:
            for prop2 in implications[prop1]:
                if not P[prop2]:
                    raise ValueError("error: %s should implicate %s" %
                                     (prop1, prop2))

    # Impossible combinations
    for p1, p2 in mutually_exclusive:
        if P[p1] and P[p2]:
            raise ValueError(
                "error: %s and %s should be impossible combination" % (p1, p2))

    # Two-property implications
    for p1, p2, p3 in two_to_one:
        if P[p1] and P[p2] and not P[p3]:
            raise ValueError("error: %s and %s, so should be %s" %
                             (p1, p2, p3))

    Ldual = L.dual()
    # Selfdual properties
    for p in selfdual_properties:
        if P[p] != test_attrcall('is_' + p, Ldual):
            raise ValueError("selfdual property %s error" % p)
    # Dual properties and elements
    for p1, p2 in dual_properties:
        if P[p1] != test_attrcall('is_' + p2, Ldual):
            raise ValueError("dual properties error %s" % p1)
    for e1, e2 in dual_elements:
        if set(attrcall(e1)(L)) != set(attrcall(e2)(Ldual)):
            raise ValueError("dual elements error %s" % e1)

    ### Certificates ###

    # Return value must be a pair with correct result as first element.
    for p_ in all_props:
        # Dirty fix first
        if p_[:9] == 'doubling_' or p_[:5] == 'uniq_': continue
        p = "is_" + p_
        if 'certificate' in sage_getargspec(getattr(L, p)).args:
            res = attrcall(p, certificate=True)(L)
            if type(res) != type((1, 2)) or len(res) != 2:
                raise ValueError(
                    "certificate-option does not return a pair in %s" % p)
            if P[p_] != res[0]:
                raise ValueError("certificate-option changes result in %s" % p)

    # Test for "yes"-certificates
    if P['supersolvable']:
        a = L.is_supersolvable(certificate=True)[1]
        S = Subsets(L).random_element()
        if L.is_chain_of_poset(S):
            if not L.sublattice(a + list(S)).is_distributive():
                raise ValueError("certificate error in is_supersolvable")
    if P['dismantlable']:
        elms = L.is_dismantlable(certificate=True)[1]
        if len(elms) != L.cardinality():
            raise ValueError("certificate error 1 in is_dismantlable")
        elms = elms[:randint(0, len(elms) - 1)]
        L_ = L.sublattice([x for x in L if x not in elms])
        if L_.cardinality() != L.cardinality() - len(elms):
            raise ValueError("certificate error 2 in is_dismantlable")
    if P['vertically_decomposable']:
        c = L.is_vertically_decomposable(certificate=True)[1]
        if c == L.bottom() or c == L.top():
            raise ValueError(
                "certificate error 1 in is_vertically_decomposable")
        e = L.random_element()
        if L.compare_elements(c, e) is None:
            raise ValueError(
                "certificate error 2 in is_vertically_decomposable")

    # Test for "no"-certificates
    if not P['atomic']:
        a = L.is_atomic(certificate=True)[1]
        if a in L.atoms() or a not in L.join_irreducibles():
            raise ValueError("certificate error in is_atomic")
    if not P['coatomic']:
        a = L.is_coatomic(certificate=True)[1]
        if a in L.coatoms() or a not in L.meet_irreducibles():
            raise ValueError("certificate error in is_coatomic")

    if not P['complemented']:
        a = L.is_complemented(certificate=True)[1]
        if L.complements(a) != []:
            raise ValueError("compl. error 1")
    if not P['sectionally_complemented']:
        a, b = L.is_sectionally_complemented(certificate=True)[1]
        L_ = L.sublattice(L.interval(L.bottom(), a))
        if L_.is_complemented():
            raise ValueError("sec. compl. error 1")
        if len(L_.complements(b)) > 0:
            raise ValueError("sec. compl. error 2")
    if not P['cosectionally_complemented']:
        a, b = L.is_cosectionally_complemented(certificate=True)[1]
        L_ = L.sublattice(L.interval(a, L.top()))
        if L_.is_complemented():
            raise ValueError("cosec. compl. error 1")
        if len(L_.complements(b)) > 0:
            raise ValueError("cosec. compl. error 2")
    if not P['relatively_complemented']:
        a, b, c = L.is_relatively_complemented(certificate=True)[1]
        I = L.interval(a, c)
        if len(I) != 3 or b not in I:
            raise ValueError("rel. compl. error 1")

    if not P['upper_semimodular']:
        a, b = L.is_upper_semimodular(certificate=True)[1]
        if not set(L.lower_covers(a)).intersection(set(
                L.lower_covers(b))) or set(L.upper_covers(a)).intersection(
                    set(L.upper_covers(b))):
            raise ValueError("certificate error in is_upper_semimodular")
    if not P['lower_semimodular']:
        a, b = L.is_lower_semimodular(certificate=True)[1]
        if set(L.lower_covers(a)).intersection(set(
                L.lower_covers(b))) or not set(L.upper_covers(a)).intersection(
                    set(L.upper_covers(b))):
            raise ValueError("certificate error in is_lower_semimodular")

    if not P['distributive']:
        x, y, z = L.is_distributive(certificate=True)[1]
        if L.meet(x, L.join(y, z)) == L.join(L.meet(x, y), L.meet(x, z)):
            raise ValueError("certificate error in is_distributive")
    if not P['modular']:
        x, a, b = L.is_modular(certificate=True)[1]
        if not L.is_less_than(x, b) or L.join(x, L.meet(a, b)) == L.meet(
                L.join(x, a), b):
            raise ValueError("certificate error in is_modular")

    if not P['pseudocomplemented']:
        a = L.is_pseudocomplemented(certificate=True)[1]
        L_ = L.subposet([e for e in L if L.meet(e, a) == L.bottom()])
        if L_.has_top():
            raise ValueError("certificate error in is_pseudocomplemented")
    if not P['join_pseudocomplemented']:
        a = L.is_join_pseudocomplemented(certificate=True)[1]
        L_ = L.subposet([e for e in L if L.join(e, a) == L.top()])
        if L_.has_bottom():
            raise ValueError("certificate error in is_join_pseudocomplemented")

    if not P['join_semidistributive']:
        e, x, y = L.is_join_semidistributive(certificate=True)[1]
        if L.join(e, x) != L.join(e, y) or L.join(e, x) == L.join(
                e, L.meet(x, y)):
            raise ValueError("certificate error in is_join_semidistributive")
    if not P['meet_semidistributive']:
        e, x, y = L.is_meet_semidistributive(certificate=True)[1]
        if L.meet(e, x) != L.meet(e, y) or L.meet(e, x) == L.meet(
                e, L.join(x, y)):
            raise ValueError("certificate error in is_meet_semidistributive")

    if not P['simple']:
        c = L.is_simple(certificate=True)[1]
        if len(L.congruence([c[randint(0, len(c) - 1)]])) == 1:
            raise ValueError("certificate error in is_simple")
    if not P['isoform']:
        c = L.is_isoform(certificate=True)[1]
        if len(c) == 1:
            raise ValueError("certificate error in is_isoform")
        if all(
                L.subposet(c[i]).is_isomorphic(L.subposet(c[i + 1]))
                for i in range(len(c) - 1)):
            raise ValueError("certificate error in is_isoform")
    if not P['uniform']:
        c = L.is_uniform(certificate=True)[1]
        if len(c) == 1:
            raise ValueError("certificate error in is_uniform")
        if all(len(c[i]) == len(c[i + 1]) for i in range(len(c) - 1)):
            raise ValueError("certificate error in is_uniform")
    if not P['regular']:
        c = L.is_regular(certificate=True)[1]
        if len(c[0]) == 1:
            raise ValueError("certificate error 1 in is_regular")
        if Set(c[1]) not in c[0]:
            raise ValueError("certificate error 2 in is_regular")
        if L.congruence([c[1]]) == c[0]:
            raise ValueError("certificate error 3 in is_regular")

    if not P['subdirectly_reducible']:
        x, y = L.is_subdirectly_reducible(certificate=True)[1]
        a = L.random_element()
        b = L.random_element()
        c = L.congruence([[a, b]])
        if len(c) != L.cardinality():
            for c_ in c:
                if x in c_:
                    if y not in c_:
                        raise ValueError(
                            "certificate error 1 in is_subdirectly_reducible")
                    break
            else:
                raise ValueError(
                    "certificate error 2 in is_subdirectly_reducible")

    if not P['join_distributive']:
        a = L.is_join_distributive(certificate=True)[1]
        L_ = L.sublattice(L.interval(a, L.join(L.upper_covers(a))))
        if L_.is_distributive():
            raise ValueError("certificate error in is_join_distributive")
    if not P['meet_distributive']:
        a = L.is_meet_distributive(certificate=True)[1]
        L_ = L.sublattice(L.interval(L.meet(L.lower_covers(a)), a))
        if L_.is_distributive():
            raise ValueError("certificate error in is_meet_distributive")

    ### Other ###

    # Other ways to recognize some boolean property
    if P['distributive'] != (set(L.join_primes()) == set(
            L.join_irreducibles())):
        raise ValueError(
            "every join-irreducible of a distributive lattice should be join-prime"
        )
    if P['distributive'] != (set(L.meet_primes()) == set(
            L.meet_irreducibles())):
        raise ValueError(
            "every meet-irreducible of a distributive lattice should be meet-prime"
        )
    if P['join_semidistributive'] != all(
            L.canonical_joinands(e) is not None for e in L):
        raise ValueError(
            "every element of join-semidistributive lattice should have canonical joinands"
        )
    if P['meet_semidistributive'] != all(
            L.canonical_meetands(e) is not None for e in L):
        raise ValueError(
            "every element of meet-semidistributive lattice should have canonical meetands"
        )

    # Random verification of a Boolean property
    if P['relatively_complemented']:
        a = L.random_element()
        b = L.random_element()
        if not L.sublattice(L.interval(a, b)).is_complemented():
            raise ValueError("rel. compl. error 3")
    if P['sectionally_complemented']:
        a = L.random_element()
        if not L.sublattice(L.interval(L.bottom(), a)).is_complemented():
            raise ValueError("sec. compl. error 3")
    if P['cosectionally_complemented']:
        a = L.random_element()
        if not L.sublattice(L.interval(a, L.top())).is_complemented():
            raise ValueError("cosec. compl. error 2")

    # Element set inclusions
    for s1, s2 in set_inclusions:
        if not set(attrcall(s1)(L)).issubset(set(attrcall(s2)(L))):
            raise ValueError("%s should be a subset of %s" % (s1, s2))

    # Sublattice-closed properties
    L_ = L.sublattice(Subsets(L).random_element())
    for p in sublattice_closed:
        if P[p] and not test_attrcall('is_' + p, L_):
            raise ValueError("property %s should apply to sublattices" % p)

    # Some sublattices
    L_ = L.center()  # Center is a Boolean lattice
    if not L_.is_atomic() or not L_.is_distributive():
        raise ValueError("error in center")
    if P['pseudocomplemented']:
        L_ = L.skeleton()  # Skeleton is a Boolean lattice
        if not L_.is_atomic() or not L_.is_distributive():
            raise ValueError("error in skeleton")
    L_ = L.frattini_sublattice()
    S = Subsets(L).random_element()
    if L.sublattice(S) == L and L.sublattice([e
                                              for e in S if e not in L_]) != L:
        raise ValueError("error in Frattini sublattice")
    L_ = L.maximal_sublattices()
    L_ = L_[randint(0, len(L_) - 1)]
    e = L.random_element()
    if e not in L_ and L.sublattice(list(L_) + [e]) != L:
        raise ValueError("error in maximal_sublattices")

    # Reverse functions: vertical composition and decomposition
    L_ = reduce(lambda a, b: a.vertical_composition(b),
                L.vertical_decomposition(), LatticePoset())
    if not L.is_isomorphic(L_):
        raise ValueError("error in vertical [de]composition")

    # Meet and join
    a = L.random_element()
    b = L.random_element()
    m = L.meet(a, b)
    j = L.join(a, b)
    m_ = L.subposet([
        e for e in L.principal_lower_set(a) if e in L.principal_lower_set(b)
    ]).top()
    j_ = L.subposet([
        e for e in L.principal_upper_set(a) if e in L.principal_upper_set(b)
    ]).bottom()
    if m != m_ or m != Ldual.join(a, b):
        raise ValueError("error in meet")
    if j != j_ or j != Ldual.meet(a, b):
        raise ValueError("error in join")

    # Misc misc
    e = L.neutral_elements()
    e = e[randint(0, len(e) - 1)]
    a = L.random_element()
    b = L.random_element()
    if not L.sublattice([e, a, b]).is_distributive():
        raise ValueError("error in neutral_elements")
예제 #26
0
        def m_cambrian_lattice(self, c, m=1, on_roots=False):
            """
            Return the `m`-Cambrian lattice on `m`-delta sequences.

            See :arxiv:`1503.00710` and :arxiv:`math/0611106`.

            The `m`-delta sequences are certain `m`-colored minimal
            factorizations of `c` into reflections.

            INPUT:

            - `c` -- a Coxeter element of ``self`` (as a tuple, or
              as an element of ``self``)

            - `m` -- a positive integer (optional, default 1)

            - ``on_roots`` (optional, default ``False``) -- if
              ``on_roots`` is ``True``, the lattice is realized on
              roots rather than on reflections. In order for this to
              work, the ElementMethod ``reflection_to_root`` must be
              available.

            EXAMPLES::

                sage: CoxeterGroup(["A",2]).m_cambrian_lattice((1,2))
                Finite lattice containing 5 elements

                sage: CoxeterGroup(["A",2]).m_cambrian_lattice((1,2),2)
                Finite lattice containing 12 elements
            """
            from sage.combinat.posets.lattices import LatticePoset
            if hasattr(c, "reduced_word"):
                c = c.reduced_word()
            c = list(c)

            sorting_word = self.long_element().coxeter_sorting_word(c)

            if on_roots:
                if not hasattr(self.long_element(), "reflection_to_root"):
                    raise ValueError("The parameter 'on_root=True' needs "
                                     "the ElementMethod 'reflection_to_root'")

                inv_woc = [
                    t.reflection_to_root()
                    for t in self.inversion_sequence(sorting_word)
                ]
                S = [s.reflection_to_root() for s in self.simple_reflections()]
                PhiP = [t.reflection_to_root() for t in self.reflections()]
            else:
                inv_woc = self.inversion_sequence(sorting_word)
                S = self.simple_reflections()
                T = self.reflections_from_w0()
                Twords = {t: t.reduced_word() for t in T}

            elements = set()
            covers = []

            bottom_elt = frozenset((s, 0) for s in S)
            new = set([bottom_elt])
            while new:
                new_element = new.pop()
                elements.add(new_element)
                for t in new_element:
                    if t[1] < m:
                        cov_element = [s for s in new_element if s != t]
                        cov_element.append((t[0], t[1] + 1))
                        idx_t0 = inv_woc.index(t[0])
                        for t_conj in [(i, t[1]) for i in inv_woc[idx_t0:]] + [
                            (i, t[1] + 1) for i in inv_woc[:idx_t0]
                        ]:
                            if t_conj in cov_element:
                                cov_element.remove(t_conj)
                                if on_roots:
                                    tmp = t_conj[0].weyl_action(
                                        t[0].associated_reflection())
                                    if tmp in PhiP:
                                        cov_element.append((tmp, t_conj[1]))
                                    else:
                                        cov_element.append(
                                            (-tmp, t_conj[1] - 1))
                                else:
                                    tmp = t[0] * t_conj[0] * t[0]
                                    invs = self.inversion_sequence(
                                        Twords[t[0]] + Twords[t_conj[0]])
                                    plus_or_minus = invs.count(tmp)
                                    if plus_or_minus % 2:
                                        cov_element.append((tmp, t_conj[1]))
                                    else:
                                        cov_element.append(
                                            (tmp, t_conj[1] - 1))

                        cov_element = frozenset(cov_element)
                        if cov_element not in elements:
                            new.add(cov_element)
                        covers.append((new_element, cov_element))
            return LatticePoset([elements, covers], cover_relations=True)
예제 #27
0
def NuTamariLattice(v):
    r"""
    This function returns the `\\nu`-Tamari lattice indexed by ``v``
    
    INPUT:
    
    - ``v`` -- directed path (canopy) as a list of 0 (east step) and 1 
      (north step)
      
    OUTPUT: the `\\nu`-Tamari lattice indexed by ``v``
    """
    def extend_path(elem, cur, toextend, x, y):
        """
        Extending the path (cur) step by step, within the limit of v 
        indicated by lvl.
        
        The parameter (toextend) is the remaining steps to add.
        
        When a path is fully generated, it gets added to (elem).
        """
        if toextend == 0:
            elem.append(tuple(cur))
            return
        if y < (len(lvl) - 1):
            cur.append(1)
            extend_path(elem, cur, toextend - 1, x, y + 1)
            cur.pop()
        if x < lvl[y]:
            cur.append(0)
            extend_path(elem, cur, toextend - 1, x + 1, y)
            cur.pop()
        return

    def generate_elements():
        elem = []
        extend_path(elem, [], len(v), 0, 0)
        return elem

    def swap(e, p):
        """
        Given a valley p, this function does the v-Tamari switch to obtain a 
        covering element.
        """
        # Initial coordinates and horizontal distance
        x = [e[:p + 1].count(0), e[:p + 1].count(1)]
        hdist = lvl[x[1]] - x[0]

        # Find the next point with the same horizontal distance
        for j in range(p + 1, len(e)):
            x[e[j]] += 1
            if hdist == (lvl[x[1]] - x[0]):
                break

        # Construct a new path with the portion switched
        e1 = list(e)
        for i in range(p, j):
            e1[i] = e1[i + 1]
        e1[j] = 0

        return tuple(e1)

    def get_cover_elem(e):
        return [
            swap(e, x) for x in range(len(v) - 1)
            if (e[x] == 0) and (e[x + 1] == 1)
        ]

    checkpath(v)
    lvl = get_level_list(v)
    return LatticePoset(
        dict((e, get_cover_elem(e)) for e in generate_elements()))
예제 #28
0
        def order_ideals_lattice(self, as_ideals=True):
            r"""
            Return the lattice of order ideals of a poset ``self``,
            ordered by inclusion.

            The lattice of order ideals of a poset `P` is usually
            denoted by `J(P)`. Its underlying set is the set of order
            ideals of `P`, and its partial order is given by
            inclusion.

            The order ideals of `P` are in a canonical bijection
            with the antichains of `P`. The bijection maps every
            order ideal to the antichain formed by its maximal
            elements. By setting the ``as_ideals`` keyword variable to
            ``False``, one can make this method apply this bijection
            before returning the lattice.

            INPUT:

            - ``as_ideals`` -- Boolean, if ``True`` (default) returns
              a poset on the set of order ideals, otherwise on the set
              of antichains

            EXAMPLES::

                sage: P = Posets.PentagonPoset(facade = True)
                sage: P.cover_relations()
                [[0, 1], [0, 2], [1, 4], [2, 3], [3, 4]]
                sage: J = P.order_ideals_lattice(); J
                Finite lattice containing 8 elements
                sage: list(J)
                [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 2, 3}, {0, 1, 2, 3}, {0, 1, 2, 3, 4}]

            As a lattice on antichains::

                sage: J2 = P.order_ideals_lattice(False); J2
                Finite lattice containing 8 elements
                sage: list(J2)
                [(0,), (1, 2), (1, 3), (1,), (2,), (3,), (4,), ()]

            TESTS::

                sage: J = Posets.DiamondPoset(4, facade = True).order_ideals_lattice(); J
                Finite lattice containing 6 elements
                sage: list(J)
                [{}, {0}, {0, 2}, {0, 1}, {0, 1, 2}, {0, 1, 2, 3}]
                sage: J.cover_relations()
                [[{}, {0}], [{0}, {0, 2}], [{0}, {0, 1}], [{0, 2}, {0, 1, 2}], [{0, 1}, {0, 1, 2}], [{0, 1, 2}, {0, 1, 2, 3}]]

            .. NOTE:: we use facade posets in the examples above just
               to ensure a nicer ordering in the output.
            """
            from sage.combinat.posets.lattices import LatticePoset
            if as_ideals:
                from sage.misc.misc import attrcall
                from sage.sets.set import Set
                ideals = [
                    Set(self.order_ideal(antichain))
                    for antichain in self.antichains()
                ]
                return LatticePoset((ideals, attrcall("issubset")))
            else:
                from sage.misc.cachefunc import cached_function
                antichains = [tuple(a) for a in self.antichains()]

                @cached_function
                def is_above(a, xb):
                    return any(self.is_lequal(xa, xb) for xa in a)

                def cmp(a, b):
                    return all(is_above(a, xb) for xb in b)

                return LatticePoset((antichains, cmp))
예제 #29
0
def GeneralizedTamariLattice(a,b,m=1):
    r"""
    Returns the `(a,b)`-Tamari lattice of parameter `m`.

    INPUT:

    - `a` and `b` coprime integers with `a \geq b`

    - `m` a nonnegative integer such that `a \geq b \times m`

    OUTPUT:

    - a finite lattice (the lattice property is only conjectural in general)

    The elements of the lattice are :func:`Dyck paths<sage.combinat.dyck_word.DyckWord>` in the `(a \times b)`-rectangle.

    The parameter `m` (slope) is used only to define the covering relations.
    When the slope `m` is `0`, two paths are comparable if and only if
    one is always above the other.

    The usual :wikipedia:`Tamari lattice<Tamari lattice>` of index `b` is the special
    case `a=b+1` and `m=1`.

    Other special cases give the `m`-Tamari lattices studied in [BMFPR]_.

    EXAMPLES::

        sage: from sage.combinat.tamari_lattices import GeneralizedTamariLattice
        sage: GeneralizedTamariLattice(3,2)
        Finite lattice containing 2 elements
        sage: GeneralizedTamariLattice(4,3)
        Finite lattice containing 5 elements
        sage: GeneralizedTamariLattice(4,4)
        Traceback (most recent call last):
        ...
        ValueError: The numbers a and b must be coprime with a>=b.
        sage: GeneralizedTamariLattice(7,5,2)
        Traceback (most recent call last):
        ...
        ValueError: The condition a>=b*m does not hold.
        sage: P = GeneralizedTamariLattice(5,3);P
        Finite lattice containing 7 elements

    TESTS::

        sage: P.coxeter_transformation()**18 == 1
        True

    REFERENCES:

    .. [BMFPR] M. Bousquet-Melou, E. Fusy, L.-F. Preville Ratelle. "The number of intervals in the m-Tamari lattices". arXiv:1106.1498

    """
    if not(gcd(a,b)==1 and a>=b):
        raise ValueError("The numbers a and b must be coprime with a>=b.")
    if not(a>=b*m):
        raise ValueError("The condition a>=b*m does not hold.")
    def covers(p):
        return [swap(p,i,m) for i in range(len(p)-1) if p[i]==0 and p[i+1]==1]
    return LatticePoset(dict([[p,covers(p)]
                    for p in paths_in_triangle(a,b,a,b)]))