Esempio n. 1
0
    def __init__(self, R):
        """
        The Hopf algebra of quasi-symmetric functions.
        See ``QuasiSymmetricFunctions`` for full documentation.

        EXAMPLES::

            sage: QuasiSymmetricFunctions(QQ)
            Quasisymmetric functions over the Rational Field
            sage: TestSuite(QuasiSymmetricFunctions(QQ)).run()

        """
        assert R in Rings()
        self._base = R  # Won't be needed once CategoryObject won't override base_ring
        category = GradedHopfAlgebras(R)  # TODO: .Commutative()
        Parent.__init__(self, category=category.WithRealizations())

        # Bases
        Monomial = self.Monomial()
        Fundamental = self.Fundamental()
        dualImmaculate = self.dualImmaculate()

        # Change of bases
        Fundamental.module_morphism(Monomial.sum_of_finer_compositions,
                                    codomain=Monomial,
                                    category=category).register_as_coercion()
        Monomial.module_morphism(
            Fundamental.alternating_sum_of_finer_compositions,
            codomain=Fundamental,
            category=category).register_as_coercion()
        #This changes dualImmaculate into Monomial
        dualImmaculate.module_morphism(
            dualImmaculate._to_Monomial_on_basis,
            codomain=Monomial,
            category=category).register_as_coercion()
        #This changes Monomial into dualImmaculate
        Monomial.module_morphism(dualImmaculate._from_Monomial_on_basis,
                                 codomain=dualImmaculate,
                                 category=category).register_as_coercion()
        # Embedding of Sym into QSym in the monomial bases
        Sym = SymmetricFunctions(self.base_ring())
        Sym_m_to_M = Sym.m().module_morphism(
            Monomial.sum_of_partition_rearrangements,
            triangular='upper',
            inverse_on_support=Monomial._comp_to_par,
            codomain=Monomial,
            category=category)
        Sym_m_to_M.register_as_coercion()
        self.to_symmetric_function = Sym_m_to_M.section()
Esempio n. 2
0
    def __init__(self, R):
        """
        The Hopf algebra of quasi-symmetric functions.
        See ``QuasiSymmetricFunctions`` for full documentation.

        EXAMPLES::

            sage: QuasiSymmetricFunctions(QQ)
            Quasisymmetric functions over the Rational Field
            sage: TestSuite(QuasiSymmetricFunctions(QQ)).run()

        """
        assert R in Rings()
        self._base = R # Won't be needed once CategoryObject won't override base_ring
        category = GradedHopfAlgebras(R)  # TODO: .Commutative()
        Parent.__init__(self, category = category.WithRealizations())

        # Bases
        Monomial    = self.Monomial()
        Fundamental = self.Fundamental()
        dualImmaculate = self.dualImmaculate()

        # Change of bases
        Fundamental.module_morphism(Monomial.sum_of_finer_compositions,
                                    codomain=Monomial, category=category
                                    ).register_as_coercion()
        Monomial   .module_morphism(Fundamental.alternating_sum_of_finer_compositions,
                                    codomain=Fundamental, category=category
                                    ).register_as_coercion()
        #This changes dualImmaculate into Monomial
        dualImmaculate.module_morphism(dualImmaculate._to_Monomial_on_basis,
                                          codomain = Monomial, category = category
                                          ).register_as_coercion()
        #This changes Monomial into dualImmaculate
        Monomial.module_morphism(dualImmaculate._from_Monomial_on_basis,
                                          codomain = dualImmaculate, category = category
                                          ).register_as_coercion()
        # Embedding of Sym into QSym in the monomial bases
        Sym = SymmetricFunctions(self.base_ring())
        Sym_m_to_M = Sym.m().module_morphism(Monomial.sum_of_partition_rearrangements,
                                           triangular='upper', inverse_on_support=Monomial._comp_to_par,
                                           codomain=Monomial, category=category)
        Sym_m_to_M.register_as_coercion()
        self.to_symmetric_function = Sym_m_to_M.section()
Esempio n. 3
0
def polarizationSpace(P, generators, verbose=False, row_symmetry=None, use_commutativity=False, side="down"):
    """
    Starting from  polynomials (generators)of the polynomial ring in one 
    set of variables (possibly with additional inert variables), constructs
    the space obtained by polarization.
    
    The possible values for row_symmetry : 
        - "permutation" : the action of the symmetric group on the rows
        - "euler+intersection" or "decompose" or "multipolarization" for stategies on lie algebras
    
    INPUT:
    
        - `P` -- a diagonal polynomial ring (or assymmetric version)
        - `generators`: polynomials in one set of variables (and possibly inert variables) 
            
    OUTPUT: `F`  -- a Subspace

    EXAMPLES::
        sage: load("derivative_space.py")
        sage: P = DiagonalPolynomialRing(QQ, 3, 2, inert=1)
        sage: mu = Partition([3])
        sage: basis = DerivativeHarmonicSpace(QQ, mu.size()).basis_by_shape(Partition([2,1]))
        sage: generators = {}
        sage: for gen in basis : 
        ....:     d = P.multidegree((P(gen)))
        ....:     if d in generators.keys():
        ....:         generators[d] += [P(gen)]
        ....:     else:
        ....:         generators[d] = [P(gen)]
        sage: generators
        {(2, 0): [1/3*x00^2 - 2/3*x00*x01 + 2/3*x01*x02 - 1/3*x02^2],
         (1, 0): [-2*x00 + 2*x02]}
        sage: S = polarizationSpace(P, generators)
        sage: S.basis()
        {(0, 1): (x10 - x12,),
         (2, 0): (-1/2*x00^2 + x00*x01 - x01*x02 + 1/2*x02^2,),
         (1, 0): (x00 - x02,),
         (1, 1): (x00*x10 - x01*x10 - x00*x11 + x02*x11 + x01*x12 - x02*x12,),
         (0, 2): (1/2*x10^2 - x10*x11 + x11*x12 - 1/2*x12^2,)}
         
        sage: basis = DerivativeVandermondeSpaceWithInert(QQ, mu).basis_by_shape(Partition([1,1,1]))
        sage: generators = {P.multidegree(P(gen)): [P(gen) for gen in g] for (d,g) in basis.iteritems()}
        sage: generators
        {(3, 0): [-x00^2*x01 + x00*x01^2 + x00^2*x02 - x01^2*x02 - x00*x02^2 + x01*x02^2]}
        sage: S = polarizationSpace(P, generators)
        sage: S.basis()
        {(1, 2): (-1/2*x01*x10^2 + 1/2*x02*x10^2 - x00*x10*x11 + x01*x10*x11 + 1/2*x00*x11^2 - 1/2*x02*x11^2 + x00*x10*x12 - x02*x10*x12 - x01*x11*x12 + x02*x11*x12 - 1/2*x00*x12^2 + 1/2*x01*x12^2,),
         (3, 0): (x00^2*x01 - x00*x01^2 - x00^2*x02 + x01^2*x02 + x00*x02^2 - x01*x02^2,),
         (0, 3): (x10^2*x11 - x10*x11^2 - x10^2*x12 + x11^2*x12 + x10*x12^2 - x11*x12^2,),
         (1, 1): (-x01*x10 + x02*x10 + x00*x11 - x02*x11 - x00*x12 + x01*x12,),
         (2, 1): (-x00*x01*x10 + 1/2*x01^2*x10 + x00*x02*x10 - 1/2*x02^2*x10 - 1/2*x00^2*x11 + x00*x01*x11 - x01*x02*x11 + 1/2*x02^2*x11 + 1/2*x00^2*x12 - 1/2*x01^2*x12 - x00*x02*x12 + x01*x02*x12,)}
        
        sage: mu = Partition([2,1])
        sage: basis = DerivativeVandermondeSpaceWithInert(QQ, mu).basis_by_shape(Partition([2,1]))
        sage: generators = {P.multidegree(P(gen)): [P(gen) for gen in g] for (d,g) in basis.iteritems()}
        sage: generators
        {(0, 0): [-theta00 + theta02]}
        sage: S = polarizationSpace(P, generators)
        sage: S.basis()
        {(0, 0): (theta00 - theta02,)}

    """
    S = SymmetricFunctions(QQ)
    s = S.s()
    m = S.m()
    r = P._r
    
    if isinstance(P, DiagonalAntisymmetricPolynomialRing):
        antisymmetries = P._antisymmetries
    else:
        antisymmetries = None
        
    if row_symmetry in ("euler+intersection", "decompose", "multipolarization")  :
        # The hilbert series will be directly expressed in terms of the
        # dimensions of the highest weight spaces, thus as a symmetric
        # function in the Schur basis
        def hilbert_parent(dimensions):
            return s.sum_of_terms([Partition(d), c]
                                   for d,c in dimensions.iteritems() if c)
    elif row_symmetry == "permutation":
        def hilbert_parent(dimensions):
            return s(m.sum_of_terms([Partition(d), c]
                                     for d,c in dimensions.iteritems())
                    ).restrict_partition_lengths(r, exact=False)
    else:
        def hilbert_parent(dimensions):
            return s(S.from_polynomial(P._hilbert_parent(dimensions))
                    ).restrict_partition_lengths(r,exact=False)

    operators = polarization_operators_by_multidegree(P, side=side, row_symmetry=row_symmetry, min_degree=1 if row_symmetry and row_symmetry!="permutation" else 0)
    #ajout operateurs Steenrod
    #for i in range(1, r):
    #    for d in [2,3]:
    #        operators[P._grading_set((-d+1 if j==i else 0 for j in range(0,r)))] = [functools.partial(P.steenrod_op, i=i, k=d)]
    
    if row_symmetry == "euler+intersection":
        operators[P._grading_set.zero()] = [
            functools.partial(lambda v,i: P.polarization(P.polarization(v, i+1, i, 1, antisymmetries=antisymmetries), i, i+1, 1, antisymmetries=antisymmetries), i=i)
            for i in range(r-1)]
    elif row_symmetry == "decompose":
        def post_compose(f):
            return lambda x: [q for (q,word) in P.highest_weight_vectors_decomposition(f(x))]
        operators = {d: [post_compose(op) for op in ops]for d, ops in operators.iteritems()}
    elif row_symmetry == "multipolarization":
        F = HighestWeightSubspace(generators,
                 ambient=self,
                 add_degrees=add_degree, degree=P.multidegree,
                 hilbert_parent = hilbert_parent,
                 antisymmetries=antisymmetries,
                 verbose=verbose)
        return F
        
    operators_by_degree = {}
    for degree,ops in operators.iteritems(): 
        d = sum(degree)
        operators_by_degree.setdefault(d,[])
        operators_by_degree[d].extend(ops)

    ranks = {}
    for d, ops in operators_by_degree.iteritems():
        ranker = rank_from_list(ops)
        for op in ops:
            ranks[op] = (d, ranker(op))
    ranker = ranks.__getitem__
    def extend_word(word, op):
        new_word = word + [ranker(op)]
        if use_commutativity and sorted(new_word) != new_word:
            return None
        return new_word

    if row_symmetry == "permutation":
        add_deg = add_degree_symmetric
    else:
        add_deg = add_degree
    
    F = Subspace(generators, operators=operators,
                 add_degrees=add_deg, degree=P.multidegree,
                 hilbert_parent = hilbert_parent,
                 extend_word=extend_word, verbose=verbose) 
    F._antisymmetries = antisymmetries
    return F
Esempio n. 4
0
def higher_specht(R, P, Q=None, harmonic=False, use_antisymmetry=False):
    """
    Return a basis element of the coinvariants

    INPUT:

    - `R` -- a polynomial ring
    - `P` -- a standard tableau of some shape `\lambda`, or a partition `\lambda`
    - `Q` -- a standard tableau of shape `\lambda`
             (default: the initial tableau of shape `\lambda`)

    - ``harmonic`` -- a boolean (default False)

    The family `(H_{P,Q})_{P,Q}` is a basis of the space of `R_{S_n}`
    coinvariants in `R` which is compatible with the action of the
    symmetric group: namely, for each `P`, the family `(H_{P,Q})_Q`
    forms the basis of an `S_n`-irreducible module `V_{P}` of type
    `\lambda`.

    If `P` is a partition `\lambda` or equivalently the initial
    tableau of shape `\lambda`, then `H_{P,Q}` is the usual Specht
    polynomial, and `V_P` the Specht module.

    EXAMPLES::

        sage: Tableaux.options.convention="french"

        sage: R = PolynomialRing(QQ, 'x,y,z')
        sage: for la in Partitions(3):
        ....:     for P in StandardTableaux(la):
        ....:         for Q in StandardTableaux(la):
        ....:             print(ascii_art(la, P, Q, factor(higher_specht(R, P, Q)), sep="    "))
        ....:             print
            ***      1  2  3      1  2  3    2 * 3
            <built-in function print>
            *       2         2       
            **      1  3      1  3    (-1) * z * (x - y)
            <built-in function print>
            *       2         3       
            **      1  3      1  2    (-1) * y * (x - z)
            <built-in function print>
            *       3         2       
            **      1  2      1  3    (-2) * (x - y)
            <built-in function print>
            *       3         3       
            **      1  2      1  2    (-2) * (x - z)
            <built-in function print>
            *      3      3    
            *      2      2    
            *      1      1    (y - z) * (-x + y) * (x - z)
            <built-in function print>


        sage: factor(higher_specht(R, Partition([2,1])))
        (-2) * (x - z)

        sage: for la in Partitions(3):
        ....:     for P in StandardTableaux(la):
        ....:         print(ascii_art(la, P, factor(higher_specht(R, P)), sep="    "))
        ....:         print
            ***      1  2  3    2 * 3
            <built-in function print>
            *       2       
            **      1  3    (-1) * y * (x - z)
            <built-in function print>
            *       3       
            **      1  2    (-2) * (x - z)
            <built-in function print>
            *      3    
            *      2    
            *      1    (y - z) * (-x + y) * (x - z)
            <built-in function print>


        sage: R = PolynomialRing(QQ, 'x,y,z')
        sage: for la in Partitions(3):
        ....:     for P in StandardTableaux(la):
        ....:         for Q in StandardTableaux(la):
        ....:             print(ascii_art(la, P, Q, factor(higher_specht(R, P, Q, harmonic=True)), sep="    "))
        ....:             print
        ***      1  2  3      1  2  3    2 * 3
        <built-in function print>
        *       2         2
        **      1  3      1  3    (-1/3) * (-x - y + 2*z) * (x - y)
        <built-in function print>
        *       2         3
        **      1  3      1  2    (-1/3) * (-x + 2*y - z) * (x - z)
        <built-in function print>
        *       3         2
        **      1  2      1  3    (-2) * (x - y)
        <built-in function print>
        *       3         3
        **      1  2      1  2    (-2) * (x - z)
        <built-in function print>
        *      3      3
        *      2      2
        *      1      1    (y - z) * (-x + y) * (x - z)
        <built-in function print>

        sage: R = PolynomialRing(QQ, 'x,y,z')
        sage: for la in Partitions(3):
        ....:     for P in StandardTableaux(la):
        ....:         for Q in StandardTableaux(la):
        ....:             print(ascii_art(la, P, Q, factor(higher_specht(R, P, Q, harmonic="dual")), sep="    "))
        ....:             print
        ***      1  2  3      1  2  3    2^2 * 3
        <built-in function print>
        *       2         2
        **      1  3      1  3    (-2) * (-x^2 - 2*x*y + 2*y^2 + 4*x*z - 2*y*z - z^2)
        <built-in function print>
        *       2         3
        **      1  3      1  2    (-2) * (x^2 - 4*x*y + y^2 + 2*x*z + 2*y*z - 2*z^2)
        <built-in function print>
        *       3         2
        **      1  2      1  3    (-2) * (-x + 2*y - z)
        <built-in function print>
        *       3         3
        **      1  2      1  2    (-2) * (x + y - 2*z)
        <built-in function print>
        *      3      3
        *      2      2
        *      1      1    (6) * (y - z) * (-x + y) * (x - z)
        <built-in function print>

    This caught two bugs::

        sage: R = DerivativeHarmonicSpace(QQ, 6)
        sage: for mu in Partitions(6):             # long time
        ....:     for t in StandardTableaux(mu):
        ....:         p = R.higher_specht(t, harmonic=True, use_antisymmetry=True)
    """
    if not isinstance(P, StandardTableau):
        P = Partition(P).initial_tableau()
    n = P.size()
    assert (n == R.ngens()), "Given partition doesn't have the right size."
    if Q is None:
        Q = P.shape().initial_tableau()
    if harmonic == "dual":
        # Computes an harmonic polynomial obtained by applying h as
        # differential operator on the van der mond
        P = P.conjugate()
        Q = Q.conjugate()  # Is this really what we want?
        h = higher_specht(R, P, Q)
        vdm = higher_specht(R, Partition([1] * n).initial_tableau())
        return polynomial_derivative(h, vdm)
    elif harmonic:
        # TODO: normalization
        n = R.ngens()
        Sym = SymmetricFunctions(R.base_ring())
        m = Sym.m()
        p = Sym.p()
        d = P.cocharge()
        B = [higher_specht(R, P, Q, use_antisymmetry=use_antisymmetry)] + \
            [higher_specht(R, P2, Q, use_antisymmetry=use_antisymmetry) * m[nu].expand(n, R.gens())
             for P2 in StandardTableaux(P.shape()) if P2.cocharge() < d
             for nu in Partitions(d-P2.cocharge(), max_length=n)]
        if use_antisymmetry:
            antisymmetries = antisymmetries_of_tableau(Q)
            B = [antisymmetric_normal(b, n, 1, antisymmetries) for b in B]
        operators = [p[k].expand(n, R.gens()) for k in range(1, n + 1)]
        if use_antisymmetry:

            def action(e, f):
                return antisymmetric_normal(polynomial_derivative(e, f), n, 1,
                                            antisymmetries)
        else:
            action = polynomial_derivative
        ann = annihilator_basis(B, operators, action=action, side='left')
        assert len(ann) == 1
        return ann[0]

    exponents = index_filling(P)
    X = R.gens()
    m = R.prod(X[i - 1]**d for (d, i) in zip(exponents.entries(), Q.entries()))
    return apply_young_idempotent(m, Q, use_antisymmetry=use_antisymmetry)