Example #1
0
        def _from_Monomial_on_basis(self, J):
            r"""
            Given a quasi-symmetric monomial function, this method returns the expansion into the dual immaculate basis.

            INPUT:

            - ``J`` -- a composition

            OUTPUT:

            - A quasi-symmetric function in the dual immaculate basis.

            EXAMPLES:

                sage: dI = QuasiSymmetricFunctions(QQ).dI()
                sage: dI._from_Monomial_on_basis(Composition([]))
                dI[]
                sage: dI._from_Monomial_on_basis(Composition([2,1]))
                -dI[1, 1, 1] - dI[1, 2] + dI[2, 1]
                sage: dI._from_Monomial_on_basis(Composition([3,1,2]))
                -dI[1, 1, 1, 1, 1, 1] + dI[1, 1, 1, 1, 2] + dI[1, 1, 1, 3] - dI[1, 1, 4] - dI[1, 2, 1, 1, 1] + dI[1, 2, 3] + dI[2, 1, 1, 1, 1] - dI[2, 1, 1, 2] + dI[2, 2, 1, 1] - dI[2, 2, 2] - dI[3, 1, 1, 1] + dI[3, 1, 2]
            """
            n = J.size()
            C = Compositions()
            C_n = Compositions(n)
            mat = self._matrix_monomial_to_dual_immaculate(n)
            column = C_n.list().index(J)
            return self.sum_of_terms( (C(I), mat[C_n.list().index(I)][column])
                                            for I in C_n)
Example #2
0
        def to_B_basis(self, S):
            r"""
            Return `D_S` as a linear combination of `B_p`-basis elements.

            EXAMPLES::

                sage: DA = DescentAlgebra(QQ, 4)
                sage: D = DA.D()
                sage: B = DA.B()
                sage: for b in D.basis(): B(b) # indirect doctest
                B[4]
                B[1, 3] - B[4]
                B[2, 2] - B[4]
                B[1, 1, 2] - B[1, 3] - B[2, 2] + B[4]
                B[3, 1] - B[4]
                B[1, 2, 1] - B[1, 3] - B[3, 1] + B[4]
                B[2, 1, 1] - B[2, 2] - B[3, 1] + B[4]
                B[1, 1, 1, 1] - B[1, 1, 2] - B[1, 2, 1] + B[1, 3] - B[2, 1, 1] + B[2, 2] + B[3, 1] - B[4]
            """
            B = self.realization_of().B()

            if len(S) == 0:
                return B.one()

            n = self.realization_of()._n
            C = Compositions(n)
            return B.sum_of_terms([(C.from_subset(T, n), (-1)**(len(S)-len(T))) for T in subsets(S)])
Example #3
0
    def __init__(self, parent, t):
        r"""
        Initialize a composition tableau.

        TESTS::

            sage: t = CompositionTableaux()([[1],[2,2]])
            sage: s = CompositionTableaux(3)([[1],[2,2]])
            sage: s==t
            True
            sage: t.parent()
            Composition Tableaux
            sage: s.parent()
            Composition Tableaux of size 3 and maximum entry 3
            sage: r = CompositionTableaux()(s)
            sage: r.parent()
            Composition Tableaux
        """
        if isinstance(t, CompositionTableau):
            CombinatorialElement.__init__(self, parent, t._list)
            return

        # CombinatorialObject verifies that t is a list
        # We must verify t is a list of lists
        if not all(isinstance(row, list) for row in t):
            raise ValueError("A composition tableau must be a list of lists.")

        if not [len(_) for _ in t] in Compositions():
            raise ValueError(
                "A composition tableau must be a list of non-empty lists.")

        # Verify rows weakly decrease from left to right
        for row in t:
            if any(row[i] < row[i + 1] for i in range(len(row) - 1)):
                raise ValueError(
                    "Rows must weakly decrease from left to right.")

        # Verify leftmost column strictly increases from top to bottom
        first_col = [row[0] for row in t if t != [[]]]
        if any(first_col[i] >= first_col[i + 1] for i in range(len(t) - 1)):
            raise ValueError(
                "Leftmost column must strictly increase from top to bottom.")

        # Verify triple condition
        l = len(t)
        m = max([len(_) for _ in t] + [0])
        TT = [row + [0] * (m - len(row)) for row in t]
        for i in range(l):
            for j in range(i + 1, l):
                for k in range(1, m):
                    if TT[j][k] != 0 and TT[j][k] >= TT[i][k] and TT[j][
                            k] <= TT[i][k - 1]:
                        raise ValueError("Triple condition must be satisfied.")

        CombinatorialElement.__init__(self, parent, t)
Example #4
0
        def __init__(self, QSym):
            """
            EXAMPLES::

                sage: M = QuasiSymmetricFunctions(QQ).Monomial(); M
                Quasisymmetric functions over the Rational Field in the Monomial basis
                sage: TestSuite(M).run()
            """
            CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(),
                                             prefix='M', bracket=False,
                                             category=QSym.Bases())
Example #5
0
        def product_on_basis(self, p, q):
            r"""
            Return `B_p B_q`, where `p` and `q` are compositions of `n`.

            EXAMPLES::

                sage: DA = DescentAlgebra(QQ, 4)
                sage: B = DA.B()
                sage: p = Composition([1,2,1])
                sage: q = Composition([3,1])
                sage: B.product_on_basis(p, q)
                B[1, 1, 1, 1] + 2*B[1, 2, 1]
            """
            IM = IntegerMatrices(list(p), list(q))
            P = Compositions(self.realization_of()._n)
            to_composition = lambda m: P([x for x in m.list() if x != 0])
            return self.sum_of_monomials([to_composition(_) for _ in IM])
Example #6
0
        def one_basis(self):
            r"""
            Return the empty composition.

            OUTPUT

            - The empty composition.

            EXAMPLES::

                sage: L=NonCommutativeSymmetricFunctions(QQ).L()
                sage: parent(L)
                <class 'sage.combinat.ncsf_qsym.ncsf.NonCommutativeSymmetricFunctions.Elementary_with_category'>
                sage: parent(L).one_basis()
                []
            """
            return Compositions()([])
Example #7
0
    def __init__(self, w1, w2, r):
        """
        EXAMPLES::

            sage: from sage.combinat.words.shuffle_product import ShuffleProduct_overlapping_r
            sage: w, u = map(Words("abcdef"), ["ab", "cd"])
            sage: S = ShuffleProduct_overlapping_r(w,u,1)
            sage: S == loads(dumps(S))
            True
        """
        self._w1 = w1
        self._w2 = w2
        self.r = r
        self.W = self._w1.parent()
        # Special situation: the parent of w1 is too
        # restrictive to be cast on the shuffles.
        if isinstance(self.W, Compositions_n):
            self.W = Compositions()
        def __init__(self, alg, prefix="B"):
            r"""
            Initialize ``self``.

            EXAMPLES::

                sage: TestSuite(DescentAlgebra(QQ, 4).B()).run()
            """
            self._prefix = prefix
            self._basis_name = "subset"
            CombinatorialFreeModule.__init__(self, alg.base_ring(),
                                             Compositions(alg._n),
                                             category=DescentAlgebraBases(alg),
                                             bracket="", prefix=prefix)

            S = NonCommutativeSymmetricFunctions(alg.base_ring()).Complete()
            self.module_morphism(self.to_nsym,
                                 codomain=S, category=Algebras(alg.base_ring())
                                 ).register_as_coercion()
Example #9
0
    def IntegerCompositions(n):
        """
        Returns the poset of integer compositions of the integer ``n``.

        A composition of a positive integer `n` is a list of positive
        integers that sum to `n`. The order is reverse refinement:
        `[p_1,p_2,...,p_l] < [q_1,q_2,...,q_m]` if `q` consists
        of an integer composition of `p_1`, followed by an integer
        composition of `p_2`, and so on.

        EXAMPLES::

            sage: P = Posets.IntegerCompositions(7); P
            Finite poset containing 64 elements
            sage: len(P.cover_relations())
            192
        """
        from sage.combinat.composition import Compositions
        C = Compositions(n)
        return Poset((C, [[c,d] for c in C for d in C if d.is_finer(c)]), cover_relations=False)
Example #10
0
        def one_basis(self):
            r"""
            Return the identity element which is the composition `[n]`, as per
            ``AlgebrasWithBasis.ParentMethods.one_basis``.

            EXAMPLES::

                sage: DescentAlgebra(QQ, 4).B().one_basis()
                [4]
                sage: DescentAlgebra(QQ, 0).B().one_basis()
                []

                sage: all( U * DescentAlgebra(QQ, 3).B().one() == U
                ....:      for U in DescentAlgebra(QQ, 3).B().basis() )
                True
            """
            n = self.realization_of()._n
            P = Compositions(n)
            if not n:  # n == 0
                return P([])
            return P([n])
Example #11
0
    def __iter__(self):
        """
        EXAMPLES::

            sage: [ p for p in OrderedSetPartitions([1,2,3]) ]
            [[{1}, {2}, {3}],
             [{1}, {3}, {2}],
             [{2}, {1}, {3}],
             [{3}, {1}, {2}],
             [{2}, {3}, {1}],
             [{3}, {2}, {1}],
             [{1}, {2, 3}],
             [{2}, {1, 3}],
             [{3}, {1, 2}],
             [{1, 2}, {3}],
             [{1, 3}, {2}],
             [{2, 3}, {1}],
             [{1, 2, 3}]]
        """
        for x in Compositions(len(self._set)):
            for z in OrderedSetPartitions(self._set, x):
                yield self.element_class(self, z)
Example #12
0
def number_of_fCT(content_comp, shape_comp):
    r"""
    Return the number of Immaculate tableaux of shape
    ``shape_comp`` and content ``content_comp``.

    See [BBSSZ2012]_, Definition 3.9, for the notion of an
    immaculate tableau.

    INPUT:

    - ``content_comp``, ``shape_comp`` -- compositions

    OUTPUT:

    - An integer

    EXAMPLES::

        sage: from sage.combinat.ncsf_qsym.combinatorics import number_of_fCT
        sage: number_of_fCT(Composition([3,1]), Composition([1,3]))
        0
        sage: number_of_fCT(Composition([1,2,1]), Composition([1,3]))
        1
        sage: number_of_fCT(Composition([1,1,3,1]), Composition([2,1,3]))
        2
    """
    if content_comp.to_partition().length() == 1:
        if shape_comp.to_partition().length() == 1:
            return 1
        else:
            return 0
    C = Compositions(content_comp.size() - content_comp[-1],
                     outer=list(shape_comp))
    s = 0
    for x in C:
        if len(x) >= len(shape_comp) - 1:
            s += number_of_fCT(Composition(content_comp[:-1]), x)
    return s
Example #13
0
def m_to_s_stat(R, I, K):
    r"""
    Return the coefficient of the complete non-commutative symmetric
    function `S^K` in the expansion of the monomial non-commutative
    symmetric function `M^I` with respect to the complete basis
    over the ring `R`. This is the coefficient in formula (36) of
    Tevlin's paper [Tev2007]_.

    INPUT:

    - ``R`` -- A ring, supposed to be a `\QQ`-algebra
    - ``I``, ``K`` -- compositions

    OUTPUT:

    - The coefficient of `S^K` in the expansion of `M^I` in the
      complete basis of the non-commutative symmetric functions
      over ``R``.

    EXAMPLES::

        sage: from sage.combinat.ncsf_qsym.combinatorics import m_to_s_stat
        sage: m_to_s_stat(QQ, Composition([2,1]), Composition([1,1,1]))
        -1
        sage: m_to_s_stat(QQ, Composition([3]), Composition([1,2]))
        -2
        sage: m_to_s_stat(QQ, Composition([2,1,2]), Composition([2,1,2]))
        8/3
    """
    stat = 0
    for J in Compositions(I.size()):
        if (I.is_finer(J) and K.is_finer(J)):
            pvec = [
                0
            ] + Composition(I).refinement_splitting_lengths(J).partial_sums()
            pp = prod(R(len(I) - pvec[i]) for i in range(len(pvec) - 1))
            stat += R((-1)**(len(I) - len(K)) / pp * coeff_lp(K, J))
    return stat
Example #14
0
    def fatter(self):
        """
        Return the set of ordered set partitions which are fatter
        than ``self``.

        See :meth:`finer` for the definition of "fatter".

        EXAMPLES::

            sage: C = OrderedSetPartition([[2, 5], [1], [3, 4]]).fatter()
            sage: C.cardinality()
            4
            sage: sorted(C)
            [[{1, 2, 3, 4, 5}],
             [{1, 2, 5}, {3, 4}],
             [{2, 5}, {1, 3, 4}],
             [{2, 5}, {1}, {3, 4}]]

            sage: OrderedSetPartition([[4, 9], [-1, 2]]).fatter().list()
            [[{4, 9}, {-1, 2}], [{-1, 2, 4, 9}]]

        Some extreme cases::

            sage: list(OrderedSetPartition([[5]]).fatter())
            [[{5}]]
            sage: list(Composition([]).fatter())
            [[]]
            sage: sorted(OrderedSetPartition([[1], [2], [3], [4]]).fatter())
            [[{1, 2, 3, 4}],
             [{1, 2, 3}, {4}],
             [{1, 2}, {3, 4}],
             [{1, 2}, {3}, {4}],
             [{1}, {2, 3, 4}],
             [{1}, {2, 3}, {4}],
             [{1}, {2}, {3, 4}],
             [{1}, {2}, {3}, {4}]]
        """
        return Compositions(len(self)).map(self.fatten)
Example #15
0
    def __init__(self, w1, w2, r):
        """
        The overlapping shuffle product of the two words ``w1`` and ``w2``
        with precisely ``r`` overlaps.

        See :class:`ShuffleProduct_overlapping` for a definition.

        EXAMPLES::

            sage: from sage.combinat.words.shuffle_product import ShuffleProduct_overlapping_r
            sage: w, u = map(Words(range(20)), [[2, 9], [9, 1]])
            sage: S = ShuffleProduct_overlapping_r(w,u,1)
            sage: S == loads(dumps(S))
            True
        """
        self._w1 = w1
        self._w2 = w2
        self.r = r
        self.W = self._w1.parent()
        # Special situation: the parent of w1 is too
        # restrictive to be cast on the shuffles.
        if isinstance(self.W, Compositions_n):
            self.W = Compositions()
Example #16
0
        def idempotent(self, la):
            """
            Return the idemponent corresponding to the partition ``la``.

            EXAMPLES::

                sage: I = DescentAlgebra(QQ, 4).I()
                sage: E = I.idempotent([3,1]); E
                1/2*I[1, 3] + 1/2*I[3, 1]
                sage: E*E == E
                True
                sage: E2 = I.idempotent([2,1,1]); E2
                1/6*I[1, 1, 2] + 1/6*I[1, 2, 1] + 1/6*I[2, 1, 1]
                sage: E2*E2 == E2
                True
                sage: E*E2 == I.zero()
                True
            """
            from sage.combinat.permutation import Permutations
            k = len(la)
            C = Compositions(self.realization_of()._n)
            return self.sum_of_terms([(C(x), ~QQ(factorial(k)))
                                      for x in Permutations(la)])
Example #17
0
    def __iter__(self):
        """
        EXAMPLES::

            sage: [ p for p in OrderedSetPartitions([1,2,3,4], 2) ]
            [[{1, 2, 3}, {4}],
             [{1, 2, 4}, {3}],
             [{1, 3, 4}, {2}],
             [{2, 3, 4}, {1}],
             [{1, 2}, {3, 4}],
             [{1, 3}, {2, 4}],
             [{1, 4}, {2, 3}],
             [{2, 3}, {1, 4}],
             [{2, 4}, {1, 3}],
             [{3, 4}, {1, 2}],
             [{1}, {2, 3, 4}],
             [{2}, {1, 3, 4}],
             [{3}, {1, 2, 4}],
             [{4}, {1, 2, 3}]]
        """
        for x in Compositions(len(self._set), length=self.n):
            for z in OrderedSetPartitions_scomp(self._set, x):
                yield self.element_class(self, z)
        def __init__(self, alg, prefix="I"):
            r"""
            Initialize ``self``.

            EXAMPLES::

                sage: TestSuite(DescentAlgebra(QQ, 4).B()).run()
            """
            self._prefix = prefix
            self._basis_name = "idempotent"
            CombinatorialFreeModule.__init__(self, alg.base_ring(),
                                             Compositions(alg._n),
                                             category=DescentAlgebraBases(alg),
                                             bracket="", prefix=prefix)

            # Change of basis:
            B = alg.B()
            self.module_morphism(self.to_B_basis,
                                 codomain=B, category=self.category()
                                 ).register_as_coercion()

            B.module_morphism(B.to_I_basis,
                              codomain=self, category=self.category()
                              ).register_as_coercion()
Example #19
0
    def strongly_finer(self):
        """
        Return the set of ordered set partitions which are strongly
        finer than ``self``.

        See :meth:`is_strongly_finer` for the definition of "strongly
        finer".

        EXAMPLES::

            sage: C = OrderedSetPartition([[1, 3], [2]]).strongly_finer()
            sage: C.cardinality()
            2
            sage: C.list()
            [[{1}, {3}, {2}], [{1, 3}, {2}]]

            sage: OrderedSetPartition([]).strongly_finer()
            {[]}

            sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
            sage: W.strongly_finer().list()
            [[{4}, {9}, {-1}, {2}],
             [{4}, {9}, {-1, 2}],
             [{4, 9}, {-1}, {2}],
             [{4, 9}, {-1, 2}]]
        """
        par = parent(self)
        if not self:
            return FiniteEnumeratedSet([self])
        else:
            buo = OrderedSetPartition.bottom_up_osp
            return FiniteEnumeratedSet([
                par(sum((list(P) for P in C), [])) for C in cartesian_product(
                    [[buo(X, comp) for comp in Compositions(len(X))]
                     for X in self])
            ])
Example #20
0
def compositions_order(n):
    r"""
    Return the compositions of `n` ordered as defined in [QSCHUR]_.

    Let `S(\gamma)` return the composition `\gamma` after sorting. For
    compositions `\alpha` and `\beta`, we order `\alpha \rhd \beta` if

    1) `S(\alpha) > S(\beta)` lexicographically, or
    2) `S(\alpha) = S(\beta)` and `\alpha > \beta` lexicographically.

    INPUT:

    - ``n`` -- a positive integer

    OUTPUT:

    - A list of the compositions of ``n`` sorted into decreasing order
      by `\rhd`

    EXAMPLES::

        sage: from sage.combinat.ncsf_qsym.combinatorics import compositions_order
        sage: compositions_order(3)
        [[3], [2, 1], [1, 2], [1, 1, 1]]
        sage: compositions_order(4)
        [[4], [3, 1], [1, 3], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
    """
    def _myorder(I, J):
        pI = sorted(I, reverse=True)
        pJ = sorted(J, reverse=True)
        if pI == pJ:
            return cmp(list(J), list(I))
        else:
            return cmp(pJ, pI)

    return sorted(Compositions(n), cmp=_myorder)
Example #21
0
        def duality_pairing_matrix(self, basis, degree):
            r"""
            The matrix of scalar products between elements of NSym and
            elements of QSym.

            INPUT:

            - ``basis`` -- A basis of the dual Hopf algebra
            - ``degree`` -- a non-negative integer

            OUTPUT:

            - The matrix of scalar products between the basis ``self`` and the basis
              ``basis`` in the dual Hopf algebra of degree ``degree``.

            EXAMPLES:

            The ribbon basis of NCSF is dual to the fundamental basis of
            QSym::

                sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon()
                sage: F = QuasiSymmetricFunctions(QQ).Fundamental()
                sage: R.duality_pairing_matrix(F, 3)
                [1 0 0 0]
                [0 1 0 0]
                [0 0 1 0]
                [0 0 0 1]
                sage: F.duality_pairing_matrix(R, 3)
                [1 0 0 0]
                [0 1 0 0]
                [0 0 1 0]
                [0 0 0 1]

            The complete basis of NCSF is dual to the monomial basis of
            QSym::

                sage: S = NonCommutativeSymmetricFunctions(QQ).complete()
                sage: M = QuasiSymmetricFunctions(QQ).Monomial()
                sage: S.duality_pairing_matrix(M, 3)
                [1 0 0 0]
                [0 1 0 0]
                [0 0 1 0]
                [0 0 0 1]
                sage: M.duality_pairing_matrix(S, 3)
                [1 0 0 0]
                [0 1 0 0]
                [0 0 1 0]
                [0 0 0 1]

            The matrix between the ribbon basis of NCSF and the monomial
            basis of QSym::

                sage: R = NonCommutativeSymmetricFunctions(QQ).ribbon()
                sage: M = QuasiSymmetricFunctions(QQ).Monomial()
                sage: R.duality_pairing_matrix(M, 3)
                [ 1 -1 -1  1]
                [ 0  1  0 -1]
                [ 0  0  1 -1]
                [ 0  0  0  1]
                sage: M.duality_pairing_matrix(R, 3)
                [ 1  0  0  0]
                [-1  1  0  0]
                [-1  0  1  0]
                [ 1 -1 -1  1]

            The matrix between the complete basis of NCSF and the
            fundamental basis of QSym::

                sage: S = NonCommutativeSymmetricFunctions(QQ).complete()
                sage: F = QuasiSymmetricFunctions(QQ).Fundamental()
                sage: S.duality_pairing_matrix(F, 3)
                [1 1 1 1]
                [0 1 0 1]
                [0 0 1 1]
                [0 0 0 1]

            A base case test::

                sage: R.duality_pairing_matrix(M,0)
                [1]
            """
            from sage.matrix.constructor import matrix
            # TODO: generalize to keys indexing the basis of the graded component
            from sage.combinat.composition import Compositions
            return matrix(self.base_ring(),
                    [[self.duality_pairing(self[I], basis[J]) \
                            for J in Compositions(degree)] \
                            for I in Compositions(degree)])
Example #22
0
def number_of_SSRCT(content_comp, shape_comp):
    r"""
    The number of semi-standard reverse composition tableaux.

    The dual quasisymmetric-Schur functions satisfy a left Pieri rule
    where `S_n dQS_\gamma` is a sum over dual quasisymmetric-Schur
    functions indexed by compositions which contain the composition
    `\gamma`.  The definition of an SSRCT comes from this rule.  The
    number of SSRCT of content `\beta` and shape `\alpha` is equal to
    the number of SSRCT of content `(\beta_2, \ldots, \beta_\ell)`
    and shape `\gamma` where `dQS_\alpha` appears in the expansion of
    `S_{\beta_1} dQS_\gamma`.

    In sage the recording tableau for these objects are called
    :class:`~sage.combinat.composition_tableau.CompositionTableaux`.

    INPUT:

    - ``content_comp``, ``shape_comp`` -- compositions

    OUTPUT:

    - An integer

    EXAMPLES::

        sage: from sage.combinat.ncsf_qsym.combinatorics import number_of_SSRCT
        sage: number_of_SSRCT(Composition([3,1]), Composition([1,3]))
        0
        sage: number_of_SSRCT(Composition([1,2,1]), Composition([1,3]))
        1
        sage: number_of_SSRCT(Composition([1,1,2,2]), Composition([3,3]))
        2
        sage: all(CompositionTableaux(be).cardinality()
        ....:     == sum(number_of_SSRCT(al,be)*binomial(4,len(al))
        ....:            for al in Compositions(4))
        ....:     for be in Compositions(4))
        True
    """
    if len(content_comp) == 1:
        if len(shape_comp) == 1:
            return ZZ.one()
        else:
            return ZZ.zero()
    s = ZZ.zero()
    cond = lambda al, be: all(al[j] <= be_val and not any(al[
        i] <= k and k <= be[i] for k in range(al[j], be_val) for i in range(j))
                              for j, be_val in enumerate(be))
    C = Compositions(content_comp.size() - content_comp[0],
                     inner=[1] * len(shape_comp),
                     outer=list(shape_comp))
    for x in C:
        if cond(x, shape_comp):
            s += number_of_SSRCT(Composition(content_comp[1:]), x)
    if shape_comp[0] <= content_comp[0]:
        C = Compositions(
            content_comp.size() - content_comp[0],
            inner=[min(val, shape_comp[0] + 1) for val in shape_comp[1:]],
            outer=shape_comp[1:])
        Comps = Compositions()
        for x in C:
            if cond([shape_comp[0]] + list(x), shape_comp):
                s += number_of_SSRCT(Comps(content_comp[1:]), x)
    return s
def LyndonWords(e=None, k=None):
    """
    Returns the combinatorial class of Lyndon words.

    A Lyndon word `w` is a word that is lexicographically less than all of
    its rotations.  Equivalently, whenever `w` is split into two non-empty
    substrings, `w` is lexicographically less than the right substring.

    INPUT:

    - no input at all

    or

    - ``e`` - integer, size of alphabet
    - ``k`` - integer, length of the words

    or

    - ``e`` - a composition

    OUTPUT:

    A combinatorial class of Lyndon words.

    EXAMPLES::

        sage: LyndonWords()
        Lyndon words

    If e is an integer, then e specifies the length of the
    alphabet; k must also be specified in this case::

        sage: LW = LyndonWords(3,3); LW
        Lyndon words from an alphabet of size 3 of length 3
        sage: LW.first()
        word: 112
        sage: LW.last()
        word: 233
        sage: LW.random_element()
        word: 112
        sage: LW.cardinality()
        8

    If e is a (weak) composition, then it returns the class of Lyndon
    words that have evaluation e::

        sage: LyndonWords([2, 0, 1]).list()
        [word: 113]
        sage: LyndonWords([2, 0, 1, 0, 1]).list()
        [word: 1135, word: 1153, word: 1315]
        sage: LyndonWords([2, 1, 1]).list()
        [word: 1123, word: 1132, word: 1213]
    """
    if e is None and k is None:
        return LyndonWords_class()
    elif isinstance(e, (int, Integer)):
        if e > 0:
            if not isinstance(k, (int, Integer)):
                raise TypeError("k must be a non-negative integer")
            if k < 0:
                raise TypeError("k must be a non-negative integer")
            return LyndonWords_nk(e, k)
    elif e in Compositions():
        return LyndonWords_evaluation(e)

    raise TypeError("e must be a positive integer or a composition")
Example #24
0
    def __classcall_private__(cls, *args, **kwargs):
        r"""
        This is a factory class which returns the appropriate parent based on
        arguments.  See the documentation for :class:`CompositionTableaux` for
        more information.

        TESTS::

            sage: CT = CompositionTableaux(3); CT
            Composition Tableaux of size 3 and maximum entry 3
            sage: CT = CompositionTableaux(size=3); CT
            Composition Tableaux of size 3 and maximum entry 3
            sage: CT = CompositionTableaux([1,2]); CT
            Composition tableaux of shape [1, 2] and maximun entry 3
            sage: CT = CompositionTableaux(shape=[1,2]); CT
            Composition tableaux of shape [1, 2] and maximun entry 3
            sage: CT = CompositionTableaux(shape=[]); CT
            Composition tableaux of shape [] and maximun entry 0
            sage: CT = CompositionTableaux(0); CT
            Composition Tableaux of size 0 and maximum entry 0
            sage: CT = CompositionTableaux(max_entry=3); CT
            Composition tableaux with maximum entry 3
            sage: CT = CompositionTableaux([1,2],max_entry=3); CT
            Composition tableaux of shape [1, 2] and maximun entry 3
            sage: CT = CompositionTableaux(size=2,shape=[1,2]); CT
            Traceback (most recent call last):
            ...
            ValueError: size and shape are different sizes
        """
        # Process keyword arguments first
        n = kwargs.get('n', None)
        size = kwargs.get('size', n)

        comp = kwargs.get('comp', None)
        shape = kwargs.get('shape', comp)

        max_entry = kwargs.get('max_entry', None)

        # Process positional arguments
        if args:
            # The first arg could be either a size or a shape
            if isinstance(args[0], (int, Integer)):
                if size is not None:
                    raise ValueError("size was specified more than once")
                else:
                    size = args[0]
            else:
                if shape is not None:
                    raise ValueError("the shape was specified more than once")
                shape = args[0]

        # Consistency checks
        if size is not None:
            if not isinstance(size, (int, Integer)):
                raise ValueError("size must be an integer")
            elif size < 0:
                raise ValueError("size must be non-negative")

        if shape is not None:
            # use in (and not isinstance) below so that lists can be used as
            # shorthand
            if not shape in Compositions():
                raise ValueError("shape must be a composition")
            if any(i == 0 for i in shape):
                raise ValueError("shape must have non-zero parts")
            shape = Composition(shape)

        if (size is not None) and (shape is not None):
            if sum(shape) != size:
                raise ValueError("size and shape are different sizes")

        if max_entry is not None:
            if not isinstance(max_entry, (int, Integer)):
                raise ValueError("max_entry must be an integer")
            elif max_entry <= 0:
                raise ValueError("max_entry must be positive")

        # Dispatch to appropriate class
        if (shape is not None):
            return CompositionTableaux_shape(shape, max_entry)

        if (size is not None):
            return CompositionTableaux_size(size, max_entry)

        return CompositionTableaux_all(max_entry)