def __init__(self, base_ring=QQ['t'], prefix='S'):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: S = ShiftingOperatorAlgebra(QQ['t'])
            sage: TestSuite(S).run()
        """
        indices = ShiftingSequenceSpace()
        cat = Algebras(base_ring).WithBasis()
        CombinatorialFreeModule.__init__(self,
                                         base_ring,
                                         indices,
                                         prefix=prefix,
                                         bracket=False,
                                         category=cat)

        # Setup default conversions
        sym = SymmetricFunctions(base_ring)
        self._sym_h = sym.h()
        self._sym_s = sym.s()
        self._sym_h.register_conversion(
            self.module_morphism(self._supp_to_h, codomain=self._sym_h))
        self._sym_s.register_conversion(
            self.module_morphism(self._supp_to_s, codomain=self._sym_s))
Ejemplo n.º 2
0
    def __init__(self, R):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ).dual()).run()
        """
        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
        w = self.w()

        # Embedding of Sym in the homogeneous bases into DNCSym in the w basis
        Sym = SymmetricFunctions(self.base_ring())
        Sym_h_to_w = Sym.h().module_morphism(
            w.sum_of_partitions,
            triangular='lower',
            inverse_on_support=w._set_par_to_par,
            codomain=w,
            category=category)
        Sym_h_to_w.register_as_coercion()
        self.to_symmetric_function = Sym_h_to_w.section()
Ejemplo n.º 3
0
    def K_k_Schur_non_commutative_variables(self,la):
        r"""
        Returns the K-`k`-Schur function, as embedded inside the affine zero Hecke algebra.

        INPUT:

        - ``la`` -- A `k`-bounded Partition

        OUTPUT:

        - An element of the affine zero Hecke algebra.

        EXAMPLES::

            sage: g = SymmetricFunctions(QQ).kBoundedSubspace(3,1).K_kschur()
            sage: g.K_k_Schur_non_commutative_variables([2,1])
            T3*T1*T0 + T1*T2*T0 + T3*T2*T0 - T2*T0 + T0*T1*T0 + T2*T0*T1 + T0*T3*T0 + T2*T0*T3 + T0*T3*T1 + T2*T3*T2 - T3*T1 + T2*T3*T1 + T3*T1*T2 + T1*T2*T1
            sage: g.K_k_Schur_non_commutative_variables([])
            1
            sage: g.K_k_Schur_non_commutative_variables([4,1])
            Traceback (most recent call last):
            ...
            ValueError: Partition should be 3-bounded
        """
        SF = SymmetricFunctions(self.base_ring())
        h = SF.h()
        S = h(self._g_to_kh_on_basis(la)).support()
        return sum(h(self._g_to_kh_on_basis(la)).coefficient(x)*self.homogeneous_basis_noncommutative_variables_zero_Hecke(x) for x in S)
Ejemplo n.º 4
0
def _cl_term(n, R=RationalField()):
    """
    Compute the order-n term of the cycle index series of the virtual species `\Omega`,
    the compositional inverse of the species `E^{+}` of nonempty sets.

    EXAMPLES::

        sage: from sage.combinat.species.generating_series import _cl_term
        sage: [_cl_term(i) for i in range(4)]
        [0, p[1], -1/2*p[1, 1] - 1/2*p[2], 1/3*p[1, 1, 1] - 1/3*p[3]]
    """

    n = Integer(n)  #check that n is an integer

    p = SymmetricFunctions(R).power()

    res = p.zero()
    if n == 1:
        res = p([1])
    elif n > 1:
        res = 1 / n * ((-1)**(n - 1) * p([1])**n -
                       sum(d * p([Integer(n / d)]).plethysm(_cl_term(d, R))
                           for d in divisors(n)[:-1]))

    return res
Ejemplo n.º 5
0
    def K_k_Schur_non_commutative_variables(self,la):
        r"""
        Returns the K-`k`-Schur function, as embedded inside the affine zero Hecke algebra.

        INPUT:

        - ``la`` -- A `k`-bounded Partition

        OUTPUT:

        - An element of the affine zero Hecke algebra.

        EXAMPLES::

            sage: g = SymmetricFunctions(QQ).kBoundedSubspace(3,1).K_kschur()
            sage: g.K_k_Schur_non_commutative_variables([2,1])
            T3*T1*T0 + T1*T2*T0 + T3*T2*T0 - T2*T0 + T0*T1*T0 + T2*T0*T1 + T0*T3*T0 + T2*T0*T3 + T0*T3*T1 + T2*T3*T2 - T3*T1 + T2*T3*T1 + T3*T1*T2 + T1*T2*T1
            sage: g.K_k_Schur_non_commutative_variables([])
            1
            sage: g.K_k_Schur_non_commutative_variables([4,1])
            Traceback (most recent call last):
            ...
            ValueError: Partition should be 3-bounded
        """
        SF = SymmetricFunctions(self.base_ring())
        h = SF.h()
        S = h(self._g_to_kh_on_basis(la)).support()
        return sum(h(self._g_to_kh_on_basis(la)).coefficient(x)*self.homogeneous_basis_noncommutative_variables_zero_Hecke(x) for x in S)
Ejemplo n.º 6
0
    def __init__(self, R):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: NCSymD1 = SymmetricFunctionsNonCommutingVariablesDual(FiniteField(23))
            sage: NCSymD2 = SymmetricFunctionsNonCommutingVariablesDual(Integers(23))
            sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ).dual()).run()
        """
        # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved
        assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R
        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
        w = self.w()

        # Embedding of Sym in the homogeneous bases into DNCSym in the w basis
        Sym = SymmetricFunctions(self.base_ring())
        Sym_h_to_w = Sym.h().module_morphism(w.sum_of_partitions,
                                             triangular='lower',
                                             inverse_on_support=w._set_par_to_par,
                                             codomain=w, category=category)
        Sym_h_to_w.register_as_coercion()
        self.to_symmetric_function = Sym_h_to_w.section()
Ejemplo n.º 7
0
    def __init__(self, w, n, x=None):
        r"""
        EXAMPLES::

            sage: B = crystals.AffineFactorization([[3,2],[2]],4,x=0,k=3)
            Traceback (most recent call last):
            ...
            ValueError: x cannot be in reduced word of s0*s3*s2

            sage: B = crystals.AffineFactorization([[3,2],[2]],4,k=3)
            sage: B.x
            1
            sage: B.w
            s0*s3*s2
            sage: B.k
            3
            sage: B.n
            4

        TESTS::

            sage: W = WeylGroup(['A',3,1], prefix='s')
            sage: w = W.from_reduced_word([2,3,2,1])
            sage: B = crystals.AffineFactorization(w,3)
            sage: TestSuite(B).run()
        """
        Parent.__init__(self, category=ClassicalCrystals())
        self.n = n
        self.k = w.parent().n - 1
        self.w = w
        cartan_type = CartanType(['A', n - 1])
        self._cartan_type = cartan_type
        from sage.combinat.sf.sf import SymmetricFunctions
        from sage.rings.rational_field import QQ
        Sym = SymmetricFunctions(QQ)
        s = Sym.schur()
        support = s(w.stanley_symmetric_function()).support()
        support = [[0] * (n - len(mu)) +
                   [mu[len(mu) - i - 1] for i in range(len(mu))]
                   for mu in support]
        generators = [
            tuple(p) for mu in support
            for p in affine_factorizations(w, n, mu)
        ]
        #generators = [tuple(p) for p in affine_factorizations(w, n)]
        self.module_generators = [self(t) for t in generators]
        if x is None:
            if generators:
                x = min(
                    set(range(self.k + 1)).difference(
                        set(sum([i.reduced_word() for i in generators[0]],
                                []))))
            else:
                x = 0
        if x in set(w.reduced_word()):
            raise ValueError("x cannot be in reduced word of {}".format(w))
        self.x = x
Ejemplo n.º 8
0
    def k_schur_noncommutative_variables(self, la):
        r"""
        In type `A^{(1)}` this is the `k`-Schur function in noncommutative variables defined by Thomas Lam.

        REFERENCES:

           .. [Lam2005] T. Lam, Affine Stanley symmetric functions, Amer. J. Math.  128  (2006),  no. 6, 1553--1586.

        This function is currently only defined in type `A^{(1)}`.

        INPUT:

        - ``la`` -- a partition with first part bounded by the rank of the Weyl group

        EXAMPLES::

            sage: A = NilCoxeterAlgebra(WeylGroup(['A',3,1]))
            sage: A.k_schur_noncommutative_variables([2,2])
            u[0,3,1,0] + u[3,1,2,0] + u[1,2,0,1] + u[3,2,0,3] + u[2,0,3,1] + u[2,3,1,2]

        TESTS::

            sage: A = NilCoxeterAlgebra(WeylGroup(['A',3,1]))
            sage: A.k_schur_noncommutative_variables([])
            1

            sage: A.k_schur_noncommutative_variables([1,2])
            Traceback (most recent call last):
            ...
            AssertionError: [1, 2] is not a partition.

            sage: A.k_schur_noncommutative_variables([4,2])
            Traceback (most recent call last):
            ...
            AssertionError: [4, 2] is not a 3-bounded partition.

            sage: C = NilCoxeterAlgebra(WeylGroup(['C',3,1]))
            sage: C.k_schur_noncommutative_variables([2,2])
            Traceback (most recent call last):
            ...
            AssertionError: Weyl Group of type ['C', 3, 1] (as a matrix group acting on the root space) is not affine type A.


        """
        assert self._cartan_type[0] == 'A' and len(
            self._cartan_type) == 3 and self._cartan_type[
                2] == 1, "%s is not affine type A." % (self._W)
        assert la in Partitions(), "%s is not a partition." % (la)
        assert (len(la) == 0 or la[0] < self._W.n
                ), "%s is not a %s-bounded partition." % (la, self._W.n - 1)
        Sym = SymmetricFunctions(self._base_ring)
        h = Sym.homogeneous()
        ks = Sym.kschur(self._n - 1, 1)
        f = h(ks[la])
        return sum(
            f.coefficient(x) * self.homogeneous_noncommutative_variables(x)
            for x in f.support())
Ejemplo n.º 9
0
    def k_schur_noncommutative_variables(self, la):
        r"""
        In type `A^{(1)}` this is the `k`-Schur function in noncommutative variables defined by Thomas Lam.

        REFERENCES:

           .. [Lam2005] T. Lam, Affine Stanley symmetric functions, Amer. J. Math.  128  (2006),  no. 6, 1553--1586.

        This function is currently only defined in type `A^{(1)}`.

        INPUT:

        - ``la`` -- a partition with first part bounded by the rank of the Weyl group

        EXAMPLES::

            sage: A = NilCoxeterAlgebra(WeylGroup(['A',3,1]))
            sage: A.k_schur_noncommutative_variables([2,2])
            u[0,3,1,0] + u[3,1,2,0] + u[1,2,0,1] + u[3,2,0,3] + u[2,0,3,1] + u[2,3,1,2]

        TESTS::

            sage: A = NilCoxeterAlgebra(WeylGroup(['A',3,1]))
            sage: A.k_schur_noncommutative_variables([])
            1

            sage: A.k_schur_noncommutative_variables([1,2])
            Traceback (most recent call last):
            ...
            AssertionError: [1, 2] is not a partition.

            sage: A.k_schur_noncommutative_variables([4,2])
            Traceback (most recent call last):
            ...
            AssertionError: [4, 2] is not a 3-bounded partition.

            sage: C = NilCoxeterAlgebra(WeylGroup(['C',3,1]))
            sage: C.k_schur_noncommutative_variables([2,2])
            Traceback (most recent call last):
            ...
            AssertionError: Weyl Group of type ['C', 3, 1] (as a matrix group acting on the root space) is not affine type A.


        """
        assert self._cartan_type[0] == 'A' and len(self._cartan_type) == 3 and self._cartan_type[2] == 1, "%s is not affine type A."%(self._W)
        assert la in Partitions(), "%s is not a partition."%(la)
        assert (len(la) == 0 or la[0] < self._W.n), "%s is not a %s-bounded partition."%(la, self._W.n-1)
        Sym = SymmetricFunctions(self._base_ring)
        h = Sym.homogeneous()
        ks = Sym.kschur(self._n-1,1)
        f = h(ks[la])
        return sum(f.coefficient(x)*self.homogeneous_noncommutative_variables(x) for x in f.support())
Ejemplo n.º 10
0
    def __init__(self, R, k, t=None):
        """
        EXAMPLES::

            sage: kSchurFunctions(QQ, 3).base_ring()
            doctest:1: DeprecationWarning: Deprecation warning: Please use SymmetricFunctions(QQ).kschur() instead!
            See http://trac.sagemath.org/5457 for details.
            Univariate Polynomial Ring in t over Rational Field
            sage: kSchurFunctions(QQ, 3, t=1).base_ring()
            Rational Field
            sage: ks3 = kSchurFunctions(QQ, 3)
            sage: ks3 == loads(dumps(ks3))
            True
        """
        self.k = k
        self._name = "k-Schur Functions at level %s" % k
        self._prefix = "ks%s" % k
        self._element_class = kSchurFunctions_t.Element

        if t is None:
            R = R['t']
            self.t = R.gen()
        elif t not in R:
            raise ValueError, "t (=%s) must be in R (=%s)" % (t, R)
        else:
            self.t = R(t)
            if str(t) != 't':
                self._name += " with t=%s" % self.t

        self._s_to_self_cache = s_to_k_cache.get(k, {})
        self._self_to_s_cache = k_to_s_cache.get(k, {})

        # This is an abuse, since kschur functions do not form a basis of Sym
        from sage.combinat.sf.sf import SymmetricFunctions
        Sym = SymmetricFunctions(R)
        sfa.SymmetricFunctionAlgebra_generic.__init__(self, Sym)
        # so we need to take some counter measures
        self._basis_keys = sage.combinat.partition.Partitions(max_part=k)
        # The following line is just a temporary workaround to keep
        # the repr of those k-schur as they were before #13404; since
        # they are deprecated, there is no need to bother about them.
        self.rename(self._name + " over %s" % self.base_ring())

        self._s = Sym.s()
        # temporary until Hom(GradedHopfAlgebrasWithBasis work better)
        category = sage.categories.all.ModulesWithBasis(self.base_ring())
        # This really should be a conversion, not a coercion (it can fail)
        self.register_coercion(
            SetMorphism(Hom(self._s, self, category), self._s_to_self))
        self._s.register_coercion(
            SetMorphism(Hom(self, self._s, category), self._self_to_s))
Ejemplo n.º 11
0
    def __init__(self, w, n, x = None):
        r"""
        EXAMPLES::

            sage: B = crystals.AffineFactorization([[3,2],[2]],4,x=0,k=3)
            Traceback (most recent call last):
            ...
            ValueError: x cannot be in reduced word of s0*s3*s2

            sage: B = crystals.AffineFactorization([[3,2],[2]],4,k=3)
            sage: B.x
            1
            sage: B.w
            s0*s3*s2
            sage: B.k
            3
            sage: B.n
            4

        TESTS::

            sage: W = WeylGroup(['A',3,1], prefix='s')
            sage: w = W.from_reduced_word([2,3,2,1])
            sage: B = crystals.AffineFactorization(w,3)
            sage: TestSuite(B).run()
        """
        Parent.__init__(self, category = ClassicalCrystals())
        self.n = n
        self.k = w.parent().n-1
        self.w = w
        cartan_type = CartanType(['A',n-1])
        self._cartan_type = cartan_type
        from sage.combinat.sf.sf import SymmetricFunctions
        from sage.rings.all import QQ
        Sym = SymmetricFunctions(QQ)
        s = Sym.schur()
        support = s(w.stanley_symmetric_function()).support()
        support = [ [0]*(n-len(mu))+[mu[len(mu)-i-1] for i in range(len(mu))] for mu in support]
        generators = [tuple(p) for mu in support for p in affine_factorizations(w,n,mu)]
        #generators = [tuple(p) for p in affine_factorizations(w, n)]
        self.module_generators = [self(t) for t in generators]
        if x is None:
            if generators != []:
                x = min( set(range(self.k+1)).difference(set(
                            sum([i.reduced_word() for i in generators[0]],[]))))
            else:
                x = 0
        if x in set(w.reduced_word()):
            raise ValueError("x cannot be in reduced word of {}".format(w))
        self.x = x
Ejemplo n.º 12
0
    def __init__(self, R, k, t=None):
        """
        EXAMPLES::

            sage: kSchurFunctions(QQ, 3).base_ring()
            doctest:1: DeprecationWarning: Deprecation warning: Please use SymmetricFunctions(QQ).kschur() instead!
            See http://trac.sagemath.org/5457 for details.
            Univariate Polynomial Ring in t over Rational Field
            sage: kSchurFunctions(QQ, 3, t=1).base_ring()
            Rational Field
            sage: ks3 = kSchurFunctions(QQ, 3)
            sage: ks3 == loads(dumps(ks3))
            True
        """
        self.k = k
        self._name = "k-Schur Functions at level %s"%k
        self._prefix = "ks%s"%k
        self._element_class = kSchurFunctions_t.Element

        if t is None:
            R = R['t']
            self.t = R.gen()
        elif t not in R:
            raise ValueError, "t (=%s) must be in R (=%s)"%(t,R)
        else:
            self.t = R(t)
            if str(t) != 't':
                self._name += " with t=%s"%self.t

        self._s_to_self_cache = s_to_k_cache.get(k, {})
        self._self_to_s_cache = k_to_s_cache.get(k, {})

        # This is an abuse, since kschur functions do not form a basis of Sym
        from sage.combinat.sf.sf import SymmetricFunctions
        Sym = SymmetricFunctions(R)
        sfa.SymmetricFunctionAlgebra_generic.__init__(self, Sym)
        # so we need to take some counter measures
        self._basis_keys = sage.combinat.partition.Partitions(max_part=k)
        # The following line is just a temporary workaround to keep
        # the repr of those k-schur as they were before #13404; since
        # they are deprecated, there is no need to bother about them.
        self.rename(self._name+" over %s"%self.base_ring())

        self._s = Sym.s()
        # temporary until Hom(GradedHopfAlgebrasWithBasis work better)
        category = sage.categories.all.ModulesWithBasis(self.base_ring())
        # This really should be a conversion, not a coercion (it can fail)
        self   .register_coercion(SetMorphism(Hom(self._s, self, category), self._s_to_self))
        self._s.register_coercion(SetMorphism(Hom(self, self._s, category), self._self_to_s))
Ejemplo n.º 13
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()
Ejemplo n.º 14
0
def factorize(f, n=0):
    """
    Return the factorization of the tensor product `f` w.r.t the right symmetric
    functions. The right symmetric functions have their supports in the partitions
    on `n`. 
    
    INPUT:
    - ``f`` -- a sum of tensor products on symmetric functions
    - ``n`` -- an Integer
    
    EXAMPLES::
    sage: factorize(E_mu(Partition([3,1])), 4)
    [((3, 1), s[]),
     ((1, 1, 1, 1), s[1, 1] + s[3]),
     ((2, 2), s[1]),
     ((2, 1, 1), s[1] + s[2]),
     ((4,), 0)]

    TODO : Delete n and correct code and worksheets 
    """
    SymmetricFunctions(QQ).s()
    supp = sorted(f.support())
    n = f.support().pop()[1].size()
    result = {}
    res = []
    for mu in Partitions(n):
        result[mu] = []
        for (a, b), c in zip(supp, f.coefficients()):
            if b == mu:
                result[mu] += [(a, c)]
    result2 = [(tuple(mu), sum(c * s(nu) for (nu, c) in result[mu]))
               for mu in result.keys()]
    return result2
Ejemplo n.º 15
0
            def to_symmetric_function(self):
                r"""
                Takes a quasi-symmetric function, expressed in the monomial basis, and
                returns its symmetric realization, when possible, expressed in the
                monomial basis of symmetric functions.

                OUTPUT:

                - If ``self`` is a symmetric function, then the expansion
                  in the monomial basis of the symmetric functions is returned.
                  Otherwise an error is raised.

                EXAMPLES::

                    sage: QSym = QuasiSymmetricFunctions(QQ)
                    sage: M = QSym.Monomial()
                    sage: (M[3,2] + M[2,3] + M[4,1]).to_symmetric_function()
                    Traceback (most recent call last):
                    ...
                    ValueError: M[2, 3] + M[3, 2] + M[4, 1] is not a symmetric function
                    sage: (M[3,2] + M[2,3] + 2*M[4,1] + 2*M[1,4]).to_symmetric_function()
                    m[3, 2] + 2*m[4, 1]
                    sage: m = SymmetricFunctions(QQ).m()
                    sage: M(m[3,1,1]).to_symmetric_function()
                    m[3, 1, 1]
                    sage: (M(m[2,1])*M(m[2,1])).to_symmetric_function()-m[2,1]*m[2,1]
                    0

                TESTS::

                    sage: (M(0)).to_symmetric_function()
                    0
                    sage: (M([])).to_symmetric_function()
                    m[]
                    sage: (2*M([])).to_symmetric_function()
                    2*m[]

                """
                m = SymmetricFunctions(self.parent().base_ring()).monomial()
                if self.is_symmetric():
                    return m.sum_of_terms(
                        [(I, coeff)
                         for (I, coeff) in self if list(I) in Partitions()],
                        distinct=True)
                else:
                    raise ValueError, "%s is not a symmetric function" % self
Ejemplo n.º 16
0
 def charpoly(self, g, var='x'):
     r"""
     Determines the characteristic polynomial `\det(I-gT)`
     """
     if self.degree() == 0:
         return QQ.one()
     from sage.combinat.sf.sf import SymmetricFunctions
     S = SymmetricFunctions(QQ)
     p = S.powersum()
     e = S.elementary()
     deg = self.degree()
     traces = [self(g ** n) for n in range(1, deg+1)]
     x = PolynomialRing(QQ, var).gen()
     cp = x ** deg
     for n in range(deg):
         mc = p(e[n+1]).monomial_coefficients()
         cp += (-1) ** (n+1) * x ** (deg-1-n) * sum(mc[k] * prod(traces[j-1] for j in k) for k in mc.keys())
     return cp
Ejemplo n.º 17
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()
Ejemplo n.º 18
0
            def to_symmetric_function( self ):
                r"""
                Takes a quasi-symmetric function, expressed in the monomial basis, and
                returns its symmetric realization, when possible, expressed in the
                monomial basis of symmetric functions.

                OUTPUT:

                - If ``self`` is a symmetric function, then the expansion
                  in the monomial basis of the symmetric functions is returned.
                  Otherwise an error is raised.

                EXAMPLES::

                    sage: QSym = QuasiSymmetricFunctions(QQ)
                    sage: M = QSym.Monomial()
                    sage: (M[3,2] + M[2,3] + M[4,1]).to_symmetric_function()
                    Traceback (most recent call last):
                    ...
                    ValueError: M[2, 3] + M[3, 2] + M[4, 1] is not a symmetric function
                    sage: (M[3,2] + M[2,3] + 2*M[4,1] + 2*M[1,4]).to_symmetric_function()
                    m[3, 2] + 2*m[4, 1]
                    sage: m = SymmetricFunctions(QQ).m()
                    sage: M(m[3,1,1]).to_symmetric_function()
                    m[3, 1, 1]
                    sage: (M(m[2,1])*M(m[2,1])).to_symmetric_function()-m[2,1]*m[2,1]
                    0

                TESTS::

                    sage: (M(0)).to_symmetric_function()
                    0
                    sage: (M([])).to_symmetric_function()
                    m[]
                    sage: (2*M([])).to_symmetric_function()
                    2*m[]

                """
                m = SymmetricFunctions(self.parent().base_ring()).monomial()
                if self.is_symmetric():
                    return m.sum_of_terms([(I, coeff) for (I, coeff) in self
                        if list(I) in Partitions()], distinct=True)
                else:
                    raise ValueError, "%s is not a symmetric function"%self
Ejemplo n.º 19
0
    def _DualGrothendieck(self,la):
        r"""
        Returns the expansion of the K-`k`-Schur function in the homogeneous basis. This
        method is here for caching purposes.

        INPUT:

        - ``la`` -- A `k`-bounded partition.

        OUTPUT:

        - A symmetric function in the homogeneous basis.

        EXAMPLES::

            sage: g = SymmetricFunctions(QQ).kBoundedSubspace(3,1).K_kschur()
            sage: g._DualGrothendieck(Partition([2,1]))
            h[2] + h[2, 1] - h[3]
            sage: g._DualGrothendieck(Partition([]))
            h[]
            sage: g._DualGrothendieck(Partition([4,1]))
            0
        """
        m = la.size()
        h = SymmetricFunctions(self.base_ring()).h()
        M = self._DualGrothMatrix(m)
        vec = []
        for i in range(m+1):
            for x in Partitions(m-i, max_part=self.k):
                if x == la:
                    vec.append(1)
                else:
                    vec.append(0)
        from sage.modules.free_module_element import vector
        vec = vector(vec)
        sol = M.solve_right(vec)
        new_function = h.zero()
        count = 0
        for i in range(m+1):
            for x in Partitions(m-i, max_part=self.k):
                new_function+= h(x) * sol[count]
                count += 1
        return new_function
Ejemplo n.º 20
0
    def _DualGrothendieck(self,la):
        r"""
        Returns the expansion of the K-`k`-Schur function in the homogeneous basis. This
        method is here for caching purposes.

        INPUT:

        - ``la`` -- A `k`-bounded partition.

        OUTPUT:

        - A symmetric function in the homogeneous basis.

        EXAMPLES::

            sage: g = SymmetricFunctions(QQ).kBoundedSubspace(3,1).K_kschur()
            sage: g._DualGrothendieck(Partition([2,1]))
            h[2] + h[2, 1] - h[3]
            sage: g._DualGrothendieck(Partition([]))
            h[]
            sage: g._DualGrothendieck(Partition([4,1]))
            0
        """
        m = la.size()
        h = SymmetricFunctions(self.base_ring()).h()
        M = self._DualGrothMatrix(m)
        vec = []
        for i in range(m+1):
            for x in Partitions(m-i, max_part=self.k):
                if x == la:
                    vec.append(1)
                else:
                    vec.append(0)
        from sage.modules.free_module_element import vector
        vec = vector(vec)
        sol = M.solve_right(vec)
        new_function = h.zero()
        count = 0
        for i in range(m+1):
            for x in Partitions(m-i, max_part=self.k):
                new_function+= h(x) * sol[count]
                count += 1
        return new_function
Ejemplo n.º 21
0
    def _DualGrothMatrix(self, m):
        r"""
        Returns the change of basis matrix between the K_kschur basis and the `k`-bounded
        homogeneous basis.

        INPUT:

        - ``m`` -- An integer

        OUTPUT:

        - A matrix.

        EXAMPLES::

            sage: g = SymmetricFunctions(QQ).kBoundedSubspace(3,1).K_kschur()
            sage: g._DualGrothMatrix(3)
            [ 1  1  1  0  0  0  0]
            [ 0  1  2  0  0  0  0]
            [ 0  0  1  0  0  0  0]
            [ 0 -1 -2  1  1  0  0]
            [ 0  0 -2  0  1  0  0]
            [ 0  0  1  0 -1  1  0]
            [ 0  0  0  0  0  0  1]
            sage: g._DualGrothMatrix(0)
            [1]
        """
        new_mat = []
        Sym = SymmetricFunctions(self.base_ring())
        Q = Sym.kBoundedQuotient(self.k,t=1)
        mon = Q.km()
        G = Q.AffineGrothendieckPolynomial
        for i in range(m+1):
            for x in Partitions(m-i, max_part = self.k):
                f =  mon(G(x,m))
                vec = []
                for j in range(m+1):
                    for y in Partitions(m-j, max_part = self.k):
                        vec.append(f.coefficient(y))
                new_mat.append(vec)
        from sage.matrix.constructor import Matrix
        return Matrix(new_mat)
Ejemplo n.º 22
0
    def _DualGrothMatrix(self, m):
        r"""
        Returns the change of basis matrix between the K_kschur basis and the `k`-bounded
        homogeneous basis.

        INPUT:

        - ``m`` -- An integer

        OUTPUT:

        - A matrix.

        EXAMPLES::

            sage: g = SymmetricFunctions(QQ).kBoundedSubspace(3,1).K_kschur()
            sage: g._DualGrothMatrix(3)
            [ 1  1  1  0  0  0  0]
            [ 0  1  2  0  0  0  0]
            [ 0  0  1  0  0  0  0]
            [ 0 -1 -2  1  1  0  0]
            [ 0  0 -2  0  1  0  0]
            [ 0  0  1  0 -1  1  0]
            [ 0  0  0  0  0  0  1]
            sage: g._DualGrothMatrix(0)
            [1]
        """
        new_mat = []
        Sym = SymmetricFunctions(self.base_ring())
        Q = Sym.kBoundedQuotient(self.k,t=1)
        mon = Q.km()
        G = Q.AffineGrothendieckPolynomial
        for i in range(m+1):
            for x in Partitions(m-i, max_part = self.k):
                f =  mon(G(x,m))
                vec = []
                for j in range(m+1):
                    for y in Partitions(m-j, max_part = self.k):
                        vec.append(f.coefficient(y))
                new_mat.append(vec)
        from sage.matrix.constructor import Matrix
        return Matrix(new_mat)
Ejemplo n.º 23
0
            def to_symmetric_function(self):
                r"""
                Return the image of ``self`` under the natural projection
                map to `Sym`.

                The natural projection map `FSym \to Sym` sends each
                standard tableau `t` to the Schur function `s_\lambda`,
                where `\lambda` is the shape of `t`.
                This map is a surjective Hopf algebra homomorphism.

                EXAMPLES::

                    sage: FSym = algebras.FSym(QQ)
                    sage: G = FSym.G()
                    sage: t = StandardTableau([[1,3],[2,4],[5]])
                    sage: G[t].to_symmetric_function()
                    s[2, 2, 1]
                """
                s = SymmetricFunctions(self.parent().base_ring()).s()
                return s.sum_of_terms((t.shape(), coeff) for t, coeff in self)
Ejemplo n.º 24
0
            def to_symmetric_function(self):
                r"""
                Return the image of ``self`` under the natural projection
                map to `Sym`.

                The natural projection map `FSym \to Sym` sends each
                standard tableau `t` to the Schur function `s_\lambda`,
                where `\lambda` is the shape of `t`.
                This map is a surjective Hopf algebra homomorphism.

                EXAMPLES::

                    sage: FSym = algebras.FSym(QQ)
                    sage: G = FSym.G()
                    sage: t = StandardTableau([[1,3],[2,4],[5]])
                    sage: G[t].to_symmetric_function()
                    s[2, 2, 1]
                """
                s = SymmetricFunctions(self.parent().base_ring()).s()
                return s.sum_of_terms((t.shape(), coeff) for t, coeff in self)
Ejemplo n.º 25
0
    def __init__(self, R):
        """
        EXAMPLES::

            sage: from sage.combinat.species.generating_series import CycleIndexSeriesRing
            sage: R = CycleIndexSeriesRing(QQ); R
            Cycle Index Series Ring over Symmetric Functions over Rational Field in the powersum basis
            sage: R == loads(dumps(R))
            True
        """
        R = SymmetricFunctions(R).power()
        LazyPowerSeriesRing.__init__(self, R, CycleIndexSeries)
Ejemplo n.º 26
0
def _exp_term(n, R = RationalField()):
    """
    Compute the order-n term of the cycle index series of the species `E` of sets.

    EXAMPLES::

        sage: from sage.combinat.species.generating_series import _exp_term
        sage: [_exp_term(i) for i in range(4)]
        [p[], p[1], 1/2*p[1, 1] + 1/2*p[2], 1/6*p[1, 1, 1] + 1/2*p[2, 1] + 1/3*p[3]]
    """
    p = SymmetricFunctions(R).power()
    return sum(p(part) / part.aut() for part in Partitions(n))
Ejemplo n.º 27
0
    def _multiply_basis(self, part1, part2):
        """
        TESTS::

            sage: s = sage.combinat.combinatorial_algebra.TestAlgebra(QQ)
            sage: a = s([2])
            sage: a._mul_(a) #indirect doctest
            s[2, 2] + s[3, 1] + s[4]
        """
        from sage.combinat.sf.sf import SymmetricFunctions
        S = SymmetricFunctions(self.base_ring()).schur()
        return self.sum_of_terms(S(part1) * S(part2))
Ejemplo n.º 28
0
 def charpoly_reverse(self, g, var='x'):
     r"""
     Determines the characteristic polynomial `\det(I-gT)`
     
     sage: from sage.rings.number_field.galois_group import GaloisGroup_v3
     sage: from sage.rings.number_field.artin_representation import ArtinRepresentation
     sage: K = NumberField(x^3 - 2, 'a')
     sage: G = GaloisGroup_v3(K, names='b2')
     sage: chi = ArtinRepresentation(G, [2, 0, -1])
     sage: L = G.splitting_field()
     sage: for p in prime_range(5, 50):
     ...    print p, chi.charpoly_reverse(G.artin_symbol(L.primes_above(p)[0]))
     5 -x^2 + 1
     7 x^2 + x + 1
     11 -x^2 + 1
     13 x^2 + x + 1
     17 -x^2 + 1
     19 x^2 + x + 1
     23 -x^2 + 1
     29 -x^2 + 1
     31 x^2 - 2*x + 1
     37 x^2 + x + 1
     41 -x^2 + 1
     43 x^2 - 2*x + 1
     47 -x^2 + 1
     """
     if self.degree() == 0:
         return QQ.one()
     from sage.combinat.sf.sf import SymmetricFunctions
     S = SymmetricFunctions(QQ)
     p = S.powersum()
     e = S.elementary()
     deg = self.degree()
     traces = [self(g ** n) for n in range(1, deg+1)]
     x = PolynomialRing(QQ, var).gen()
     cp = QQ.one()
     for n in range(deg):
         mc = p(e[n+1]).monomial_coefficients()
         cp += (-1) ** (n+1) * x ** (n+1) * sum(mc[k] * prod(traces[j-1] for j in k) for k in mc.keys())
     return cp
Ejemplo n.º 29
0
            def to_symmetric_function(self):
                r"""
                Take a function in the `\mathbf{w}` basis, and return its
                symmetric realization, when possible, expressed in the
                homogeneous basis of symmetric functions.

                OUTPUT:

                - If ``self`` is a symmetric function, then the expansion
                  in the homogeneous basis of the symmetric functions is returned.
                  Otherwise an error is raised.

                EXAMPLES::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: elt = w[[1],[2,3]] + w[[1,2],[3]] + w[[1,3],[2]]
                    sage: elt.to_symmetric_function()
                    h[2, 1]
                    sage: elt = w.sum_of_partitions([2,1,1]) / 2
                    sage: elt.to_symmetric_function()
                    1/2*h[2, 1, 1]

                TESTS::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: w(0).to_symmetric_function()
                    0
                    sage: w([]).to_symmetric_function()
                    h[]
                    sage: (2*w([])).to_symmetric_function()
                    2*h[]
                """
                if not self.is_symmetric():
                    raise ValueError("not a symmetric function")
                h = SymmetricFunctions(self.parent().base_ring()).homogeneous()
                d = {A.shape(): c for A, c in self}
                return h.sum_of_terms(
                    [(AA, cc / prod(map(factorial, AA.to_exp())))
                     for AA, cc in d.items()],
                    distinct=True)
Ejemplo n.º 30
0
def _cl_term(n, R = RationalField()):
    r"""
    Compute the order-n term of the cycle index series of the virtual species `\Omega`,
    the compositional inverse of the species `E^{+}` of nonempty sets.

    EXAMPLES::

        sage: from sage.combinat.species.generating_series import _cl_term
        sage: [_cl_term(i) for i in range(4)]
        [0, p[1], -1/2*p[1, 1] - 1/2*p[2], 1/3*p[1, 1, 1] - 1/3*p[3]]
    """
    n = Integer(n)  # check that n is an integer

    p = SymmetricFunctions(R).power()

    res = p.zero()
    if n == 1:
        res = p([1])
    elif n > 1:
        res = 1/n * ((-1)**(n-1) * p([1])**n - sum(d * p([n // d]).plethysm(_cl_term(d, R)) for d in divisors(n)[:-1]))

    return res
Ejemplo n.º 31
0
            def to_symmetric_function(self):
                r"""
                Take a function in the `\mathbf{w}` basis, and return its
                symmetric realization, when possible, expressed in the
                homogeneous basis of symmetric functions.

                OUTPUT:

                - If ``self`` is a symmetric function, then the expansion
                  in the homogeneous basis of the symmetric functions is returned.
                  Otherwise an error is raised.

                EXAMPLES::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: elt = w[[1],[2,3]] + w[[1,2],[3]] + w[[1,3],[2]]
                    sage: elt.to_symmetric_function()
                    h[2, 1]
                    sage: elt = w.sum_of_partitions([2,1,1]) / 2
                    sage: elt.to_symmetric_function()
                    1/2*h[2, 1, 1]

                TESTS::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: w(0).to_symmetric_function()
                    0
                    sage: w([]).to_symmetric_function()
                    h[]
                    sage: (2*w([])).to_symmetric_function()
                    2*h[]
                """
                if not self.is_symmetric():
                    raise ValueError("not a symmetric function")
                h = SymmetricFunctions(self.parent().base_ring()).homogeneous()
                d = {A.shape(): c for A, c in self}
                return h.sum_of_terms(
                    [(AA, cc / prod(map(factorial, AA.to_exp()))) for AA, cc in d.items()], distinct=True
                )
Ejemplo n.º 32
0
    def _cis_iterator(self, base_ring):
        """
        EXAMPLES::

            sage: L = species.LinearOrderSpecies()
            sage: g = L.cycle_index_series()
            sage: g.coefficients(5)
            [p[], p[1], p[1, 1], p[1, 1, 1], p[1, 1, 1, 1]]
        """
        from sage.combinat.sf.sf import SymmetricFunctions
        p = SymmetricFunctions(base_ring).power()
        for n in _integers_from(0):
            yield p([1]*n)
Ejemplo n.º 33
0
    def __init__(self, R):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ).dual()).run()
        """
        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
        w = self.w()

        # Embedding of Sym in the homogeneous bases into DNCSym in the w basis
        Sym = SymmetricFunctions(self.base_ring())
        Sym_h_to_w = Sym.h().module_morphism(
            w.sum_of_partitions, triangular="lower", inverse_on_support=w._set_par_to_par, codomain=w, category=category
        )
        Sym_h_to_w.register_as_coercion()
        self.to_symmetric_function = Sym_h_to_w.section()
Ejemplo n.º 34
0
    def _cis_gen(self, base_ring):
        """
        EXAMPLES::

            sage: S = species.SetSpecies()
            sage: g = S._cis_gen(QQ)
            sage: [next(g) for i in range(5)]
            [0, p[1], 1/2*p[2], 1/3*p[3], 1/4*p[4]]
        """
        from sage.combinat.sf.sf import SymmetricFunctions
        p = SymmetricFunctions(base_ring).power()
        yield p(0)
        for n in _integers_from(1):
            yield p([n])/n
Ejemplo n.º 35
0
    def jacobi_trudi(self):
        """
        EXAMPLES::

            sage: SkewPartition([[3,2,1],[2,1]]).jacobi_trudi()
            [h[1]    0    0]
            [h[3] h[1]    0]
            [h[5] h[3] h[1]]
            sage: SkewPartition([[4,3,2],[2,1]]).jacobi_trudi()
            [h[2]  h[]    0]
            [h[4] h[2]  h[]]
            [h[6] h[4] h[2]]
        """
        p = self.outer()
        q = self.inner()
        from sage.combinat.sf.sf import SymmetricFunctions
        if len(p) == 0 and len(q) == 0:
            return MatrixSpace(SymmetricFunctions(QQ).homogeneous(), 0)(0)
        nn = len(p)
        h = SymmetricFunctions(QQ).homogeneous()
        H = MatrixSpace(h, nn)

        q  = q + [0]*int(nn-len(q))
        m = []
        for i in range(1,nn+1):
            row = []
            for j in range(1,nn+1):
                v = p[j-1]-q[i-1]-j+i
                if v < 0:
                    row.append(h(0))
                elif v == 0:
                    row.append(h([]))
                else:
                    row.append(h([v]))
            m.append(row)
        return H(m)
Ejemplo n.º 36
0
    def __init__(self, base_ring, q, prefix='I'):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: R.<q> = ZZ[]
            sage: I = HallAlgebra(R, q).monomial_basis()
            sage: TestSuite(I).run()
            sage: R = PolynomialRing(ZZ, 'q').fraction_field()
            sage: q = R.gen()
            sage: I = HallAlgebra(R, q).monomial_basis()
            sage: TestSuite(I).run()
            sage: R.<q> = LaurentPolynomialRing(ZZ)
            sage: I = HallAlgebra(R, q).monomial_basis()
            sage: TestSuite(I).run()
        """
        self._q = q
        try:
            q_inverse = q**-1
            if not q_inverse in base_ring:
                hopf_structure = False
            else:
                hopf_structure = True
        except Exception:
            hopf_structure = False
        if hopf_structure:
            category = HopfAlgebrasWithBasis(base_ring)
        else:
            category = AlgebrasWithBasis(base_ring)
        CombinatorialFreeModule.__init__(self,
                                         base_ring,
                                         Partitions(),
                                         prefix=prefix,
                                         bracket=False,
                                         category=category)

        # Coercions
        if hopf_structure:
            e = SymmetricFunctions(base_ring).e()
            f = lambda la: q**sum(-((r * (r - 1)) // 2) for r in la)
            M = self.module_morphism(diagonal=f, codomain=e)
            M.register_as_coercion()
            (~M).register_as_coercion()
Ejemplo n.º 37
0
    def _cis_iterator(self, base_ring):
        r"""
        The cycle index series of the species of cyclic permutations is
        given by

        .. MATH::

             -\sum_{k=1}^\infty \phi(k)/k * log(1 - x_k)


        which is equal to

        .. MATH::

             \sum_{n=1}^\infty \frac{1}{n} * \sum_{k|n} \phi(k) * x_k^{n/k}

        .

        EXAMPLES::

            sage: P = species.CycleSpecies()
            sage: cis = P.cycle_index_series()
            sage: cis.coefficients(7)
            [0,
             p[1],
             1/2*p[1, 1] + 1/2*p[2],
             1/3*p[1, 1, 1] + 2/3*p[3],
             1/4*p[1, 1, 1, 1] + 1/4*p[2, 2] + 1/2*p[4],
             1/5*p[1, 1, 1, 1, 1] + 4/5*p[5],
             1/6*p[1, 1, 1, 1, 1, 1] + 1/6*p[2, 2, 2] + 1/3*p[3, 3] + 1/3*p[6]]
        """
        from sage.combinat.sf.sf import SymmetricFunctions
        p = SymmetricFunctions(base_ring).power()

        zero = base_ring(0)

        yield zero
        for n in _integers_from(1):
            res = zero
            for k in divisors(n):
                res += euler_phi(k) * p([k])**(n // k)
            res /= n
            yield self._weight * res
Ejemplo n.º 38
0
    def cardinality(self):
        r"""
        The number of integer matrices with the prescribed row sums and columns
        sums.

        EXAMPLES::

            sage: from sage.combinat.integer_matrices import IntegerMatrices
            sage: IntegerMatrices([2,5], [3,2,2]).cardinality()
            6
            sage: IntegerMatrices([1,1,1,1,1], [1,1,1,1,1]).cardinality()
            120
            sage: IntegerMatrices([2,2,2,2], [2,2,2,2]).cardinality()
            282
            sage: IntegerMatrices([4], [3]).cardinality()
            0
            sage: len(IntegerMatrices([0,0], [0]).list())
            1

        This method computes the cardinality using symmetric functions. Below
        are the same examples, but computed by generating the actual matrices::

            sage: from sage.combinat.integer_matrices import IntegerMatrices
            sage: len(IntegerMatrices([2,5], [3,2,2]).list())
            6
            sage: len(IntegerMatrices([1,1,1,1,1], [1,1,1,1,1]).list())
            120
            sage: len(IntegerMatrices([2,2,2,2], [2,2,2,2]).list())
            282
            sage: len(IntegerMatrices([4], [3]).list())
            0
            sage: len(IntegerMatrices([0], [0]).list())
            1

        """
        from sage.combinat.sf.sf import SymmetricFunctions
        from sage.combinat.partition import Partition
        h = SymmetricFunctions(ZZ).homogeneous()
        row_partition = Partition(sorted(self._row_sums, reverse=True))
        col_partition = Partition(sorted(self._col_sums, reverse=True))
        return h[row_partition].scalar(h[col_partition])
Ejemplo n.º 39
0
    def _cis_gen(self, base_ring, n):
        """
        EXAMPLES::

            sage: P = species.PermutationSpecies()
            sage: g = P._cis_gen(QQ, 2)
            sage: [g.next() for i in range(10)]
            [p[], 0, p[2], 0, p[2, 2], 0, p[2, 2, 2], 0, p[2, 2, 2, 2], 0]
        """
        from sage.combinat.sf.sf import SymmetricFunctions
        p = SymmetricFunctions(base_ring).power()

        pn = p([n])

        n = n - 1
        yield p(1)

        for k in _integers_from(1):
            for i in range(n):
                yield base_ring(0)
            yield pn**k
Ejemplo n.º 40
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pypersist import persist
from sage.misc.misc import attrcall
from sage.categories.tensor import tensor
from sage.misc.latex import latex

from diagonal_polynomial_ring import *
from subspace import *
from young_idempotent import *
from add_degree import *
from diagram import *

from sage.combinat.sf.sf import SymmetricFunctions
m = SymmetricFunctions(QQ).m()
s = SymmetricFunctions(QQ).s()
# Workaround #25491 which prevents early unpickling of tensor products
# of symmetric functions
from sage.categories.hopf_algebras_with_basis import HopfAlgebrasWithBasis
HopfAlgebrasWithBasis.TensorProducts

##############################################################################
# Vandermonde like determinant
##############################################################################


def vandermonde(gamma, r=0):
    """
    Let `gamma` be a diagram of $n$ cells and $x = (x_1, x_2, \dots, x_n)$ and
    $\theta = (\theta_1, \theta_2, \dots, \theta_n)$ two sets of n variables.
Ejemplo n.º 41
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
Ejemplo n.º 42
0
def GL_irreducible_character(n, mu, KK):
    r"""
    Return the character of the irreducible module indexed by ``mu``
    of `GL(n)` over the field ``KK``.

    INPUT:

    - ``n`` -- a positive integer
    - ``mu`` -- a partition of at most ``n`` parts
    - ``KK`` -- a field

    OUTPUT:

    a symmetric function which should be interpreted in ``n``
    variables to be meaningful as a character

    EXAMPLES:

    Over `\QQ`, the irreducible character for `\mu` is the Schur
    function associated to `\mu`, plus garbage terms (Schur
    functions associated to partitions with more than `n` parts)::

        sage: from sage.algebras.schur_algebra import GL_irreducible_character
        sage: sbasis = SymmetricFunctions(QQ).s()
        sage: z = GL_irreducible_character(2, [2], QQ)
        sage: sbasis(z)
        s[2]

        sage: z = GL_irreducible_character(4, [3, 2], QQ)
        sage: sbasis(z)
        -5*s[1, 1, 1, 1, 1] + s[3, 2]

    Over a Galois field, the irreducible character for `\mu` will
    in general be smaller.

    In characteristic `p`, for a one-part partition `(r)`, where
    `r = a_0 + p a_1 + p^2 a_2 + \dots`, the result is (see [GreenPoly]_,
    after 5.5d) the product of `h[a_0], h[a_1]( pbasis[p]), h[a_2]
    ( pbasis[p^2]), \dots,` which is consistent with the following ::

        sage: from sage.algebras.schur_algebra import GL_irreducible_character
        sage: GL_irreducible_character(2, [7], GF(3))
        m[4, 3] + m[6, 1] + m[7]
    """
    mbasis = SymmetricFunctions(QQ).m()
    r = sum(mu)
    M = SchurTensorModule(KK, n, r)
    A = M._schur
    SGA = M._sga

    # make ST the superstandard tableau of shape mu
    from sage.combinat.tableau import from_shape_and_word

    ST = from_shape_and_word(mu, range(1, r + 1), convention="English")

    # make ell the reading word of the highest weight tableau of shape mu
    ell = [i + 1 for i, l in enumerate(mu) for dummy in range(l)]

    e = M.basis()[tuple(ell)]  # the element e_l

    # This is the notation `\{X\}` from just before (5.3a) of [GreenPoly]_.
    S = SGA._indices
    BracC = SGA._from_dict({S(x.tuple()): x.sign() for x in ST.column_stabilizer()}, remove_zeros=False)
    f = e * BracC  # M.action_by_symmetric_group_algebra(e, BracC)

    # [Green, Theorem 5.3b] says that a basis of the Carter-Lusztig
    # module V_\mu is given by taking this f, and multiplying by all
    # xi_{i,ell} with ell as above and i semistandard.

    carter_lusztig = []
    for T in SemistandardTableaux(mu, max_entry=n):
        i = tuple(flatten(T))
        schur_rep = schur_representative_from_index(i, tuple(ell))
        y = A.basis()[schur_rep] * e  # M.action_by_Schur_alg(A.basis()[schur_rep], e)
        carter_lusztig.append(y.to_vector())

    # Therefore, we now have carter_lusztig as a list giving the basis
    # of `V_\mu`

    # We want to think of expressing this character as a sum of monomial
    # symmetric functions.

    # We will determine a basis element for each m_\lambda in the
    # character, and we want to keep track of them by \lambda.

    # That means that we only want to pick out the basis elements above for
    # those semistandard words whose content is a partition.

    contents = Partitions(r, max_length=n).list()
    # all partitions of r, length at most n

    # JJ will consist of a list for each element of `contents`,
    # recording the list
    # of semistandard tableaux words with that content

    # graded_basis will consist of the a corresponding basis element
    graded_basis = []
    JJ = []
    for i in range(len(contents)):
        graded_basis.append([])
        JJ.append([])
    for T in SemistandardTableaux(mu, max_entry=n):
        i = tuple(flatten(T))
        # Get the content of T
        con = [0] * n
        for a in i:
            con[a - 1] += 1
        try:
            P = Partition(con)
            P_index = contents.index(P)
            JJ[P_index].append(i)
            schur_rep = schur_representative_from_index(i, tuple(ell))
            x = A.basis()[schur_rep] * f  # M.action_by_Schur_alg(A.basis()[schur_rep], f)
            graded_basis[P_index].append(x.to_vector())
        except ValueError:
            pass

    # There is an inner product on the Carter-Lusztig module V_\mu; its
    # maximal submodule is exactly the kernel of the inner product.

    # Now, for each possible partition content, we look at the graded piece of
    # that degree, and we record how these elements pair with each of the
    # elements of carter_lusztig.

    # The kernel of this pairing is the part of this graded piece which is
    # not in the irreducible module for \mu.

    length = len(carter_lusztig)

    phi = mbasis.zero()
    for aa in range(len(contents)):
        mat = []
        for kk in range(len(JJ[aa])):
            temp = []
            for j in range(length):
                temp.append(graded_basis[aa][kk].inner_product(carter_lusztig[j]))
            mat.append(temp)
        angle = Matrix(mat)
        phi += (len(JJ[aa]) - angle.nullity()) * mbasis(contents[aa])
    return phi
        def cycle_index(self, parent = None):
            r"""
            INPUT:

             - ``self`` - a permutation group `G`
             - ``parent`` -- a free module with basis indexed by partitions,
               or behave as such, with a ``term`` and ``sum`` method
               (default: the symmetric functions over the rational field in the p basis)

            Returns the *cycle index* of `G`, which is a gadget counting
            the elements of `G` by cycle type, averaged over the group:

            .. math::

                P = \frac{1}{|G|} \sum_{g\in G} p_{ \operatorname{cycle\ type}(g) }

            EXAMPLES:

            Among the permutations of the symmetric group `S_4`, there is
            the identity, 6 cycles of length 2, 3 products of two cycles
            of length 2, 8 cycles of length 3, and 6 cycles of length 4::

                sage: S4 = SymmetricGroup(4)
                sage: P = S4.cycle_index()
                sage: 24 * P
                p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]

            If `l = (l_1,\dots,l_k)` is a partition, ``|G| P[l]`` is the number
            of elements of `G` with cycles of length `(p_1,\dots,p_k)`::

                sage: 24 * P[ Partition([3,1]) ]
                8

            The cycle index plays an important role in the enumeration of
            objects modulo the action of a group (Polya enumeration), via
            the use of symmetric functions and plethysms. It is therefore
            encoded as a symmetric function, expressed in the powersum
            basis::

                sage: P.parent()
                Symmetric Functions over Rational Field in the powersum basis

            This symmetric function can have some nice properties; for
            example, for the symmetric group `S_n`, we get the complete
            symmetric function `h_n`::

                sage: S = SymmetricFunctions(QQ); h = S.h()
                sage: h( P )
                h[4]

            TODO: add some simple examples of Polya enumeration, once it
            will be easy to expand symmetric functions on any alphabet.

            Here are the cycle indices of some permutation groups::

                sage: 6 * CyclicPermutationGroup(6).cycle_index()
                p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6]

                sage: 60 * AlternatingGroup(5).cycle_index()
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]

                sage: for G in TransitiveGroups(5):               # optional - database_gap # long time
                ...       G.cardinality() * G.cycle_index()
                p[1, 1, 1, 1, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]
                p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]

            One may specify another parent for the result::

                sage: F = CombinatorialFreeModule(QQ, Partitions())
                sage: P = CyclicPermutationGroup(6).cycle_index(parent = F)
                sage: 6 * P
                B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]]
                sage: P.parent() is F
                True

            This parent should have a ``term`` and ``sum`` method::

                sage: CyclicPermutationGroup(6).cycle_index(parent = QQ)
                Traceback (most recent call last):
                  ...
                AssertionError: `parent` should be (or behave as) a free module with basis indexed by partitions

            REFERENCES:

             .. [Ker1991] A. Kerber. Algebraic combinatorics via finite group actions, 2.2 p. 70.
               BI-Wissenschaftsverlag, Mannheim, 1991.

            AUTHORS:

             - Nicolas Borie and Nicolas M. Thiery

            TESTS::

                sage: P = PermutationGroup([]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
                sage: P = PermutationGroup([[(1)]]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
            """
            from sage.combinat.permutation import Permutation
            if parent is None:
                 from sage.rings.rational_field import QQ
                 from sage.combinat.sf.sf import SymmetricFunctions
                 parent = SymmetricFunctions(QQ).powersum()
            else:
                assert hasattr(parent, "term") and hasattr(parent, "sum"), \
                    "`parent` should be (or behave as) a free module with basis indexed by partitions"
            base_ring = parent.base_ring()
            # TODO: use self.conjugacy_classes() once available
            from sage.interfaces.gap import gap
            CC = ([Permutation(self(C.Representative())).cycle_type(), base_ring(C.Size())] for C in gap(self).ConjugacyClasses())
            return parent.sum( parent.term( partition, coeff ) for (partition, coeff) in CC)/self.cardinality()
Ejemplo n.º 44
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)
Ejemplo n.º 45
0
        def cycle_index(self, parent = None):
            r"""
            Return the *cycle index* of ``self``.

            INPUT:

             - ``self`` - a permutation group `G`
             - ``parent`` -- a free module with basis indexed by partitions,
               or behave as such, with a ``term`` and ``sum`` method
               (default: the symmetric functions over the rational field in the `p` basis)

            The *cycle index* of a permutation group `G`
            (:wikipedia:`Cycle_index`) is a gadget counting the
            elements of `G` by cycle type, averaged over the group:

            .. MATH::

                P = \frac{1}{|G|} \sum_{g\in G} p_{ \operatorname{cycle\ type}(g) }

            EXAMPLES:

            Among the permutations of the symmetric group `S_4`, there is
            the identity, 6 cycles of length 2, 3 products of two cycles
            of length 2, 8 cycles of length 3, and 6 cycles of length 4::

                sage: S4 = SymmetricGroup(4)
                sage: P = S4.cycle_index()
                sage: 24 * P
                p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]

            If `l = (l_1,\dots,l_k)` is a partition, ``|G| P[l]`` is the number
            of elements of `G` with cycles of length `(p_1,\dots,p_k)`::

                sage: 24 * P[ Partition([3,1]) ]
                8

            The cycle index plays an important role in the enumeration of
            objects modulo the action of a group (Pólya enumeration), via
            the use of symmetric functions and plethysms. It is therefore
            encoded as a symmetric function, expressed in the powersum
            basis::

                sage: P.parent()
                Symmetric Functions over Rational Field in the powersum basis

            This symmetric function can have some nice properties; for
            example, for the symmetric group `S_n`, we get the complete
            symmetric function `h_n`::

                sage: S = SymmetricFunctions(QQ); h = S.h()
                sage: h( P )
                h[4]

            .. TODO::

                Add some simple examples of Pólya enumeration, once
                it will be easy to expand symmetric functions on any
                alphabet.

            Here are the cycle indices of some permutation groups::

                sage: 6 * CyclicPermutationGroup(6).cycle_index()
                p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6]

                sage: 60 * AlternatingGroup(5).cycle_index()
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]

                sage: for G in TransitiveGroups(5):               # optional - database_gap # long time
                ....:     G.cardinality() * G.cycle_index()
                p[1, 1, 1, 1, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]
                p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]

            Permutation groups with arbitrary domains are supported
            (see :trac:`22765`)::

                sage: G = PermutationGroup([['b','c','a']], domain=['a','b','c'])
                sage: G.cycle_index()
                1/3*p[1, 1, 1] + 2/3*p[3]

            One may specify another parent for the result::

                sage: F = CombinatorialFreeModule(QQ, Partitions())
                sage: P = CyclicPermutationGroup(6).cycle_index(parent = F)
                sage: 6 * P
                B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]]
                sage: P.parent() is F
                True

            This parent should be a module with basis indexed by partitions::

                sage: CyclicPermutationGroup(6).cycle_index(parent = QQ)
                Traceback (most recent call last):
                  ...
                ValueError: `parent` should be a module with basis indexed by partitions

            REFERENCES:

            - [Ke1991]_

            AUTHORS:

            - Nicolas Borie and Nicolas M. Thiéry

            TESTS::

                sage: P = PermutationGroup([]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
                sage: P = PermutationGroup([[(1)]]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
            """
            from sage.categories.modules import Modules
            if parent is None:
                 from sage.rings.rational_field import QQ
                 from sage.combinat.sf.sf import SymmetricFunctions
                 parent = SymmetricFunctions(QQ).powersum()
            elif not parent in Modules.WithBasis:
                raise ValueError("`parent` should be a module with basis indexed by partitions")
            base_ring = parent.base_ring()
            return parent.sum_of_terms([C.an_element().cycle_type(), base_ring(C.cardinality())]
                                       for C in self.conjugacy_classes()
                                      ) / self.cardinality()
Ejemplo n.º 46
0
def GL_irreducible_character(n, mu, KK):
    r"""
    Return the character of the irreducible module indexed by ``mu``
    of `GL(n)` over the field ``KK``.

    INPUT:

    - ``n`` -- a positive integer
    - ``mu`` -- a partition of at most ``n`` parts
    - ``KK`` -- a field

    OUTPUT:

    a symmetric function which should be interpreted in ``n``
    variables to be meaningful as a character

    EXAMPLES:

    Over `\QQ`, the irreducible character for `\mu` is the Schur
    function associated to `\mu`, plus garbage terms (Schur
    functions associated to partitions with more than `n` parts)::

        sage: from sage.algebras.schur_algebra import GL_irreducible_character
        sage: sbasis = SymmetricFunctions(QQ).s()
        sage: z = GL_irreducible_character(2, [2], QQ)
        sage: sbasis(z)
        s[2]

        sage: z = GL_irreducible_character(4, [3, 2], QQ)
        sage: sbasis(z)
        -5*s[1, 1, 1, 1, 1] + s[3, 2]

    Over a Galois field, the irreducible character for `\mu` will
    in general be smaller.

    In characteristic `p`, for a one-part partition `(r)`, where
    `r = a_0 + p a_1 + p^2 a_2 + \dots`, the result is (see [Gr2007]_,
    after 5.5d) the product of `h[a_0], h[a_1]( pbasis[p]), h[a_2]
    ( pbasis[p^2]), \dots,` which is consistent with the following ::

        sage: from sage.algebras.schur_algebra import GL_irreducible_character
        sage: GL_irreducible_character(2, [7], GF(3))
        m[4, 3] + m[6, 1] + m[7]
    """
    mbasis = SymmetricFunctions(QQ).m()
    r = sum(mu)
    M = SchurTensorModule(KK, n, r)
    A = M._schur
    SGA = M._sga

    #make ST the superstandard tableau of shape mu
    from sage.combinat.tableau import from_shape_and_word
    ST = from_shape_and_word(mu, list(range(1, r + 1)), convention='English')

    #make ell the reading word of the highest weight tableau of shape mu
    ell = [i + 1 for i, l in enumerate(mu) for dummy in range(l)]

    e = M.basis()[tuple(ell)]  # the element e_l

    # This is the notation `\{X\}` from just before (5.3a) of [Gr2007]_.
    S = SGA._indices
    BracC = SGA._from_dict(
        {S(x.tuple()): x.sign()
         for x in ST.column_stabilizer()},
        remove_zeros=False)
    f = e * BracC  # M.action_by_symmetric_group_algebra(e, BracC)

    # [Green, Theorem 5.3b] says that a basis of the Carter-Lusztig
    # module V_\mu is given by taking this f, and multiplying by all
    # xi_{i,ell} with ell as above and i semistandard.

    carter_lusztig = []
    for T in SemistandardTableaux(mu, max_entry=n):
        i = tuple(flatten(T))
        schur_rep = schur_representative_from_index(i, tuple(ell))
        y = A.basis(
        )[schur_rep] * e  # M.action_by_Schur_alg(A.basis()[schur_rep], e)
        carter_lusztig.append(y.to_vector())

    #Therefore, we now have carter_lusztig as a list giving the basis
    #of `V_\mu`

    #We want to think of expressing this character as a sum of monomial
    #symmetric functions.

    #We will determine a basis element for each m_\lambda in the
    #character, and we want to keep track of them by \lambda.

    #That means that we only want to pick out the basis elements above for
    #those semistandard words whose content is a partition.

    contents = Partitions(r, max_length=n).list()
    # all partitions of r, length at most n

    # JJ will consist of a list for each element of `contents`,
    # recording the list
    # of semistandard tableaux words with that content

    # graded_basis will consist of the a corresponding basis element
    graded_basis = []
    JJ = []
    for i in range(len(contents)):
        graded_basis.append([])
        JJ.append([])
    for T in SemistandardTableaux(mu, max_entry=n):
        i = tuple(flatten(T))
        # Get the content of T
        con = [0] * n
        for a in i:
            con[a - 1] += 1
        try:
            P = Partition(con)
            P_index = contents.index(P)
            JJ[P_index].append(i)
            schur_rep = schur_representative_from_index(i, tuple(ell))
            x = A.basis(
            )[schur_rep] * f  # M.action_by_Schur_alg(A.basis()[schur_rep], f)
            graded_basis[P_index].append(x.to_vector())
        except ValueError:
            pass

    #There is an inner product on the Carter-Lusztig module V_\mu; its
    #maximal submodule is exactly the kernel of the inner product.

    #Now, for each possible partition content, we look at the graded piece of
    #that degree, and we record how these elements pair with each of the
    #elements of carter_lusztig.

    #The kernel of this pairing is the part of this graded piece which is
    #not in the irreducible module for \mu.

    length = len(carter_lusztig)

    phi = mbasis.zero()
    for aa in range(len(contents)):
        mat = []
        for kk in range(len(JJ[aa])):
            temp = []
            for j in range(length):
                temp.append(graded_basis[aa][kk].inner_product(
                    carter_lusztig[j]))
            mat.append(temp)
        angle = Matrix(mat)
        phi += (len(JJ[aa]) - angle.nullity()) * mbasis(contents[aa])
    return phi
Ejemplo n.º 47
0
        def cycle_index(self, parent = None):
            r"""
            INPUT:

             - ``self`` - a permutation group `G`
             - ``parent`` -- a free module with basis indexed by partitions,
               or behave as such, with a ``term`` and ``sum`` method
               (default: the symmetric functions over the rational field in the p basis)

            Returns the *cycle index* of `G`, which is a gadget counting
            the elements of `G` by cycle type, averaged over the group:

            .. math::

                P = \frac{1}{|G|} \sum_{g\in G} p_{ \operatorname{cycle\ type}(g) }

            EXAMPLES:

            Among the permutations of the symmetric group `S_4`, there is
            the identity, 6 cycles of length 2, 3 products of two cycles
            of length 2, 8 cycles of length 3, and 6 cycles of length 4::

                sage: S4 = SymmetricGroup(4)
                sage: P = S4.cycle_index()
                sage: 24 * P
                p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]

            If `l = (l_1,\dots,l_k)` is a partition, ``|G| P[l]`` is the number
            of elements of `G` with cycles of length `(p_1,\dots,p_k)`::

                sage: 24 * P[ Partition([3,1]) ]
                8

            The cycle index plays an important role in the enumeration of
            objects modulo the action of a group (Polya enumeration), via
            the use of symmetric functions and plethysms. It is therefore
            encoded as a symmetric function, expressed in the powersum
            basis::

                sage: P.parent()
                Symmetric Functions over Rational Field in the powersum basis

            This symmetric function can have some nice properties; for
            example, for the symmetric group `S_n`, we get the complete
            symmetric function `h_n`::

                sage: S = SymmetricFunctions(QQ); h = S.h()
                sage: h( P )
                h[4]

            TODO: add some simple examples of Polya enumeration, once it
            will be easy to expand symmetric functions on any alphabet.

            Here are the cycle indices of some permutation groups::

                sage: 6 * CyclicPermutationGroup(6).cycle_index()
                p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6]

                sage: 60 * AlternatingGroup(5).cycle_index()
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]

                sage: for G in TransitiveGroups(5):               # optional - database_gap # long time
                ...       G.cardinality() * G.cycle_index()
                p[1, 1, 1, 1, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]
                p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]

            One may specify another parent for the result::

                sage: F = CombinatorialFreeModule(QQ, Partitions())
                sage: P = CyclicPermutationGroup(6).cycle_index(parent = F)
                sage: 6 * P
                B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]]
                sage: P.parent() is F
                True

            This parent should have a ``term`` and ``sum`` method::

                sage: CyclicPermutationGroup(6).cycle_index(parent = QQ)
                Traceback (most recent call last):
                  ...
                AssertionError: `parent` should be (or behave as) a free module with basis indexed by partitions

            REFERENCES:

             .. [Ker1991] A. Kerber. Algebraic combinatorics via finite group actions, 2.2 p. 70.
               BI-Wissenschaftsverlag, Mannheim, 1991.

            AUTHORS:

             - Nicolas Borie and Nicolas M. Thiery

            TESTS::

                sage: P = PermutationGroup([]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
                sage: P = PermutationGroup([[(1)]]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
            """
            from sage.combinat.permutation import Permutation
            if parent is None:
                 from sage.rings.rational_field import QQ
                 from sage.combinat.sf.sf import SymmetricFunctions
                 parent = SymmetricFunctions(QQ).powersum()
            else:
                assert hasattr(parent, "term") and hasattr(parent, "sum"), \
                    "`parent` should be (or behave as) a free module with basis indexed by partitions"
            base_ring = parent.base_ring()
            # TODO: use self.conjugacy_classes() once available
            from sage.interfaces.gap import gap
            CC = ([Permutation(self(C.Representative())).cycle_type(), base_ring(C.Size())] for C in gap(self).ConjugacyClasses())
            return parent.sum( parent.term( partition, coeff ) for (partition, coeff) in CC)/self.cardinality()