Beispiel #1
0
    def _induced_flags(self, n, tg, type_edges):

        flag_counts = {}
        flags = []
        total = 0

        for p in Tuples([0, 1], binomial(n, 2) - binomial(tg.n, 2)):

            edges = list(type_edges)

            c = 0
            for i in range(tg.n + 1, n + 1):
                for j in range(1, i):
                    if p[c] == 0:
                        edges.append((i, j))
                    else:
                        edges.append((j, i))
                    c += 1

            ig = ThreeGraphFlag()
            ig.n = n
            ig.t = tg.n

            for s in Combinations(range(1, n + 1), 3):
                if self._variant:
                    if ((s[1], s[0]) in edges and
                        (s[0], s[2]) in edges) or ((s[2], s[0]) in edges and
                                                   (s[0], s[1]) in edges):
                        ig.add_edge(s)
                else:
                    if ((s[0], s[1]) in edges and (s[1], s[2]) in edges and
                        (s[2], s[0]) in edges) or ((s[0], s[2]) in edges and
                                                   (s[2], s[1]) in edges and
                                                   (s[1], s[0]) in edges):
                        ig.add_edge(s)

            it = ig.induced_subgraph(range(1, tg.n + 1))
            if tg.is_labelled_isomorphic(it):
                ig.make_minimal_isomorph()

                ghash = hash(ig)
                if ghash in flag_counts:
                    flag_counts[ghash] += 1
                else:
                    flags.append(ig)
                    flag_counts[ghash] = 1

            total += 1

        return [(f, flag_counts[hash(f)] / Integer(total)) for f in flags]
Beispiel #2
0
    def tangents(self, P):
        r"""
        Return the tangents of this affine plane curve at the point ``P``.

        The point ``P`` must be a point on this curve.

        INPUT:

        - ``P`` -- a point on this curve.

        OUTPUT:

        - a list of polynomials in the coordinate ring of the ambient space of this curve.

        EXAMPLES::

            sage: R.<a> = QQ[]
            sage: K.<b> = NumberField(a^2 - 3)
            sage: A.<x,y> = AffineSpace(K, 2)
            sage: C = Curve([(x^2 + y^2 - 2*x)^2 - x^2 - y^2], A)
            sage: Q = A([0,0])
            sage: C.tangents(Q)
            [x + (-1/3*b)*y, x + (1/3*b)*y]

        ::

            sage: A.<x,y> = AffineSpace(QQ, 2)
            sage: C = A.curve([y^2 - x^3 - x^2])
            sage: Q = A([0,0])
            sage: C.tangents(Q)
            [x - y, x + y]

        ::

            sage: A.<x,y> = AffineSpace(QQ, 2)
            sage: C = A.curve([y*x - x^4 + 2*x^2])
            sage: Q = A([1,1])
            sage: C.tangents(Q)
            Traceback (most recent call last):
            ...
            TypeError: (=(1, 1)) is not a point on (=Affine Plane Curve over
            Rational Field defined by -x^4 + 2*x^2 + x*y)
        """
        r = self.multiplicity(P)
        f = self.defining_polynomials()[0]
        vars = self.ambient_space().gens()
        deriv = [
            f.derivative(vars[0], i).derivative(vars[1], r - i)(list(P))
            for i in range(r + 1)
        ]
        from sage.arith.misc import binomial
        T = sum([
            binomial(r, i) * deriv[i] * (vars[0] - P[0])**i *
            (vars[1] - P[1])**(r - i) for i in range(r + 1)
        ])
        fact = T.factor()
        return [l[0] for l in fact]
Beispiel #3
0
 def eqs_affine(x0, y0):
     r"""
     Make equation for the affine point x0, y0. Return a list of
     equations, each equation being a list of coefficients corresponding to
     the monomials in ``monomials``.
     """
     eqs = []
     for i in range(s):
         for j in range(s - i):
             eq = dict()
             for monomial in monomials:
                 ihat = monomial[0]
                 jhat = monomial[1]
                 if ihat >= i and jhat >= j:
                     icoeff = binomial(ihat, i) * x0**(ihat-i) \
                                 if ihat > i else 1
                     jcoeff = binomial(jhat, j) * y0**(jhat-j) \
                                 if jhat > j else 1
                     eq[monomial] = jcoeff * icoeff
             eqs.append([eq.get(monomial, 0) for monomial in monomials])
     return eqs
    def __init__(self, base_field, order, num_of_var):
        r"""
        TESTS:

        Note that the order given cannot be greater than (q-1). An error is raised if that happens::

            sage: from sage.coding.reed_muller_code import QAryReedMullerCode
            sage: C = QAryReedMullerCode(GF(3), 4, 4)
            Traceback (most recent call last):
            ...
            ValueError: The order must be less than 3

        The order and the number of variable must be integers::

            sage: C = QAryReedMullerCode(GF(3),1.1,4)
            Traceback (most recent call last):
            ...
            ValueError: The order of the code must be an integer

        The base_field parameter must be a finite field::

            sage: C = QAryReedMullerCode(QQ,1,4)
            Traceback (most recent call last):
            ...
            ValueError: the input `base_field` must be a FiniteField
        """
        # input sanitization
        if base_field not in FiniteFields():
            raise ValueError("the input `base_field` must be a FiniteField")
        if not (isinstance(order, (Integer, int))):
            raise ValueError("The order of the code must be an integer")
        if not (isinstance(num_of_var, (Integer, int))):
            raise ValueError("The number of variables must be an integer")
        q = base_field.cardinality()
        if (order >= q):
            raise ValueError("The order must be less than %s" % q)

        super(QAryReedMullerCode,
              self).__init__(base_field, q**num_of_var, "EvaluationVector",
                             "Syndrome")
        self._order = order
        self._num_of_var = num_of_var
        self._dimension = binomial(num_of_var + order, order)
Beispiel #5
0
    def zero_eigenvectors(self, tg, flags):

        rows = set()
        for p in Tuples([0, 1], binomial(tg.n, 2)):
            edges = []
            c = 0
            for i in range(1, tg.n + 1):
                for j in range(1, i):
                    if p[c] == 0:
                        edges.append((i, j))
                    else:
                        edges.append((j, i))
                    c += 1
            graphs = self._induced_flags(flags[0].n, tg, edges)
            row = [0 for f in flags]
            for pair in graphs:
                g, den = pair
                for i in range(len(flags)):
                    if g.is_labelled_isomorphic(flags[i]):
                        row[i] = den
                        break
            rows.add(tuple(row))

        return matrix_of_independent_rows(self._field, list(rows), len(flags))
    def coproduct_on_basis(self, i):
        r"""
        The coproduct of a basis element.

        .. MATH::

            \Delta(P_i) = \sum_{j=0}^i P_{i-j} \otimes P_j

        INPUT:

        - ``i`` -- a non-negative integer

        OUTPUT:

        - an element of the tensor square of ``self``

        TESTS::

            sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example()
            sage: H.monomial(3).coproduct()
            P0 # P3 + 3*P1 # P2 + 3*P2 # P1 + P3 # P0
        """
        return self.sum_of_terms(
            ((i - j, j), binomial(i, j)) for j in range(i + 1))
Beispiel #7
0
def symbolic_matrix_power(M, n):
    r"""
    Return the symbolic power ``M^n`` of the unipotent matrix ``M``.

    EXAMPLES::

        sage: from surface_dynamics.misc.linalg import symbolic_matrix_power
        sage: m = matrix(3, [1,1,1,0,1,1,0,0,1])
        sage: n = polygen(QQ, 'n')
        sage: symbolic_matrix_power(m, n)
        [              1               n 1/2*n^2 + 1/2*n]
        [              0               1               n]
        [              0               0               1]

        sage: m = matrix(2, [2,1,1,1])
        sage: symbolic_matrix_power(m, n)
        Traceback (most recent call last):
        ...
        NotImplementedError: power only implemented for unipotent matrices
    """
    d = M.nrows()
    I = M.parent().identity_matrix()
    N = M - M.parent().identity_matrix()
    char = N.charpoly()
    if any(char[i] for i in range(d)):
        raise NotImplementedError(
            'power only implemented for unipotent matrices')

    result = I
    P = N
    p = 1
    while P:
        result += binomial(n, p) * P
        P *= N
        p += 1
    return result
    def Chow_form(self):
        r"""
        Returns the Chow form associated to this subscheme.

        For a `k`-dimensional subvariety of `\mathbb{P}^N` of degree `D`.
        The `(N-k-1)`-dimensional projective linear subspaces of `\mathbb{P}^N`
        meeting `X` form a hypersurface in the Grassmannian `G(N-k-1,N)`.
        The homogeneous form of degree `D` defining this hypersurface in Plucker
        coordinates is called the Chow form of `X`.

        The base ring needs to be a number field, finite field, or `\QQbar`.

        ALGORITHM:

        For a `k`-dimension subscheme `X` consider the `k+1` linear forms
        `l_i = u_{i0}x_0 + \cdots + u_{in}x_n`. Let `J` be the ideal in the
        polynomial ring `K[x_i,u_{ij}]` defined by the equations of `X` and the `l_i`.
        Let `J'` be the saturation of `J` with respect to the irrelevant ideal of
        the ambient projective space of `X`. The elimination ideal `I = J' \cap K[u_{ij}]`
        is a principal ideal, let `R` be its generator. The Chow form is obtained by
        writing `R` as a polynomial in Plucker coordinates (i.e. bracket polynomials).
        [DalbecSturmfels]_.

        OUTPUT: a homogeneous polynomial.

        REFERENCES:

        .. [DalbecSturmfels] J. Dalbec and B. Sturmfels. Invariant methods in discrete and computational geometry,
           chapter Introduction to Chow forms, pages 37-58. Springer Netherlands, 1994.

        EXAMPLES::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(GF(17), 3)
            sage: X = P.subscheme([x3+x1,x2-x0,x2-x3])
            sage: X.Chow_form()
            t0 - t1 + t2 + t3

        ::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x3^2 -101*x1^2 - 3*x2*x0])
            sage: X.Chow_form()
            t0^2 - 101*t2^2 - 3*t1*t3

        ::

            sage: P.<x0,x1,x2,x3>=ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x0*x2-x1^2, x0*x3-x1*x2, x1*x3-x2^2])
            sage: Ch = X.Chow_form(); Ch
            t2^3 + 2*t2^2*t3 + t2*t3^2 - 3*t1*t2*t4 - t1*t3*t4 + t0*t4^2 + t1^2*t5
            sage: Y = P.subscheme_from_Chow_form(Ch, 1); Y
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              x2^2*x3 - x1*x3^2,
              -x2^3 + x0*x3^2,
              -x2^2*x3 + x1*x3^2,
              x1*x2*x3 - x0*x3^2,
              3*x1*x2^2 - 3*x0*x2*x3,
              -2*x1^2*x3 + 2*x0*x2*x3,
              -3*x1^2*x2 + 3*x0*x1*x3,
              x1^3 - x0^2*x3,
              x2^3 - x1*x2*x3,
              -3*x1*x2^2 + 2*x1^2*x3 + x0*x2*x3,
              2*x0*x2^2 - 2*x0*x1*x3,
              3*x1^2*x2 - 2*x0*x2^2 - x0*x1*x3,
              -x0*x1*x2 + x0^2*x3,
              -x0*x1^2 + x0^2*x2,
              -x1^3 + x0*x1*x2,
              x0*x1^2 - x0^2*x2
            sage: I = Y.defining_ideal()
            sage: I.saturation(I.ring().ideal(list(I.ring().gens())))[0]
            Ideal (x2^2 - x1*x3, x1*x2 - x0*x3, x1^2 - x0*x2) of Multivariate
            Polynomial Ring in x0, x1, x2, x3 over Rational Field
        """
        I = self.defining_ideal()
        P = self.ambient_space()
        R = P.coordinate_ring()
        N = P.dimension() + 1
        d = self.dimension()
        # create the ring for the generic linear hyperplanes
        # u0x0 + u1x1 + ...
        SS = PolynomialRing(R.base_ring(), 'u', N * (d + 1), order='lex')
        vars = SS.variable_names() + R.variable_names()
        S = PolynomialRing(R.base_ring(), vars, order='lex')
        n = S.ngens()
        newcoords = [S.gen(n - N + t) for t in range(N)]
        # map the generators of the subscheme into the ring with the hyperplane variables
        phi = R.hom(newcoords, S)
        phi(self.defining_polynomials()[0])
        # create the dim(X)+1 linear hyperplanes
        l = []
        for i in range(d + 1):
            t = 0
            for j in range(N):
                t += S.gen(N * i + j) * newcoords[j]
            l.append(t)
        # intersect the hyperplanes with X
        J = phi(I) + S.ideal(l)
        # saturate the ideal with respect to the irrelevant ideal
        J2 = J.saturation(S.ideal([phi(u) for u in R.gens()]))[0]
        # eliminate the original variables to be left with the hyperplane coefficients 'u'
        E = J2.elimination_ideal(newcoords)
        # create the plucker coordinates
        D = binomial(N, N - d - 1)  #number of plucker coordinates
        tvars = [str('t') + str(i) for i in range(D)]  #plucker coordinates
        T = PolynomialRing(R.base_ring(),
                           tvars + list(S.variable_names()),
                           order='lex')
        L = []
        coeffs = [
            T.gen(i) for i in range(0 + len(tvars),
                                    N * (d + 1) + len(tvars))
        ]
        M = matrix(T, d + 1, N, coeffs)
        i = 0
        for c in M.minors(d + 1):
            L.append(T.gen(i) - c)
            i += 1
        # create the ideal that we can use for eliminating to get a polynomial
        # in the plucker coordinates (brackets)
        br = T.ideal(L)
        # create a mapping into a polynomial ring over the plucker coordinates
        # and the hyperplane coefficients
        psi = S.hom(coeffs + [0 for _ in range(N)], T)
        E2 = T.ideal([psi(u) for u in E.gens()] + br)
        # eliminate the hyperplane coefficients
        CH = E2.elimination_ideal(coeffs)
        # CH should be a principal ideal, but because of the relations among
        # the plucker coordinates, the elimination will probably have several generators

        # get the relations among the plucker coordinates
        rel = br.elimination_ideal(coeffs)
        # reduce CH with respect to the relations
        reduced = []
        for f in CH.gens():
            reduced.append(f.reduce(rel))
        # find the principal generator

        # polynomial ring in just the plucker coordinates
        T2 = PolynomialRing(R.base_ring(), tvars)
        alp = T.hom(tvars + (N * (d + 1) + N) * [0], T2)
        # get the degrees of the reduced generators of CH
        degs = [u.degree() for u in reduced]
        mind = max(degs)
        # need the smallest degree form that did not reduce to 0
        for d in degs:
            if d < mind and d > 0:
                mind = d
        ind = degs.index(mind)
        CF = reduced[ind]  #this should be the Chow form of X
        # check that it is correct (i.e., it is a principal generator for CH + the relations)
        rel2 = rel + [CF]
        assert all(f in rel2
                   for f in CH.gens()), "did not find a principal generator"
        return alp(CF)
        def _test_jacobi(self, **options):
            """
            Test the Jacobi axiom of this Lie conformal algebra.

            INPUT:

            - ``options`` -- any keyword arguments acceptde by :meth:`_tester`

            EXAMPLES:

            By default, this method tests only the elements returned by
            ``self.some_elements()``::

                sage: V = lie_conformal_algebras.Affine(QQ, 'B2')
                sage: V._test_jacobi()      # long time (6 seconds)

            It works for super Lie conformal algebras too::

                sage: V = lie_conformal_algebras.NeveuSchwarz(QQ)
                sage: V._test_jacobi()

            We can use specific elements by passing the ``elements``
            keyword argument::

                sage: V = lie_conformal_algebras.Affine(QQ, 'A1', names=('e', 'h', 'f'))
                sage: V.inject_variables()
                Defining e, h, f, K
                sage: V._test_jacobi(elements=(e, 2*f+h, 3*h))

            TESTS::

                sage: wrongdict = {('a', 'a'): {0: {('b', 0): 1}}, ('b', 'a'): {0: {('a', 0): 1}}}
                sage: V = LieConformalAlgebra(QQ, wrongdict, names=('a', 'b'), parity=(1, 0))
                sage: V._test_jacobi()
                Traceback (most recent call last):
                ...
                AssertionError: {(0, 0): -3*a} != {}
                - {(0, 0): -3*a}
                + {}
            """
            tester = self._tester(**options)
            S = tester.some_elements()
            from sage.misc.misc import some_tuples
            from sage.arith.misc import binomial
            pz = tester._instance.zero()
            for x, y, z in some_tuples(S, 3, tester._max_runs):
                brxy = x.bracket(y)
                brxz = x.bracket(z)
                bryz = y.bracket(z)
                br1 = {k: x.bracket(v) for k, v in bryz.items()}
                br2 = {k: v.bracket(z) for k, v in brxy.items()}
                br3 = {k: y.bracket(v) for k, v in brxz.items()}
                jac1 = {(j, k): v for k in br1 for j, v in br1[k].items()}
                jac3 = {(k, j): v for k in br3 for j, v in br3[k].items()}
                jac2 = {}
                for k, br in br2.items():
                    for j, v in br.items():
                        for r in range(j + 1):
                            jac2[(k + r, j - r)] = (jac2.get(
                                (k + r, j - r), pz) + binomial(k + r, r) * v)
                for k, v in jac2.items():
                    jac1[k] = jac1.get(k, pz) - v
                for k, v in jac3.items():
                    jac1[k] = jac1.get(k, pz) - v
                jacobiator = {k: v for k, v in jac1.items() if v}
                tester.assertDictEqual(jacobiator, {})
    def Chow_form(self):
        r"""
        Returns the Chow form associated to this subscheme.

        For a `k`-dimensional subvariety of `\mathbb{P}^N` of degree `D`.
        The `(N-k-1)`-dimensional projective linear subspaces of `\mathbb{P}^N`
        meeting `X` form a hypersurface in the Grassmannian `G(N-k-1,N)`.
        The homogeneous form of degree `D` defining this hypersurface in Plucker
        coordinates is called the Chow form of `X`.

        The base ring needs to be a number field, finite field, or `\QQbar`.

        ALGORITHM:

        For a `k`-dimension subscheme `X` consider the `k+1` linear forms
        `l_i = u_{i0}x_0 + \cdots + u_{in}x_n`. Let `J` be the ideal in the
        polynomial ring `K[x_i,u_{ij}]` defined by the equations of `X` and the `l_i`.
        Let `J'` be the saturation of `J` with respect to the irrelevant ideal of
        the ambient projective space of `X`. The elimination ideal `I = J' \cap K[u_{ij}]`
        is a principal ideal, let `R` be its generator. The Chow form is obtained by
        writing `R` as a polynomial in Plucker coordinates (i.e. bracket polynomials).
        [DalbecSturmfels]_.

        OUTPUT: a homogeneous polynomial.

        REFERENCES:

        .. [DalbecSturmfels] J. Dalbec and B. Sturmfels. Invariant methods in discrete and computational geometry,
           chapter Introduction to Chow forms, pages 37-58. Springer Netherlands, 1994.

        EXAMPLES::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(GF(17), 3)
            sage: X = P.subscheme([x3+x1,x2-x0,x2-x3])
            sage: X.Chow_form()
            t0 - t1 + t2 + t3

        ::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x3^2 -101*x1^2 - 3*x2*x0])
            sage: X.Chow_form()
            t0^2 - 101*t2^2 - 3*t1*t3

        ::

            sage: P.<x0,x1,x2,x3>=ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x0*x2-x1^2, x0*x3-x1*x2, x1*x3-x2^2])
            sage: Ch = X.Chow_form(); Ch
            t2^3 + 2*t2^2*t3 + t2*t3^2 - 3*t1*t2*t4 - t1*t3*t4 + t0*t4^2 + t1^2*t5
            sage: Y = P.subscheme_from_Chow_form(Ch, 1); Y
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              x2^2*x3 - x1*x3^2,
              -x2^3 + x0*x3^2,
              -x2^2*x3 + x1*x3^2,
              x1*x2*x3 - x0*x3^2,
              3*x1*x2^2 - 3*x0*x2*x3,
              -2*x1^2*x3 + 2*x0*x2*x3,
              -3*x1^2*x2 + 3*x0*x1*x3,
              x1^3 - x0^2*x3,
              x2^3 - x1*x2*x3,
              -3*x1*x2^2 + 2*x1^2*x3 + x0*x2*x3,
              2*x0*x2^2 - 2*x0*x1*x3,
              3*x1^2*x2 - 2*x0*x2^2 - x0*x1*x3,
              -x0*x1*x2 + x0^2*x3,
              -x0*x1^2 + x0^2*x2,
              -x1^3 + x0*x1*x2,
              x0*x1^2 - x0^2*x2
            sage: I = Y.defining_ideal()
            sage: I.saturation(I.ring().ideal(list(I.ring().gens())))[0]
            Ideal (x2^2 - x1*x3, x1*x2 - x0*x3, x1^2 - x0*x2) of Multivariate
            Polynomial Ring in x0, x1, x2, x3 over Rational Field
        """
        I = self.defining_ideal()
        P = self.ambient_space()
        R = P.coordinate_ring()
        N = P.dimension()+1
        d = self.dimension()
        #create the ring for the generic linear hyperplanes
        # u0x0 + u1x1 + ...
        SS = PolynomialRing(R.base_ring(), 'u', N*(d+1), order='lex')
        vars = SS.variable_names() + R.variable_names()
        S = PolynomialRing(R.base_ring(), vars, order='lex')
        n = S.ngens()
        newcoords = [S.gen(n-N+t) for t in range(N)]
        #map the generators of the subscheme into the ring with the hyperplane variables
        phi = R.hom(newcoords,S)
        phi(self.defining_polynomials()[0])
        #create the dim(X)+1 linear hyperplanes
        l = []
        for i in range(d+1):
            t = 0
            for j in range(N):
                t += S.gen(N*i + j)*newcoords[j]
            l.append(t)
        #intersect the hyperplanes with X
        J = phi(I) + S.ideal(l)
        #saturate the ideal with respect to the irrelevant ideal
        J2 = J.saturation(S.ideal([phi(t) for t in R.gens()]))[0]
        #eliminate the original variables to be left with the hyperplane coefficients 'u'
        E = J2.elimination_ideal(newcoords)
        #create the plucker coordinates
        D = binomial(N,N-d-1) #number of plucker coordinates
        tvars = [str('t') + str(i) for i in range(D)] #plucker coordinates
        T = PolynomialRing(R.base_ring(), tvars+list(S.variable_names()), order='lex')
        L = []
        coeffs = [T.gen(i) for i in range(0+len(tvars), N*(d+1)+len(tvars))]
        M = matrix(T,d+1,N,coeffs)
        i = 0
        for c in M.minors(d+1):
            L.append(T.gen(i)-c)
            i += 1
        #create the ideal that we can use for eliminating to get a polynomial
        #in the plucker coordinates (brackets)
        br = T.ideal(L)
        #create a mapping into a polynomial ring over the plucker coordinates
        #and the hyperplane coefficients
        psi = S.hom(coeffs + [0 for i in range(N)],T)
        E2 = T.ideal([psi(u) for u in E.gens()] +br)
        #eliminate the hyperplane coefficients
        CH = E2.elimination_ideal(coeffs)
        #CH should be a principal ideal, but because of the relations among
        #the plucker coordinates, the elimination will probably have several generators

        #get the relations among the plucker coordinates
        rel = br.elimination_ideal(coeffs)
        #reduce CH with respect to the relations
        reduced = []
        for f in CH.gens():
            reduced.append(f.reduce(rel))
        #find the principal generator

        #polynomial ring in just the plucker coordinates
        T2 = PolynomialRing(R.base_ring(), tvars)
        alp = T.hom(tvars + (N*(d+1) +N)*[0], T2)
        #get the degrees of the reduced generators of CH
        degs = [u.degree() for u in reduced]
        mind = max(degs)
        #need the smallest degree form that did not reduce to 0
        for d in degs:
            if d < mind and d >0:
                mind = d
        ind = degs.index(mind)
        CF = reduced[ind] #this should be the Chow form of X
        #check that it is correct (i.e., it is a principal generator for CH + the relations)
        rel2 = rel + [CF]
        assert all([f in rel2 for f in CH.gens()]), "did not find a principal generator"
        return(alp(CF))
Beispiel #11
0
    def _virasoro(self, g, n, I):
        # TODO: we should use exponential notations for I
        if (g, n, I) in self._cache:
            return self._cache[(g, n, I)]

        Idict = defaultdict(int)
        for i in I[1:]:
            Idict[i] += 1
        Ituple = sorted(Idict.items())

        # set to True for debugging information
        verbose = False

        if verbose:
            print("Frec({}, {}, {}".format(g, n, I))

        B = self.B
        C = self.C
        F = self.F

        if verbose:
            print("compute S1")
        J = I[1:]
        S1 = ZZ_0
        for im, _ in Ituple:
            fac = Idict[im]
            J = []
            for j, mult in Ituple:
                if j == im:
                    J.extend([j] * (mult - 1))
                else:
                    J.extend([j] * mult)
            J = tuple(J)

            s = sum(J)  # = i + j
            for (a, value) in B(g, n - s - 1, I[0], im):
                if verbose:
                    print("[S1] B({}, {}, {}) F({}, {}, {})".format(
                        I[0], im, a, g, n - 1, (a, ) + J))
                S1 += fac * value * F(g, n - 1, (a, ) + J)
        if verbose:
            print("S1 = {}".format(S1))

        if verbose:
            print("S2")
        S2 = ZZ_0
        if g >= 1:
            # TODO: here the bound is actually for the sum since the new tuple
            # is (a, b) + I[1:].
            I1 = I[1:]
            abbound = 3 * (g - 1) - 3 + (n + 1) - sum(I1)
            for (a, b, value) in C(I[0], abbound, abbound, abbound):
                if verbose:
                    print("[S2] C({}, {}, {}) F({}, {}, {})".format(
                        I[0], a, b, g - 1, n + 1, (a, b) + I1))
                S2 += value * F(g - 1, n + 1, (a, b) + I1)
        if verbose:
            print("S2 = {}".format(S2))

        if verbose:
            print("S3")
        S3 = ZZ_0
        for n1 in range(n):
            n2 = n - n1 - 1

            g1min = int(n1 < 2)
            g2min = int(n2 < 2)

            for M1 in IntegerListsLex(min_sum=n1,
                                      max_sum=n1,
                                      length=len(Ituple),
                                      ceiling=[v for k, v in Ituple]):
                I1 = []
                I2 = []
                fac = 1
                for m, (k, v) in zip(M1, Ituple):
                    I1.extend([k] * m)
                    I2.extend([k] * (v - m))
                    fac *= binomial(v, m)
                I1 = tuple(I1)
                I2 = tuple(I2)

                s1 = sum(I1)
                s2 = sum(I2)

                # the above choices of combinations already forces the genus
                # ie, 3g1-3+n1 >= s1 and 3g2-3+n2 >= s2
                # g1 >= (s1 + 3 - n1)/3
                gg1min = max(g1min, (s1 - n1 + 4) // 3)
                gg2min = max(g2min, (s2 - n2 + 4) // 3)
                gg1max = g - gg2min
                for g1 in range(gg1min, gg1max + 1):
                    g2 = g - g1
                    a1bound = 3 * g1 - 3 + (n1 + 1) - s1
                    a2bound = 3 * g2 - 3 + (n2 + 1) - s2
                    for (a1, a2, value) in C(I[0], a1bound, a2bound,
                                             a1bound + a2bound):
                        f1 = F(g1, n1 + 1, (a1, ) + I1)
                        f2 = F(g2, n2 + 1, (a2, ) + I2)
                        if verbose:
                            print(
                                "[S3] C({}, {}, {}) F({}, {}, {}) F({}, {}, {})"
                                .format(I[0], a1, a2, g1, n1 + 1, (a1, ) + I1,
                                        g2, n2 + 1, (a2, ) + I2))
                        S3 += fac * value * f1 * f2

        if verbose:
            print("S3 = {}".format(S3))

        value = S1 + (S2 + S3) / ZZ_2
        if self._cache_all or I[0] >= 2:
            # We do not cache string/dilaton if _cache_all = False
            self._cache[(g, n, I)] = value
        return value
Beispiel #12
0
        def principal_specialization(self, n=infinity, q=None):
            r"""
            Return the principal specialization of a symmetric function.

            The *principal specialization* of order `n` at `q`
            is the ring homomorphism `ps_{n,q}` from the ring of
            symmetric functions to another commutative ring `R`
            given by `x_i \mapsto q^{i-1}` for `i \in \{1,\dots,n\}`
            and `x_i \mapsto 0` for `i > n`.
            Here, `q` is a given element of `R`, and we assume that
            the variables of our symmetric functions are
            `x_1, x_2, x_3, \ldots`.
            (To be more precise, `ps_{n,q}` is a `K`-algebra
            homomorphism, where `K` is the base ring.)
            See Section 7.8 of [EnumComb2]_.

            The *stable principal specialization* at `q` is the ring
            homomorphism `ps_q` from the ring of symmetric functions
            to another commutative ring `R` given by
            `x_i \mapsto q^{i-1}` for all `i`.
            This is well-defined only if the resulting infinite sums
            converge; thus, in particular, setting `q = 1` in the
            stable principal specialization is an invalid operation.

            INPUT:

            - ``n`` (default: ``infinity``) -- a nonnegative integer or
              ``infinity``, specifying whether to compute the principal
              specialization of order ``n`` or the stable principal
              specialization.

            - ``q`` (default: ``None``) -- the value to use for `q`; the
              default is to create a ring of polynomials in ``q``
              (or a field of rational functions in ``q``) over the
              given coefficient ring.

            For ``q=1`` and finite ``n`` we use the formula from
            Proposition 7.8.3 of [EnumComb2]_:

            .. MATH::

                ps_{n,1}(m_\lambda) = \binom{n}{\ell(\lambda)}
                                      \binom{\ell(\lambda)}{m_1(\lambda), m_2(\lambda),\dots},

            where `\ell(\lambda)` denotes the length of `\lambda`.

            In all other cases, we convert to complete homogeneous
            symmetric functions.

            EXAMPLES::

                sage: m = SymmetricFunctions(QQ).m()
                sage: x = m[3,1]
                sage: x.principal_specialization(3)
                q^7 + q^6 + q^5 + q^3 + q^2 + q

                sage: x = 5*m[2] + 3*m[1] + 1
                sage: x.principal_specialization(3, q=var("q"))
                -10*(q^3 - 1)*q/(q - 1) + 5*(q^3 - 1)^2/(q - 1)^2 + 3*(q^3 - 1)/(q - 1) + 1

            TESTS::

                sage: m.zero().principal_specialization(3)
                0

            """
            if q == 1:
                if n == infinity:
                    raise ValueError(
                        "the stable principal specialization at q=1 is not defined"
                    )
                f = lambda partition: binomial(n, len(
                    partition)) * multinomial(partition.to_exp())
                return self.parent()._apply_module_morphism(
                    self, f, q.parent())

            # heuristically, it seems fastest to fall back to the
            # elementary basis - using the powersum basis would
            # introduce singularities, because it is not a Z-basis
            return self.parent().realization_of().elementary()(
                self).principal_specialization(n=n, q=q)