Esempio n. 1
0
        def coproduct_on_basis(self, compo):
            r"""
            Returns the coproduct of a Monomial basis element.

            Combinatorial rule: deconcatenation.

            INPUT:

            - ``compo`` -- composition

            OUTPUT:

            - The coproduct applied to the Monomial quasi-symmetric function indexed by
              ``compo``, expressed in the Monomial basis.

            EXAMPLES::

                sage: M=QuasiSymmetricFunctions(QQ).Monomial()
                sage: M[4,2,3].coproduct()
                M[] # M[4, 2, 3] + M[4] # M[2, 3] + M[4, 2] # M[3] + M[4, 2, 3] # M[]
                sage: M.coproduct_on_basis(Composition([]))
                M[] # M[]

            """
            return self.tensor_square().sum_of_monomials((Composition(compo[:i]), Composition(compo[i:]))
                                                         for i in range(0,len(compo)+1))
Esempio n. 2
0
    def __classcall__(cls, row_sums, column_sums):
        r"""
        Normalize the inputs so that they are hashable.

        INPUT:

        - ``row_sums`` -- list, tuple, or anything defining a Composition
        - ``column_sums`` -- list, tuple, or anything defining a Composition

        EXAMPLES::

            sage: from sage.combinat.integer_matrices import IntegerMatrices
            sage: IM = IntegerMatrices([4,4,5], [3,7,1,2]); IM
            Non-negative integer matrices with row sums [4, 4, 5] and column sums [3, 7, 1, 2]
            sage: IM = IntegerMatrices((4,4,5), (3,7,1,2)); IM
            Non-negative integer matrices with row sums [4, 4, 5] and column sums [3, 7, 1, 2]
            sage: IM = IntegerMatrices(Composition([4,4,5]), Composition([3,7,1,2])); IM
            Non-negative integer matrices with row sums [4, 4, 5] and column sums [3, 7, 1, 2]

        """
        from sage.combinat.composition import Composition
        row_sums = Composition(row_sums)
        column_sums = Composition(column_sums)
        return super(IntegerMatrices,
                     cls).__classcall__(cls, row_sums, column_sums)
Esempio n. 3
0
        def __getitem__(self, c, *rest):
            """
            This method implements the abuses of notations::

                sage: Psi = NonCommutativeSymmetricFunctions(QQ).Psi()
                sage: Psi[2,1]
                Psi[2, 1]
                sage: Psi[[2,1]]
                Psi[2, 1]
                sage: Psi[Composition([2,1])]
                Psi[2, 1]

            .. todo::

                This should call ``super.monomial`` if the input can't
                be made into a composition so as not to interfere with
                the standard notation ``Psi['x,y,z']``.

                This could possibly be shared with Sym, FQSym, and
                other algebras with bases indexed by list-like objects
            """
            if isinstance(c, Composition):
                assert len(rest) == 0
            else:
                if len(rest) > 0 or isinstance(c, (int, Integer)):
                    c = Composition([c] + list(rest))
                else:
                    c = Composition(list(c))
            return self.monomial(c)
Esempio n. 4
0
def m_to_s_stat(R, I, K):
    r"""
    Returns the statistic for the expansion of the Monomial basis element indexed by two
    compositions, as in formula (36) of Tevlin's "Noncommutative Analogs of Monomial Symmetric
    Functions, Cauchy Identity, and Hall Scalar Product".

    INPUT:

    - ``R`` -- A ring
    - ``I``, ``K`` -- compositions

    OUTPUT:

    - An integer

    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
    """
    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
Esempio n. 5
0
    def to_composition(self, x):
        r"""
        The composition corresponding to the integer matrix.

        This is the composition obtained by reading the entries of the matrix
        from left to right along each row, and reading the rows from top to
        bottom, ignore zeros.

        INPUT:

        - ``x`` -- matrix

        EXAMPLES::

            sage: from sage.combinat.integer_matrices import IntegerMatrices
            sage: IM = IntegerMatrices([3,2,2], [2,5]); IM
            Non-negative integer matrices with row sums [3, 2, 2] and column sums [2, 5]
            sage: IM.list()
            [
            [2 1]  [1 2]  [1 2]  [0 3]  [0 3]  [0 3]
            [0 2]  [1 1]  [0 2]  [2 0]  [1 1]  [0 2]
            [0 2], [0 2], [1 1], [0 2], [1 1], [2 0]
            ]
            sage: for m in IM: print(IM.to_composition(m))
            [2, 1, 2, 2]
            [1, 2, 1, 1, 2]
            [1, 2, 2, 1, 1]
            [3, 2, 2]
            [3, 1, 1, 1, 1]
            [3, 2, 2]
        """
        from sage.combinat.composition import Composition
        return Composition([entry for row in x for entry in row if entry != 0])
Esempio n. 6
0
        def sum_of_partition_rearrangements(self, par):
            """
            Returns the sum of all basis elements indexed by compositions which can be
            shuffled to obtain a partition.

            INPUT:

            - ``par`` -- a partition

            OUTPUT:

            - Returns the sum of all ``self`` basis elements indexed by compositions which
              are shuffles of ``par``.

            EXAMPLES::

                sage: NCSF=NonCommutativeSymmetricFunctions(QQ)
                sage: elementary = NCSF.elementary()
                sage: elementary.sum_of_partition_rearrangements(Partition([2,2,1]))
                L[1, 2, 2] + L[2, 1, 2] + L[2, 2, 1]
                sage: elementary.sum_of_partition_rearrangements(Partition([3,2,1]))
                L[1, 2, 3] + L[1, 3, 2] + L[2, 1, 3] + L[2, 3, 1] + L[3, 1, 2] + L[3, 2, 1]
                sage: elementary.sum_of_partition_rearrangements(Partition([]))
                L[]
            """
            return self.sum_of_monomials( Composition(comp) for comp in Permutations(par) )
Esempio n. 7
0
    def __classcall_private__(cls, s=None, c=None):
        """
        Choose the correct parent based upon input.

        EXAMPLES::

            sage: OrderedSetPartitions(4)
            Ordered set partitions of {1, 2, 3, 4}
            sage: OrderedSetPartitions(4, [1, 2, 1])
            Ordered set partitions of {1, 2, 3, 4} into parts of size [1, 2, 1]
        """
        if s is None:
            if c is not None:
                raise NotImplementedError(
                    "cannot specify 'c' without specifying 's'")
            return OrderedSetPartitions_all()
        if isinstance(s, (int, Integer)):
            if s < 0:
                raise ValueError("s must be non-negative")
            s = frozenset(range(1, s + 1))
        else:
            s = frozenset(s)

        if c is None:
            return OrderedSetPartitions_s(s)

        if isinstance(c, (int, Integer)):
            return OrderedSetPartitions_sn(s, c)
        if c not in Compositions(len(s)):
            raise ValueError("c must be a composition of %s" % len(s))
        return OrderedSetPartitions_scomp(s, Composition(c))
Esempio n. 8
0
def number_of_fCT(content_comp, shape_comp):
    r"""
    Returns the number of Immaculate tableau of shape ``shape_comp`` and content ``content_comp``.

    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
Esempio n. 9
0
    def __init__(self, s, comp):
        """
        TESTS::

            sage: OS = OrderedSetPartitions([1,2,3,4], [2,1,1])
            sage: OS == loads(dumps(OS))
            True
        """
        OrderedSetPartitions.__init__(self, s)
        self.c = Composition(comp)
    def __init__(self, e):
        """
        TESTS::

            sage: LW21 = LyndonWords([2,1]); LW21
            Lyndon words with evaluation [2, 1]
            sage: LW21 == loads(dumps(LW21))
            True
        """
        self.e = Composition(e)
Esempio n. 11
0
    def descent_composition(self):
        r"""
        Return the composition corresponding to the set of all `i` that do
        not have `i+1` appearing strictly to the left of `i` in ``self``.

        EXAMPLES::

            sage: CompositionTableau([[1],[3,2],[4,4]]).descent_composition()
            [1, 2, 2]
        """
        return Composition(from_subset=(self.descent_set(), self.size()))
Esempio n. 12
0
    def shape_composition(self):
        r"""
        Return a Composition object which is the shape of ``self``.

        EXAMPLES::

            sage: CompositionTableau([[1,1],[3,2],[4,4,3]]).shape_composition()
            [2, 2, 3]
            sage: CompositionTableau([[2,1],[3],[4]]).shape_composition()
            [2, 1, 1]
        """
        return Composition([len(row) for row in self])
Esempio n. 13
0
 def __init__(self, e):
     """
     TESTS::
     
         sage: N = Necklaces([2,2,2])
         sage: N == loads(dumps(N))
         True
     """
     if isinstance(e, Composition):
         self.e = e
     else:
         self.e = Composition(e)
Esempio n. 14
0
    def __classcall_private__(cls, content):
        """
        Return the correct parent object, with standardized parameters.

        EXAMPLES::

            sage: Necklaces([2,1,1]) is Necklaces(Composition([2,1,1]))
            True
        """
        if isinstance(content, Composition):
            return super(Necklaces_evaluation, cls).__classcall__(cls, content)
        else:
            content = Composition(content)
            return super(Necklaces_evaluation, cls).__classcall__(cls, content)
Esempio n. 15
0
    def __init__(self, content):
        r"""
        Initialize ``self``.

        TESTS::

            sage: N = Necklaces([2,2,2])
            sage: N == loads(dumps(N))
            True
        """
        if isinstance(content, Composition):
            self._content = content
        else:
            self._content = Composition(content)
Esempio n. 16
0
    def weight(self):
        r"""
        Return a composition where entry `i` is the number of times that `i` appears in
        ``self``.

        EXAMPLES::

            sage: CompositionTableau([[1],[3,2],[4,4]]).weight()
            [1, 1, 1, 2, 0]
        """
        w = {i: 0 for i in range(1, self.size() + 1)}
        for row in self:
            for i in row:
                w[i] += 1
        return Composition([w[i] for i in range(1, self.size() + 1)])
Esempio n. 17
0
    def to_composition(self):
        r"""
        Return the integer composition whose parts are the sizes of the sets
        in ``self``.

        EXAMPLES::

            sage: S = OrderedSetPartitions(5)
            sage: x = S([[3,5,4], [1, 2]])
            sage: x.to_composition()
            [3, 2]
            sage: y = S([[3,1], [2], [5,4]])
            sage: y.to_composition()
            [2, 1, 2]
        """
        return Composition([len(p) for p in self])
Esempio n. 18
0
    def __iter__(self):
        """
        TESTS::

            sage: LyndonWords(3,3).list() # indirect doctest
            [word: 112, word: 113, word: 122, word: 123, word: 132, word: 133, word: 223, word: 233]
        """
        for c in IntegerVectors(self._k, self._n):
            cf = []
            nonzero_indices = []
            for i, x in enumerate(c):
                if x:
                    nonzero_indices.append(i)
                    cf.append(x)
            for lw in LyndonWords_evaluation(Composition(cf)):
                yield self._words([nonzero_indices[x - 1] + 1 for x in lw],
                                  check=False)
Esempio n. 19
0
        def one_basis(self):
            r"""
            This returns 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 Composition([])
Esempio n. 20
0
    def to_composition(self):
        r"""
        Concatenate the antisymmetric and symmetric parts to a composition.

        OUTPUT:

        - a (possibly weak) composition

        EXAMPLES::

            sage: SuperPartition([[3,1],[2,2,1]]).to_composition()
            [3, 1, 2, 2, 1]
            sage: SuperPartition([[2,1,0],[3,3]]).to_composition()
            [2, 1, 0, 3, 3]
            sage: SuperPartition([[2,1,0],[3,3]]).to_composition().parent()
            Compositions of non-negative integers
        """
        return Composition(self[0] + self[1])
Esempio n. 21
0
def descent_composition(t):
    """
    Return the descent composition of a standard tableau ``t``.

    This is the composition of the size of `t` whose partial
    sums are the elements of the descent set of ``t`` (see
    :meth:`descent_set`).

    EXAMPLES::

        sage: from sage.combinat.chas.fsym import descent_composition
        sage: t = StandardTableau([[1,3,4,7],[2,5,6],[8]])
        sage: descent_composition(t)
        [1, 3, 3, 1]
        sage: descent_composition([[1, 3, 5], [2, 4]])
        [1, 2, 2]
    """
    n = sum(len(row) for row in t)
    return Composition(from_subset=(descent_set(t), n))
Esempio n. 22
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
Esempio n. 23
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 shape(self):
     from sage.combinat.composition import Composition
     return Composition([len(B) for B in self.value])
Esempio n. 25
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)
Esempio n. 26
0
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() # random
        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(Integer(e), Integer(k))
    elif e in Compositions():
        return LyndonWords_evaluation(Composition(e))

    raise TypeError("e must be a positive integer or a composition")
Esempio n. 27
0
    def from_polynomial(self, f, check=True):
        """
        Returns the quasi-symmetric function in the Monomial basis
        corresponding to the quasi-symmetric polynomial ``f``.

        INPUT:

        - ``f`` -- a polynomial in finitely many variables over the same base
          ring as ``self``. It is assumed that this polynomial is
          quasi-symmetric.
        - ``check`` -- boolean (default: ``True``), checks whether the
          polynomial is indeed quasi-symmetric.

        OUTPUT:

        - quasi-symmetric function in the Monomial basis

        EXAMPLES::

            sage: P = PolynomialRing(QQ, 'x', 3)
            sage: x = P.gens()
            sage: f = x[0] + x[1] + x[2]
            sage: QSym = QuasiSymmetricFunctions(QQ)
            sage: QSym.from_polynomial(f)
            M[1]

        Beware of setting ``check=False``::

            sage: f = x[0] + 2*x[1] + x[2]
            sage: QSym.from_polynomial(f, check=True)
            Traceback (most recent call last):
            ...
            ValueError: x0 + 2*x1 + x2 is not a quasi-symmetric polynomial
            sage: QSym.from_polynomial(f, check=False)
            M[1]

        To expand the quasi-symmetric function in a basis other than the
        Monomial basis, the following shorthands are provided::

            sage: M = QSym.Monomial()
            sage: f = x[0]**2+x[1]**2+x[2]**2
            sage: g = M.from_polynomial(f); g
            M[2]
            sage: F = QSym.Fundamental()
            sage: F(g)
            -F[1, 1] + F[2]
            sage: F.from_polynomial(f)
            -F[1, 1] + F[2]

        """
        assert self.base_ring() == f.base_ring()
        exponent_coefficient = f.dict()
        z = {}
        for (e, c) in exponent_coefficient.iteritems():
            I = Composition([ei for ei in e if ei > 0])
            if I not in z:
                z[I] = c
        out = self.Monomial()._from_dict(z)
        if check and out.expand(f.parent().ngens(), f.parent().gens()) != f:
            raise ValueError("%s is not a quasi-symmetric polynomial" % f)
        return out
Esempio n. 28
0
    def _proc(self, vect):
        """
        Return the shuffle of ``w1`` with ``w2`` with 01-vector
        ``vect``.

        The 01-vector of a shuffle is a list of 0s and 1s whose
        length is the sum of the lengths of ``w1`` and ``w2``,
        and whose `k`-th entry is `1` if the `k`-th letter of
        the shuffle is taken from ``w1`` and `0` if it is taken
        from ``w2``.

        EXAMPLES::

            sage: from sage.combinat.words.shuffle_product import ShuffleProduct_w1w2
            sage: w, u = map(Words("abcd"), ["ab", "cd"])
            sage: S = ShuffleProduct_w1w2(w,u)
            sage: S._proc([0,1,0,1])
            word: cadb
            sage: S._proc([1,1,0,0])
            word: abcd

            sage: I = Composition([1, 1])
            sage: J = Composition([2])
            sage: S = ShuffleProduct_w1w2(I, J)
            sage: S._proc([1,0,1])
            [1, 2, 1]

        TESTS:

        Sage is no longer confused by a too-restrictive parent
        of `I` when shuffling two compositions `I` and `J`
        (cf. :trac:`15131`)::

            sage: I = Compositions(2)([1, 1])
            sage: J = Composition([2])
            sage: S = ShuffleProduct_w1w2(I, J)
            sage: S._proc([1,0,1])
            [1, 2, 1]
            sage: S.list()
            [[1, 1, 2], [1, 2, 1], [2, 1, 1]]
        """
        i1 = -1
        i2 = -1
        res = []
        for v in vect:
            if v == 1:
                i1 += 1
                res.append(self._w1[i1])
            else:
                i2 += 1
                res.append(self._w2[i2])
        try:
            return self._w1.parent()(res)
        except ValueError:
            # Special situation: the parent of w1 is too
            # restrictive to be cast on res.
            if isinstance(self._w1, Composition):
                return Composition(res)
            elif isinstance(self._w1, Word_class):
                return Word(res)
            return res