Exemplo n.º 1
0
    def riemann_sum(self,f,center=1,level=0,E=None):
        r"""
        This function evaluates the integral of the funtion ``f`` with respect to the measure determined by ``self``.

        EXAMPLES:

        This example illustrates ...

        ::
        """
        R1=LaurentSeriesRing(f.base_ring(),'r1')
        R1.set_default_prec(self._parent._k-1)
        R2=PolynomialRing(f.base_ring(),'r2')

        if E is None:
            E=self._parent._X._BT.get_balls(center,level)
        else:
            E=self._parent._X._BT.subdivide(E,level)
        value=0
        ii=0
        for e in E:
            ii+=1
            exp=R1([e[1,1],e[1,0]])**(self._parent._k-2)*e.determinant()**(-(self._parent._k-2)/2)*f(R1([e[0,1],e[0,0]])/R1([e[1,1],e[1,0]])).truncate(self._parent._k-1)
            new=self.evaluate(e).l_act_by(e.inverse()).evaluate(exp)
            value+=new
        return value
Exemplo n.º 2
0
    def integrate(self,f,center=1,level=0,method='moments'):
        r"""
        Calculate
        .. MATH::

            \int_{\PP^1(\QQ_p)} f(x)d\mu(x)

        were `\mu` is the measure associated to ``self``.

        INPUT:

         - ``f`` - An analytic function.

         - ``center`` - 2x2 matrix over Qp (default: 1)

         - ``level`` - integer (default: 0)

         - ``method`` - string (default: 'moments'). Which method of integration to use. Either 'moments' or 'riemann_sum'.


        EXAMPLES:

        ::


        AUTHORS:

        - Marc Masdeu (2012-02-20)
        - Cameron Franc (2012-02-20)

        """
        E=self._parent._X._BT.get_balls(center,level)
        R1=LaurentSeriesRing(f.base_ring(),'r1')
        R2=PolynomialRing(f.base_ring(),'r2')
        value=0
        ii=0
        if(method=='riemann_sum'):
            R1.set_default_prec(self._parent._U.weight()+1)
            for e in E:
                ii+=1
                #print ii,"/",len(E)
                exp=((R1([e[1,1],e[1,0]]))**(self._parent._U.weight())*e.determinant()**(-(self._parent._U.weight())/2))*f(R1([e[0,1],e[0,0]])/R1([e[1,1],e[1,0]]))
                #exp=R2([tmp[jj] for jj in range(self._parent._k-1)])
                new=self.evaluate(e).evaluate(exp.truncate(self._parent._U.weight()+1))
                value+=new
        elif(method=='moments'):
            R1.set_default_prec(self._parent._U.dimension())
            for e in E:
                ii+=1
                #print ii,"/",len(E)
                tmp=((R2([e[1,1],e[1,0]]))**(self._parent._U.weight())*e.determinant()**(-(self._parent._U.weight())/2))*f(R2([e[0,1],e[0,0]])/R2([e[1,1],e[1,0]]))
                exp=R1(tmp.numerator())/R1(tmp.denominator())
                new=self.evaluate(e).evaluate(exp)
                value+=new
        else:
            print 'The available methods are either "moments" or "riemann_sum". The latter is only provided for consistency check, and should never be used.'
            return False
        return value
Exemplo n.º 3
0
    def series(self, n):
        """
        Return the Laurent power series associated with the CFiniteSequence, with precision `n`.
        
        INPUT:

        - ``n`` -- a nonnegative integer

        EXAMPLES::

            sage: r = CFiniteSequence.from_recurrence([-1,2],[0,1])
            sage: s = r.series(4); s
            x + 2*x^2 + 3*x^3 + 4*x^4 + O(x^5)
            sage: type(s)
            <type 'sage.rings.laurent_series_ring_element.LaurentSeries'>
        """

        R = LaurentSeriesRing(QQ, 'x')
        R.set_default_prec(n)
        return R(self.ogf())
Exemplo n.º 4
0
    def coleman(self,t1,t2,E=None,method='moments',mult=False,delta=-1,level=0):
        r"""
        If ``self`` is a `p`-adic automorphic form that corresponds to a rigid modular form,
        then this computes the coleman integral of this form between two points on
        the boundary `\PP^1(\QQ_p)` of the `p`-adic upper half plane.

        INPUT:

         - ``t1``, ``t2`` - elements of `\PP^1(\QQ_p)` (the endpoints of integration)

         - ``E`` - (Default: None). If specified, will not compute the covering adapted
            to ``t1`` and ``t2`` and instead use the given one. In that case, ``E``
            should be a list of matrices corresponding to edges describing the open
            balls to be considered.

         - ``method`` - string (Default: 'moments'). Tells which algorithm to use 
           (alternative is 'riemann_sum', which is unsuitable for computations 
           requiring high precision)

         - ``mult`` - boolean (Default: False). Whether to use the multiplicative version.

         - ``delta`` - integer (Default: -1)

         - ``level`` - integer (Default: 0)

        OUTPUT:

          The result of the coleman integral

        EXAMPLES:

        This example illustrates ...

        ::

        TESTS:

        ::
            sage: p = 7
            sage: lev = 2
            sage: prec = 20
            sage: X = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M = HarmonicCocycles(X,k,prec) # optional - magma
            sage: B = M.basis() # optional - magma
            sage: f = 3*B[0] # optional - magma
            sage: MM = pAutomorphicForms(X,k,prec,overconvergent=True) # optional - magma
            sage: D = -11 # optional - magma
            sage: X.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = X.get_CM_points(D,prec=prec) # optional - magma
            sage: Kp = CM[0].parent() # optional - magma
            sage: P=CM[0] # optional - magma
            sage: Q=P.trace()-P # optional - magma
            sage: F=MM.lift(f, verbose = False) # long time optional - magma
            sage: J0=F.coleman(P,Q,mult=True) # long time optional - magma
            sage: E=EllipticCurve([1,0,1,4,-6]) # optional - magma
            sage: T=E.tate_curve(p) # optional - magma
            sage: xx,yy=getcoords(T,J0,prec) # long time optional -magma
            sage: P = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); P # long time optional - magma
            (7/11 : 58/121*a - 9/11 : 1)

            sage: p = 13 # optional - magma
            sage: lev = 2 # optional - magma
            sage: prec = 20 # optional - magma
            sage: Y = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M=HarmonicCocycles(Y,k,prec) # optional - magma
            sage: B=M.basis() # optional - magma

            sage: f = B[1] # optional - magma
            sage: g = -4*B[0]+3*B[1] # optional - magma
            sage: MM = pAutomorphicForms(Y,k,prec,overconvergent=True) # optional - magma
            sage: D = -11 # optional - magma
            sage: Y.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = Y.get_CM_points(D,prec=prec) # optional - magma
            sage: Kp = parent(CM[0]) # optional - magma
            sage: P = CM[0] # optional - magma
            sage: Q = P.trace()-P # optional - magma
            sage: F = MM.lift(f, verbose = False) # long time optional - magma
            sage: J11 = F.coleman(P,Q,mult = True) # long time optional - magma
            sage: E = EllipticCurve('26a2') # optional - magma
            sage: T = E.tate_curve(p) # optional - magma
            sage: xx,yy = getcoords(T,J11,prec) # long time optional - magma
            sage: HP = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); HP # long time optional - magma
            (-137/11 : 2/121*a + 63/11 : 1)

        AUTHORS:

        - Cameron Franc (2012-02-20)
        - Marc Masdeu (2012-02-20)
        """
        if(mult and delta>=0):
            raise NotImplementedError, "Need to figure out how to implement the multiplicative part."
        p=self._parent._X._p
        K=t1.parent()
        R=PolynomialRing(K,'x')
        x=R.gen()
        R1=LaurentSeriesRing(K,'r1')
        r1=R1.gen()
        if(E is None):
            E=self._parent._X._BT.find_covering(t1,t2)
            # print 'Got %s open balls.'%len(E)
        value=0
        ii=0
        value_exp=K(1)
        if(method=='riemann_sum'):
            R1.set_default_prec(self._parent._U.weight()+1)
            for e in E:
                ii+=1
                b=e[0,1]
                d=e[1,1]
                y=(b-d*t1)/(b-d*t2)
                poly=R1(y.log()) #R1(our_log(y))
                c_e=self.evaluate(e)
                new=c_e.evaluate(poly)
                value+=new
                if mult:
                    value_exp *= K.teichmuller(y)**Integer(c_e[0].rational_reconstruction())

        elif(method=='moments'):
            R1.set_default_prec(self._parent._U.dimension())
            for e in E:
                ii+=1
                f=(x-t1)/(x-t2)
                a,b,c,d=e.list()
                y0=f(R1([b,a])/R1([d,c])) #f( (ax+b)/(cx+d) )
                y0=p**(-y0(0).valuation())*y0
                mu=K.teichmuller(y0(0))
                y=y0/mu-1
                poly=R1(0)
                ypow=y
                for jj in range(1,R1.default_prec()+10):
                    poly+=(-1)**(jj+1)*ypow/jj
                    ypow*=y
                if(delta>=0):
                    poly*=((r1-t1)**delta*(r1-t2)**(self._parent._n-delta))
                c_e=self.evaluate(e)
                new=c_e.evaluate(poly)
                value+=new
                if mult:
                    value_exp *= K.teichmuller((b-d*t1)/(b-d*t2))**Integer(c_e[0].rational_reconstruction())

        else:
            print 'The available methods are either "moments" or "riemann_sum". The latter is only provided for consistency check, and should not be used in practice.'
            return False
        if mult:
            return value_exp * value.exp()
        return value
Exemplo n.º 5
0
    def coleman(self,t1,t2,poly = None, E = None,method = 'moments',mult = False,level = 0, branch = 0):
        r"""
        If ``self`` is a `p`-adic automorphic form that corresponds to a rigid modular form,
        then this computes the coleman integral of this form between two points on
        the boundary `\PP^1(\QQ_p)` of the `p`-adic upper half plane.

        INPUT:

        - ``t1``, ``t2`` - elements of `\PP^1(\QQ_p)` (the endpoints of integration)

        - ``E`` - (Default: None). If specified, will not compute the covering adapted
           to ``t1`` and ``t2`` and instead use the given one. In that case, ``E``
           should be a list of matrices corresponding to edges describing the open
           balls to be considered.

        - ``method`` - string (Default: 'moments'). Tells which algorithm to use
          (alternative is 'riemann_sum', which is unsuitable for computations
          requiring high precision)

        - ``mult`` - boolean (Default: False). Whether to use the multiplicative version.

        - ``poly`` - polynomial (Default: None)

        - ``level`` - integer (Default: 0)

        OUTPUT:

          The result of the coleman integral

        EXAMPLES::

            sage: p = 7
            sage: lev = 2
            sage: prec = 20
            sage: X = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M = HarmonicCocycles(X,k,prec) # optional - magma
            sage: B = M.basis() # optional - magma
            sage: f = 3*M.decomposition()[0].gen(0) # optional - magma
            sage: MM = pAutomorphicForms(X,k,prec,overconvergent = True) # optional - magma
            sage: D = -11 # optional - magma
            sage: X.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = X.get_CM_points(D,prec = prec) # optional - magma
            sage: P = CM[0] # optional - magma
            sage: Q = P.trace()-P # optional - magma
            sage: F = MM.lift(f, verbose = False) # long time optional - magma
            sage: J0 = F.coleman(P,Q,mult = True) # long time optional - magma
            sage: E = EllipticCurve([1,0,1,4,-6]) # optional - magma
            sage: T = E.tate_curve(p) # optional - magma
            sage: xx,yy = getcoords(T,J0,prec) # long time optional -magma
            sage: P = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); P # long time optional - magma
            (7/11 : 58/121*a - 9/11 : 1)

            sage: p = 13 # optional - magma
            sage: lev = 2 # optional - magma
            sage: prec = 20 # optional - magma
            sage: Y = BTQuotient(p,lev, use_magma = True) # optional - magma
            sage: k = 2 # optional - magma
            sage: M = HarmonicCocycles(Y,k,prec) # optional - magma
            sage: B = M.basis() # optional - magma
            sage: f = M.decomposition()[1].gen(0) # optional - magma
            sage: g = M.decomposition()[0].gen(0) # optional - magma
            sage: MM = pAutomorphicForms(Y,k,prec,overconvergent = True) # optional - magma
            sage: D = -11 # optional - magma
            sage: Y.is_admissible(D) # optional - magma
            True
            sage: K.<a> = QuadraticField(D) # optional - magma
            sage: CM = Y.get_CM_points(D,prec = prec) # optional - magma
            sage: P = CM[0] # optional - magma
            sage: Q = P.trace()-P # optional - magma
            sage: F = MM.lift(f, verbose = False) # long time optional - magma
            sage: J11 = F.coleman(P,Q,mult = True) # long time optional - magma
            sage: E = EllipticCurve('26a2') # optional - magma
            sage: T = E.tate_curve(p) # optional - magma
            sage: xx,yy = getcoords(T,J11,prec) # long time optional - magma
            sage: HP = E.base_extend(K).lift_x(algdep(xx,1).roots(QQ)[0][0]); HP # long time optional - magma
            (-137/11 : 2/121*a + 63/11 : 1)

        AUTHORS:

        - Cameron Franc (2012-02-20)
        - Marc Masdeu (2012-02-20)
        """
        p = self.parent().prime()
        K = t1.parent()
        if mult:
            branch = 0

        R = PolynomialRing(K,'x')
        x = R.gen()
        R1 = LaurentSeriesRing(K,'r1')
        r1 = R1.gen()
        if E is None:
            E = self.parent()._source._BT.find_covering(t1,t2,level)
            print 'Got %s open balls.'%len(E)
        value = K(0)
        ii = 0
        value_exp = K(1)
        wt = self.parent()._U.weight()
        dim = self.parent()._U.dimension()
        if(method == 'riemann_sum'):
            R1.set_default_prec(wt+1)
            for e in E:
                ii += 1
                b = e[0,1]
                d = e[1,1]
                y = (b-d*t1)/(b-d*t2)
                pol = R1(y.log(branch = branch))
                c_e = self.evaluate(e)
                new = c_e.evaluate(pol)
                value += new
                if mult:
                    value_exp  *=  K.teichmuller(y)**Integer(c_e[0].rational_reconstruction())

        elif method == 'moments':
            R1.set_default_prec(dim)
            for e in E:
                ii += 1
                f = (x-t1)/(x-t2)
                a,b,c,d = e.list()
                y0 = f((a*r1+b)/(c*r1+d))
                pol = y0(0).log(branch = branch)+((y0.derivative()/y0).integral())
                if poly is not None:
                    pol *= poly(r1) #((r1-t1)**delta*(r1-t2)**(self.parent()._n-delta))
                c_e = self.evaluate(e)
                new = c_e.evaluate(pol)
                value += new
                if mult:
                    base = ((b-d*t1)/(b-d*t2))
                    pwr = ZZ(c_e[0].rational_reconstruction())
                    value_exp  *=  base**pwr
        else:
            print 'The available methods are either "moments" or "riemann_sum". The latter is only provided for consistency check, and should not be used in practice.'
            return False
        if mult:
            a = value_exp.valuation(p)
            print 'a=',a
            return p**a*K.teichmuller(p**(-a)*value_exp) * value.exp(prec = 2*dim) +O(p**(dim+a))
        return value +O(p**(dim+value.valuation(p)))
Exemplo n.º 6
0
    def __init__(self, ogf, *args, **kwargs):

        """
    Create a C-finite sequence given its ordinary generating function.

    INPUT:

    - ``ogf`` -- the ordinary generating function, a fraction of polynomials over the rationals


    OUTPUT:

    - A CFiniteSequence object

    EXAMPLES::

        sage: R.<x> = QQ[]
        sage: CFiniteSequence((2-x)/(1-x-x^2))     # the Lucas sequence
        C-finite sequence, generated by (-x + 2)/(-x^2 - x + 1)
        sage: CFiniteSequence(x/(1-x)^3)           # triangular numbers
        C-finite sequence, generated by x/(-x^3 + 3*x^2 - 3*x + 1)
        
    Polynomials are interpreted as finite sequences, or recurrences of degree 0::
    
        sage: CFiniteSequence(x^2-4*x^5)
        Finite sequence [1, 0, 0, -4], offset = 2
        sage: CFiniteSequence(1)
        Finite sequence [1], offset = 0

    This implementation allows any polynomial fraction as o.g.f. by interpreting
    any power of `x` dividing the o.g.f. numerator or denominator as a right or left shift
    of the sequence offset::

        sage: CFiniteSequence(x^2+3/x)
        Finite sequence [3, 0, 0, 1], offset = -1
        sage: CFiniteSequence(1/x+4/x^3)
        Finite sequence [4, 0, 1], offset = -3
        sage: P = LaurentPolynomialRing(QQ.fraction_field(), 'X')
        sage: X=P.gen()
        sage: CFiniteSequence(1/(1-X))
        C-finite sequence, generated by 1/(-x + 1)
        
    The o.g.f. is always normalized to get a denominator constant coefficient of `+1`::
    
        sage: CFiniteSequence(1/(x-2))
        C-finite sequence, generated by -1/2/(-1/2*x + 1)
    
    TESTS::
    
        sage: P.<x> = QQ[]
        sage: CFiniteSequence(0.1/(1-x))
        Traceback (most recent call last):
        ...
        ValueError: O.g.f. base not rational.
        sage: P.<x,y> = QQ[]
        sage: CFiniteSequence(x*y)
        Traceback (most recent call last):
        ...
        NotImplementedError: Multidimensional o.g.f. not implemented.
        """

        self._br = ogf.base_ring()
        if (self._br <> QQ) and (self._br <> ZZ) and not is_FiniteField(self._br):
            raise ValueError('O.g.f. base not proper.')
        
        P = PolynomialRing(self._br, 'x')
        if ogf in QQ:
            ogf = P(ogf)
        if hasattr(ogf,'numerator'):
            try:
                num = P(ogf.numerator())
                den = P(ogf.denominator())
            except TypeError:
                if ogf.numerator().parent().ngens() > 1:
                    raise NotImplementedError('Multidimensional o.g.f. not implemented.')
                else:
                    raise ValueError('Numerator and denominator must be polynomials.')
        else:
            num = P(ogf)
            den = 1
        
        # Transform the ogf numerator and denominator to canonical form
        # to get the correct offset, degree, and recurrence coeffs and
        # start values.
        self._off = 0
        self._deg = 0
        if isinstance (ogf, FractionFieldElement) and den == 1:
            ogf = num        # case p(x)/1: fall through
            
        if isinstance (ogf, (FractionFieldElement, FpTElement)):
            x = P.gen()
            if num.constant_coefficient() == 0:
                self._off = num.valuation()
                num = P(num / x**self._off)
            elif den.constant_coefficient() == 0:
                self._off = -den.valuation()
                den = P(den * x**self._off)
            f = den.constant_coefficient()
            num = P(num / f)
            den = P(den / f)
            f = gcd(num, den)
            num = P(num / f) 
            den = P(den / f)
            self._deg = den.degree()
            self._c = [-den.list()[i] for i in range(1, self._deg + 1)]
            if self._off >= 0:
                num = x**self._off * num
            else:
                den = x**(-self._off) * den

            # determine start values (may be different from _get_item_ values)
            R = LaurentSeriesRing(self._br, 'x')
            rem = num % den
            alen = max(self._deg, num.degree() + 1)
            R.set_default_prec (alen)
            if den <> 1:
                self._a = R(num/(den+O(x**alen))).list()
                self._aa = R(rem/(den+O(x**alen))).list()[:self._deg]  # needed for _get_item_
            else:
                self._a = num.list()
            if len(self._a) < alen:
                self._a.extend([0] * (alen - len(self._a)))
                
            super(CFiniteSequence, self).__init__(P.fraction_field(), num, den, *args, **kwargs)
            
        elif ogf.parent().is_integral_domain():
            super(CFiniteSequence, self).__init__(ogf.parent().fraction_field(), P(ogf), 1, *args, **kwargs)
            self._c = []
            self._off = P(ogf).valuation()
            if ogf == 0:
                self._a = [0]
            else:
                self._a = ogf.parent()((ogf / (ogf.parent().gen())**self._off)).list()
        else:
            raise ValueError("Cannot convert a " + str(type(ogf)) + " to CFiniteSequence.")