Exemple #1
0
    def __call__(self, x):
        r"""
        Evaluate this character at an element of `\ZZ_p^\times`.

        EXAMPLES::

            sage: kappa = pAdicWeightSpace(23)(1 + 23^2 + O(23^20), 4, False)
            sage: kappa(2)
            16 + 7*23 + 7*23^2 + 16*23^3 + 23^4 + 20*23^5 + 15*23^7 + 11*23^8 + 12*23^9 + 8*23^10 + 22*23^11 + 16*23^12 + 13*23^13 + 4*23^14 + 19*23^15 + 6*23^16 + 7*23^17 + 11*23^19 + O(23^20)
            sage: kappa(-1)
            1 + O(23^20)
            sage: kappa(23)
            0
            sage: kappa(2 + 2*23 + 11*23^2 + O(23^3))
            16 + 7*23 + O(23^3)
        """

        if not isinstance(x, pAdicGenericElement):
            x = Qp(self._p)(x)
        if x.valuation() != 0:
            return 0

        teich = x.parent().teichmuller(x, x.precision_absolute())
        xx = x / teich
        if (xx - 1).valuation() <= 0:
            raise ArithmeticError
        verbose("Normalised element is %s" % xx)

        e = xx.log() / self.parent()._param.log()
        verbose("Exponent is %s" % e)

        return teich**(self.t) * (self.w.log() * e).exp()
Exemple #2
0
    def __call__(self, x):
        r"""
        Evaluate this character at an element of `\ZZ_p^\times`.

        EXAMPLES::

            sage: kappa = pAdicWeightSpace(23)(1 + 23^2 + O(23^20), 4, False)
            sage: kappa(2)
            16 + 7*23 + 7*23^2 + 16*23^3 + 23^4 + 20*23^5 + 15*23^7 + 11*23^8 + 12*23^9 + 8*23^10 + 22*23^11 + 16*23^12 + 13*23^13 + 4*23^14 + 19*23^15 + 6*23^16 + 7*23^17 + 11*23^19 + O(23^20)
            sage: kappa(-1)
            1 + O(23^20)
            sage: kappa(23)
            0
            sage: kappa(2 + 2*23 + 11*23^2 + O(23^3))
            16 + 7*23 + O(23^3)
        """

        if not isinstance(x, pAdicGenericElement):
            x = Qp(self._p)(x)
        if x.valuation() != 0:
            return 0

        teich = x.parent().teichmuller(x)
        xx = x / teich
        if (xx - 1).valuation() <= 0:
            raise ArithmeticError
        verbose("Normalised element is %s" % xx)

        e = xx.log() / self.parent()._param.log()
        verbose("Exponent is %s" % e)

        return teich**(self.t) * (self.w.log() * e).exp()
 def embed_order(self, p, K, prec, outfile=None, return_all=False):
     r'''
     '''
     from .limits import find_the_unit_of
     verbose('Computing quadratic embedding to precision %s' % prec)
     verbose('Finding module generators')
     w = module_generators(K)[1]
     verbose('Done')
     w_minpoly = w.minpoly().change_ring(Qp(p, prec))
     Cp = Qp(p, prec).extension(w_minpoly, names='g')
     wl = w.list()
     assert len(wl) == 2
     r0 = -wl[0] / wl[1]
     r1 = 1 / wl[1]
     assert r0 + r1 * w == K.gen()
     padic_Kgen = Cp(r0) + Cp(r1) * Cp.gen()
     try:
         fwrite(
             '# d_K = %s, h_K = %s, h_K^- = %s' %
             (K.discriminant(), K.class_number(), len(
                 K.narrow_class_group())), outfile)
     except NotImplementedError:
         pass
     fwrite('# w_K satisfies: %s' % w.minpoly(), outfile)
     #####
     uk = find_the_unit_of(self.F, K)
     tu = uk.trace()
     verb_level = get_verbose()
     set_verbose(0)
     for g in self.enumerate_elements():
         if g.trace() == tu:
             gamma = self(g)
             a, b, c, d = gamma.quaternion_rep.list()
             rt_list = our_sqrt((d - a)**2 + 4 * b * c, Cp, return_all=True)
             tau1, tau2 = [(Cp(a - d) + rt) / Cp(2 * c) for rt in rt_list]
             assert (Cp(c) * tau1**2 + Cp(d - a) * tau1 - Cp(b)) == 0
             assert (Cp(c) * tau2**2 + Cp(d - a) * tau2 - Cp(b)) == 0
             r, s = uk.coordinates_in_terms_of_powers()(K.gen())
             assert r + s * uk == K.gen()
             assert uk.charpoly() == gamma.quaternion_rep.charpoly()
             mtx = r + s * gamma.quaternion_rep
             if mtx.denominator() == 1:
                 break
     set_verbose(verb_level)
     emb = K.hom([mtx])
     mu = emb(w)
     fwrite('# \cO_K to R_0 given by w_K |-> %s' % mu, outfile)
     fwrite('# gamma_psi = %s' % gamma, outfile)
     fwrite('# tau_psi = %s' % tau1, outfile)
     fwrite('# (where g satisfies: %s)' % w.minpoly(), outfile)
     if return_all:
         return gamma, tau1, tau2
     else:
         return gamma, tau1
 def embed_order(self,p,K,prec,outfile = None, return_all = False):
     r'''
     '''
     from limits import find_the_unit_of
     verbose('Computing quadratic embedding to precision %s'%prec)
     verbose('Finding module generators')
     w = module_generators(K)[1]
     verbose('Done')
     w_minpoly = w.minpoly().change_ring(Qp(p,prec))
     Cp = Qp(p,prec).extension(w_minpoly,names = 'g')
     wl = w.list()
     assert len(wl) == 2
     r0 = -wl[0]/wl[1]
     r1 = 1/wl[1]
     assert r0 + r1 * w == K.gen()
     padic_Kgen = Cp(r0)+Cp(r1)*Cp.gen()
     try:
         fwrite('# d_K = %s, h_K = %s, h_K^- = %s'%(K.discriminant(),K.class_number(),len(K.narrow_class_group())),outfile)
     except NotImplementedError: pass
     fwrite('# w_K satisfies: %s'%w.minpoly(),outfile)
     #####
     uk = find_the_unit_of(self.F,K)
     tu = uk.trace()
     verb_level = get_verbose()
     set_verbose(0)
     for g in self.enumerate_elements():
         if g.trace() == tu:
             gamma = self(g)
             a,b,c,d = gamma.quaternion_rep.list()
             rt_list = our_sqrt((d-a)**2 + 4*b*c,Cp,return_all=True)
             tau1, tau2 = [(Cp(a-d) + rt)/Cp(2*c) for rt in rt_list]
             assert (Cp(c)*tau1**2 + Cp(d-a)*tau1-Cp(b)) == 0
             assert (Cp(c)*tau2**2 + Cp(d-a)*tau2-Cp(b)) == 0
             r,s = uk.coordinates_in_terms_of_powers()(K.gen())
             assert r+s*uk == K.gen()
             assert uk.charpoly() == gamma.quaternion_rep.charpoly()
             mtx  = r + s*gamma.quaternion_rep
             if mtx.denominator() == 1:
                 break
     set_verbose(verb_level)
     emb = K.hom([mtx])
     mu = emb(w)
     fwrite('# \cO_K to R_0 given by w_K |-> %s'%mu,outfile)
     fwrite('# gamma_psi = %s'%gamma,outfile)
     fwrite('# tau_psi = %s'%tau1,outfile)
     fwrite('# (where g satisfies: %s)'%w.minpoly(),outfile)
     if return_all:
         return gamma, tau1, tau2
     else:
         return gamma, tau1
Exemple #5
0
def WeightSpace_constructor(p, base_ring=None):
    r"""
    Construct the p-adic weight space for the given prime p.  A `p`-adic weight
    is a continuous character `\ZZ_p^\times \to \CC_p^\times`.
    These are the `\CC_p`-points of a rigid space over `\QQ_p`,
    which is isomorphic to a disjoint union of copies (indexed by
    `(\ZZ/p\ZZ)^\times`) of the open unit `p`-adic disc.

    Note that the "base ring" of a `p`-adic weight is the smallest ring
    containing the image of `\ZZ`; in particular, although the default base
    ring is `\QQ_p`, base ring `\QQ` will also work.

    EXAMPLES::

        sage: pAdicWeightSpace(3) # indirect doctest
        Space of 3-adic weight-characters defined over '3-adic Field with capped relative precision 20'
        sage: pAdicWeightSpace(3, QQ)
        Space of 3-adic weight-characters defined over 'Rational Field'
        sage: pAdicWeightSpace(10)
        Traceback (most recent call last):
        ...
        ValueError: p must be prime
    """
    if base_ring is None:
        base_ring = Qp(p)
    if (p, base_ring) in _wscache:
        m = _wscache[(p, base_ring)]()
        if m is not None:
            return m
    m = WeightSpace_class(p, base_ring)
    _wscache[(p, base_ring)] = weakref.ref(m)
    return m
Exemple #6
0
 def embed(self, q, prec):
     if prec is None:
         return None
     elif prec == -1:
         prec = self._prec
     if self.F == QQ and self.discriminant == 1:
         return set_immutable(q.change_ring(Qp(self.p, prec)))
     else:
         try:
             q = q.coefficient_tuple()
         except AttributeError:
             pass
         I, J, K = self.local_splitting(prec)
         f = self._F_to_local
         return set_immutable((f(q[0]) + f(q[1]) * I + f(q[2]) * J +
                               f(q[3]) * K).change_ring(Qp(self.p, prec)))
Exemple #7
0
    def __init__(self,X,k,prec=None,basis_matrix=None,base_field=None):
        self._k=k
        self._X=X
        self._E=self._X.get_edge_list()
        self._V=self._X.get_vertex_list()

        if prec is None:
            self._prec=None
            if base_field is None:
                try:
                    self._R= X.get_splitting_field()
                except AttributeError:
                    raise ValueError, "It looks like you are not using Magma as backend...and still we don't know how to compute splittings in that case!"
            else:
                pol=X.get_splitting_field().defining_polynomial().factor()[0][0]
                self._R=base_field.extension(pol,pol.variable_name()).absolute_field(name='r')
            self._U=OCVn(self._k-2,self._R)
        else:
            self._prec=prec
            if base_field is None:
                self._R=Qp(self._X._p,prec=prec)
            else:
                self._R=base_field
            self._U=OCVn(self._k-2,self._R,self._k-1)
        self.__rank = self._X.dimension_harmonic_cocycles(self._k)
        if basis_matrix is not None:
            self.__matrix=basis_matrix
            self.__matrix.set_immutable()
            assert self.__rank == self.__matrix.nrows()

        AmbientHeckeModule.__init__(self, self._R, self.__rank, self._X.prime()*self._X.Nplus()*self._X.Nminus(), weight=self._k)
        self._populate_coercion_lists_()
Exemple #8
0
def my_algdep(z,n,prec = None):
    K = z.parent()
    p = K.prime()
    z = p**(-z.valuation(p))*z
    zpows = [K(1)]
    for ii in range(n):
        zpows.append(zpows[ii]*z)

    if prec is None:
        prec = z.precision_absolute()
    field_deg = K.degree()

    M = matrix(Qp(p,prec),field_deg,n+1)
    for ii in range(field_deg):
        for jj in range(n+1):
            M[ii,jj]=O(p^prec)
    for jj in range(n+1):
        V = zpows[jj]._ntl_rep().list()
        for ii in range(len(V)):
            M[ii,jj]+= ZZ(V[ii])+O(p^prec)

    argmax = None
    vmax = -1
    Rx = PolynomialRing(QQ,names = 'x')
    x = Rx.gens()[0]
    for ii in range(field_deg):
        lincomb = gp.lindep(M.row(ii).list())
        lincomb = Rx([lincomb[ii+1].sage() for ii in range(n+1)])
        newval = lincomb.subs(z).valuation()
        if newval > vmax:
            argmax = lincomb
            vmax = newval
    print vmax
    return argmax
Exemple #9
0
 def __init__(self,X,U,prec=None,t=None,R=None,overconvergent=False):
     if(R is None):
         if(not isinstance(U,Integer)):
             self._R=U.base_ring()
         else:
             if(prec is None):
                 prec=100
             self._R=Qp(X._p,prec)
     else:
         self._R=R
     #U is a CoefficientModuleSpace
     if(isinstance(U,Integer)):
         if(t is None):
             if(overconvergent):
                 t=prec-U+1
             else:
                 t=0
         self._U=OCVn(U-2,self._R,U-1+t)
     else:
         self._U=U
     self._X=X
     self._V=self._X.get_vertex_list()
     self._E=self._X.get_edge_list()
     self._prec=self._R.precision_cap()
     self._n=self._U.weight()
     Module.__init__(self,base=self._R)
     self._populate_coercion_lists_()
Exemple #10
0
    def get_embedding(self, prec):
        r"""
        Returns an embedding of the quaternion algebra
        into the algebra of 2x2 matrices with coefficients in `\QQ_p`.

        INPUT:

        - prec -- Integer. The precision of the splitting.

        """
        if prec == -1:
            prec = self._prec
        if self.F == QQ and self.discriminant == 1:
            R = Qp(self.p, prec)
            self._F_to_local = QQ.hom([R(1)])

            def iota(q):
                return q.change_ring(R)

            if prec > self._prec:  # DEBUG
                self._prec = prec
        else:
            I, J, K = self.local_splitting(prec)
            mats = [1, I, J, K]

            def iota(q):
                R = I.parent()
                try:
                    q = q.coefficient_tuple()
                except AttributeError:
                    q = q.list()
                return sum(self._F_to_local(a) * b for a, b in zip(q, mats))

        return iota
Exemple #11
0
    def _compute_padic_splitting(self, prec):
        verbose('Entering compute_padic_splitting')
        prime = self.p
        if self.seed is not None:
            self.magma.eval('SetSeed(%s)' % self.seed)
        R = Qp(prime, prec + 10)  #Zmod(prime**prec) #
        B_magma = self.Gpn._get_B_magma()
        a, b = self.Gpn.B.invariants()
        if self._hardcode_matrices:
            self._II = matrix(R, 2, 2, [1, 0, 0, -1])
            self._JJ = matrix(R, 2, 2, [0, 1, 1, 0])
            goodroot = self.F.gen().minpoly().change_ring(R).roots()[0][0]
            self._F_to_local = self.F.hom([goodroot])
        else:
            verbose('Calling magma pMatrixRing')
            if self.F == QQ:
                _, f = self.magma.pMatrixRing(self.Gpn._Omax_magma,
                                              prime *
                                              self.Gpn._Omax_magma.BaseRing(),
                                              Precision=20,
                                              nvals=2)
                self._F_to_local = QQ.hom([R(1)])
            else:
                _, f = self.magma.pMatrixRing(self.Gpn._Omax_magma,
                                              sage_F_ideal_to_magma(
                                                  self.Gpn._F_magma,
                                                  self.ideal_p),
                                              Precision=20,
                                              nvals=2)
                try:
                    self._goodroot = R(
                        f.Image(B_magma(
                            B_magma.BaseRing().gen(1))).Vector()[1]._sage_())
                except SyntaxError:
                    raise SyntaxError(
                        "Magma has trouble finding local splitting")
                self._F_to_local = None
                for o, _ in self.F.gen().minpoly().change_ring(R).roots():
                    if (o - self._goodroot).valuation() > 5:
                        self._F_to_local = self.F.hom([o])
                        break
                assert self._F_to_local is not None
            verbose('Initializing II,JJ,KK')
            v = f.Image(B_magma.gen(1)).Vector()
            self._II = matrix(R, 2, 2, [v[i + 1]._sage_() for i in xrange(4)])
            v = f.Image(B_magma.gen(2)).Vector()
            self._JJ = matrix(R, 2, 2, [v[i + 1]._sage_() for i in xrange(4)])
            v = f.Image(B_magma.gen(3)).Vector()
            self._KK = matrix(R, 2, 2, [v[i + 1]._sage_() for i in xrange(4)])
            self._II, self._JJ = lift_padic_splitting(self._F_to_local(a),
                                                      self._F_to_local(b),
                                                      self._II, self._JJ,
                                                      prime, prec)
        self.Gn._F_to_local = self._F_to_local
        if not self.use_shapiro():
            self.Gpn._F_to_local = self._F_to_local

        self._KK = self._II * self._JJ
        self._prec = prec
        return self._II, self._JJ, self._KK
 def __init__(self,domain,U,prec = None,t = None,R = None,overconvergent = False):
     if(R is None):
         if not isinstance(U,Integer):
             self._R = U.base_ring()
         else:
             if prec is None:
                 prec = 20
             self._R = Qp(domain._p,prec)
     else:
         self._R = R
     #U is a CoefficientModuleSpace
     if isinstance(U,Integer):
         if t is None:
             if overconvergent:
                 t = prec-U+1
             else:
                 t = 0
         self._U = OCVn(U-2,self._R,U-1+t)
     else:
         self._U = U
     self._source = domain
     self._list = self._source.get_list() # Contains also the opposite edges
     self._prec = self._R.precision_cap()
     self._n = self._U.weight()
     self._p = self._source._p
     Module.__init__(self,base = self._R)
     self._populate_coercion_lists_()
Exemple #13
0
 def embed_matrix(self, q, prec):
     if prec is None:
         return None
     elif prec == -1:
         prec = self._prec
     if self.F == QQ and self.discriminant == 1:
         return set_immutable(q.change_ring(Qp(self.p, prec)))
     else:
         return q.apply_map(self._F_to_local)
Exemple #14
0
def tate_parameter(E, p, prec = 20, R = None):
    if R is None:
        R = Qp(p,prec)
    jE = E.j_invariant()
    E4 = EisensteinForms(weight=4).basis()[0]
    Delta = CuspForms(weight=12).basis()[0]
    j = (E4.q_expansion(prec+3))**3/Delta.q_expansion(prec+3)
    jinv = (1/j).power_series()
    q_in_terms_of_jinv = jinv.reversion()
    return q_in_terms_of_jinv(R(1/E.j_invariant()))
Exemple #15
0
 def embed(self, q, prec):
     if prec is None:
         return None
     elif prec == -1:
         prec = self._prec
     if self.F == QQ and self.discriminant == 1:
         return set_immutable(q.change_ring(Qp(self.p, prec)))
     else:
         if hasattr(q, 'rows'):
             return q.apply_map(self._F_to_local)
         try:
             return self.Gn.quaternion_to_matrix(q).apply_map(
                 self._F_to_local)
         except AttributeError:
             pass
         try:
             q = q.coefficient_tuple()
         except AttributeError:
             q = q.list()
         I, J, K = self.local_splitting(prec)
         f = self._F_to_local
         return set_immutable((f(q[0]) + f(q[1]) * I + f(q[2]) * J +
                               f(q[3]) * K).change_ring(Qp(self.p, prec)))
Exemple #16
0
    def __init__(self, p, base_ring):
        r"""
        Initialisation function.

        EXAMPLES::

            sage: pAdicWeightSpace(17)
            Space of 17-adic weight-characters defined over '17-adic Field with capped relative precision 20'
        """
        ParentWithBase.__init__(self, base=base_ring)
        p = ZZ(p)
        if not p.is_prime():
            raise ValueError("p must be prime")
        self._p = p
        self._param = Qp(p)((p == 2 and 5) or (p + 1))
Exemple #17
0
class HarmonicCocycles(AmbientHeckeModule):
    Element=HarmonicCocycleElement
    r"""
    This object represents a space of Gamma invariant harmonic cocycles valued in
    a cofficient module.

    INPUT:

     - ``X`` - A BTQuotient object
     - ``k`` - integer - The weight.
     - ``prec`` - integer (Default: None). If specified, the precision for the coefficient module
     - ``basis_matrix`` - integer (Default: None)
     - ``base_field`` - (Default: None)

    EXAMPLES:

    ::

    AUTHORS:

    - Cameron Franc (2012-02-20)
    - Marc Masdeu
    """
    def __init__(self,X,k,prec=None,basis_matrix=None,base_field=None):
        self._k=k
        self._X=X
        self._E=self._X.get_edge_list()
        self._V=self._X.get_vertex_list()

        if prec is None:
            self._prec=None
            if base_field is None:
                try:
                    self._R= X.get_splitting_field()
                except AttributeError:
                    raise ValueError, "It looks like you are not using Magma as backend...and still we don't know how to compute splittings in that case!"
            else:
                pol=X.get_splitting_field().defining_polynomial().factor()[0][0]
                self._R=base_field.extension(pol,pol.variable_name()).absolute_field(name='r')
            self._U=OCVn(self._k-2,self._R)
        else:
            self._prec=prec
            if base_field is None:
                self._R=Qp(self._X._p,prec=prec)
            else:
                self._R=base_field
            self._U=OCVn(self._k-2,self._R,self._k-1)
        self.__rank = self._X.dimension_harmonic_cocycles(self._k)
        if basis_matrix is not None:
            self.__matrix=basis_matrix
            self.__matrix.set_immutable()
            assert self.__rank == self.__matrix.nrows()

        AmbientHeckeModule.__init__(self, self._R, self.__rank, self._X.prime()*self._X.Nplus()*self._X.Nminus(), weight=self._k)
        self._populate_coercion_lists_()

    def base_extend(self,base_ring):
        r"""
        This function extends the base ring of the coefficient module.
        
        INPUT:

        - ``base_ring`` - a ring that has a coerce map from the current base ring

        EXAMPLES:

        ::
        """
        if not base_ring.has_coerce_map_from(self.base_ring()):
            raise ValueError, "No coercion defined"
        else:
            return self.change_ring(base_ring)

    def change_ring(self, new_base_ring):
        r"""
        This function changes the base ring of the coefficient module.

        INPUT:

        - ``new_base_ring'' - a ring that has a coerce map from the current base ring

        EXAMPLES:
        ::

        """
        if not new_base_ring.has_coerce_map_from(self.base_ring()):
            raise ValueError, "No coercion defined"
        else:
            return self.__class__(self._X,self._k,prec=self._prec,basis_matrix=self.basis_matrix().change_ring(base_ring),base_field=new_base_ring)

    def rank(self):
        r"""
        The rank (dimension) of ``self``.
        
        EXAMPLES:
        ::

        """
        return self.__rank

    def submodule(self,v,check=False):
        r"""
        Return the submodule of ``self`` spanned by ``v``.

        EXAMPLES:
        """
        return HarmonicCocyclesSubmodule(self,v,dual=None,check=check)

    def is_simple(self):
        r"""
        Whether ``self`` is irreducible.

        EXAMPLES:
        ::

        """
        return self.rank()==1

    def _repr_(self):
        r"""
        This returns the representation of self as a string.
        """
        return 'Space of harmonic cocycles of weight %s on %s'%(self._k,self._X)

    def _latex_(self):
        r"""
        A LaTeX representation of ``self``.

        EXAMPLES:
        ::
        """
        s='\\text{Space of harmonic cocycles of weight }'+latex(self._k)+'\\text{ on }'+latex(self._X)
        return s

    def _an_element_(self):
        r"""

        """
        return self.basis()[0]


    def _coerce_map_from_(self, S):
        r"""
        Can coerce from other HarmonicCocycles or from pAutomorphicForms
        """
        if isinstance(S,(HarmonicCocycles,pAutomorphicForms)):
            if(S._k!=self._k):
                return False
            if(S._X!=self._X):
                return False
            return True
        return False

    def __cmp__(self,other):
        r"""

        """
        try:
            res=(self.base_ring()==other.base_ring() and self._X==other._X and self._k==other._k)
            return res
        except:
            return False

    def _element_constructor_(self,x):
        r"""

        """
        #Code how to coherce x into the space
        #Admissible values of x?
        if isinstance(x,HarmonicCocycleElement):
            return HarmonicCocycleElement(self,x)
        elif isinstance(x,pAutomorphicForm):
            tmp=[self._U.element_class(_parent._U,x._F[ii]).l_act_by(self._E[ii].rep) for ii in range(self._nE)]
            return HarmonicCocycleElement(self,tmp,from_values=True)
        else:
            return HarmonicCocycleElement(self,x)


    def free_module(self):
        r"""
        This function returns the underlying free module

        EXAMPLES:
        ::
        """
        try: return self.__free_module
        except AttributeError: pass
        V = self.base_ring()**self.dimension()
        self.__free_module = V
        return V

    def character(self):
        r"""
        Only implemented the trivial character so far.

        EXAMPLES:

        """
        return lambda x:x

    def embed_quaternion(self,g):
        r"""
        Embed the quaternion element ``g`` into the matrix algebra.

        EXAMPLES:
        ::
        """
        return self._X.embed_quaternion(g,exact = self._R.is_exact(), prec = self._prec)

    def basis_matrix(self):
        r"""
        Returns a basis of ``self`` in matrix form.

        If the coefficient module `M` is of finite rank then the space of Gamma invariant
        `M` valued harmonic cocycles can be represented as a subspace of the finite rank
        space of all functions from the finitely many edges in the corresponding 
        BTQuotient into `M`. This function computes this representation of the space of
        cocycles.

        OUTPUT:

          A basis matrix describing the cocycles in the spaced of all `M` valued Gamma
          invariant functions on the tree.

        EXAMPLES:

        ::

            sage: X = BTQuotient(3,19)
            sage: C = HarmonicCocycles(X,4,prec = 5)
            sage: B = C.basis()
            Traceback (most recent call last):
            ...
            RuntimeError: The computed dimension does not agree with the expectation. Consider increasing precision!

        We try increasing the precision:

        ::

            sage: C = HarmonicCocycles(X,4,prec = 20)
            sage: B = C.basis()
            sage: len(B) == X.dimension_harmonic_cocycles(4)
            True

        AUTHORS:

        - Cameron Franc (2012-02-20)
        - Marc Masdeu (2012-02-20)
        """
        try: return self.__matrix
        except AttributeError: pass
        nV=len(self._V)
        nE=len(self._E)
        stab_conds=[]
        S=self._X.get_edge_stabs()
        p=self._X._p
        d=self._k-1
        for e in self._E:
            try:
                g=filter(lambda g:g[2],S[e.label])[0]
                C=self._U.l_matrix_representation(self.embed_quaternion(g[0]))
                C-=self._U.l_matrix_representation(Matrix(QQ,2,2,p**g[1]))
                stab_conds.append([e.label,C])
            except IndexError: pass

        n_stab_conds=len(stab_conds)
        self._M=Matrix(self._R,(nV+n_stab_conds)*d,nE*d,0,sparse=True)
        for v in self._V:
            for e in filter(lambda e:e.parity==0,v.leaving_edges):
                C=sum([self._U.l_matrix_representation(self.embed_quaternion(x[0])) for x in e.links],Matrix(self._R,d,d,0))
                self._M.set_block(v.label*d,e.label*d,C)
            for e in filter(lambda e:e.parity==0,v.entering_edges):
                C=sum([self._U.l_matrix_representation(self.embed_quaternion(x[0])) for x in e.opposite.links],Matrix(self._R,d,d,0))
                self._M.set_block(v.label*d,e.opposite.label*d,C)

        for kk in range(n_stab_conds):
            v=stab_conds[kk]
            self._M.set_block((nV+kk)*d,v[0]*d,v[1])

        x1=self._M.right_kernel().matrix()

        if x1.nrows() != self.rank():
            raise RuntimeError, 'The computed dimension does not agree with the expectation. Consider increasing precision!'

        K=[c for c in x1.rows()]

        if not self._R.is_exact():
            for ii in range(len(K)):
                s=min([t.valuation() for t in K[ii]])
                for jj in range(len(K[ii])):
                    K[ii][jj]=(p**(-s))*K[ii][jj]

        self.__matrix=Matrix(self._R,len(K),nE*d,K)
        self.__matrix.set_immutable()
        return self.__matrix

    def __apply_atkin_lehner(self,q,f):
        r"""
        This function applies an Atkin-Lehner involution to a harmonic cocycle

        INPUT:

          - ``q`` - an integer dividing the full level p*Nminus*Nplus

          - ``f`` - a harmonic cocycle

        OUTPUT:

          The harmonic cocycle obtained by hitting f with the Atkin-Lehner at q

        EXAMPLES:
        ::
        """
        R=self._R
        Data=self._X._get_atkin_lehner_data(q)
        p=self._X._p
        tmp=[self._U.element_class(self._U,zero_matrix(self._R,self._k-1,1),quick=True) for jj in range(len(self._E))]
        d1=Data[1]
        mga=self.embed_quaternion(Data[0])
        for jj in range(len(self._E)):
            t=d1[jj]
            tmp[jj]+=(t.sign()*f._F[t.label]).l_act_by(p**(-t.power)*mga*t.igamma(self.embed_quaternion))
        return HarmonicCocycleElement(self,tmp,from_values=True)

    def __apply_hecke_operator(self,l,f):
        r"""
        This function applies a Hecke operator to a harmonic cocycle.

        INPUT:

          - ``l`` - an integer

          - ``f`` - a harmonic cocycle

        OUTPUT:

          A harmonic cocycle which is the result of applying the lth Hecke operator
          to f

        EXAMPLES:
        ::

        """
        R=self._R
        HeckeData,alpha=self._X._get_hecke_data(l)
        if(self.level()%l==0):
            factor=QQ(l**(Integer((self._k-2)/2))/(l+1))
        else:
            factor=QQ(l**(Integer((self._k-2)/2)))
        p=self._X._p
        alphamat=self.embed_quaternion(alpha)
        tmp=[self._U.element_class(self._U,zero_matrix(self._R,self._k-1,1),quick=True) for jj in range(len(self._E))]
        for ii in range(len(HeckeData)):
            d1=HeckeData[ii][1]
            mga=self.embed_quaternion(HeckeData[ii][0])*alphamat
            for jj in range(len(self._E)):
                t=d1[jj]
                tmp[jj]+=(t.sign()*f._F[t.label]).l_act_by(p**(-t.power)*mga*t.igamma(self.embed_quaternion))
        return HarmonicCocycleElement(self,[factor*x for x in tmp],from_values=True)

    def _compute_atkin_lehner_matrix(self,d):
        r"""
        When the underlying coefficient module is finite, this function computes the 
        matrix of an Atkin-Lehner involution in the basis provided by the function
        basis_matrix

        INPUT:

          - ``d`` - an integer dividing p*Nminus*Nplus

        OUTPUT:

          The matrix of the AL-involution at d in the basis given by self.basis_matrix

        EXAMPLES:
        ::

        """
        res=self.__compute_operator_matrix(lambda f:self.__apply_atkin_lehner(d,f))
        return res

    def _compute_hecke_matrix_prime(self,l):
        r"""
        When the underlying coefficient module is finite, this function computes the 
        matrix of a (prime) Hecke operator in the basis provided by the function
        basis_matrix

        INPUT:

          - ``l`` - an integer prime

        OUTPUT:

          The matrix of T_l acting on the cocycles in the basis given by 
          self.basis_matrix

        EXAMPLES:
        ::

        """
        res=self.__compute_operator_matrix(lambda f:self.__apply_hecke_operator(l,f))
        return res

    def __compute_operator_matrix(self,T):
        r"""
        Compute the matrix of the operator ``T``.

        EXAMPLES:
        ::

        """
        R=self._R
        A=self.basis_matrix().transpose()
        basis=self.basis()
        B=zero_matrix(R,len(self._E)*(self._k-1),self.dimension())
        for rr in range(len(basis)):
            g=T(basis[rr])
            B.set_block(0,rr,Matrix(R,len(self._E)*(self._k-1),1,[g._F[e]._val[ii,0]  for e in range(len(self._E)) for ii in range(self._k-1) ]))

        try:
            res=(A.solve_right(B)).transpose()
            res.set_immutable()
            return res
        except ValueError:
            print A
            print B
            raise ValueError
Exemple #18
0
class pAutomorphicForms(Module):
    Element=pAutomorphicForm
    r"""
    The module of (quaternionic) `p`-adic automorphic forms.

    EXAMPLES:

    ::


    AUTHORS:

    - Cameron Franc (2012-02-20)
    - Marc Masdeu (2012-02-20)
    """
    def __init__(self,X,U,prec=None,t=None,R=None,overconvergent=False):
        if(R is None):
            if(not isinstance(U,Integer)):
                self._R=U.base_ring()
            else:
                if(prec is None):
                    prec=100
                self._R=Qp(X._p,prec)
        else:
            self._R=R
        #U is a CoefficientModuleSpace
        if(isinstance(U,Integer)):
            if(t is None):
                if(overconvergent):
                    t=prec-U+1
                else:
                    t=0
            self._U=OCVn(U-2,self._R,U-1+t)
        else:
            self._U=U
        self._X=X
        self._V=self._X.get_vertex_list()
        self._E=self._X.get_edge_list()
        self._prec=self._R.precision_cap()
        self._n=self._U.weight()
        Module.__init__(self,base=self._R)
        self._populate_coercion_lists_()

    def _repr_(self):
        r"""
        This returns the representation of self as a string.

        EXAMPLES:

        This example illustrates ...

        ::
        """
        s='Space of automorphic forms on '+str(self._X)+' with values in '+str(self._U)
        return s

    def _coerce_map_from_(self, S):
        r"""
        Can coerce from other HarmonicCocycles or from pAutomorphicForms
        """
        if(isinstance(S,HarmonicCocycles)):
            if(S._k-2!=self._n):
                return False
            if(S._X!=self._X):
                return False
            return True
        if(isinstance(S,pAutomorphicForms)):
            if(S._n!=self._n):
                return False
            if(S._X!=self._X):
                return False
            return True
        return False

    def _element_constructor_(self,x):
        r"""
        """
        #Code how to coherce x into the space
        #Admissible values of x?
        if isinstance(x,(HarmonicCocycleElement,pAutomorphicForm)):
            return pAutomorphicForm(self,x)

    def _an_element_(self):
        r"""
        Returns an element of the module.
        """
        return pAutomorphicForm(self,1)

    def embed_quaternion(self,g):
        r"""
        Returns the image of ``g`` under the embedding
        of the quaternion algebra into 2x2 matrices.
        """
        return self._X.embed_quaternion(g,prec = self._prec)

    def lift(self,f, verbose = True):
        r"""
        Lifts the harmonic cocycle ``f`` to an
        overconvegent automorphic form, thus computing
        all the moments.
        """
        F=self.element_class(self,f)
        F.improve(verbose = verbose)
        return F

    def _apply_Up_operator(self,f,scale=False, fix_lowdeg_terms = True):
        r"""
        Apply the Up operator to ``f``.

        EXAMPLES:

        ::
            sage: X = BTQuotient(3,11)
            sage: M = HarmonicCocycles(X,4,30)
            sage: A = pAutomorphicForms(X,4,10, overconvergent = True)
            sage: F = A.lift(M.basis()[0], verbose = False); F
            p-adic automorphic form on Space of automorphic forms on Quotient of the Bruhat T**s tree of GL_2(QQ_3) with discriminant 11 and level 1 with values in Overconvergent coefficient module of weight n=2 over the ring 3-adic Field with capped relative precision 10 and depth 10:
            e   |   c(e)
            0 | 3^2 + O(3^12) + O(3^32)*z + O(3^26)*z^2 + (2*3^2 + 3^3 + 2*3^5 + 3^7 + 3^8 + 2*3^9 + O(3^10))*z^3 + (2*3^5 + 2*3^6 + 2*3^7 + 3^9 + O(3^10))*z^4 + (3^2 + 3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + O(3^10))*z^5 + (3^2 + 2*3^3 + 3^4 + 2*3^6 + O(3^10))*z^6 + (2*3^3 + 3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 3^8 + 3^9 + O(3^10))*z^7 + (3^2 + 3^3 + 2*3^6 + 3^7 + 3^8 + 3^9 + O(3^10))*z^8 + (2*3^2 + 2*3^3 + 2*3^5 + 2*3^7 + 3^8 + 2*3^9 + O(3^10))*z^9
            1 | 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12) + (3^2 + O(3^12))*z + (2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12))*z^2 + (2*3^2 + 2*3^3 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + O(3^10))*z^3 + (2*3^3 + 3^5 + 3^7 + 3^8 + O(3^10))*z^4 + (2*3^3 + 3^6 + 3^7 + 3^9 + O(3^10))*z^5 + (3^3 + 2*3^4 + 2*3^5 + 2*3^7 + 3^8 + 3^9 + O(3^10))*z^6 + (3^7 + 2*3^8 + 2*3^9 + O(3^10))*z^7 + (3^3 + 2*3^4 + 3^7 + O(3^10))*z^8 + (2*3^2 + 3^4 + 3^6 + 2*3^7 + 3^8 + 2*3^9 + O(3^10))*z^9
            2 | 3^2 + 2*3^3 + 2*3^6 + 3^7 + 2*3^8 + O(3^12) + (3 + 2*3^2 + 2*3^3 + 3^5 + 2*3^6 + 3^7 + 3^10 + O(3^11))*z + (2*3 + 2*3^2 + 3^4 + 2*3^5 + 2*3^6 + 2*3^8 + 3^10 + O(3^11))*z^2 + (2*3 + 3^2 + 2*3^7 + 3^9 + O(3^10))*z^3 + (3 + 2*3^2 + 2*3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + O(3^10))*z^4 + (3 + 3^2 + 3^4 + 2*3^9 + O(3^10))*z^5 + (3^3 + 2*3^5 + 3^6 + 3^8 + 2*3^9 + O(3^10))*z^6 + (3^5 + 2*3^7 + 3^9 + O(3^10))*z^7 + (2*3 + 3^3 + 3^4 + 2*3^6 + O(3^10))*z^8 + (2*3 + 2*3^3 + 2*3^4 + 2*3^6 + O(3^10))*z^9
            3 | 3^2 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12) + (3^3 + 2*3^4 + 2*3^8 + O(3^13))*z + (3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^9 + 2*3^10 + O(3^11))*z^2 + (3^2 + 2*3^3 + 3^4 + 3^7 + 3^8 + 2*3^9 + O(3^10))*z^3 + (3 + 2*3^2 + 2*3^3 + 3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 3^8 + O(3^10))*z^4 + (3 + 3^3 + 3^4 + 2*3^5 + 2*3^6 + 3^7 + 2*3^8 + 2*3^9 + O(3^10))*z^5 + (3 + 3^4 + 3^5 + 3^6 + 2*3^7 + O(3^10))*z^6 + (2*3 + 3^2 + 2*3^3 + 3^4 + 2*3^6 + 3^8 + 3^9 + O(3^10))*z^7 + (3 + 3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 3^7 + 2*3^9 + O(3^10))*z^8 + (2*3^2 + 3^4 + 3^5 + 3^8 + 3^9 + O(3^10))*z^9

        """
        HeckeData=self._X._get_Up_data()
        if scale == False:
            factor=(self._X._p)**(self._U.weight()/2)
        else:
            factor=1
        Tf=[]
        for jj in range(2*len(self._E)):
            tmp=self._U(0)
            for d in HeckeData:
                gg=d[0] # acter
                u=d[1][jj] # edge_list[jj]
                r=self._X._p**(-(u.power))*(u.t()*gg)
                tmp+=f._F[u.label+u.parity*len(self._E)].r_act_by(r)
            tmp *= factor
            for ii in range(self._n+1):
                tmp[ii] = f._F[jj][ii]
            Tf.append(tmp)
        return pAutomorphicForm(self,Tf,quick=True)
Exemple #19
0
    def simplify(self, x, error=None, force=False, size_heuristic_bound=32):
        r"""
        Return a simplified version of ``x``.

        Produce an element which differs from ``x`` by an element of
        valuation strictly greater than the valuation of ``x`` (or strictly
        greater than ``error`` if set.)

        INPUT:

        - ``x`` -- an element in the domain of this valuation

        - ``error`` -- a rational, infinity, or ``None`` (default: ``None``),
          the error allowed to introduce through the simplification

        - ``force`` -- ignored

        - ``size_heuristic_bound` -- when ``force`` is not set, the expected
          factor by which the ``x`` need to shrink to perform an actual
          simplification (default: 32)

        EXAMPLES::

            sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone
            sage: v = pAdicValuation(ZZ, 2)
            sage: v.simplify(6, force=True)
            2
            sage: v.simplify(6, error=0, force=True)
            0

        """
        if not force and self._relative_size(x) <= size_heuristic_bound:
            return x

        x = self.domain().coerce(x)

        v = self(x)
        if error is None:
            error = v
        from sage.rings.all import infinity
        if error is infinity:
            return x
        if error < v:
            return self.domain().zero()
        from sage.rings.all import QQ
        error = QQ(error).ceil()
        
        from sage.rings.all import Qp
        precision_ring = Qp(self.p(), error + 1 - v)
        reduced = precision_ring(x)
        if error - v >= 5:
            # If there is not much relative precision left, it is better to
            # just go with the integer/rational lift. The rational
            # reconstruction is likely not smaller.
            try:
                reconstruction = reduced.rational_reconstruction()
                if reconstruction in self.domain():
                    return self.domain()(reconstruction)
            except ArithmeticError:pass
        
        return self.domain()(reduced.lift())
class pAutomorphicForms(Module):
    Element = pAutomorphicFormElement
    r"""
    The module of (quaternionic) `p`-adic automorphic forms.

    EXAMPLES::

    AUTHORS:

    - Cameron Franc (2012-02-20)
    - Marc Masdeu (2012-02-20)
    """
    def __init__(self,domain,U,prec = None,t = None,R = None,overconvergent = False):
        if(R is None):
            if not isinstance(U,Integer):
                self._R = U.base_ring()
            else:
                if prec is None:
                    prec = 20
                self._R = Qp(domain._p,prec)
        else:
            self._R = R
        #U is a CoefficientModuleSpace
        if isinstance(U,Integer):
            if t is None:
                if overconvergent:
                    t = prec-U+1
                else:
                    t = 0
            self._U = OCVn(U-2,self._R,U-1+t)
        else:
            self._U = U
        self._source = domain
        self._list = self._source.get_list() # Contains also the opposite edges
        self._prec = self._R.precision_cap()
        self._n = self._U.weight()
        self._p = self._source._p
        Module.__init__(self,base = self._R)
        self._populate_coercion_lists_()

    def prime(self):
        return self._p

    def _repr_(self):
        r"""
        This returns the representation of self as a string.

        EXAMPLES::
        """
        s = 'Space of automorphic forms on '+str(self._source)+' with values in '+str(self._U)
        return s

    def _coerce_map_from_(self, S):
        r"""
        Can coerce from other HarmonicCocycles or from pAutomorphicForms
        """
        if isinstance(S,HarmonicCocycles):
            if S.weight()-2 != self._n:
                return False
            if S._source != self._source:
                return False
            return True
        if isinstance(S,pAutomorphicForms):
            if S._n != self._n:
                return False
            if S._source != self._source:
                return False
            return True
        return False

    def _element_constructor_(self,x):
        r"""
        """
        #Code how to coherce x into the space
        #Admissible values of x?
        if isinstance(x,(HarmonicCocycleElement,pAutomorphicFormElement)):
            return pAutomorphicFormElement(self,x)

    def _an_element_(self):
        r"""
        Returns an element of the module.
        """
        return pAutomorphicFormElement(self,1)

    def lift(self,f, verbose = True):
        r"""
        Lifts the harmonic cocycle ``f`` to an
        overconvegent automorphic form, thus computing
        all the moments.
        """
        F = self.element_class(self,f)
        F.improve(verbose = verbose)
        return F

    def _make_invariant(self, F):
        r"""
        EXAMPLES::
        """
        S = self._source.get_stabilizers()
        M  = [e.rep for e in self._list]
        coeff_module_class = self._U.element_class
        newF = []
        for ii in range(len(S)):
            Si = S[ii]
            x = coeff_module_class(F[ii].parent(),F[ii]._val,quick = True)
            if(any([v[2] for v in Si])):
                newFi = coeff_module_class(F[ii].parent(),0)
                s = QQ(0)
                m = M[ii]
                for v in Si:
                    s += 1
                    # self._source should has a embed method that, given stabilizers,
                    # returns 2x2 matrices that can act on the distributions.
                    newFi  +=  x.r_act_by(m.adjoint()*self._source.embed(v[0],prec = self._prec)*m)
                newF.append((1/s)*newFi)
            else:
                newF.append(x)
        return newF

    def _apply_Up_operator(self,f,scale = False):
        r"""
        Apply the Up operator to ``f``.

        EXAMPLES::

            sage: X = BTQuotient(3,11)
            sage: M = HarmonicCocycles(X,4,20)
            sage: A = pAutomorphicForms(X,4,10, overconvergent = True)
            sage: F = A.lift(M.basis()[0], verbose = False)
            sage: print F.values()
            [3^2 + O(3^12) + O(3^22)*z + O(3^16)*z^2 + (2*3^2 + O(3^10))*z^3 + (3^4 + O(3^10))*z^4 + (3^2 + 3^3 + O(3^10))*z^5 + (3^2 + 2*3^3 + 2*3^4 + O(3^10))*z^6 + (2*3^3 + O(3^10))*z^7 + (3^2 + 3^3 + 2*3^4 + 3^5 + O(3^10))*z^8 + (2*3^2 + 2*3^3 + O(3^10))*z^9, 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12) + (3^2 + O(3^12))*z + (2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12))*z^2 + (2*3^2 + 3^4 + 3^6 + 3^8 + O(3^10))*z^3 + (3^4 + 2*3^5 + 2*3^6 + 3^8 + 2*3^9 + O(3^10))*z^4 + (3^3 + 2*3^4 + 2*3^7 + 3^8 + O(3^10))*z^5 + (2*3^4 + 2*3^6 + 3^7 + 3^8 + 2*3^9 + O(3^10))*z^6 + (3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 3^9 + O(3^10))*z^7 + (2*3^4 + 3^7 + O(3^10))*z^8 + (2*3^2 + 3^6 + 2*3^7 + 2*3^8 + O(3^10))*z^9, 3^2 + 2*3^3 + 2*3^6 + 3^7 + 2*3^8 + O(3^12) + (3 + 2*3^2 + 2*3^3 + 3^5 + 2*3^6 + 3^7 + 3^10 + O(3^11))*z + (2*3 + 2*3^2 + 3^4 + 2*3^5 + 2*3^6 + 2*3^8 + 3^10 + O(3^11))*z^2 + (2*3 + 3^2 + 3^4 + 3^5 + 2*3^7 + 2*3^8 + O(3^10))*z^3 + (3 + 2*3^2 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + O(3^10))*z^4 + (3 + 3^2 + 3^4 + 2*3^5 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + O(3^10))*z^5 + (3^3 + 3^4 + 3^7 + O(3^10))*z^6 + (2*3^4 + 3^5 + 3^6 + 2*3^9 + O(3^10))*z^7 + (2*3 + 3^3 + 3^5 + 3^6 + 3^7 + 3^8 + 3^9 + O(3^10))*z^8 + (2*3 + 2*3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + O(3^10))*z^9, 3^2 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12) + (3^3 + 2*3^4 + 2*3^8 + O(3^12))*z + (3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 2*3^9 + O(3^10))*z^2 + (3^2 + 2*3^3 + 3^4 + 3^5 + 2*3^8 + 3^9 + O(3^10))*z^3 + (3 + 2*3^2 + 2*3^3 + 3^4 + 2*3^5 + 2*3^9 + O(3^10))*z^4 + (3 + 3^3 + 2*3^4 + 2*3^5 + 2*3^7 + 3^8 + 3^9 + O(3^10))*z^5 + (3 + 3^4 + 3^5 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + O(3^10))*z^6 + (2*3 + 3^2 + 2*3^3 + 2*3^5 + 3^7 + 3^8 + 3^9 + O(3^10))*z^7 + (3 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 3^7 + 3^9 + O(3^10))*z^8 + (2*3^2 + 3^4 + 2*3^5 + 2*3^6 + 3^7 + 2*3^8 + O(3^10))*z^9]
        """
        HeckeData = self._source._get_Up_data()
        if scale == False:
            factor = (self._p)**(self._n/2)
        else:
            factor = 1
        Tf = []
        for jj in range(len(self._list)):
            tmp = self._U(0)
            for d in HeckeData:
                gg = d[0] # acter
                u = d[1][jj] # edge_list[jj]
                r = self._p**(-u.power) * (u.t(2*self._prec+1)*gg)
                tmp += f._value[u.label].r_act_by(r)
            tmp  *=  factor
            for ii in range(self._n+1):
                tmp[ii] = f._value[jj][ii]
            Tf.append(tmp)
        return pAutomorphicFormElement(self,Tf,quick = True)
Exemple #21
0
def darmon_point(P,
                 E,
                 beta,
                 prec,
                 ramification_at_infinity=None,
                 input_data=None,
                 magma=None,
                 working_prec=None,
                 recognize_point=True,
                 **kwargs):
    r'''

    EXAMPLES:

    We first need to import the module::

    sage: from darmonpoints.darmonpoints import darmon_point

    A first example (Stark--Heegner point)::

    sage: from darmonpoints.darmonpoints import darmon_point
    sage: darmon_point(7,EllipticCurve('35a1'),41,20, cohomological=False, use_magma=False, use_ps_dists = True)
    Starting computation of the Darmon point
    ...
    (-70*alpha + 449 : 2100*alpha - 13444 : 1)

    A quaternionic (Greenberg) point::

    sage: darmon_point(13,EllipticCurve('78a1'),5,20) # long time # optional - magma

    A Darmon point over a cubic (1,1) field::

    sage: F.<r> = NumberField(x^3 - x^2 - x + 2)
    sage: E = EllipticCurve([-r -1, -r, -r - 1,-r - 1, 0])
    sage: N = E.conductor()
    sage: P = F.ideal(r^2 - 2*r - 1)
    sage: beta = -3*r^2 + 9*r - 6
    sage: darmon_point(P,E,beta,20) # long time # optional - magma

    '''
    # global G, Coh, phiE, Phi, dK, J, J1, cycleGn, nn, Jlist

    config = ConfigParser.ConfigParser()
    config.read('config.ini')
    param_dict = config_section_map(config, 'General')
    param_dict.update(config_section_map(config, 'DarmonPoint'))
    param_dict.update(kwargs)
    param = Bunch(**param_dict)

    # Get general parameters
    outfile = param.get('outfile')
    use_ps_dists = param.get('use_ps_dists', False)
    use_shapiro = param.get('use_shapiro', False)
    use_sage_db = param.get('use_sage_db', False)
    magma_seed = param.get('magma_seed', 1515316)
    parallelize = param.get('parallelize', False)
    Up_method = param.get('up_method', 'naive')
    use_magma = param.get('use_magma', True)
    progress_bar = param.get('progress_bar', True)
    sign_at_infinity = param.get('sign_at_infinity', ZZ(1))

    # Get darmon_point specific parameters
    idx_orientation = param.get('idx_orientation')
    idx_embedding = param.get('idx_embedding', 0)
    algorithm = param.get('algorithm')
    quaternionic = param.get('quaternionic')
    cohomological = param.get('cohomological', True)

    if Up_method == "bigmatrix" and use_shapiro == True:
        import warnings
        warnings.warn(
            'Use of "bigmatrix" for Up iteration is incompatible with Shapiro Lemma trick. Using "naive" method for Up.'
        )
        Up_method = 'naive'

    if working_prec is None:
        working_prec = max([2 * prec + 10, 30])

    if use_magma:
        page_path = os.path.dirname(__file__) + '/KleinianGroups-1.0/klngpspec'
        if magma is None:
            from sage.interfaces.magma import Magma
            magma = Magma()
            quit_when_done = True
        else:
            quit_when_done = False
        magma.attach_spec(page_path)
    else:
        quit_when_done = False

    sys.setrecursionlimit(10**6)

    F = E.base_ring()
    beta = F(beta)
    DB, Np, Ncartan = get_heegner_params(P, E, beta)
    if quaternionic is None:
        quaternionic = (DB != 1)
    if cohomological is None:
        cohomological = quaternionic
    if quaternionic and not cohomological:
        raise ValueError(
            "Need cohomological algorithm when dealing with quaternions")
    if use_ps_dists is None:
        use_ps_dists = False if cohomological else True
    try:
        p = ZZ(P)
    except TypeError:
        p = ZZ(P.norm())
    if not p.is_prime():
        raise ValueError('P (= %s) should be a prime, of inertia degree 1' % P)

    if F == QQ:
        dK = ZZ(beta)
        extra_conductor_sq = dK / fundamental_discriminant(dK)
        assert ZZ(extra_conductor_sq).is_square()
        extra_conductor = extra_conductor_sq.sqrt()
        dK = dK / extra_conductor_sq
        assert dK == fundamental_discriminant(dK)
        if dK % 4 == 0:
            dK = ZZ(dK / 4)
        beta = dK
    else:
        dK = beta

    # Compute the completion of K at p
    x = QQ['x'].gen()
    K = F.extension(x * x - dK, names='alpha')
    if F == QQ:
        dK = K.discriminant()
    else:
        dK = K.relative_discriminant()

    hK = K.class_number()

    sgninfty = 'plus' if sign_at_infinity == 1 else 'minus'
    if hasattr(E, 'cremona_label'):
        Ename = E.cremona_label()
    elif hasattr(E, 'ainvs'):
        Ename = E.ainvs()
    else:
        Ename = 'unknown'
    fname = 'moments_%s_%s_%s_%s.sobj' % (P, Ename, sgninfty, prec)

    if use_sage_db:
        print("Moments will be stored in database as %s" % (fname))

    if outfile == 'log':
        outfile = '%s_%s_%s_%s_%s_%s.log' % (
            P, Ename, dK, sgninfty, prec,
            datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
        outfile = outfile.replace('/', 'div')
        outfile = '/tmp/darmonpoint_' + outfile

    fwrite("Starting computation of the Darmon point", outfile)
    fwrite('D_B = %s  %s' % (DB, factor(DB)), outfile)
    fwrite('Np = %s' % Np, outfile)
    if Ncartan is not None:
        fwrite('Ncartan = %s' % Ncartan, outfile)
    fwrite('dK = %s (class number = %s)' % (dK, hK), outfile)
    fwrite('Calculation with p = %s and prec = %s' % (P, prec), outfile)
    fwrite('Elliptic curve %s: %s' % (Ename, E), outfile)
    if outfile is not None:
        print("Partial results will be saved in %s" % outfile)

    if input_data is None:
        if cohomological:
            # Define the S-arithmetic group
            if F != QQ and ramification_at_infinity is None:
                if F.signature()[0] > 1:
                    if F.signature()[1] == 1:
                        ramification_at_infinity = F.real_places(
                            prec=Infinity)  # Totally 'definite'
                    else:
                        raise ValueError(
                            'Please specify the ramification at infinity')
                elif F.signature()[0] == 1:
                    if len(F.ideal(DB).factor()) % 2 == 0:
                        ramification_at_infinity = []  # Split at infinity
                    else:
                        ramification_at_infinity = F.real_places(
                            prec=Infinity)  # Ramified at infinity
                else:
                    ramification_at_infinity = None
            if F == QQ:
                abtuple = QuaternionAlgebra(DB).invariants()
            else:
                abtuple = quaternion_algebra_invariants_from_ramification(
                    F, DB, ramification_at_infinity, magma=magma)

            G = BigArithGroup(P,
                              abtuple,
                              Np,
                              base=F,
                              outfile=outfile,
                              seed=magma_seed,
                              use_sage_db=use_sage_db,
                              magma=magma,
                              use_shapiro=use_shapiro,
                              nscartan=Ncartan)

            # Define the cycle ( in H_1(G,Div^0 Hp) )
            Coh = ArithCoh(G)
            while True:
                try:
                    cycleGn, nn, ell = construct_homology_cycle(
                        p,
                        G.Gn,
                        beta,
                        working_prec,
                        lambda q: Coh.hecke_matrix(q).minpoly(),
                        outfile=outfile,
                        elliptic_curve=E)
                    break
                except PrecisionError:
                    working_prec *= 2
                    verbose(
                        'Encountered precision error, trying with higher precision (= %s)'
                        % working_prec)
                except ValueError:
                    fwrite(
                        'ValueError occurred when constructing homology cycle. Returning the S-arithmetic group.',
                        outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
                except AssertionError as e:
                    fwrite(
                        'Assertion occurred when constructing homology cycle. Returning the S-arithmetic group.',
                        outfile)
                    fwrite('%s' % str(e), outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
            eisenstein_constant = -ZZ(E.reduction(ell).count_points())
            fwrite(
                'r = %s, so a_r(E) - r - 1 = %s' % (ell, eisenstein_constant),
                outfile)
            fwrite('exponent = %s' % nn, outfile)
            phiE = Coh.get_cocycle_from_elliptic_curve(E,
                                                       sign=sign_at_infinity)
            if hasattr(E, 'ap'):
                sign_ap = E.ap(P)
            else:
                try:
                    sign_ap = ZZ(P.norm() + 1 - E.reduction(P).count_points())
                except ValueError:
                    sign_ap = ZZ(P.norm() + 1 - Curve(E).change_ring(
                        P.residue_field()).count_points(1)[0])

            Phi = get_overconvergent_class_quaternionic(
                P,
                phiE,
                G,
                prec,
                sign_at_infinity,
                sign_ap,
                use_ps_dists=use_ps_dists,
                use_sage_db=use_sage_db,
                parallelize=parallelize,
                method=Up_method,
                progress_bar=progress_bar,
                Ename=Ename)
            # Integration with moments
            tot_time = walltime()
            J = integrate_H1(G,
                             cycleGn,
                             Phi,
                             1,
                             method='moments',
                             prec=working_prec,
                             parallelize=parallelize,
                             twist=True,
                             progress_bar=progress_bar)
            verbose('integration tot_time = %s' % walltime(tot_time))
            if use_sage_db:
                G.save_to_db()
        else:  # not cohomological
            nn = 1
            eisenstein_constant = 1
            if algorithm is None:
                if Np == 1:
                    algorithm = 'darmon_pollack'
                else:
                    algorithm = 'guitart_masdeu'
            w = K.maximal_order().ring_generators()[0]
            r0, r1 = w.coordinates_in_terms_of_powers()(K.gen())
            QQp = Qp(p, working_prec)
            Cp = QQp.extension(w.minpoly().change_ring(QQp), names='g')
            v0 = K.hom([r0 + r1 * Cp.gen()])

            # Optimal embeddings of level one
            fwrite("Computing optimal embeddings of level one...", outfile)
            Wlist = find_optimal_embeddings(K,
                                            use_magma=use_magma,
                                            extra_conductor=extra_conductor)
            fwrite("Found %s such embeddings." % len(Wlist), outfile)
            if idx_embedding is not None:
                if idx_embedding >= len(Wlist):
                    fwrite(
                        'There are not enough embeddings. Taking the index modulo %s'
                        % len(Wlist), outfile)
                    idx_embedding = idx_embedding % len(Wlist)
                fwrite('Taking only embedding number %s' % (idx_embedding),
                       outfile)
                Wlist = [Wlist[idx_embedding]]

            # Find the orientations
            orients = K.maximal_order().ring_generators()[0].minpoly().roots(
                Zmod(Np), multiplicities=False)
            fwrite("Possible orientations: %s" % orients, outfile)
            if len(Wlist) == 1 or idx_orientation == -1:
                fwrite("Using all orientations, since hK = 1", outfile)
                chosen_orientation = None
            else:
                fwrite("Using orientation = %s" % orients[idx_orientation],
                       outfile)
                chosen_orientation = orients[idx_orientation]

            emblist = []
            for i, W in enumerate(Wlist):
                tau, gtau, sign, limits = find_tau0_and_gtau(
                    v0,
                    Np,
                    W,
                    algorithm=algorithm,
                    orientation=chosen_orientation,
                    extra_conductor=extra_conductor)
                fwrite(
                    'n_evals = %s' % sum(
                        (num_evals(t1, t2) for t1, t2 in limits)), outfile)
                emblist.append((tau, gtau, sign, limits))

            # Get the cohomology class from E
            Phi = get_overconvergent_class_matrices(P,
                                                    E,
                                                    prec,
                                                    sign_at_infinity,
                                                    use_ps_dists=use_ps_dists,
                                                    use_sage_db=use_sage_db,
                                                    parallelize=parallelize,
                                                    progress_bar=progress_bar)

            J = 1
            Jlist = []
            for i, emb in enumerate(emblist):
                fwrite(
                    "Computing %s-th period, attached to the embedding: %s" %
                    (i, Wlist[i].list()), outfile)
                tau, gtau, sign, limits = emb
                n_evals = sum((num_evals(t1, t2) for t1, t2 in limits))
                fwrite(
                    "Computing one period...(total of %s evaluations)" %
                    n_evals, outfile)
                newJ = prod((double_integral_zero_infty(Phi, t1, t2)
                             for t1, t2 in limits))**ZZ(sign)
                Jlist.append(newJ)
                J *= newJ
    else:  # input_data is not None
        Phi, J = input_data[1:3]
    fwrite('Integral done. Now trying to recognize the point', outfile)
    fwrite('J_psi = %s' % J, outfile)
    fwrite('g belongs to %s' % J.parent(), outfile)
    #Try to recognize a generator
    if quaternionic:
        local_embedding = G.base_ring_local_embedding(working_prec)
        twopowlist = [
            4, 3, 2, 1,
            QQ(1) / 2,
            QQ(3) / 2,
            QQ(1) / 3,
            QQ(2) / 3,
            QQ(1) / 4,
            QQ(3) / 4,
            QQ(5) / 2,
            QQ(4) / 3
        ]
    else:
        local_embedding = Qp(p, working_prec)
        twopowlist = [
            4, 3, 2, 1,
            QQ(1) / 2,
            QQ(3) / 2,
            QQ(1) / 3,
            QQ(2) / 3,
            QQ(1) / 4,
            QQ(3) / 4,
            QQ(5) / 2,
            QQ(4) / 3
        ]

    known_multiple = QQ(
        nn * eisenstein_constant
    )  # It seems that we are not getting it with present algorithm.
    while known_multiple % p == 0:
        known_multiple = ZZ(known_multiple / p)

    if not recognize_point:
        fwrite('known_multiple = %s' % known_multiple, outfile)
        if quit_when_done:
            magma.quit()
        return J, Jlist

    candidate, twopow, J1 = recognize_J(E,
                                        J,
                                        K,
                                        local_embedding=local_embedding,
                                        known_multiple=known_multiple,
                                        twopowlist=twopowlist,
                                        prec=prec,
                                        outfile=outfile)

    if candidate is not None:
        HCF = K.hilbert_class_field(names='r1') if hK > 1 else K
        if hK == 1:
            try:
                verbose('candidate = %s' % candidate)
                Ptsmall = E.change_ring(HCF)(candidate)
                fwrite('twopow = %s' % twopow, outfile)
                fwrite(
                    'Computed point:  %s * %s * %s' %
                    (twopow, known_multiple, Ptsmall), outfile)
                fwrite('(first factor is not understood, second factor is)',
                       outfile)
                fwrite(
                    '(r satisfies %s = 0)' %
                    (Ptsmall[0].parent().gen().minpoly()), outfile)
                fwrite('================================================',
                       outfile)
                if quit_when_done:
                    magma.quit()
                return Ptsmall
            except (TypeError, ValueError):
                verbose("Could not recognize the point.")
        else:
            verbose('candidate = %s' % candidate)
            fwrite('twopow = %s' % twopow, outfile)
            fwrite(
                'Computed point:  %s * %s * (x,y)' % (twopow, known_multiple),
                outfile)
            fwrite('(first factor is not understood, second factor is)',
                   outfile)
            try:
                pols = [HCF(c).relative_minpoly() for c in candidate[:2]]
            except AttributeError:
                pols = [HCF(c).minpoly() for c in candidate[:2]]
            fwrite('Where x satisfies %s' % pols[0], outfile)
            fwrite('and y satisfies %s' % pols[1], outfile)
            fwrite('================================================', outfile)
            if quit_when_done:
                magma.quit()
            return candidate
    else:
        fwrite('================================================', outfile)
        if quit_when_done:
            magma.quit()
        return []
Exemple #22
0
def darmon_point(P, E, beta, prec, ramification_at_infinity = None, input_data = None, magma = None, working_prec = None, **kwargs):
    r'''

    EXAMPLES:

    We first need to import the module::

    sage: from darmonpoints.darmonpoints import darmon_point

    A first example (Stark--Heegner point)::

    sage: from darmonpoints.darmonpoints import darmon_point
    sage: darmon_point(7,EllipticCurve('35a1'),41,20, cohomological=False, use_magma=False, use_ps_dists = True)
    Starting computation of the Darmon point
    ...
    (-70*alpha + 449 : 2100*alpha - 13444 : 1)

    A quaternionic (Greenberg) point::

    sage: darmon_point(13,EllipticCurve('78a1'),5,20) # long time # optional - magma

    A Darmon point over a cubic (1,1) field::

    sage: F.<r> = NumberField(x^3 - x^2 - x + 2)
    sage: E = EllipticCurve([-r -1, -r, -r - 1,-r - 1, 0])
    sage: N = E.conductor()
    sage: P = F.ideal(r^2 - 2*r - 1)
    sage: beta = -3*r^2 + 9*r - 6
    sage: darmon_point(P,E,beta,20) # long time # optional - magma

    '''
    # global G, Coh, phiE, Phi, dK, J, J1, cycleGn, nn, Jlist

    config = ConfigParser.ConfigParser()
    config.read('config.ini')
    param_dict = config_section_map(config, 'General')
    param_dict.update(config_section_map(config, 'DarmonPoint'))
    param_dict.update(kwargs)
    param = Bunch(**param_dict)

    # Get general parameters
    outfile = param.get('outfile')
    use_ps_dists = param.get('use_ps_dists',False)
    use_shapiro = param.get('use_shapiro',True)
    use_sage_db = param.get('use_sage_db',False)
    magma_seed = param.get('magma_seed',1515316)
    parallelize = param.get('parallelize',False)
    Up_method = param.get('up_method','naive')
    use_magma = param.get('use_magma',True)
    progress_bar = param.get('progress_bar',True)
    sign_at_infinity = param.get('sign_at_infinity',ZZ(1))

    # Get darmon_point specific parameters
    idx_orientation = param.get('idx_orientation')
    idx_embedding = param.get('idx_embedding',0)
    algorithm = param.get('algorithm')
    quaternionic = param.get('quaternionic')
    cohomological = param.get('cohomological',True)

    if Up_method == "bigmatrix" and use_shapiro == True:
        import warnings
        warnings.warn('Use of "bigmatrix" for Up iteration is incompatible with Shapiro Lemma trick. Using "naive" method for Up.')
        Up_method = 'naive'

    if working_prec is None:
        working_prec = max([2 * prec + 10, 30])

    if use_magma:
        page_path = os.path.dirname(__file__) + '/KleinianGroups-1.0/klngpspec'
        if magma is None:
            from sage.interfaces.magma import Magma
            magma = Magma()
            quit_when_done = True
        else:
            quit_when_done = False
        magma.attach_spec(page_path)
    else:
        quit_when_done = False

    sys.setrecursionlimit(10**6)

    F = E.base_ring()
    beta = F(beta)
    DB,Np,Ncartan = get_heegner_params(P,E,beta)
    if quaternionic is None:
        quaternionic = ( DB != 1 )
    if cohomological is None:
        cohomological = quaternionic
    if quaternionic and not cohomological:
        raise ValueError("Need cohomological algorithm when dealing with quaternions")
    if use_ps_dists is None:
        use_ps_dists = False if cohomological else True
    try:
        p = ZZ(P)
    except TypeError:
        p = ZZ(P.norm())
    if not p.is_prime():
        raise ValueError,'P (= %s) should be a prime, of inertia degree 1'%P

    if F == QQ:
        dK = ZZ(beta)
        extra_conductor_sq = dK/fundamental_discriminant(dK)
        assert ZZ(extra_conductor_sq).is_square()
        extra_conductor = extra_conductor_sq.sqrt()
        dK = dK / extra_conductor_sq
        assert dK == fundamental_discriminant(dK)
        if dK % 4 == 0:
            dK = ZZ(dK/4)
        beta = dK
    else:
        dK = beta

    # Compute the completion of K at p
    x = QQ['x'].gen()
    K = F.extension(x*x - dK,names = 'alpha')
    if F == QQ:
        dK = K.discriminant()
    else:
        dK = K.relative_discriminant()

    hK = K.class_number()

    sgninfty = 'plus' if sign_at_infinity == 1 else 'minus'
    if hasattr(E,'cremona_label'):
        Ename = E.cremona_label()
    elif hasattr(E,'ainvs'):
        Ename = E.ainvs()
    else:
        Ename = 'unknown'
    fname = 'moments_%s_%s_%s_%s.sobj'%(P,Ename,sgninfty,prec)

    if use_sage_db:
        print("Moments will be stored in database as %s"%(fname))

    if outfile == 'log':
        outfile = '%s_%s_%s_%s_%s_%s.log'%(P,Ename,dK,sgninfty,prec,datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
        outfile = outfile.replace('/','div')
        outfile = '/tmp/darmonpoint_' + outfile

    fwrite("Starting computation of the Darmon point",outfile)
    fwrite('D_B = %s  %s'%(DB,factor(DB)),outfile)
    fwrite('Np = %s'%Np,outfile)
    if Ncartan is not None:
        fwrite('Ncartan = %s'%Ncartan,outfile)
    fwrite('dK = %s (class number = %s)'%(dK,hK),outfile)
    fwrite('Calculation with p = %s and prec = %s'%(P,prec),outfile)
    fwrite('Elliptic curve %s: %s'%(Ename,E),outfile)
    if outfile is not None:
        print("Partial results will be saved in %s"%outfile)

    if input_data is None:
        if cohomological:
            # Define the S-arithmetic group
            if F != QQ and ramification_at_infinity is None:
                if F.signature()[0] > 1:
                    if F.signature()[1] == 1:
                        ramification_at_infinity = F.real_places(prec = Infinity) # Totally 'definite'
                    else:
                        raise ValueError,'Please specify the ramification at infinity'
                elif F.signature()[0] == 1:
                    if len(F.ideal(DB).factor()) % 2 == 0:
                        ramification_at_infinity = [] # Split at infinity
                    else:
                        ramification_at_infinity = F.real_places(prec = Infinity) # Ramified at infinity
                else:
                    ramification_at_infinity = None
            if F == QQ:
                abtuple = QuaternionAlgebra(DB).invariants()
            else:
                abtuple = quaternion_algebra_invariants_from_ramification(F, DB, ramification_at_infinity)

            G = BigArithGroup(P,abtuple,Np,base = F,outfile = outfile,seed = magma_seed,use_sage_db = use_sage_db,magma = magma, use_shapiro = use_shapiro, nscartan=Ncartan)

            # Define the cycle ( in H_1(G,Div^0 Hp) )
            Coh = ArithCoh(G)
            while True:
                try:
                    cycleGn,nn,ell = construct_homology_cycle(G,beta,working_prec,lambda q: Coh.hecke_matrix(q).minpoly(), outfile = outfile, elliptic_curve = E)
                    break
                except PrecisionError:
                    working_prec *= 2
                    verbose('Encountered precision error, trying with higher precision (= %s)'%working_prec)
                except ValueError:
                    fwrite('ValueError occurred when constructing homology cycle. Returning the S-arithmetic group.', outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
                except AssertionError as e:
                    fwrite('Assertion occurred when constructing homology cycle. Returning the S-arithmetic group.', outfile)
                    fwrite('%s'%str(e), outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
            eisenstein_constant = -ZZ(E.reduction(ell).count_points())
            fwrite('r = %s, so a_r(E) - r - 1 = %s'%(ell,eisenstein_constant), outfile)
            fwrite('exponent = %s'%nn, outfile)
            phiE = Coh.get_cocycle_from_elliptic_curve(E, sign = sign_at_infinity)
            if hasattr(E,'ap'):
                sign_ap = E.ap(P)
            else:
                try:
                    sign_ap = ZZ(P.norm() + 1 - E.reduction(P).count_points())
                except ValueError:
                    sign_ap = ZZ(P.norm() + 1 - Curve(E).change_ring(P.residue_field()).count_points(1)[0])

            Phi = get_overconvergent_class_quaternionic(P,phiE,G,prec,sign_at_infinity,sign_ap,use_ps_dists = use_ps_dists,use_sage_db = use_sage_db,parallelize = parallelize,method = Up_method, progress_bar = progress_bar,Ename = Ename)
            # Integration with moments
            tot_time = walltime()
            J = integrate_H1(G,cycleGn,Phi,1,method = 'moments',prec = working_prec,parallelize = parallelize,twist = True,progress_bar = progress_bar)
            verbose('integration tot_time = %s'%walltime(tot_time))
            if use_sage_db:
                G.save_to_db()
        else: # not cohomological
            nn = 1
            eisenstein_constant = 1
            if algorithm is None:
                if Np == 1:
                    algorithm = 'darmon_pollack'
                else:
                    algorithm = 'guitart_masdeu'
            w = K.maximal_order().ring_generators()[0]
            r0,r1 = w.coordinates_in_terms_of_powers()(K.gen())
            QQp = Qp(p,working_prec)
            Cp = QQp.extension(w.minpoly().change_ring(QQp),names = 'g')
            v0 = K.hom([r0 + r1 * Cp.gen()])

            # Optimal embeddings of level one
            fwrite("Computing optimal embeddings of level one...", outfile)
            Wlist = find_optimal_embeddings(K,use_magma = use_magma, extra_conductor = extra_conductor)
            fwrite("Found %s such embeddings."%len(Wlist), outfile)
            if idx_embedding is not None:
                if idx_embedding >= len(Wlist):
                    fwrite('There are not enough embeddings. Taking the index modulo %s'%len(Wlist), outfile)
                    idx_embedding = idx_embedding % len(Wlist)
                fwrite('Taking only embedding number %s'%(idx_embedding), outfile)
                Wlist = [Wlist[idx_embedding]]

            # Find the orientations
            orients = K.maximal_order().ring_generators()[0].minpoly().roots(Zmod(Np),multiplicities = False)
            fwrite("Possible orientations: %s"%orients, outfile)
            if len(Wlist) == 1 or idx_orientation == -1:
                fwrite("Using all orientations, since hK = 1", outfile)
                chosen_orientation = None
            else:
                fwrite("Using orientation = %s"%orients[idx_orientation], outfile)
                chosen_orientation = orients[idx_orientation]

            emblist = []
            for i,W in enumerate(Wlist):
                tau, gtau,sign,limits = find_tau0_and_gtau(v0,Np,W,algorithm = algorithm,orientation = chosen_orientation,extra_conductor = extra_conductor)
                fwrite('n_evals = %s'%sum((num_evals(t1,t2) for t1,t2 in limits)), outfile)
                emblist.append((tau,gtau,sign,limits))

            # Get the cohomology class from E
            Phi = get_overconvergent_class_matrices(P,E,prec,sign_at_infinity,use_ps_dists = use_ps_dists,use_sage_db = use_sage_db,parallelize = parallelize,progress_bar = progress_bar)

            J = 1
            Jlist = []
            for i,emb in enumerate(emblist):
                fwrite("Computing %s-th period, attached to the embedding: %s"%(i,Wlist[i].list()), outfile)
                tau, gtau,sign,limits = emb
                n_evals = sum((num_evals(t1,t2) for t1,t2 in limits))
                fwrite("Computing one period...(total of %s evaluations)"%n_evals, outfile)
                newJ = prod((double_integral_zero_infty(Phi,t1,t2) for t1,t2 in limits))**ZZ(sign)
                Jlist.append(newJ)
                J *= newJ
    else: # input_data is not None
        Phi,J = input_data[1:3]
    fwrite('Integral done. Now trying to recognize the point', outfile)
    fwrite('J_psi = %s'%J,outfile)
    fwrite('g belongs to %s'%J.parent(),outfile)
    #Try to recognize a generator
    if quaternionic:
        local_embedding = G.base_ring_local_embedding(working_prec)
        twopowlist = [4, 3, 2, 1, QQ(1)/2, QQ(3)/2, QQ(1)/3, QQ(2)/3, QQ(1)/4, QQ(3)/4, QQ(5)/2, QQ(4)/3]
    else:
        local_embedding = Qp(p,working_prec)
        twopowlist = [4, 3, 2, 1, QQ(1)/2, QQ(3)/2, QQ(1)/3, QQ(2)/3, QQ(1)/4, QQ(3)/4, QQ(5)/2, QQ(4)/3]

    known_multiple = QQ(nn * eisenstein_constant) # It seems that we are not getting it with present algorithm.
    while known_multiple % p == 0:
        known_multiple = ZZ(known_multiple / p)

    candidate,twopow,J1 = recognize_J(E,J,K,local_embedding = local_embedding,known_multiple = known_multiple,twopowlist = twopowlist,prec = prec, outfile = outfile)

    if candidate is not None:
        HCF = K.hilbert_class_field(names = 'r1') if hK > 1 else K
        if hK == 1:
            try:
                verbose('candidate = %s'%candidate)
                Ptsmall = E.change_ring(HCF)(candidate)
                fwrite('twopow = %s'%twopow,outfile)
                fwrite('Computed point:  %s * %s * %s'%(twopow,known_multiple,Ptsmall),outfile)
                fwrite('(first factor is not understood, second factor is)',outfile)
                fwrite('(r satisfies %s = 0)'%(Ptsmall[0].parent().gen().minpoly()),outfile)
                fwrite('================================================',outfile)
                if quit_when_done:
                    magma.quit()
                return Ptsmall
            except (TypeError,ValueError):
                verbose("Could not recognize the point.")
        else:
            verbose('candidate = %s'%candidate)
            fwrite('twopow = %s'%twopow,outfile)
            fwrite('Computed point:  %s * %s * (x,y)'%(twopow,known_multiple),outfile)
            fwrite('(first factor is not understood, second factor is)',outfile)
            try:
                pols = [HCF(c).relative_minpoly() for c in candidate[:2]]
            except AttributeError:
                pols = [HCF(c).minpoly() for c in candidate[:2]]
            fwrite('Where x satisfies %s'%pols[0],outfile)
            fwrite('and y satisfies %s'%pols[1],outfile)
            fwrite('================================================',outfile)
            if quit_when_done:
                magma.quit()
            return candidate
    else:
        fwrite('================================================',outfile)
        if quit_when_done:
            magma.quit()
        return []
Exemple #23
0
    def simplify(self, x, error=None, force=False, size_heuristic_bound=32):
        r"""
        Return a simplified version of ``x``.

        Produce an element which differs from ``x`` by an element of
        valuation strictly greater than the valuation of ``x`` (or strictly
        greater than ``error`` if set.)

        INPUT:

        - ``x`` -- an element in the domain of this valuation

        - ``error`` -- a rational, infinity, or ``None`` (default: ``None``),
          the error allowed to introduce through the simplification

        - ``force`` -- ignored

        - ``size_heuristic_bound`` -- when ``force`` is not set, the expected
          factor by which the ``x`` need to shrink to perform an actual
          simplification (default: 32)

        EXAMPLES::

            sage: v = ZZ.valuation(2)
            sage: v.simplify(6, force=True)
            2
            sage: v.simplify(6, error=0, force=True)
            0

        In this example, the usual rational reconstruction misses a good answer
        for some moduli (because the absolute value of the numerator is not
        bounded by the square root of the modulus)::

            sage: v = QQ.valuation(2)
            sage: v.simplify(110406, error=16, force=True)
            562/19
            sage: Qp(2, 16)(110406).rational_reconstruction()
            Traceback (most recent call last):
            ...
            ArithmeticError: rational reconstruction of 55203 (mod 65536) does not exist

        """
        if not force and self._relative_size(x) <= size_heuristic_bound:
            return x

        x = self.domain().coerce(x)

        v = self(x)
        if error is None:
            error = v
        from sage.rings.all import infinity
        if error is infinity:
            return x
        if error < v:
            return self.domain().zero()

        from sage.rings.all import QQ
        from sage.rings.all import Qp
        precision_ring = Qp(self.p(), QQ(error).floor() + 1 - v)
        reduced = precision_ring(x)
        lift = (reduced >> v).lift()
        best = self.domain()(lift) * self.p()**v

        if self._relative_size(x) < self._relative_size(best):
            best = x

        # We implement a modified version of the usual rational reconstruction
        # algorithm (based on the extended Euclidean algorithm) here. We do not
        # get the uniqueness properties but we do not need them actually.
        # This is certainly slower than the implementation in Cython.
        from sage.categories.all import Fields
        m = self.p()**(QQ(error).floor() + 1 - v)
        if self.domain() in Fields():
            r = (m, lift)
            s = (0, 1)
            while r[1]:
                qq, rr = r[0].quo_rem(r[1])
                r = r[1], rr
                s = s[1], s[0] - qq * s[1]
                from sage.arith.all import gcd
                if s[1] != 0 and gcd(s[1], r[1]) == 1:
                    rational = self.domain()(r[1]) / self.domain()(
                        s[1]) * self.p()**v
                    if self._relative_size(rational) < self._relative_size(
                            best):
                        best = rational

        assert (self(x - best) > error)

        return best