def replace_p(P, listP, FractionField):
    """
    Take a rational fraction P and a list of rational fractions

    and try to find the simplest product or quotient
    """
    if P == 0:
        return P
    Q = FractionField(P)
    d = Q.numerator().degree() + Q.denominator().degree()
    case = 0
    ind = -1
    for i, PP in enumerate(listP):
        PP = FractionField(PP)
        if not (PP == P):
            QQ1 = P * PP
            dd1 = QQ1.numerator().degree() + QQ1.denominator().degree()
            if dd1 < d:
                Q = QQ1
                d = Q.numerator().degree() + Q.denominator().degree()
                case = 1
                ind = i
            QQ2 = PP / P
            dd2 = QQ2.numerator().degree() + QQ2.denominator().degree()
            if dd2 < d:
                Q = QQ2
                d = Q.numerator().degree() + Q.denominator().degree()
                case = -1
                ind = i
    return FractionField(Q), [case, ind]
    def canonical_scheme(self, t=None):
        """
        Return the canonical scheme.

        This is a scheme that contains this hypergeometric motive in its cohomology.

        EXAMPLES::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: H = Hyp(cyclotomic=([3],[4]))
            sage: H.gamma_list()
            [-1, 2, 3, -4]
            sage: H.canonical_scheme()
            Spectrum of Quotient of Multivariate Polynomial Ring
            in X0, X1, Y0, Y1 over Fraction Field of Univariate Polynomial Ring
            in t over Rational Field by the ideal
            (X0 + X1 - 1, Y0 + Y1 - 1, (-t)*X0^2*X1^3 + 27/64*Y0*Y1^4)

            sage: H = Hyp(gamma_list=[-2, 3, 4, -5])
            sage: H.canonical_scheme()
            Spectrum of Quotient of Multivariate Polynomial Ring
            in X0, X1, Y0, Y1 over Fraction Field of Univariate Polynomial Ring
            in t over Rational Field by the ideal
            (X0 + X1 - 1, Y0 + Y1 - 1, (-t)*X0^3*X1^4 + 1728/3125*Y0^2*Y1^5)

        REFERENCES:

        [Kat1991]_, section 5.4
        """
        if t is None:
            t = FractionField(QQ['t']).gen()
        basering = t.parent()
        gamma_pos = [u for u in self.gamma_list() if u > 0]
        gamma_neg = [u for u in self.gamma_list() if u < 0]
        N_pos = len(gamma_pos)
        N_neg = len(gamma_neg)
        varX = ['X{}'.format(i) for i in range(N_pos)]
        varY = ['Y{}'.format(i) for i in range(N_neg)]
        ring = PolynomialRing(basering, varX + varY)
        gens = ring.gens()
        X = gens[:N_pos]
        Y = gens[N_pos:]
        eq0 = ring.sum(X) - 1
        eq1 = ring.sum(Y) - 1
        eq2_pos = ring.prod(X[i] ** gamma_pos[i] for i in range(N_pos))
        eq2_neg = ring.prod(Y[j] ** -gamma_neg[j] for j in range(N_neg))

        ideal = ring.ideal([eq0, eq1, self.M_value() * eq2_neg - t * eq2_pos])
        return Spec(ring.quotient(ideal))
예제 #3
0
    def canonical_scheme(self, t=None):
        """
        Return the canonical scheme.

        This is a scheme that contains this hypergeometric motive in its cohomology.

        EXAMPLES::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: H = Hyp(cyclotomic=([3],[4]))
            sage: H.gamma_list()
            [-1, 2, 3, -4]
            sage: H.canonical_scheme()
            Spectrum of Quotient of Multivariate Polynomial Ring
            in X0, X1, Y0, Y1 over Fraction Field of Univariate Polynomial Ring
            in t over Rational Field by the ideal
            (X0 + X1 - 1, Y0 + Y1 - 1, (-t)*X0^2*X1^3 + 27/64*Y0*Y1^4)

            sage: H = Hyp(gamma_list=[-2, 3, 4, -5])
            sage: H.canonical_scheme()
            Spectrum of Quotient of Multivariate Polynomial Ring
            in X0, X1, Y0, Y1 over Fraction Field of Univariate Polynomial Ring
            in t over Rational Field by the ideal
            (X0 + X1 - 1, Y0 + Y1 - 1, (-t)*X0^3*X1^4 + 1728/3125*Y0^2*Y1^5)

        REFERENCES:

        [Kat1991]_, section 5.4
        """
        if t is None:
            t = FractionField(QQ['t']).gen()
        basering = t.parent()
        gamma_pos = [u for u in self.gamma_list() if u > 0]
        gamma_neg = [u for u in self.gamma_list() if u < 0]
        N_pos = len(gamma_pos)
        N_neg = len(gamma_neg)
        varX = ['X{}'.format(i) for i in range(N_pos)]
        varY = ['Y{}'.format(i) for i in range(N_neg)]
        ring = PolynomialRing(basering, varX + varY)
        gens = ring.gens()
        X = gens[:N_pos]
        Y = gens[N_pos:]
        eq0 = ring.sum(X) - 1
        eq1 = ring.sum(Y) - 1
        eq2_pos = ring.prod(X[i] ** gamma_pos[i] for i in range(N_pos))
        eq2_neg = ring.prod(Y[j] ** -gamma_neg[j] for j in range(N_neg))

        ideal = ring.ideal([eq0, eq1, self.M_value() * eq2_neg - t * eq2_pos])
        return Spec(ring.quotient(ideal))
def compacte_liste(listP, FractionField):
    """
    Take a list of rational fractions

    and return the an equivalent list with minimal degrees.
    """
    check = matrix.zero(ZZ, len(listP))
    Res = [P for P in listP]
    for i, P in enumerate(listP):
        P = FractionField(P)
        Q, [case, ind] = replace_p(P, listP, FractionField)
        check[i, i] = 1
        if case != 0:
            check2 = check
            check2[i, ind] = case

            if check2.rank() < check.rank(
            ):  #On vérifie qu'on n'oublie pas une équation!
                Q = P
            else:
                check = check2
        if not (Q in Res):
            Res.remove(P)
            if Q.numerator().degree() + Q.denominator().degree() == 0:
                #(in case we had to proportional equations
                pass
            else:
                Res += [Q]
    return Res
예제 #5
0
    def __init__(self, polynomial_ring, category):
        r"""
        Create the ring of CFiniteSequences over ``base_ring``

        INPUT:

        - ``base_ring`` -- the base ring for the o.g.f (either ``QQ`` or ``ZZ``)
        - ``names`` -- an iterable of variables (should contain only one variable)
        - ``category`` -- the category of the ring (default: ``Fields()``)

        TESTS::

            sage: C.<y> = CFiniteSequences(QQ); C
            The ring of C-Finite sequences in y over Rational Field
            sage: C.<x> = CFiniteSequences(QQ); C
            The ring of C-Finite sequences in x over Rational Field
            sage: C.<x> = CFiniteSequences(ZZ); C
            The ring of C-Finite sequences in x over Integer Ring
            sage: C.<x,y> = CFiniteSequences(ZZ)
            Traceback (most recent call last):
            ...
            NotImplementedError: Multidimensional o.g.f. not implemented.
            sage: C.<x> = CFiniteSequences(CC)
            Traceback (most recent call last):
            ...
            ValueError: O.g.f. base not rational.
        """
        base_ring = polynomial_ring.base_ring()
        self._polynomial_ring = polynomial_ring
        self._fraction_field = FractionField(self._polynomial_ring)
        CommutativeRing.__init__(self, base_ring, self._polynomial_ring.gens(),
                                 category)
예제 #6
0
    def local_height(self, v, prec=None):
        r"""
        Returns the maximum of the local height of the coordinates of this point.

        INPUT:

        - ``v`` -- a prime or prime ideal of the base ring.

        - ``prec`` -- desired floating point precision (default:
          default RealField precision).

        OUTPUT:

        - a real number.

        EXAMPLES::

            sage: P.<x,y,z>=  ProjectiveSpace(QQ,2)
            sage: Q = P.point([4,4,1/150], False)
            sage: Q.local_height(5)
            3.21887582486820

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: Q = P([4, 1, 30])
            sage: Q.local_height(2)
            0.693147180559945
        """
        K = FractionField(self.domain().base_ring())
        if K not in _NumberFields:
            raise TypeError("must be over a number field or a number field order")
        return max([K(c).local_height(v, prec=prec) for c in self])
def find_monom_eqs(sys):
    """
    Take a list of polynomials (seen as equations P=0

    and returns the list A/B where P = A-B and A, B are monomials
    """
    if sys == []:
        return sys
    P = sys[0]
    Ring = P.parent()  # On vérifie le type
    for Q in sys[1:]:
        if not (Q.parent() == Ring):
            print "Problème de type"
            return []

    Monom = []
    Others = []
    Field = FractionField(Ring)
    for P in sys:
        MON = P.monomials()
        if len(MON) == 2:
            Monom.append(
                Field(-P.monomial_coefficient(MON[0]) /
                      P.monomial_coefficient(MON[1]) * MON[0] / MON[1]))
        else:
            Others.append(P)
    return Monom, Others, Field
예제 #8
0
    def __hash__(self):
        """
        Compute the hash value of this point.

        If the base ring has a fraction field, normalize the point in
        the fraction field and then hash so that equal points have
        equal hash values. If the base ring is not an integral domain,
        return the hash of the parent.

        OUTPUT: Integer.

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(ZZ, 1)
            sage: hash(P([1, 1]))
            1300952125                      # 32-bit
            3713081631935493181             # 64-bit
            sage: hash(P.point([2, 2], False))
            1300952125                      # 32-bit
            3713081631935493181             # 64-bit

        ::

            sage: R.<x> = PolynomialRing(QQ)
            sage: K.<w> = NumberField(x^2 + 3)
            sage: O = K.maximal_order()
            sage: P.<x,y> = ProjectiveSpace(O, 1)
            sage: hash(P([1+w, 2]))
            -1562365407                    # 32-bit
            1251212645657227809            # 64-bit
            sage: hash(P([2, 1-w]))
            -1562365407                    # 32-bit
            1251212645657227809            # 64-bit

        TESTS::

            sage: P.<x,y> = ProjectiveSpace(Zmod(10), 1)
            sage: Q.<x,y> = ProjectiveSpace(Zmod(10), 1)
            sage: hash(P([2, 5])) == hash(Q([2, 5]))
            True
            sage: hash(P([2, 5])) == hash(P([2,5]))
            True
            sage: hash(P([3, 7])) == hash(P([2,5]))
            True
        """
        R = self.codomain().base_ring()
        #if there is a fraction field normalize the point so that
        #equal points have equal hash values
        if R in IntegralDomains():
            P = self.change_ring(FractionField(R))
            P.normalize_coordinates()
            return hash(tuple(P))
        #if there is no good way to normalize return
        #a constant value
        return hash(self.codomain())
예제 #9
0
    def __hash__(self):
        """
        Computes the hash value of this point.

        OUTPUT: Integer.

        EXAMPLES::

            sage: PP = ProductProjectiveSpaces(Zmod(6), [1, 1])
            sage: hash(PP([5, 1, 2, 4]))
            1266382469                            # 32-bit
            -855399699883264379                   # 64-bit

        ::

            sage: PP = ProductProjectiveSpaces(ZZ, [1, 2])
            sage: hash(PP([1, 1, 2, 2, 2]))
            805439612                            # 32-bit
            7267864846446758012                  # 64-bit
            sage: hash(PP([1, 1, 1, 1, 1]))
            805439612                            # 32-bit
            7267864846446758012                  # 64-bit

        ::

            sage: PP = ProductProjectiveSpaces(QQ, [1, 1])
            sage: hash(PP([1/7, 1, 2, 1]))
            1139616004                          # 32-bit
            -7585172175017137916                # 64-bit

        ::

            sage: PP = ProductProjectiveSpaces(GF(7), [1, 1, 1])
            sage: hash(PP([4, 1, 5, 4, 6, 1]))
            1796924635                          # 32-bit
            -4539377540667874085                # 64-bit
        """
        R = self.codomain().base_ring()
        # if there is a fraction field normalize the point so that
        # equal points have equal hash values
        if R in IntegralDomains():
            P = self.change_ring(FractionField(R))
            P.normalize_coordinates()
            return hash(tuple(P))
        # if there is no good way to normalize return
        # a constant value
        return hash(self.codomain())
예제 #10
0
    def local_height(self, v, prec=None):
        r"""
        Returns the maximum of the local height of the coefficients in any
        of the coordinate functions of this map.

        INPUT:

        - ``v`` -- a prime or prime ideal of the base ring.

        - ``prec`` -- desired floating point precision (default:
          default RealField precision).

        OUTPUT:

        - a real number.

        EXAMPLES::

            sage: T.<x,y,z,w,u> = ProductProjectiveSpaces([2, 1], QQ)
            sage: H = T.Hom(T)
            sage: f = H([4*x^2+3/100*y^2, 8/210*x*y, 1/10000*z^2, 20*w^2, 1/384*u*w])
            sage: f.local_height(2)
            4.85203026391962

        ::

            sage: R.<z> = PolynomialRing(QQ)
            sage: K.<w> = NumberField(z^2-5)
            sage: P.<x,y,a,b> = ProductProjectiveSpaces([1, 1], K)
            sage: H = Hom(P,P)
            sage: f = H([2*x^2 + w/3*y^2, 1/w*y^2, a^2, 6*b^2 + 1/9*a*b])
            sage: f.local_height(K.ideal(3))
            2.19722457733622
        """
        K = FractionField(self.domain().base_ring())
        if K not in NumberFields():
            raise TypeError(
                "must be over a number field or a number field order")

        H = 0
        for i in range(self.domain().ambient_space().ngens()):
            C = self[i].coefficients()
            h = max(K(c).local_height(v, prec) for c in C)
            H = max(H, h)
        return H
예제 #11
0
    def __hash__(self):
        """
        Compute the hash value of this point.

        OUTPUT: Integer.

        EXAMPLES::

            sage: PP = ProductProjectiveSpaces(Zmod(6), [1, 1])
            sage: H = hash(PP([5, 1, 2, 4]))

        ::

            sage: PP = ProductProjectiveSpaces(ZZ, [1, 2])
            sage: hash(PP([1, 1, 2, 2, 2])) == hash(PP([1, 1, 1, 1, 1]))
            True

        ::

            sage: PP = ProductProjectiveSpaces(QQ, [1, 1])
            sage: hash(PP([1/7, 1, 2, 1])) == hash((1/7, 1, 2, 1))
            True

        ::

            sage: PP = ProductProjectiveSpaces(GF(7), [1, 1, 1])
            sage: hash(PP([4, 1, 5, 4, 6, 1])) == hash((4, 1, 5, 4, 6, 1))
            False
            sage: hash(PP([4, 1, 5, 4, 6, 1])) == hash((4, 1, 3, 1, 6, 1))
            True
        """
        R = self.codomain().base_ring()
        # if there is a fraction field normalize the point so that
        # equal points have equal hash values
        if R in IntegralDomains():
            P = self.change_ring(FractionField(R))
            P.normalize_coordinates()
            return hash(tuple(P))
        # if there is no good way to normalize return
        # a constant value
        return hash(self.codomain())
예제 #12
0
파일: point.py 프로젝트: ye-man/sage
    def local_height(self, v, prec=None):
        r"""
        Return the maximum of the local height of the coordinates of this point.

        This function computes the maximum of local height of each
        component point in the product. Local height of component
        point is computed using function for projective point.

        INPUT:

        - ``v`` -- a prime or prime ideal of the base ring.

        - ``prec`` -- desired floating point precision (default:
          default RealField precision).

        OUTPUT:

        - a real number.

        EXAMPLES::

            sage: PP = ProductProjectiveSpaces(QQ, [1, 1], 'x')
            sage: A = PP([11, 5, 10, 2])
            sage: A.local_height(5)
            1.60943791243410

        ::

            sage: P = ProductProjectiveSpaces(QQ, [1,2], 'x')
            sage: Q = P([1, 4, 1/2, 2, 32])
            sage: Q.local_height(2)
            4.15888308335967
        """
        K = FractionField(self.domain().base_ring())
        if K not in NumberFields():
            raise TypeError(
                "must be over a number field or a number field order")

        n = self.codomain().ambient_space().num_components()
        return max(self[i].local_height(v, prec=prec) for i in range(n))
예제 #13
0
    def local_height_arch(self, i, prec=None):
        r"""
        Returns the maximum of the local heights at the ``i``-th infinite place of this point.

        INPUT:

        - ``i`` -- an integer.

        - ``prec`` -- desired floating point precision (default:
          default RealField precision).

        OUTPUT:

        - a real number.

        EXAMPLES::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: Q = P.point([4, 4, 1/150], False)
            sage: Q.local_height_arch(0)
            1.38629436111989

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QuadraticField(5, 'w'), 2)
            sage: Q = P.point([4, 1, 30], False)
            sage: Q.local_height_arch(1)
            3.401197381662155375413236691607
        """
        K = FractionField(self.domain().base_ring())
        if K not in _NumberFields:
            raise TypeError(
                "must be over a number field or a number field order")
        if K == QQ:
            return max(K(c).local_height_arch(prec=prec) for c in self)
        else:
            return max(K(c).local_height_arch(i, prec=prec) for c in self)
def const_sys(self,n):
    """
    self is a Defor manifold.
    
    Return the system (a DeforSystem) defining its Deformation Variety
    together with inequations.
    """
    Eq=self.manifold.gluing_equations_pgl(N=n,equation_type='non_peripheral')#On récupère les equations d'aretes et de faces
    Mat=Eq.matrix;#c'est la matrice des exposants dans les equations
    variabl=Eq.explain_columns;#On récupère les variables
    ring=PolynomialRing(QQ,variabl);#On définit l'anneau des polynômes où on travaille
    field = FractionField(ring)
    
    ineqs = set([x for x in ring.gens()]+[x-1 for x in ring.gens()]);
    proj = {};
    
    sys1 = [ construire_equation(r,ring) for r in Mat.rows() ];
    sys2=[ring.gens()[3*i]*ring.gens()[3*i+1]*ring.gens()[3*i+2] +1  for i in range(len(variabl)/3)];
    sys3=[ring.gens()[3*i]*(1-ring.gens()[3*i+2])-1 for i in range(len(variabl)/3)] +\
        [ring.gens()[3*i+1]*(1-ring.gens()[3*i])-1 for i in range(len(variabl)/3)] +\
        [ring.gens()[3*i+2]*(1-ring.gens()[3*i+1])-1 for i in range(len(variabl)/3)]
    eqs = sys1 + sys2 + sys3
    
    return deforsys.DeforSystem(eqs,ineqs,proj,self.manifold,n)
예제 #15
0
    def green_function(self, G, v, **kwds):
        r"""
        Evaluates the local Green's function with respect to the morphism ``G``
        at the place ``v`` for ``self`` with ``N`` terms of the
        series or to within a given error bound.  Must be over a number field
        or order of a number field. Note that this is the absolute local Green's function
        so is scaled by the degree of the base field.

        Use ``v=0`` for the archimedean place over `\QQ` or field embedding. Non-archimedean
        places are prime ideals for number fields or primes over `\QQ`.

        ALGORITHM:

        See Exercise 5.29 and Figure 5.6 of ``The Arithmetic of Dynamics Systems``, Joseph H. Silverman, Springer, GTM 241, 2007.

        INPUT:

        - ``G`` - a projective morphism whose local Green's function we are computing

        - ``v`` - non-negative integer. a place, use v=0 for the archimedean place

        kwds:

        - ``N`` - positive integer. number of terms of the series to use, default: 10

        - ``prec`` - positive integer, float point or p-adic precision, default: 100

        - ``error_bound`` - a positive real number

        OUTPUT:

        - a real number

        EXAMPLES::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,x*y]);
            sage: Q=P(5,1)
            sage: f.green_function(Q,0,N=30)
            1.6460930159932946233759277576

        ::

            sage: P.<x,y>=ProjectiveSpace(QQ,1)
            sage: H=Hom(P,P)
            sage: f=H([x^2+y^2,x*y]);
            sage: Q=P(5,1)
            sage: Q.green_function(f,0,N=200,prec=200)
            1.6460930160038721802875250367738355497198064992657997569827

        ::

            sage: K.<w> = QuadraticField(3)
            sage: P.<x,y> = ProjectiveSpace(K,1)
            sage: H = Hom(P,P)
            sage: f = H([17*x^2+1/7*y^2,17*w*x*y])
            sage: f.green_function(P.point([w,2],False), K.places()[1])
            1.7236334013785676107373093775
            sage: print f.green_function(P([2,1]), K.ideal(7), N=7)
            0.48647753726382832627633818586
            sage: print f.green_function(P([w,1]), K.ideal(17), error_bound=0.001)
            -0.70761163353747779889947530309

        .. TODO:: Implement general p-adic extensions so that the flip trick can be used
             for number fields.
        """
        N = kwds.get('N', 10)                     #Get number of iterates (if entered)
        err = kwds.get('error_bound', None)         #Get error bound (if entered)
        prec = kwds.get('prec', 100)                #Get precision (if entered)
        R = RealField(prec)
        localht = R(0)
        BR = FractionField(self.codomain().base_ring())
        GBR = G.change_ring(BR) #so the heights work

        if not BR in NumberFields():
            raise NotImplementedError("Must be over a NumberField or a NumberField Order")

        #For QQ the 'flip-trick' works better over RR or Qp
        if isinstance(v, (NumberFieldFractionalIdeal, RingHomomorphism_im_gens)):
            K = BR
        elif is_prime(v):
            K = Qp(v, prec)
        elif v == 0:
            K = R
            v = BR.places(prec=prec)[0]
        else:
            raise ValueError("Invalid valuation (=%s) entered."%v)

        #Coerce all polynomials in F into polynomials with coefficients in K
        F = G.change_ring(K, False)
        d = F.degree()
        dim = F.codomain().ambient_space().dimension_relative()
        P = self.change_ring(K, False)

        if err is not None:
            err = R(err)
            if not err>0:
                raise ValueError("Error bound (=%s) must be positive."%err)
            if G.is_endomorphism() == False:
                raise NotImplementedError("Error bounds only for endomorphisms")

            #if doing error estimates, compute needed number of iterates
            D = (dim + 1) * (d - 1) + 1
            #compute upper bound
            if isinstance(v, RingHomomorphism_im_gens): #archimedean
                vindex = BR.places(prec=prec).index(v)
                U = GBR.local_height_arch(vindex, prec=prec) + R(binomial(dim + d, d)).log()
            else: #non-archimedean
                U = GBR.local_height(v, prec=prec)

            #compute lower bound - from explicit polynomials of Nullstellensatz
            CR = GBR.codomain().ambient_space().coordinate_ring() #.lift() only works over fields
            I = CR.ideal(GBR.defining_polynomials())
            maxh = 0
            for k in range(dim + 1):
                CoeffPolys = (CR.gen(k) ** D).lift(I)
                Res = 1
                h = 1
                for poly in CoeffPolys:
                    if poly != 0:
                        for c in poly.coefficients():
                            Res = lcm(Res, c.denominator())
                for poly in CoeffPolys:
                    if poly != 0:
                        if isinstance(v, RingHomomorphism_im_gens): #archimedean
                            if BR == QQ:
                                h = max([(Res*c).local_height_arch(prec=prec) for c in poly.coefficients()])
                            else:
                                h = max([(Res*c).local_height_arch(vindex, prec=prec) for c in poly.coefficients()])
                        else: #non-archimedean
                            h = max([c.local_height(v, prec=prec) for c in poly.coefficients()])
                        if h > maxh:
                            maxh=h
            if isinstance(v, RingHomomorphism_im_gens): #archimedean
                L = R(Res / ((dim + 1) * binomial(dim + D - d, D - d) * maxh)).log().abs()
            else: #non-archimedean
                L = R(1 / maxh).log().abs()
            C = max([U, L])
            if C != 0:
                N = R(C/(err)).log(d).abs().ceil()
            else: #we just need log||P||_v
                N=1

        #START GREEN FUNCTION CALCULATION
        if isinstance(v, RingHomomorphism_im_gens):  #embedding for archimedean local height
            for i in range(N+1):
                Pv = [ (v(t).abs()) for t in P ]
                m = -1
                #compute the maximum absolute value of entries of a, and where it occurs
                for n in range(dim + 1):
                    if Pv[n] > m:
                        j = n
                        m = Pv[n]
                # add to sum for the Green's function
                localht += ((1/R(d))**R(i)) * (R(m).log())
                #get the next iterate
                if i < N:
                    P.scale_by(1/P[j])
                    P = F(P, False)
            return (1/BR.absolute_degree()) * localht

        #else - prime or prime ideal for non-archimedean
        for i in range(N + 1):
            if BR == QQ:
                Pv = [ R(K(t).abs()) for t in P ]
            else:
                Pv = [ R(t.abs_non_arch(v)) for t in P ]
            m = -1
            #compute the maximum absolute value of entries of a, and where it occurs
            for n in range(dim + 1):
                if Pv[n] > m:
                    j = n
                    m = Pv[n]
            # add to sum for the Green's function
            localht += ((1/R(d))**R(i)) * (R(m).log())
            #get the next iterate
            if i < N:
                P.scale_by(1/P[j])
                P = F(P, False)
        return (1/BR.absolute_degree()) * localht
예제 #16
0
    def multiplier(self, P, n, check=True):
        r"""
        Returns the multiplier of the point ``P`` of period ``n`` by the map.

        The map must be an endomorphism.

        INPUT:

        - ``P`` - a point on domain of the map.

        - ``n`` - a positive integer, the period of ``P``.

        - ``check`` -- verify that ``P`` has period ``n``, Default:True.

        OUTPUT:

        - a square matrix of size ``self.codomain().dimension_relative()`` in
          the ``base_ring`` of the map.

        EXAMPLES::

            sage: P.<x,y> = AffineSpace(QQ, 2)
            sage: H = End(P)
            sage: f = H([x^2, y^2])
            sage: f.multiplier(P([1, 1]), 1)
            [2 0]
            [0 2]

        ::

            sage: P.<x,y,z> = AffineSpace(QQ, 3)
            sage: H = End(P)
            sage: f = H([x, y^2, z^2 - y])
            sage: f.multiplier(P([1/2, 1, 0]), 2)
            [1 0 0]
            [0 4 0]
            [0 0 0]

        ::

            sage: P.<x> = AffineSpace(CC, 1)
            sage: H = End(P)
            sage: f = H([x^2 + 1/2])
            sage: f.multiplier(P([0.5 + 0.5*I]), 1)
            [1.00000000000000 + 1.00000000000000*I]

        ::

            sage: R.<t> = PolynomialRing(CC, 1)
            sage: P.<x> = AffineSpace(R, 1)
            sage: H = End(P)
            sage: f = H([x^2 - t^2 + t])
            sage: f.multiplier(P([-t + 1]), 1)
            [(-2.00000000000000)*t + 2.00000000000000]

        ::

            sage: P.<x,y> = AffineSpace(QQ, 2)
            sage: X = P.subscheme([x^2-y^2])
            sage: H = End(X)
            sage: f = H([x^2, y^2])
            sage: f.multiplier(X([1, 1]), 1)
            [2 0]
            [0 2]
        """
        if not self.is_endomorphism():
            raise TypeError("must be an endomorphism")
        if check:
            if self.nth_iterate(P, n) != P:
                raise ValueError("%s is not periodic of period %s" % (P, n))
            if n < 1:
                raise ValueError("period must be a positive integer")
        N = self.domain().ambient_space().dimension_relative()
        l = identity_matrix(FractionField(self.codomain().base_ring()), N, N)
        Q = P
        J = self.jacobian()
        for i in range(0, n):
            R = self(Q)
            l = J(tuple(Q)) * l  #chain rule matrix multiplication
            Q = R
        return l
예제 #17
0
def rational_diagonal_form(self, return_matrix=False):
    """
    Returns a diagonal form equivalent to Q over the fraction field of
    its defining ring.  If the return_matrix is True, then we return
    the transformation matrix performing the diagonalization as the
    second argument.

    INPUT:
        none

    OUTPUT:
        Q -- the diagonalized form of this quadratic form
        (optional) T -- matrix which diagonalizes Q (over it's fraction field)

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 2, [0,1,-1])
        sage: Q
        Quadratic form in 2 variables over Integer Ring with coefficients:
        [ 0 1 ]
        [ * -1 ]
        sage: Q.rational_diagonal_form()
        Quadratic form in 2 variables over Rational Field with coefficients:
        [ -2 0 ]
        [ * 1/8 ]

    ::

        sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
        sage: Q.rational_diagonal_form(return_matrix=True)
        (
        Quadratic form in 4 variables over Rational Field with coefficients:
        [ 1 0 0 0 ]
        [ * 3 0 0 ]
        [ * * 5 0 ]
        [ * * * 7 ]                                                          ,
        <BLANKLINE>
        [1 0 0 0]
        [0 1 0 0]
        [0 0 1 0]
        [0 0 0 1]
        )

    ::

        sage: Q1 = QuadraticForm(ZZ, 4, [1, 1, 0, 0, 1, 0, 0, 1, 0, 18])
        sage: Q1
        Quadratic form in 4 variables over Integer Ring with coefficients:
        [ 1 1 0 0 ]
        [ * 1 0 0 ]
        [ * * 1 0 ]
        [ * * * 18 ]
        sage: Q1.rational_diagonal_form(return_matrix=True)
        (
        Quadratic form in 4 variables over Rational Field with coefficients:
        [ 1 0 0 0 ]
        [ * 3/4 0 0 ]
        [ * * 1 0 ]
        [ * * * 18 ]                                                         ,
        <BLANKLINE>
        [   1 -1/2    0    0]
        [   0    1    0    0]
        [   0    0    1    0]
        [   0    0    0    1]
        )
    """
    n = self.dim()
    Q = copy.deepcopy(self)
    Q.__init__(FractionField(self.base_ring()), self.dim(),
               self.coefficients())
    MS = MatrixSpace(Q.base_ring(), n, n)
    T = MS(1)

    ## Clear the entries one row at a time.
    for i in range(n):

        ## Deal with rows where the diagonal entry is zero.
        if Q[i, i] == 0:

            ## Look for a non-zero entry and use it to make the diagonal non-zero (if it exists)
            for j in range(i + 1, n):
                if Q[i, j] != 0:
                    temp = MS(1)
                    if Q[i, j] + Q[j, j] == 0:
                        temp[j, i] = -1
                    else:
                        temp[j, i] = 1

                    ## Apply the transformation
                    Q = Q(temp)
                    T = T * temp
                    break

        ## Create a matrix which deals with off-diagonal entries (all at once for each row)
        temp = MS(1)
        for j in range(i + 1, n):
            if Q[i, j] != 0:
                temp[i, j] = -Q[i, j] / (
                    Q[i, i] * 2
                )  ## This should only occur when Q[i,i] != 0, which the above step guarantees.

        Q = Q(temp)
        T = T * temp

    ## Return the appropriate output
    if return_matrix:
        return Q, T
    else:
        return Q
예제 #18
0
    def reynolds_operator(self, poly, chi=None):
        r"""
        Compute the Reynolds operator of this finite group `G`.

        This is the projection from a polynomial ring to the ring of
        relative invariants [Stu1993]_. If possible, the invariant is
        returned defined over the base field of the given polynomial
        ``poly``, otherwise, it is returned over the compositum of the
        fields involved in the computation.
        Only implemented for absolute fields.

        ALGORITHM:

        Let `K[x]` be a polynomial ring and `\chi` a linear character for `G`. Let

        .. MATH:

            K[x]^G_{\chi} = \{f \in K[x] | \pi f = \chi(\pi) f \forall \pi\in G\}

        be the ring of invariants of `G` relative to `\chi`. Then the Reynold's operator
        is a map `R` from `K[x]` into `K[x]^G_{\chi}` defined by

        .. MATH:

            f \mapsto \frac{1}{|G|} \sum_{ \pi \in G} \chi(\pi) f.

        INPUT:

        - ``poly`` -- a polynomial

        - ``chi`` -- (default: trivial character) a linear group character of this group

        OUTPUT: an invariant polynomial relative to `\chi`

        AUTHORS:

        Rebecca Lauren Miller and Ben Hutz

        EXAMPLES::

            sage: S3 = MatrixGroup(SymmetricGroup(3))
            sage: R.<x,y,z> = QQ[]
            sage: f = x*y*z^3
            sage: S3.reynolds_operator(f)
            1/3*x^3*y*z + 1/3*x*y^3*z + 1/3*x*y*z^3

        ::

            sage: G = MatrixGroup(CyclicPermutationGroup(4))
            sage: chi = G.character(G.character_table()[3])
            sage: K.<v> = CyclotomicField(4)
            sage: R.<x,y,z,w> = K[]
            sage: G.reynolds_operator(x, chi)
            1/4*x + (-1/4*v)*y - 1/4*z + (1/4*v)*w
            sage: chi = G.character(G.character_table()[2])
            sage: R.<x,y,z,w> = QQ[]
            sage: G.reynolds_operator(x*y, chi)
            1/4*x*y + (1/4*zeta4)*y*z + (-1/4*zeta4)*x*w - 1/4*z*w

        ::

            sage: K.<i> = CyclotomicField(4)
            sage: G =  MatrixGroup(CyclicPermutationGroup(3))
            sage: chi = G.character(G.character_table()[1])
            sage: R.<x,y,z> = K[]
            sage: G.reynolds_operator(x*y^5, chi)
            1/3*x*y^5 + (2/3*izeta3^3 + izeta3^2 + 8/3*izeta3 + 1)*x^5*z + (-2/3*izeta3^3 - izeta3^2 - 8/3*izeta3 - 4/3)*y*z^5
            sage: R.<x,y,z> = QQbar[]
            sage: G.reynolds_operator(x*y^5, chi)
             1/3*x*y^5 + (-0.1666666666666667? - 0.2886751345948129?*I)*x^5*z + (-0.1666666666666667? + 0.2886751345948129?*I)*y*z^5

        ::

            sage: K.<i> = CyclotomicField(4)
            sage: Tetra =  MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0])
            sage: chi = Tetra.character(Tetra.character_table()[4])
            sage: L.<v> = QuadraticField(-3)
            sage: R.<x,y> = L[]
            sage: Tetra.reynolds_operator(x^4)
            0
            sage: Tetra.reynolds_operator(x^4, chi)
            1/4*x^4 + (1/2*v)*x^2*y^2 + 1/4*y^4
            sage: R.<x>=L[]
            sage: LL.<w> = L.extension(x^2+v)
            sage: R.<x,y> = LL[]
            sage: Tetra.reynolds_operator(x^4, chi)
            Traceback (most recent call last):
            ...
            NotImplementedError: only implemented for absolute fields

        ::

            sage: G =  MatrixGroup(DihedralGroup(4))
            sage: chi = G.character(G.character_table()[1])
            sage: R.<x,y> = QQ[]
            sage: f = x^4
            sage: G.reynolds_operator(f, chi)
            Traceback (most recent call last):
            ...
            TypeError: number of variables in polynomial must match size of matrices
            sage: R.<x,y,z,w> = QQ[]
            sage: f = x^3*y
            sage: G.reynolds_operator(f, chi)
            1/8*x^3*y - 1/8*x*y^3 + 1/8*y^3*z - 1/8*y*z^3 - 1/8*x^3*w + 1/8*z^3*w +
            1/8*x*w^3 - 1/8*z*w^3

        Characteristic p>0 examples::

            sage: G = MatrixGroup([[0,1,1,0]])
            sage: R.<w,x> = GF(2)[]
            sage: G.reynolds_operator(x)
            Traceback (most recent call last):
            ...
            NotImplementedError: not implemented when characteristic divides group order

        ::

            sage: i = GF(7)(3)
            sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]])
            sage: chi = G.character(G.character_table()[4])
            sage: R.<w,x> = GF(7)[]
            sage: f = w^5*x + x^6
            sage: G.reynolds_operator(f, chi)
            Traceback (most recent call last):
            ...
            NotImplementedError: nontrivial characters not implemented for characteristic > 0
            sage: G.reynolds_operator(f)
            x^6

        ::

            sage: K = GF(3^2,'t')
            sage: G = MatrixGroup([matrix(K,2,2, [0,K.gen(),1,0])])
            sage: R.<x,y> = GF(3)[]
            sage: G.reynolds_operator(x^8)
            -x^8 - y^8

        ::

            sage: K = GF(3^2,'t')
            sage: G = MatrixGroup([matrix(GF(3),2,2, [0,1,1,0])])
            sage: R.<x,y> = K[]
            sage: f = -K.gen()*x
            sage: G.reynolds_operator(f)
            (t)*x + (t)*y
        """
        if poly.parent().ngens() != self.degree():
            raise TypeError(
                "number of variables in polynomial must match size of matrices"
            )
        R = FractionField(poly.base_ring())
        C = FractionField(self.base_ring())
        if chi is None:  #then this is the trivial character
            if R.characteristic() == 0:
                #non-modular case
                if C == QQbar or R == QQbar:
                    L = QQbar
                elif not C.is_absolute() or not R.is_absolute():
                    raise NotImplementedError(
                        "only implemented for absolute fields")
                else:  #create the compositum
                    if C.absolute_degree() == 1:
                        L = R
                    elif R.absolute_degree() == 1:
                        L = C
                    else:
                        L = C.composite_fields(R)[0]
            elif not R.characteristic().divides(self.order()):
                if R.characteristic() != C.characteristic():
                    raise ValueError(
                        "base fields must have same characteristic")
                else:
                    if R.degree() >= C.degree():
                        L = R
                    else:
                        L = C
            else:
                raise NotImplementedError(
                    "not implemented when characteristic divides group order")
            poly = poly.change_ring(L)
            poly_gens = vector(poly.parent().gens())
            F = L.zero()
            for g in self:
                F += poly(*g.matrix() * vector(poly.parent().gens()))
            F /= self.order()
            return F
        #non-trivial character case
        K = chi.values()[0].parent()
        if R.characteristic() == 0:
            #extend base_ring to compositum
            if C == QQbar or K == QQbar or R == QQbar:
                L = QQbar
            elif not C.is_absolute() or not K.is_absolute(
            ) or not R.is_absolute():
                raise NotImplementedError(
                    "only implemented for absolute fields")
            else:
                fields = []
                for M in [R, K, C]:
                    if M.absolute_degree() != 1:
                        fields.append(M)
                l = len(fields)
                if l == 0:
                    # all are QQ
                    L = R
                elif l == 1:
                    #only one is an extension
                    L = fields[0]
                elif l == 2:
                    #only two are extensions
                    L = fields[0].composite_fields(fields[1])[0]
                else:
                    #all three are extensions
                    L1 = fields[0].composite_fields(fields[1])[0]
                    L = L1.composite_fields(fields[2])[0]
        else:
            raise NotImplementedError(
                "nontrivial characters not implemented for characteristic > 0")
        poly = poly.change_ring(L)
        poly_gens = vector(poly.parent().gens())
        F = L.zero()
        for g in self:
            F += L(chi(g)) * poly(*g.matrix().change_ring(L) * poly_gens)
        F /= self.order()
        try:  # attempt to move F to base_ring of polynomial
            F = F.change_ring(R)
        except (TypeError, ValueError):
            pass
        return F
예제 #19
0
def binary_quintic_coefficients_from_invariants(invariants, K=None, invariant_choice='default', scaling='none'):
    r"""
    Reconstruct a binary quintic from the values of its (Clebsch) invariants.

    INPUT:

    - ``invariants`` -- A list or tuple of values of the three or four
      invariants. The default option requires the Clebsch invariants `A`, `B`,
      `C` and `R` of the binary quintic.

    - ``K`` -- The field over which the quintic is defined.

    - ``invariant_choice`` -- The type of invariants provided. The accepted
      options are ``'clebsch'`` and ``'default'``, which are the same. No
      other options are implemented.

    - ``scaling`` -- How the coefficients should be scaled. The accepted
      values are ``'none'`` for no scaling, ``'normalized'`` to scale in such
      a way that the resulting coefficients are independent of the scaling of
      the input invariants and ``'coprime'`` which scales the input invariants
      by dividing them by their gcd.

    OUTPUT:

    A set of coefficients of a binary quintic, whose invariants are equal to
    the given ``invariants`` up to a scaling.

    EXAMPLES:

    First we check the general case, where the invariant `M` is non-zero::

        sage: R.<x0, x1> = QQ[]
        sage: p = 3*x1^5 + 6*x1^4*x0 + 3*x1^3*x0^2 + 4*x1^2*x0^3 - 5*x1*x0^4 + 4*x0^5
        sage: quintic = invariant_theory.binary_quintic(p, x0, x1)
        sage: invs = quintic.clebsch_invariants(as_tuple=True)
        sage: reconstructed = invariant_theory.binary_form_from_invariants(5, invs, variables=quintic.variables()) # indirect doctest
        sage: reconstructed
        Binary quintic with coefficients (9592267437341790539005557/244140625000000,
        2149296928207625556323004064707/610351562500000000,
        11149651890347700974453304786783/76293945312500000,
        122650775751894638395648891202734239/47683715820312500000,
        323996630945706528474286334593218447/11920928955078125000,
        1504506503644608395841632538558481466127/14901161193847656250000)

    We can see that the invariants of the reconstructed form match the ones of
    the original form by scaling the invariants `B` and `C`::

        sage: scale = invs[0]/reconstructed.A_invariant()
        sage: invs[1] == reconstructed.B_invariant()*scale^2
        True
        sage: invs[2] == reconstructed.C_invariant()*scale^3
        True

    If we compare the form obtained by this reconstruction to the one found by
    letting the covariants `\alpha` and `\beta` be the coordinates of the form,
    we find the forms are the same up to a power of the determinant of `\alpha`
    and `\beta`::

        sage: alpha = quintic.alpha_covariant()
        sage: beta = quintic.beta_covariant()
        sage: g = matrix([[alpha(x0=1,x1=0),alpha(x0=0,x1=1)],[beta(x0=1,x1=0),beta(x0=0,x1=1)]])^-1
        sage: transformed = tuple([g.determinant()^-5*x for x in quintic.transformed(g).coeffs()])
        sage: transformed == reconstructed.coeffs()
        True

    This can also be seen by computing the `\alpha` covariant of the obtained
    form::

        sage: reconstructed.alpha_covariant().coefficient(x1)
        0
        sage: reconstructed.alpha_covariant().coefficient(x0) != 0
        True

    If the invariant `M` vanishes, then the coefficients are computed in a
    different way::

        sage: [A,B,C] = [3,1,2]
        sage: M = 2*A*B - 3*C
        sage: M
        0
        sage: from sage.rings.invariants.reconstruction import binary_quintic_coefficients_from_invariants
        sage: reconstructed = binary_quintic_coefficients_from_invariants([A,B,C])
        sage: reconstructed
        (-66741943359375/2097152,
         -125141143798828125/134217728,
         0,
         52793920040130615234375/34359738368,
         19797720015048980712890625/1099511627776,
         -4454487003386020660400390625/17592186044416)
        sage: newform = sum([ reconstructed[i]*x0^i*x1^(5-i) for i in range(6) ])
        sage: newquintic = invariant_theory.binary_quintic(newform, x0, x1)
        sage: scale = 3/newquintic.A_invariant()
        sage: [3, newquintic.B_invariant()*scale^2, newquintic.C_invariant()*scale^3]
        [3, 1, 2]

    Several special cases::

        sage: quintic = invariant_theory.binary_quintic(x0^5 - x1^5, x0, x1)
        sage: invs = quintic.clebsch_invariants(as_tuple=True)
        sage: binary_quintic_coefficients_from_invariants(invs)
        (1, 0, 0, 0, 0, 1)
        sage: quintic = invariant_theory.binary_quintic(x0*x1*(x0^3-x1^3), x0, x1)
        sage: invs = quintic.clebsch_invariants(as_tuple=True)
        sage: binary_quintic_coefficients_from_invariants(invs)
        (0, 1, 0, 0, 1, 0)
        sage: quintic = invariant_theory.binary_quintic(x0^5 + 10*x0^3*x1^2 - 15*x0*x1^4, x0, x1)
        sage: invs = quintic.clebsch_invariants(as_tuple=True)
        sage: binary_quintic_coefficients_from_invariants(invs)
        (1, 0, 10, 0, -15, 0)
        sage: quintic = invariant_theory.binary_quintic(x0^2*(x0^3 + x1^3), x0, x1)
        sage: invs = quintic.clebsch_invariants(as_tuple=True)
        sage: binary_quintic_coefficients_from_invariants(invs)
        (1, 0, 0, 1, 0, 0)
        sage: quintic = invariant_theory.binary_quintic(x0*(x0^4 + x1^4), x0, x1)
        sage: invs = quintic.clebsch_invariants(as_tuple=True)
        sage: binary_quintic_coefficients_from_invariants(invs)
        (1, 0, 0, 0, 1, 0)

    For fields of characteristic 2, 3 or 5, there is no reconstruction
    implemented. This is part of :trac:`26786`.::

        sage: binary_quintic_coefficients_from_invariants([3,1,2], K=GF(5))
        Traceback (most recent call last):
        ...
        NotImplementedError: no reconstruction of binary quintics implemented for fields of characteristic 2, 3 or 5

    TESTS::

        sage: from sage.rings.invariants.reconstruction import binary_quintic_coefficients_from_invariants
        sage: binary_quintic_coefficients_from_invariants([1,2,3], scaling='unknown')
        Traceback (most recent call last):
        ...
        ValueError: unknown scaling option 'unknown'
    """
    if invariant_choice not in ['default', 'clebsch']:
        raise ValueError('unknown choice of invariants {} for a binary quintic'
                         .format(invariant_choice))
    if scaling not in ['none', 'normalized', 'coprime']:
        raise ValueError("unknown scaling option '%s'" % scaling)
    if scaling == 'coprime':
        if len(invariants) == 3:
            invariants = _reduce_invariants(invariants, [1,2,3])
        elif len(invariants) == 4:
            invariants = _reduce_invariants(invariants, [2,4,6,9])
    A, B, C = invariants[0:3]
    if K is None:
        from sage.rings.fraction_field import FractionField
        K = FractionField(A.parent())
    if K.characteristic() in [2, 3, 5]:
        raise NotImplementedError('no reconstruction of binary quintics '
                          'implemented for fields of characteristic 2, 3 or 5')
    M = 2*A*B - 3*C
    N = K(2)**-1 * (A*C-B**2)
    R2 = -K(2)**-1 * (A*N**2-2*B*M*N+C*M**2)
    scale = [1,1,1,1,1,1]
    from sage.functions.all import binomial, sqrt
    if len(invariants) == 3:
        if R2.is_square():
            R = sqrt(R2)
        else:
            # if R2 is not a square, we scale the invariants in a suitable way
            # so that the 'new' R2 is a square
            [A, B, C] = [R2*A, R2**2*B, R2**3*C]
            [M, N] = [R2**3*M, R2**4*N]
            R = R2**5
    elif len(invariants) == 4:
        if invariants[3]**2 != R2:
            raise ValueError('provided invariants do not satisfy the syzygy '
                             'for Clebsch invariants of a binary quintic')
        R = invariants[3]
    else:
        raise ValueError('incorrect number of invariants provided, this '
                         'method requires 3 or 4 invariants')
    if M == 0:
        if N == 0:
            if A == 0:
                raise ValueError('no unique reconstruction possible for '
                                 'quintics with a treefold linear factor')
            else:
                if B == 0:
                    return (1,0,0,0,0,1)
                else:
                    return (0,1,0,0,1,0)
        else:
            # case corresponding to using alpha and gamma as coordinates
            if A == 0:
                return (1,0,0,0,1,0)
            else:
                if scaling == 'normalized':
                    # scaling z by (R/A**3)
                    scale = [ (-N)**-5*A**6*(R/A**3)**i for i in range(6) ]
                D = -N
                Delta = C
                a = [0]
                a.append((2*K(3)**-1*A**2-B)*N*B*K(2)**-1 - N**2*K(2)**-1)
                B0 = 2*K(3)**-1*A*R
                B1 = A*N*B*K(3)**-1
                C0 = 2*K(3)**-1*R
                C1 = B*N
    else:
        # case corresponding to using alpha and beta as coordinates
        if R == 0:
            if A == 0:
                return (1,0,10,0,-15,0)
            elif scaling == 'normalized':
                # scaling x by A and z by sqrt(A)
                scale = [ (-M)**(-5)*sqrt(A)**(12+i) for i in range(6) ]
        else:
            if A == 0:
                if B == 0:
                    return (1,0,0,1,0,0)
                elif scaling == 'normalized':
                    # scaling y by R/B**2
                    scale = [ (-M)**(-3)*(R/B**2)**i for i in range(6) ]
            elif scaling == 'normalized':
                # scaling y by R/A**4
                scale = [ (-M)**(-3)*(R/A**4)**i for i in range(6) ]
        D = -M
        Delta = A
        a = [0]
        a.append((2*K(3)**-1*A**2-B)*(N*A-M*B)*K(2)**-1 \
                    - M*(N*K(2)**-1-M*A*K(3)**-1))
        B0 = R
        B1 = K(2)**-1*(N*A-M*B)
        C0 = 0
        C1 = -M
    a[0] = (2*K(3)**-1*A**2-B)*R
    a.append(-D*B0 - K(2)**-1*Delta*a[0])
    a.append(-D*B1 - K(2)**-1*Delta*a[1])
    a.append(D**2*C0 + D*Delta*B0 + K(4)**-1*Delta**2*a[0])
    a.append(D**2*C1 + D*Delta*B1 + K(4)**-1*Delta**2*a[1])
    coeffs = tuple([K((-1)**i*binomial(5,i)*scale[5-i]*a[i]) for i in range(6)])
    if scaling == 'coprime':
        from sage.arith.misc import gcd
        return tuple([coeffs[i]/gcd(coeffs) for i in range(6)])
    else:
        return coeffs
예제 #20
0
    def reynolds_operator(self, poly, chi=None):
        r"""
        Compute the Reynolds operator of this finite group `G`.

        This is the projection from a polynomial ring to the ring of
        relative invariants [Stu1993]_. If possible, the invariant is
        returned defined over the base field of the given polynomial
        ``poly``, otherwise, it is returned over the compositum of the
        fields involved in the computation.
        Only implemented for absolute fields.

        ALGORITHM:

        Let `K[x]` be a polynomial ring and `\chi` a linear character for `G`. Let

        .. MATH:

            K[x]^G_{\chi} = \{f \in K[x] | \pi f = \chi(\pi) f \forall \pi\in G\}

        be the ring of invariants of `G` relative to `\chi`. Then the Reynold's operator
        is a map `R` from `K[x]` into `K[x]^G_{\chi}` defined by

        .. MATH:

            f \mapsto \frac{1}{|G|} \sum_{ \pi \in G} \chi(\pi) f.

        INPUT:

        - ``poly`` -- a polynomial

        - ``chi`` -- (default: trivial character) a linear group character of this group

        OUTPUT: an invariant polynomial relative to `\chi`

        AUTHORS:

        Rebecca Lauren Miller and Ben Hutz

        EXAMPLES::

            sage: S3 = MatrixGroup(SymmetricGroup(3))
            sage: R.<x,y,z> = QQ[]
            sage: f = x*y*z^3
            sage: S3.reynolds_operator(f)
            1/3*x^3*y*z + 1/3*x*y^3*z + 1/3*x*y*z^3

        ::

            sage: G = MatrixGroup(CyclicPermutationGroup(4))
            sage: chi = G.character(G.character_table()[3])
            sage: K.<v> = CyclotomicField(4)
            sage: R.<x,y,z,w> = K[]
            sage: G.reynolds_operator(x, chi)
            1/4*x + (1/4*v)*y - 1/4*z + (-1/4*v)*w
            sage: chi = G.character(G.character_table()[2])
            sage: R.<x,y,z,w> = QQ[]
            sage: G.reynolds_operator(x*y, chi)
            1/4*x*y + (-1/4*zeta4)*y*z + (1/4*zeta4)*x*w - 1/4*z*w

        ::

            sage: K.<i> = CyclotomicField(4)
            sage: G =  MatrixGroup(CyclicPermutationGroup(3))
            sage: chi = G.character(G.character_table()[1])
            sage: R.<x,y,z> = K[]
            sage: G.reynolds_operator(x*y^5, chi)
            1/3*x*y^5 + (2/3*izeta3^3 + izeta3^2 + 8/3*izeta3 + 1)*x^5*z +
            (-2/3*izeta3^3 - izeta3^2 - 8/3*izeta3 - 4/3)*y*z^5
            sage: R.<x,y,z> = QQbar[]
            sage: G.reynolds_operator(x*y^5, chi)
            1/3*x*y^5 + (-0.1666666666666667? - 0.2886751345948129?*I)*x^5*z +
            (-0.1666666666666667? + 0.2886751345948129?*I)*y*z^5

        ::

            sage: K.<i> = CyclotomicField(4)
            sage: Tetra =  MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0])
            sage: chi = Tetra.character(Tetra.character_table()[4])
            sage: L.<v> = QuadraticField(-3)
            sage: R.<x,y> = L[]
            sage: Tetra.reynolds_operator(x^4)
            0
            sage: Tetra.reynolds_operator(x^4, chi)
            1/4*x^4 + (1/2*v)*x^2*y^2 + 1/4*y^4
            sage: R.<x>=L[]
            sage: LL.<w> = L.extension(x^2+v)
            sage: R.<x,y> = LL[]
            sage: Tetra.reynolds_operator(x^4, chi)
            Traceback (most recent call last):
            ...
            NotImplementedError: only implemented for absolute fields

        ::

            sage: G =  MatrixGroup(DihedralGroup(4))
            sage: chi = G.character(G.character_table()[1])
            sage: R.<x,y> = QQ[]
            sage: f = x^4
            sage: G.reynolds_operator(f, chi)
            Traceback (most recent call last):
            ...
            TypeError: number of variables in polynomial must match size of matrices
            sage: R.<x,y,z,w> = QQ[]
            sage: f = x^3*y
            sage: G.reynolds_operator(f, chi)
            1/8*x^3*y - 1/8*x*y^3 + 1/8*y^3*z - 1/8*y*z^3 - 1/8*x^3*w + 1/8*z^3*w +
            1/8*x*w^3 - 1/8*z*w^3

        Characteristic p>0 examples::

            sage: G = MatrixGroup([[0,1,1,0]])
            sage: R.<w,x> = GF(2)[]
            sage: G.reynolds_operator(x)
            Traceback (most recent call last):
            ...
            NotImplementedError: not implemented when characteristic divides group order

        ::

            sage: i = GF(7)(3)
            sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]])
            sage: chi = G.character(G.character_table()[4])
            sage: R.<w,x> = GF(7)[]
            sage: f = w^5*x + x^6
            sage: G.reynolds_operator(f, chi)
            Traceback (most recent call last):
            ...
            NotImplementedError: nontrivial characters not implemented for characteristic > 0
            sage: G.reynolds_operator(f)
            x^6

        ::

            sage: K = GF(3^2,'t')
            sage: G = MatrixGroup([matrix(K,2,2, [0,K.gen(),1,0])])
            sage: R.<x,y> = GF(3)[]
            sage: G.reynolds_operator(x^8)
            -x^8 - y^8

        ::

            sage: K = GF(3^2,'t')
            sage: G = MatrixGroup([matrix(GF(3),2,2, [0,1,1,0])])
            sage: R.<x,y> = K[]
            sage: f = -K.gen()*x
            sage: G.reynolds_operator(f)
            (t)*x + (t)*y
        """
        if poly.parent().ngens() != self.degree():
            raise TypeError("number of variables in polynomial must match size of matrices")
        R = FractionField(poly.base_ring())
        C = FractionField(self.base_ring())
        if chi is None: #then this is the trivial character
            if R.characteristic() == 0:
                #non-modular case
                if C == QQbar or R == QQbar:
                    L = QQbar
                elif not C.is_absolute() or not R.is_absolute():
                    raise NotImplementedError("only implemented for absolute fields")
                else: #create the compositum
                    if C.absolute_degree() == 1:
                        L = R
                    elif R.absolute_degree() == 1:
                        L = C
                    else:
                        L = C.composite_fields(R)[0]
            elif not R.characteristic().divides(self.order()):
                if R.characteristic() != C.characteristic():
                    raise ValueError("base fields must have same characteristic")
                else:
                    if R.degree() >= C.degree():
                        L = R
                    else:
                        L = C
            else:
                raise NotImplementedError("not implemented when characteristic divides group order")
            poly = poly.change_ring(L)
            poly_gens = vector(poly.parent().gens())
            F = L.zero()
            for g in self:
                F += poly(*g.matrix()*vector(poly.parent().gens()))
            F /= self.order()
            return F
        #non-trivial character case
        K = chi.values()[0].parent()
        if R.characteristic() == 0:
            #extend base_ring to compositum
            if C == QQbar or K == QQbar or R == QQbar:
                L = QQbar
            elif not C.is_absolute() or not K.is_absolute() or not R.is_absolute():
                raise NotImplementedError("only implemented for absolute fields")
            else:
                fields = []
                for M in [R,K,C]:
                    if M.absolute_degree() != 1:
                        fields.append(M)
                l = len(fields)
                if l == 0:
                    # all are QQ
                    L = R
                elif l == 1:
                    #only one is an extension
                    L = fields[0]
                elif l == 2:
                    #only two are extensions
                    L = fields[0].composite_fields(fields[1])[0]
                else:
                    #all three are extensions
                    L1 = fields[0].composite_fields(fields[1])[0]
                    L = L1.composite_fields(fields[2])[0]
        else:
            raise NotImplementedError("nontrivial characters not implemented for characteristic > 0")
        poly = poly.change_ring(L)
        poly_gens = vector(poly.parent().gens())
        F = L.zero()
        for g in self:
            F += L(chi(g)) * poly(*g.matrix().change_ring(L)*poly_gens)
        F /= self.order()
        try: # attempt to move F to base_ring of polyomial
            F = F.change_ring(R)
        except (TypeError, ValueError):
            pass
        return F
예제 #21
0
파일: subscheme.py 프로젝트: vojtechsu/sage
    def dimension(self):
        r"""
        Return the dimension of the algebraic subscheme.

        OUTPUT:

        Integer.

        EXAMPLES::

            sage: X.<x,y,z,w,u,v> = ProductProjectiveSpaces([2,2],QQ)
            sage: L = (-w - v)*x + (-w*y - u*z)
            sage: Q = (-u*w - v^2)*x^2 + ((-w^2 - u*w + (-u*v - u^2))*y + (-w^2 - u*v)*z)*x + \
            ((-w^2 - u*w - u^2)*y^2 + (-u*w - v^2)*z*y + (-w^2 + (-v - u)*w)*z^2)
            sage: W = X.subscheme([L,Q])
            sage: W.dimension()
            2

        ::

            sage: PP.<x,y,z,u,v,s,t> = ProductProjectiveSpaces([2,1,1], QQ)
            sage: X = PP.subscheme([x^3, x^5+y^5, z^6, x*u-v*y, s^2-t^2])
            sage: X.dimension()
            -1

        ::

            sage: PP = ProductProjectiveSpaces([2,1,3], CC, 't')
            sage: PP.subscheme([]).dimension()
            6

        ::

            sage: PP = ProductProjectiveSpaces([1,3,1], ZZ, 't')
            sage: PP.subscheme([]).dimension()
            5

        ::

            sage: PP.<x,y,u,v,s,t> = ProductProjectiveSpaces([1,1,1], CC)
            sage: X = PP.subscheme([x^2-y^2, u-v, s^2-t^2])
            sage: X.dimension()
            0
        """
        try:
            return self.__dimension
        except AttributeError:
            try:
                #move to field to compute radical
                X = self.change_ring(FractionField(self.base_ring()))
                PP = X.ambient_space()
                I = X.defining_ideal().radical()
                #check if the irrelevant ideal of any component is in the radical
                if any(
                        all(t in I for t in PS.gens())
                        for PS in PP.components()):
                    self.__dimension = -1
                else:
                    self.__dimension = I.dimension() - PP.num_components()
            except TypeError:  #cannot compute radical for this base ring
                phi = self.segre_embedding()
                self.__dimension = phi.codomain().defining_ideal().dimension(
                ) - 1
            return self.__dimension
예제 #22
0
    def molien_series(self, chi=None, return_series=True, prec=20, variable='t'):
        r"""
        Compute the Molien series of this finite group with respect to the
        character ``chi``. It can be returned either as a rational function
        in one variable or a power series in one variable. The base field
        must be a finite field, the rationals, or a cyclotomic field.

        Note that the base field characteristic cannot divide the group
        order (i.e., the non-modular case).

        ALGORITHM:

        For a finite group `G` in characteristic zero we construct the Molien series as

        .. MATH::

            \frac{1}{|G|}\sum_{g \in G} \frac{\chi(g)}{\text{det}(I-tg)},

        where `I` is the identity matrix and `t` an indeterminate.

        For characteristic `p` not dividing the order of `G`, let `k` be the base field
        and `N` the order of `G`. Define `\lambda` as a primitive `N`-th root of unity over `k`
        and `\omega` as a primitive `N`-th root of unity over `\QQ`. For each `g \in G`
        define `k_i(g)` to be the positive integer such that
        `e_i = \lambda^{k_i(g)}` for each eigenvalue `e_i` of `g`. Then the Molien series
        is computed as

        .. MATH::

            \frac{1}{|G|}\sum_{g \in G} \frac{\chi(g)}{\prod_{i=1}^n(1 - t\omega^{k_i(g)})},

        where `t` is an indeterminant. [Dec1998]_

        INPUT:

        - ``chi`` -- (default: trivial character) a linear group character of this group

        - ``return_series`` -- boolean (default: ``True``) if ``True``, then returns
          the Molien series as a power series, ``False`` as a rational function

        - ``prec`` -- integer (default: 20); power series default precision

        - ``variable`` -- string (default: ``'t'``); Variable name for the Molien series

        OUTPUT: single variable rational function or power series with integer coefficients

        EXAMPLES::

            sage: MatrixGroup(matrix(QQ,2,2,[1,1,0,1])).molien_series()
            Traceback (most recent call last):
            ...
            NotImplementedError: only implemented for finite groups
            sage: MatrixGroup(matrix(GF(3),2,2,[1,1,0,1])).molien_series()
            Traceback (most recent call last):
            ...
            NotImplementedError: characteristic cannot divide group order

        Tetrahedral Group::

            sage: K.<i> = CyclotomicField(4)
            sage: Tetra =  MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0])
            sage: Tetra.molien_series(prec=30)
            1 + t^8 + 2*t^12 + t^16 + 2*t^20 + 3*t^24 + 2*t^28 + O(t^30)
            sage: mol = Tetra.molien_series(return_series=False); mol
            (t^8 - t^4 + 1)/(t^16 - t^12 - t^4 + 1)
            sage: mol.parent()
            Fraction Field of Univariate Polynomial Ring in t over Integer Ring
            sage: chi = Tetra.character(Tetra.character_table()[1])
            sage: Tetra.molien_series(chi, prec=30, variable='u')
            u^6 + u^14 + 2*u^18 + u^22 + 2*u^26 + 3*u^30 + 2*u^34 + O(u^36)
            sage: chi = Tetra.character(Tetra.character_table()[2])
            sage: Tetra.molien_series(chi)
            t^10 + t^14 + t^18 + 2*t^22 + 2*t^26 + O(t^30)

        ::

            sage: S3 = MatrixGroup(SymmetricGroup(3))
            sage: mol = S3.molien_series(prec=10); mol
            1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + 8*t^7 + 10*t^8 + 12*t^9 + O(t^10)
            sage: mol.parent()
            Power Series Ring in t over Integer Ring

        Octahedral Group::

            sage: K.<v> = CyclotomicField(8)
            sage: a = v-v^3 #sqrt(2)
            sage: i = v^2
            sage: Octa = MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [(1+i)/a,0, 0,(1-i)/a])
            sage: Octa.molien_series(prec=30)
            1 + t^8 + t^12 + t^16 + t^18 + t^20 + 2*t^24 + t^26 + t^28 + O(t^30)

        Icosahedral Group::

            sage: K.<v> = CyclotomicField(10)
            sage: z5 = v^2
            sage: i = z5^5
            sage: a = 2*z5^3 + 2*z5^2 + 1 #sqrt(5)
            sage: Ico = MatrixGroup([[z5^3,0, 0,z5^2], [0,1, -1,0], [(z5^4-z5)/a, (z5^2-z5^3)/a, (z5^2-z5^3)/a, -(z5^4-z5)/a]])
            sage: Ico.molien_series(prec=40)
            1 + t^12 + t^20 + t^24 + t^30 + t^32 + t^36 + O(t^40)

        ::

            sage: G = MatrixGroup(CyclicPermutationGroup(3))
            sage: chi = G.character(G.character_table()[1])
            sage: G.molien_series(chi, prec=10)
            t + 2*t^2 + 3*t^3 + 5*t^4 + 7*t^5 + 9*t^6 + 12*t^7 + 15*t^8 + 18*t^9 + 22*t^10 + O(t^11)

        ::

            sage: K = GF(5)
            sage: S = MatrixGroup(SymmetricGroup(4))
            sage: G = MatrixGroup([matrix(K,4,4,[K(y) for u in m.list() for y in u])for m in S.gens()])
            sage: G.molien_series(return_series=False)
            1/(t^10 - t^9 - t^8 + 2*t^5 - t^2 - t + 1)

        ::

            sage: i = GF(7)(3)
            sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]])
            sage: chi = G.character(G.character_table()[4])
            sage: G.molien_series(chi)
            3*t^5 + 6*t^11 + 9*t^17 + 12*t^23 + O(t^25)
        """
        if not self.is_finite():
            raise NotImplementedError("only implemented for finite groups")
        if chi is None:
            chi = self.trivial_character()
        M = self.matrix_space()
        R = FractionField(self.base_ring())
        N = self.order()
        if R.characteristic() == 0:
            P = PolynomialRing(R, variable)
            t = P.gen()
            #it is possible the character is over a larger cyclotomic field
            K = chi.values()[0].parent()
            if K.degree() != 1:
                if R.degree() != 1:
                    L = K.composite_fields(R)[0]
                else:
                    L = K
            else:
                L = R
            mol = P(0)
            for g in self:
                mol += L(chi(g)) / (M.identity_matrix()-t*g.matrix()).det().change_ring(L)
        elif R.characteristic().divides(N):
            raise NotImplementedError("characteristic cannot divide group order")
        else: #char p>0
            #find primitive Nth roots of unity over base ring and QQ
            F = cyclotomic_polynomial(N).change_ring(R)
            w = F.roots(ring=R.algebraic_closure(), multiplicities=False)[0]
            #don't need to extend further in this case since the order of
            #the roots of unity in the character divide the order of the group
            L = CyclotomicField(N, 'v')
            v = L.gen()
            #construct Molien series
            P = PolynomialRing(L, variable)
            t = P.gen()
            mol = P(0)
            for g in self:
                #construct Phi
                phi = L(chi(g))
                for e in g.matrix().eigenvalues():
                    #find power such that w**n  = e
                    n = 1
                    while w**n != e and n < N+1:
                        n += 1
                    #raise v to that power
                    phi *= (1-t*v**n)
                mol += P(1)/phi
        #We know the coefficients will be integers
        mol = mol.numerator().change_ring(ZZ) / mol.denominator().change_ring(ZZ)
        #divide by group order
        mol /= N
        if return_series:
            PS = PowerSeriesRing(ZZ, variable, default_prec=prec)
            return PS(mol)
        return mol
예제 #23
0
    def molien_series(self,
                      chi=None,
                      return_series=True,
                      prec=20,
                      variable='t'):
        r"""
        Compute the Molien series of this finite group with respect to the
        character ``chi``. It can be returned either as a rational function
        in one variable or a power series in one variable. The base field
        must be a finite field, the rationals, or a cyclotomic field.

        Note that the base field characteristic cannot divide the group
        order (i.e., the non-modular case).

        ALGORITHM:

        For a finite group `G` in characteristic zero we construct the Molien series as

        .. MATH::

            \frac{1}{|G|}\sum_{g \in G} \frac{\chi(g)}{\text{det}(I-tg)},

        where `I` is the identity matrix and `t` an indeterminate.

        For characteristic `p` not dividing the order of `G`, let `k` be the base field
        and `N` the order of `G`. Define `\lambda` as a primitive `N`-th root of unity over `k`
        and `\omega` as a primitive `N`-th root of unity over `\QQ`. For each `g \in G`
        define `k_i(g)` to be the positive integer such that
        `e_i = \lambda^{k_i(g)}` for each eigenvalue `e_i` of `g`. Then the Molien series
        is computed as

        .. MATH::

            \frac{1}{|G|}\sum_{g \in G} \frac{\chi(g)}{\prod_{i=1}^n(1 - t\omega^{k_i(g)})},

        where `t` is an indeterminant. [Dec1998]_

        INPUT:

        - ``chi`` -- (default: trivial character) a linear group character of this group

        - ``return_series`` -- boolean (default: ``True``) if ``True``, then returns
          the Molien series as a power series, ``False`` as a rational function

        - ``prec`` -- integer (default: 20); power series default precision

        - ``variable`` -- string (default: ``'t'``); Variable name for the Molien series

        OUTPUT: single variable rational function or power series with integer coefficients

        EXAMPLES::

            sage: MatrixGroup(matrix(QQ,2,2,[1,1,0,1])).molien_series()
            Traceback (most recent call last):
            ...
            NotImplementedError: only implemented for finite groups
            sage: MatrixGroup(matrix(GF(3),2,2,[1,1,0,1])).molien_series()
            Traceback (most recent call last):
            ...
            NotImplementedError: characteristic cannot divide group order

        Tetrahedral Group::

            sage: K.<i> = CyclotomicField(4)
            sage: Tetra =  MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [0,i, -i,0])
            sage: Tetra.molien_series(prec=30)
            1 + t^8 + 2*t^12 + t^16 + 2*t^20 + 3*t^24 + 2*t^28 + O(t^30)
            sage: mol = Tetra.molien_series(return_series=False); mol
            (t^8 - t^4 + 1)/(t^16 - t^12 - t^4 + 1)
            sage: mol.parent()
            Fraction Field of Univariate Polynomial Ring in t over Integer Ring
            sage: chi = Tetra.character(Tetra.character_table()[1])
            sage: Tetra.molien_series(chi, prec=30, variable='u')
            u^6 + u^14 + 2*u^18 + u^22 + 2*u^26 + 3*u^30 + 2*u^34 + O(u^36)
            sage: chi = Tetra.character(Tetra.character_table()[2])
            sage: Tetra.molien_series(chi)
            t^10 + t^14 + t^18 + 2*t^22 + 2*t^26 + O(t^30)

        ::

            sage: S3 = MatrixGroup(SymmetricGroup(3))
            sage: mol = S3.molien_series(prec=10); mol
            1 + t + 2*t^2 + 3*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + 8*t^7 + 10*t^8 + 12*t^9 + O(t^10)
            sage: mol.parent()
            Power Series Ring in t over Integer Ring

        Octahedral Group::

            sage: K.<v> = CyclotomicField(8)
            sage: a = v-v^3 #sqrt(2)
            sage: i = v^2
            sage: Octa = MatrixGroup([(-1+i)/2,(-1+i)/2, (1+i)/2,(-1-i)/2], [(1+i)/a,0, 0,(1-i)/a])
            sage: Octa.molien_series(prec=30)
            1 + t^8 + t^12 + t^16 + t^18 + t^20 + 2*t^24 + t^26 + t^28 + O(t^30)

        Icosahedral Group::

            sage: K.<v> = CyclotomicField(10)
            sage: z5 = v^2
            sage: i = z5^5
            sage: a = 2*z5^3 + 2*z5^2 + 1 #sqrt(5)
            sage: Ico = MatrixGroup([[z5^3,0, 0,z5^2], [0,1, -1,0], [(z5^4-z5)/a, (z5^2-z5^3)/a, (z5^2-z5^3)/a, -(z5^4-z5)/a]])
            sage: Ico.molien_series(prec=40)
            1 + t^12 + t^20 + t^24 + t^30 + t^32 + t^36 + O(t^40)

        ::

            sage: G = MatrixGroup(CyclicPermutationGroup(3))
            sage: chi = G.character(G.character_table()[1])
            sage: G.molien_series(chi, prec=10)
            t + 2*t^2 + 3*t^3 + 5*t^4 + 7*t^5 + 9*t^6 + 12*t^7 + 15*t^8 + 18*t^9 + 22*t^10 + O(t^11)

        ::

            sage: K = GF(5)
            sage: S = MatrixGroup(SymmetricGroup(4))
            sage: G = MatrixGroup([matrix(K,4,4,[K(y) for u in m.list() for y in u])for m in S.gens()])
            sage: G.molien_series(return_series=False)
            1/(t^10 - t^9 - t^8 + 2*t^5 - t^2 - t + 1)

        ::

            sage: i = GF(7)(3)
            sage: G = MatrixGroup([[i^3,0,0,-i^3],[i^2,0,0,-i^2]])
            sage: chi = G.character(G.character_table()[4])
            sage: G.molien_series(chi)
            3*t^5 + 6*t^11 + 9*t^17 + 12*t^23 + O(t^25)
        """
        if not self.is_finite():
            raise NotImplementedError("only implemented for finite groups")
        if chi is None:
            chi = self.trivial_character()
        M = self.matrix_space()
        R = FractionField(self.base_ring())
        N = self.order()
        if R.characteristic() == 0:
            P = PolynomialRing(R, variable)
            t = P.gen()
            #it is possible the character is over a larger cyclotomic field
            K = chi.values()[0].parent()
            if K.degree() != 1:
                if R.degree() != 1:
                    L = K.composite_fields(R)[0]
                else:
                    L = K
            else:
                L = R
            mol = P(0)
            for g in self:
                mol += L(chi(g)) / (M.identity_matrix() -
                                    t * g.matrix()).det().change_ring(L)
        elif R.characteristic().divides(N):
            raise NotImplementedError(
                "characteristic cannot divide group order")
        else:  #char p>0
            #find primitive Nth roots of unity over base ring and QQ
            F = cyclotomic_polynomial(N).change_ring(R)
            w = F.roots(ring=R.algebraic_closure(), multiplicities=False)[0]
            #don't need to extend further in this case since the order of
            #the roots of unity in the character divide the order of the group
            L = CyclotomicField(N, 'v')
            v = L.gen()
            #construct Molien series
            P = PolynomialRing(L, variable)
            t = P.gen()
            mol = P(0)
            for g in self:
                #construct Phi
                phi = L(chi(g))
                for e in g.matrix().eigenvalues():
                    #find power such that w**n  = e
                    n = 1
                    while w**n != e and n < N + 1:
                        n += 1
                    #raise v to that power
                    phi *= (1 - t * v**n)
                mol += P(1) / phi
        #We know the coefficients will be integers
        mol = mol.numerator().change_ring(ZZ) / mol.denominator().change_ring(
            ZZ)
        #divide by group order
        mol /= N
        if return_series:
            PS = PowerSeriesRing(ZZ, variable, default_prec=prec)
            return PS(mol)
        return mol
예제 #24
0
    def closed_form(self, n='n'):
        r"""
        Return a symbolic expression in ``n``, which equals the n-th term of
        the sequence.

        It is a well-known property of C-finite sequences ``a_n`` that they
        have a closed form of the type:

        .. MATH::

            a_n = \sum_{i=1}^d c_i(n) \cdot r_i^n,

        where ``r_i`` are the roots of the characteristic equation and
        ``c_i(n)`` is a polynomial (whose degree equals the multiplicity of
        ``r_i`` minus one).  This is a natural generalization of Binet's
        formula for Fibonacci numbers.  See, for instance, [KP2011, Theorem 4.1].

        Note that if the o.g.f. has a polynomial part, that is, if the
        numerator degree is not strictly less than the denominator degree,
        then this closed form holds only when ``n`` exceeds the degree of that
        polynomial part.  In that case, the returned expression will differ
        from the sequence for small ``n``.

        EXAMPLES::

            sage: CFiniteSequence(1/(1-x)).closed_form()
            1
            sage: CFiniteSequence(x^2/(1-x)).closed_form()
            1
            sage: CFiniteSequence(1/(1-x^2)).closed_form()
            1/2*(-1)^n + 1/2
            sage: CFiniteSequence(1/(1+x^3)).closed_form()
            1/3*(-1)^n + 1/3*(1/2*I*sqrt(3) + 1/2)^n + 1/3*(-1/2*I*sqrt(3) + 1/2)^n
            sage: CFiniteSequence(1/(1-x)/(1-2*x)/(1-3*x)).closed_form()
            9/2*3^n - 4*2^n + 1/2

        Binet's formula for the Fibonacci numbers::

            sage: CFiniteSequence(x/(1-x-x^2)).closed_form()
            sqrt(1/5)*(1/2*sqrt(5) + 1/2)^n - sqrt(1/5)*(-1/2*sqrt(5) + 1/2)^n
            sage: [_.subs(n=k).full_simplify() for k in range(6)]
            [0, 1, 1, 2, 3, 5]

            sage: CFiniteSequence((4*x+3)/(1-2*x-5*x^2)).closed_form()
            1/2*(sqrt(6) + 1)^n*(7*sqrt(1/6) + 3) - 1/2*(-sqrt(6) + 1)^n*(7*sqrt(1/6) - 3)

        Examples with multiple roots::

            sage: CFiniteSequence(x*(x^2+4*x+1)/(1-x)^5).closed_form()
            1/4*n^4 + 1/2*n^3 + 1/4*n^2
            sage: CFiniteSequence((1+2*x-x^2)/(1-x)^4/(1+x)^2).closed_form()
            1/12*n^3 - 1/8*(-1)^n*(n + 1) + 3/4*n^2 + 43/24*n + 9/8
            sage: CFiniteSequence(1/(1-x)^3/(1-2*x)^4).closed_form()
            4/3*(n^3 - 3*n^2 + 20*n - 36)*2^n + 1/2*n^2 + 19/2*n + 49
            sage: CFiniteSequence((x/(1-x-x^2))^2).closed_form()
            1/5*(n - sqrt(1/5))*(1/2*sqrt(5) + 1/2)^n + 1/5*(n + sqrt(1/5))*(-1/2*sqrt(5) + 1/2)^n
        """
        from sage.arith.all import binomial
        from sage.rings.qqbar import QQbar

        from sage.symbolic.ring import SR
        n = SR(n)
        expr = SR.zero()

        R = FractionField(PolynomialRing(QQbar, self.parent().variable_name()))
        ogf = R(self.ogf())

        __, parts = ogf.partial_fraction_decomposition(decompose_powers=False)
        for part in parts:
            denom = part.denominator().factor()
            denom_base, denom_exp = denom[0]

            # denominator is of the form (x+b)^{m+1}
            m = denom_exp - 1
            b = denom_base.constant_coefficient()
            # check that the partial fraction decomposition was indeed done correctly
            # (that is, there is only one factor, of degree 1, and monic)
            assert len(denom) == 1 and len(denom_base.list(
            )) == 2 and denom_base[1] == 1 and denom.unit() == 1

            r = SR((-1 / b).radical_expression())
            c = SR.zero()
            for k, a in enumerate(part.numerator()):
                a = -QQbar(a) if k % 2 else QQbar(a)
                bino = binomial(n + m - k, m)
                c += bino * SR((a * b**(k - m - 1)).radical_expression())

            expr += c.expand() * r**n

        return expr
예제 #25
0
    def canonical_height(self, F, **kwds):
        r"""
        Evaluates the (absolute) canonical height of ``self`` with respect to ``F``. Must be over number field
        or order of a number field. Specify either the number of terms of the series to evaluate or
        the error bound required.

        ALGORITHM:

            The sum of the Green's function at the archimedean places and the places of bad reduction.

        INPUT:

        - ``F`` - a projective morphism

        kwds:

        - ``badprimes`` - a list of primes of bad reduction

        - ``N`` - positive integer. number of terms of the series to use in the local green functions

        - ``prec`` - positive integer, float point or p-adic precision

        - ``error_bound`` - a positive real number

        OUTPUT:

        - a real number

        EXAMPLES::

            sage: P.<x,y> = ProjectiveSpace(ZZ,1)
            sage: H = Hom(P,P)
            sage: f = H([x^2+y^2,2*x*y]);
            sage: Q = P(2,1)
            sage: f.canonical_height(f(Q))
            2.1965476757927038111992627081
            sage: f.canonical_height(Q)
            1.0979353871245941198040174712

        Notice that preperiodic points may not be exactly 0. ::

            sage: P.<x,y> = ProjectiveSpace(QQ,1)
            sage: H = Hom(P,P)
            sage: f = H([x^2-29/16*y^2,y^2]);
            sage: Q = P(5,4)
            sage: f.canonical_height(Q, N=30)
            1.4989058602918874235833076226e-9

        ::

            sage: P.<x,y,z> = ProjectiveSpace(QQ,2)
            sage: X = P.subscheme(x^2-y^2);
            sage: H = Hom(X,X)
            sage: f = H([x^2,y^2,30*z^2]);
            sage: Q = X([4,4,1])
            sage: f.canonical_height(Q, badprimes=[2,3,5], prec=200)
            2.7054056208276961889784303469356774912979228770208655455481
        """
        bad_primes = kwds.pop("badprimes", None)
        prec = kwds.get("prec", 100)
        error_bound = kwds.get("error_bound", None)
        K = FractionField(self.codomain().base_ring())

        if not K in _NumberFields:
            raise NotImplementedError("Must be over a NumberField or a NumberField Order")

        if bad_primes is None:
            bad_primes = []
            for b in self:
                if K == QQ:
                    bad_primes += b.denominator().prime_factors()
                else:
                    bad_primes += b.denominator_ideal().prime_factors()
            bad_primes += K(F.resultant()).support()
            bad_primes = list(set(bad_primes))

        emb = K.places(prec=prec)
        num_places = len(emb) + len(bad_primes)
        if not error_bound is None:
            error_bound /= num_places
        R = RealField(prec)
        h = R(0)

        # Archimedean local heights
        # :: WARNING: If places is fed the default Sage precision of 53 bits,
        # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec)
        # the function is_RealField does not identify RDF as real, so we test for that ourselves.
        for v in emb:
            if is_RealField(v.codomain()) or v.codomain() is RDF:
                dv = R(1)
            else:
                dv = R(2)
            h += dv*self.green_function(F, v, **kwds)       #arch Green function

        # Non-Archimedean local heights
        for v in bad_primes:
            if K == QQ:
                dv = R(1)
            else:
                dv = R(v.residue_class_degree() * v.absolute_ramification_index())
            h += dv * self.green_function(F, v, **kwds)  #non-arch Green functions
        return h
예제 #26
0
    def __init__(self, parent, polys, check=True):
        r"""
        The Python constructor.

        See :class:`SchemeMorphism_polynomial` for details.

        INPUT:

        - ``parent`` -- Hom.

        - ``polys`` -- list or tuple of polynomial or rational functions.

        - ``check`` -- Boolean.

        OUTPUT:

        - :class:`SchemeMorphism_polynomial_affine_space`.

        EXAMPLES::

            sage: A.<x,y> = AffineSpace(ZZ, 2)
            sage: H = Hom(A, A)
            sage: H([3/5*x^2, y^2/(2*x^2)])
            Scheme endomorphism of Affine Space of dimension 2 over Integer Ring
              Defn: Defined on coordinates by sending (x, y) to
                    (3*x^2/5, y^2/(2*x^2))

        ::

            sage: A.<x,y> = AffineSpace(ZZ, 2)
            sage: H = Hom(A, A)
            sage: H([3*x^2/(5*y), y^2/(2*x^2)])
            Scheme endomorphism of Affine Space of dimension 2 over Integer Ring
              Defn: Defined on coordinates by sending (x, y) to
                    (3*x^2/(5*y), y^2/(2*x^2))

        ::

            sage: A.<x,y> = AffineSpace(QQ, 2)
            sage: H = Hom(A, A)
            sage: H([3/2*x^2, y^2])
            Scheme endomorphism of Affine Space of dimension 2 over Rational Field
              Defn: Defined on coordinates by sending (x, y) to
                    (3/2*x^2, y^2)

        ::

            sage: A.<x,y> = AffineSpace(QQ, 2)
            sage: X = A.subscheme([x-y^2])
            sage: H = Hom(X, X)
            sage: H([9/4*x^2, 3/2*y])
            Scheme endomorphism of Closed subscheme of Affine Space of dimension 2
            over Rational Field defined by:
              -y^2 + x
              Defn: Defined on coordinates by sending (x, y) to
                    (9/4*x^2, 3/2*y)

            sage: P.<x,y,z> = ProjectiveSpace(ZZ, 2)
            sage: H = Hom(P, P)
            sage: f = H([5*x^3 + 3*x*y^2-y^3, 3*z^3 + y*x^2, x^3-z^3])
            sage: f.dehomogenize(2)
            Scheme endomorphism of Affine Space of dimension 2 over Integer Ring
              Defn: Defined on coordinates by sending (x, y) to
                    ((5*x^3 + 3*x*y^2 - y^3)/(x^3 - 1), (x^2*y + 3)/(x^3 - 1))

            If you pass in quotient ring elements, they are reduced::

            sage: A.<x,y,z> = AffineSpace(QQ, 3)
            sage: X = A.subscheme([x-y])
            sage: H = Hom(X,X)
            sage: u,v,w = X.coordinate_ring().gens()
            sage: H([u, v, u+v])
            Scheme endomorphism of Closed subscheme of Affine Space of dimension 3
            over Rational Field defined by:
              x - y
              Defn: Defined on coordinates by sending (x, y, z) to
                    (y, y, 2*y)

            You must use the ambient space variables to create rational functions::

            sage: A.<x,y,z> = AffineSpace(QQ, 3)
            sage: X = A.subscheme([x^2-y^2])
            sage: H = Hom(X,X)
            sage: u,v,w = X.coordinate_ring().gens()
            sage: H([u, v, (u+1)/v])
            Traceback (most recent call last):
            ...
            ArithmeticError: Division failed. The numerator is not a multiple of the denominator.
            sage: H([x, y, (x+1)/y])
            Scheme endomorphism of Closed subscheme of Affine Space of dimension 3
            over Rational Field defined by:
              x^2 - y^2
              Defn: Defined on coordinates by sending (x, y, z) to
                    (x, y, (x + 1)/y)

            ::

            sage: R.<t> = PolynomialRing(QQ)
            sage: A.<x,y,z> = AffineSpace(R, 3)
            sage: X = A.subscheme(x^2-y^2)
            sage: H = End(X)
            sage: H([x^2/(t*y), t*y^2, x*z])
            Scheme endomorphism of Closed subscheme of Affine Space of dimension 3
            over Univariate Polynomial Ring in t over Rational Field defined by:
              x^2 - y^2
              Defn: Defined on coordinates by sending (x, y, z) to
                    (x^2/(t*y), t*y^2, x*z)
        """
        if check:
            if not isinstance(polys, (list, tuple)):
                raise TypeError("polys (=%s) must be a list or tuple" % polys)
            source_ring = parent.domain().ambient_space().coordinate_ring()
            target = parent.codomain().ambient_space()
            if len(polys) != target.ngens():
                raise ValueError("there must be %s polynomials" %
                                 target.ngens())
            try:
                polys = [source_ring(poly) for poly in polys]
            except TypeError:  #maybe given quotient ring elements
                try:
                    polys = [source_ring(poly.lift()) for poly in polys]
                except (TypeError, AttributeError):
                    #must be a rational function since we cannot have
                    #rational functions for quotient rings
                    try:
                        if not all(p.base_ring().fraction_field() ==
                                   source_ring.base_ring().fraction_field()
                                   for p in polys):
                            raise TypeError(
                                "polys (=%s) must be rational functions in %s"
                                % (polys, source_ring))
                        K = FractionField(source_ring)
                        polys = [K(p) for p in polys]
                        #polys = [source_ring(poly.numerator())/source_ring(poly.denominator()) for poly in polys]
                    except TypeError:  #can't seem to coerce
                        raise TypeError(
                            "polys (=%s) must be rational functions in %s" %
                            (polys, source_ring))
        self._is_prime_finite_field = is_PrimeFiniteField(
            polys[0].base_ring())  # Needed for _fast_eval and _fastpolys
        SchemeMorphism_polynomial.__init__(self, parent, polys, False)