Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- r""" Element class for Pollack-Stevens' Modular Symbols
This is the class of elements in the spaces of Pollack-Steven's modular symbols as described in [PS]_.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol(); phi Modular symbol of level 11 with values in Sym^0 Q^2 sage: phi.weight() # Note that weight k=2 of a modular form corresponds here to weight 0 0 sage: phi.values() [-1/5, 1, 0] sage: phi.is_ordinary(11) True sage: phi_lift = phi.lift(11, 5, eigensymbol = True) # long time sage: phi_lift.padic_lseries().series(5) # long time O(11^5) + (10 + 3*11 + 6*11^2 + 9*11^3 + O(11^4))*T + (6 + 3*11 + 2*11^2 + O(11^3))*T^2 + (2 + 2*11 + O(11^2))*T^3 + (5 + O(11))*T^4 + O(T^5)
::
sage: A = ModularSymbols(Gamma1(8),4).decomposition()[0].plus_submodule().new_subspace() sage: from sage.modular.pollack_stevens.space import ps_modsym_from_simple_modsym_space sage: phi = ps_modsym_from_simple_modsym_space(A) sage: phi.values() [(-1, 0, 0), (1, 0, 0), (-9, -6, -4)]
""" #***************************************************************************** # Copyright (C) 2012 Robert Pollack <rpollack@math.bu.edu> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #****************************************************************************** from __future__ import print_function from __future__ import absolute_import import operator from sage.structure.element import ModuleElement from sage.structure.richcmp import op_EQ, op_NE from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.misc.cachefunc import cached_method from sage.rings.padics.factory import Qp from sage.rings.polynomial.all import PolynomialRing from sage.rings.padics.padic_generic import pAdicGeneric from sage.arith.all import next_prime, binomial, gcd, kronecker from sage.misc.misc import verbose from sage.rings.padics.precision_error import PrecisionError
from sage.categories.action import Action from .manin_map import ManinMap from .sigma0 import Sigma0 from sage.misc.misc import walltime from .fund_domain import M2Z
minusproj = [1, 0, 0, -1]
def _iterate_Up(Phi, p, M, ap, q, aq, check): r""" Return an overconvergent Hecke-eigensymbol lifting self -- self must be a `p`-ordinary eigensymbol
INPUT:
- ``p`` -- prime
- ``M`` -- integer equal to the number of moments
- ``ap`` -- Hecke eigenvalue at `p`
- ``q`` -- prime
- ``aq`` -- Hecke eigenvalue at `q`
OUTPUT:
- Hecke-eigenvalue overconvergent modular symbol lifting self.
EXAMPLES::
sage: E = EllipticCurve('57a') sage: p = 5 sage: prec = 4 sage: phi = E.pollack_stevens_modular_symbol() sage: phi_stabilized = phi.p_stabilize(p,M = prec) sage: Phi = phi_stabilized.lift(p,prec) # indirect doctest """ raise ValueError("Lifting non-ordinary eigensymbols not implemented (issue #20)")
## Act by Hecke to ensure values are in D and not D^dag after solving difference equation
## Killing eisenstein part
## Iterating U_p
class PSModSymAction(Action): def __init__(self, actor, MSspace): r""" Create the action
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: g = phi._map._codomain._act._Sigma0(matrix(ZZ,2,2,[1,2,3,4])) sage: phi * g # indirect doctest Modular symbol of level 11 with values in Sym^0 Q^2 """
def _call_(self, sym, g): r""" Return the result of sym * g
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: g = phi._map._codomain._act._Sigma0(matrix(ZZ,2,2,[2,1,5,-1])) sage: phi * g # indirect doctest Modular symbol of level 11 with values in Sym^0 Q^2 """
class PSModularSymbolElement(ModuleElement): def __init__(self, map_data, parent, construct=False): r""" Initialize a modular symbol
EXAMPLES::
sage: E = EllipticCurve('37a') sage: phi = E.pollack_stevens_modular_symbol() """ else: self._map = ManinMap(parent._coefficients, parent._source, map_data)
def _repr_(self): r""" Return the string representation of the symbol.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi._repr_() 'Modular symbol of level 11 with values in Sym^0 Q^2' """
def dict(self): r""" Return dictionary on the modular symbol self, where keys are generators and values are the corresponding values of self on generators
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: Set([x.moment(0) for x in phi.dict().values()]) == Set([-1/5, 1, 0]) True """
def weight(self): r""" Return the weight of this Pollack-Stevens modular symbol.
This is `k-2`, where `k` is the usual notion of weight for modular forms!
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.weight() 0 """
def values(self): r""" Return the values of the symbol self on our chosen generators (generators are listed in ``self.dict().keys()``)
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi.dict().keys() [ [-1 -1] [1 0] [ 0 -1] [ 3 2], [0 1], [ 1 3] ] sage: sorted(phi.values()) == sorted(phi.dict().values()) True """
def _normalize(self, **kwds): """ Normalize all of the values of the symbol self
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi._normalize() Modular symbol of level 11 with values in Sym^0 Q^2 sage: phi._normalize().values() [-1/5, 1, 0] """
def _richcmp_(self, other, op): """ Check if self == other.
Here self and other have the same parent.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi == phi True sage: phi == 2*phi False sage: psi = EllipticCurve('37a').pollack_stevens_modular_symbol() sage: psi == phi False """ return NotImplemented
for g in self.parent().source().gens())
def _add_(self, right): """ Return self + right
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi + phi Modular symbol of level 11 with values in Sym^0 Q^2 sage: (phi + phi).values() [-2/5, 2, 0] """
def _lmul_(self, right): """ Return self * right
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol(); sage: phi.values() [-1/5, 1, 0] sage: 2*phi Modular symbol of level 11 with values in Sym^0 Q^2 sage: (2*phi).values() [-2/5, 2, 0] """
def _rmul_(self, right): """ Return self * right
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi*2 Modular symbol of level 11 with values in Sym^0 Q^2 sage: (phi*2).values() [-2/5, 2, 0] """
def _sub_(self, right): """ Return self - right
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi - phi Modular symbol of level 11 with values in Sym^0 Q^2 sage: (phi - phi).values() [0, 0, 0] """
def _get_prime(self, p=None, alpha=None, allow_none=False): """ Combine a prime specified by the user with the prime from the parent.
INPUT:
- ``p`` -- an integer or None (default None); if specified needs to match the prime of the parent.
- ``alpha`` -- an element or None (default None); if p-adic can contribute a prime.
- ``allow_none`` -- boolean (default False); whether to allow no prime to be specified.
OUTPUT:
- a prime or None. If ``allow_none`` is False then a ``ValueError`` will be raised rather than returning None if no prime can be determined.
EXAMPLES::
sage: from sage.modular.pollack_stevens.distributions import Symk sage: D = OverconvergentDistributions(0, 5, 10) sage: M = PollackStevensModularSymbols(Gamma0(5), coefficients=D) sage: f = M(1); f._get_prime() 5 sage: f._get_prime(5) 5 sage: f._get_prime(7) Traceback (most recent call last): ... ValueError: inconsistent prime sage: f._get_prime(alpha=Qp(5)(1)) 5 sage: D = Symk(0) sage: M = PollackStevensModularSymbols(Gamma0(2), coefficients=D) sage: f = M(1); f._get_prime(allow_none=True) is None True sage: f._get_prime(alpha=Qp(7)(1)) 7 sage: f._get_prime(7,alpha=Qp(7)(1)) 7 sage: f._get_prime() Traceback (most recent call last): ... ValueError: you must specify a prime """ and alpha.parent().prime()) or None
def plus_part(self): r""" Return the plus part of self -- i.e. ``self + self | [1,0,0,-1]``.
Note that we haven't divided by 2. Is this a problem?
OUTPUT:
- self + self | [1,0,0,-1]
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: (phi.plus_part()+phi.minus_part()) == 2 * phi True """
def minus_part(self): r""" Return the minus part of self -- i.e. self - self | [1,0,0,-1]
Note that we haven't divided by 2. Is this a problem?
OUTPUT:
- self -- self | [1,0,0,-1]
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: (phi.plus_part()+phi.minus_part()) == phi * 2 True """
def hecke(self, ell, algorithm="prep"): r""" Return self | `T_{\ell}` by making use of the precomputations in self.prep_hecke()
INPUT:
- ``ell`` -- a prime
- ``algorithm`` -- a string, either 'prep' (default) or 'naive'
OUTPUT:
- The image of this element under the Hecke operator `T_{\ell}`
ALGORITHMS:
- If ``algorithm == 'prep'``, precomputes a list of matrices that only depend on the level, then uses them to speed up the action.
- If ``algorithm == 'naive'``, just acts by the matrices defining the Hecke operator. That is, it computes sum_a self | [1,a,0,ell] + self | [ell,0,0,1], the last term occurring only if the level is prime to ell.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi.hecke(2) == phi * E.ap(2) True sage: phi.hecke(3) == phi * E.ap(3) True sage: phi.hecke(5) == phi * E.ap(5) True sage: phi.hecke(101) == phi * E.ap(101) True
sage: all([phi.hecke(p, algorithm='naive') == phi * E.ap(p) for p in [2,3,5,101]]) # long time True """ self.parent(), construct=True)
def valuation(self, p=None): r""" Return the valuation of ``self`` at `p`.
Here the valuation is the minimum of the valuations of the values of ``self``.
INPUT:
- ``p`` - prime
OUTPUT:
- The valuation of ``self`` at `p`
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi.valuation(2) 0 sage: phi.valuation(3) 0 sage: phi.valuation(5) -1 sage: phi.valuation(7) 0 sage: phi.valuation() Traceback (most recent call last): ... ValueError: you must specify a prime
sage: phi2 = phi.lift(11, M=2) sage: phi2.valuation() 0 sage: phi2.valuation(3) Traceback (most recent call last): ... ValueError: inconsistent prime sage: phi2.valuation(11) 0 """
def diagonal_valuation(self, p): """ Return the minimum of the diagonal valuation on the values of self
INPUT:
- ``p`` -- a positive integral prime
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi.diagonal_valuation(2) 0 sage: phi.diagonal_valuation(3) 0 sage: phi.diagonal_valuation(5) -1 sage: phi.diagonal_valuation(7) 0 """
@cached_method def is_Tq_eigensymbol(self, q, p=None, M=None): r""" Determine if self is an eigenvector for `T_q` modulo `p^M`
INPUT:
- ``q`` -- prime of the Hecke operator
- ``p`` -- prime we are working modulo
- ``M`` -- degree of accuracy of approximation
OUTPUT:
- True/False
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi_ord = phi.p_stabilize(p = 3, ap = E.ap(3), M = 10, ordinary = True) sage: phi_ord.is_Tq_eigensymbol(2,3,10) True sage: phi_ord.is_Tq_eigensymbol(2,3,100) False sage: phi_ord.is_Tq_eigensymbol(2,3,1000) False sage: phi_ord.is_Tq_eigensymbol(3,3,10) True sage: phi_ord.is_Tq_eigensymbol(3,3,100) False """
# what happens if a cached method raises an error? Is it # recomputed each time? @cached_method def Tq_eigenvalue(self, q, p=None, M=None, check=True): r""" Eigenvalue of `T_q` modulo `p^M`
INPUT:
- ``q`` -- prime of the Hecke operator
- ``p`` -- prime we are working modulo (default: None)
- ``M`` -- degree of accuracy of approximation (default: None)
- ``check`` -- check that ``self`` is an eigensymbol
OUTPUT:
- Constant `c` such that `self|T_q - c * self` has valuation greater than or equal to `M` (if it exists), otherwise raises ValueError
EXAMPLES::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: phi_ord = phi.p_stabilize(p = 3, ap = E.ap(3), M = 10, ordinary = True) sage: phi_ord.Tq_eigenvalue(2,3,10) + 2 O(3^10)
sage: phi_ord.Tq_eigenvalue(3,3,10) 2 + 3^2 + 2*3^3 + 2*3^4 + 2*3^6 + 3^8 + 2*3^9 + O(3^10) sage: phi_ord.Tq_eigenvalue(3,3,100) Traceback (most recent call last): ... ValueError: result not determined to high enough precision """
raise ValueError("not a scalar multiple") except IndexError: raise ValueError("self is zero")
# using != did not work raise ValueError("not a scalar multiple") except PrecisionError: if qhecke._map[g] != aq * self._map[g]: raise ValueError("not a scalar multiple") else: raise ValueError("not a scalar multiple") # if not aq.parent().is_exact() and M is not None: # aq.add_bigoh(M)
def is_ordinary(self, p=None, P=None): r""" Return true if the `p`-th eigenvalue is a `p`-adic unit.
INPUT:
- ``p`` - a positive integral prime, or None (default None) - ``P`` - a prime of the base ring above `p`, or None. This is ignored unless the base ring is a number field.
OUTPUT:
- True/False
EXAMPLES::
sage: E = EllipticCurve('11a1') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.is_ordinary(2) False sage: E.ap(2) -2 sage: phi.is_ordinary(3) True sage: E.ap(3) -1 sage: phip = phi.p_stabilize(3,20) sage: phip.is_ordinary() True
A number field example. Here there are multiple primes above `p`, and `\phi` is ordinary at one but not the other.::
sage: f = Newforms(32, 8, names='a')[1] sage: K = f.hecke_eigenvalue_field() sage: a = f[3] sage: from sage.modular.pollack_stevens.space import ps_modsym_from_simple_modsym_space sage: phi = ps_modsym_from_simple_modsym_space(f.modular_symbols(1)) sage: phi.is_ordinary(K.ideal(3, 1/16*a + 3/2)) != phi.is_ordinary(K.ideal(3, 1/16*a + 5/2)) True sage: phi.is_ordinary(3) Traceback (most recent call last): ... TypeError: P must be an ideal
""" # q is the prime below p, if base is a number field; q = p otherwise raise ValueError("need to specify a prime") else: raise ValueError("p is not prime") raise ValueError("prime does not match coefficient module's prime")
def evaluate_twisted(self, a, chi): r""" Return `\Phi_{\chi}(\{a/p\}-\{\infty\})` where `\Phi` is ``self`` and `\chi` is a quadratic character
INPUT:
- ``a`` -- integer in the range range(p) - ``chi`` -- the modulus of a quadratic character.
OUTPUT:
The distribution `\Phi_{\chi}(\{a/p\}-\{\infty\})`.
EXAMPLES::
sage: E = EllipticCurve('17a1') sage: L = E.padic_lseries(5, implementation="pollackstevens", precision=4) #long time sage: D = L.quadratic_twist() # long time sage: L.symbol().evaluate_twisted(1,D) # long time (1 + 5 + 3*5^2 + 5^3 + O(5^4), 5^2 + O(5^3), 1 + O(5^2), 2 + O(5))
sage: E = EllipticCurve('40a4') sage: L = E.padic_lseries(7, implementation="pollackstevens", precision=4) #long time sage: D = L.quadratic_twist() # long time sage: L.symbol().evaluate_twisted(1,D) # long time (4 + 6*7 + 3*7^2 + O(7^4), 6*7 + 6*7^2 + O(7^3), 6 + O(7^2), 1 + O(7)) """
def _consistency_check(self): """ Check that the map really does satisfy the Manin relations loop (for debugging). The two and three torsion relations are checked and it is checked that the symbol adds up correctly around the fundamental domain
EXAMPLES::
sage: E = EllipticCurve('37a1') sage: phi = E.pollack_stevens_modular_symbol() sage: phi._consistency_check() This modular symbol satisfies the Manin relations """ ## Test two torsion relations raise ValueError("Two torsion relation failed with", g)
## Test three torsion relations raise ValueError("Three torsion relation failed with", g)
## Test that the symbol adds to 0 around the boundary of the ## fundamental domain or g in MR.reps_with_three_torsion()): else: else:
print(t) print(f[id] * MR.gammas[id] - f[id]) raise ValueError("Does not add up correctly around loop")
class PSModularSymbolElement_symk(PSModularSymbolElement): def _find_alpha(self, p, k, M=None, ap=None, new_base_ring=None, ordinary=True, check=True, find_extraprec=True): r""" Find `\alpha`, a `U_p` eigenvalue, which is found as a root of the polynomial `x^2 - a_p * x + p^{k+1} \chi(p)`.
INPUT:
- ``p`` -- prime
- ``k`` -- Pollack-Stevens weight
- ``M`` -- precision (default: None) of `\QQ_p`
- ``ap`` -- Hecke eigenvalue at `p` (default: None)
- ``new_base_ring`` -- field of definition of `\alpha` (default: None)
- ``ordinary`` -- True if the prime is ordinary (default: True)
- ``check`` -- check to see if the prime is ordinary (default: True)
- ``find_extraprec`` -- setting this to True finds extra precision (default: True)
OUTPUT:
The output is a tuple (``alpha``, ``new_base_ring``, ``newM``, ``eisenloss``,``q``,``aq``), with
- ``alpha`` -- `U_p` eigenvalue
- ``new_base_ring`` -- field of definition of `\alpha` with precision at least ``newM``
- ``newM`` -- new precision
- ``eisenloss`` -- loss of precision
- ``q`` -- a prime not equal to `p` which was used to find extra precision
- ``aq`` -- the Hecke eigenvalue `a_q` corresponding to `q`
EXAMPLES::
sage: E = EllipticCurve('11a') sage: p = 5 sage: M = 10 sage: k = 0 sage: phi = E.pollack_stevens_modular_symbol() sage: phi._find_alpha(p,k,M) (1 + 4*5 + 3*5^2 + 2*5^3 + 4*5^4 + 4*5^5 + 4*5^6 + 3*5^7 + 2*5^8 + 3*5^9 + 3*5^10 + 3*5^12 + 2*5^13 + O(5^14), 5-adic Field with capped relative precision 14, 13, 1, 2, -2) """ raise ValueError("p is not ordinary")
else: # These should actually be completions of disc.parent() # is this the right precision adjustment for p=2? new_base_ring = Qp(2, M + 1) else: else: except (TypeError, ValueError): raise ValueError("new base ring must contain a root of x^2 - ap * x + p^(k+1)") v0, v1 = v1, v0 else: else: # We want to ensure that the relative precision of alpha # and (alpha-1) are both at least *newM*, where newM is # obtained from self._find_extraprec level=2) # if ap = 1 + p**(k+1) then alpha=1 and we need to give up. else:
def p_stabilize(self, p=None, M=20, alpha=None, ap=None, new_base_ring=None, ordinary=True, check=True): r""" Return the `p`-stabilization of self to level `N p` on which `U_p` acts by `\alpha`.
Note that since `\alpha` is `p`-adic, the resulting symbol is just an approximation to the true `p`-stabilization (depending on how well `\alpha` is approximated).
INPUT:
- ``p`` -- prime not dividing the level of self
- ``M`` -- (default: 20) precision of `\QQ_p`
- ``alpha`` -- `U_p` eigenvalue
- ``ap`` -- Hecke eigenvalue
- ``new_base_ring`` -- change of base ring
- ``ordinary`` -- (default: True) whether to return the ordinary (at ``p``) eigensymbol.
- ``check`` -- (default: True) whether to perform extra sanity checks
OUTPUT:
A modular symbol with the same Hecke eigenvalues as self away from `p` and eigenvalue `\alpha` at `p`. The eigenvalue `\alpha` depends on the parameter ``ordinary``.
If ``ordinary`` == True: the unique modular symbol of level `N p` with the same Hecke eigenvalues as self away from `p` and unit eigenvalue at `p`; else the unique modular symbol of level `N p` with the same Hecke eigenvalues as self away from `p` and non-unit eigenvalue at `p`.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: p = 5 sage: prec = 4 sage: phi = E.pollack_stevens_modular_symbol() sage: phis = phi.p_stabilize(p,M = prec) sage: phis Modular symbol of level 55 with values in Sym^0 Q_5^2 sage: phis.hecke(7) == phis*E.ap(7) True sage: phis.hecke(5) == phis*E.ap(5) False sage: phis.hecke(3) == phis*E.ap(3) True sage: phis.Tq_eigenvalue(5) 1 + 4*5 + 3*5^2 + 2*5^3 + O(5^4) sage: phis.Tq_eigenvalue(5,M = 3) 1 + 4*5 + 3*5^2 + O(5^3)
sage: phis = phi.p_stabilize(p,M = prec,ordinary=False) sage: phis.Tq_eigenvalue(5) 5 + 5^2 + 2*5^3 + O(5^5)
A complicated example (with nontrivial character)::
sage: chi = DirichletGroup(24)([-1, -1, -1]) sage: f = Newforms(chi,names='a')[0] sage: from sage.modular.pollack_stevens.space import ps_modsym_from_simple_modsym_space sage: phi = ps_modsym_from_simple_modsym_space(f.modular_symbols(1)) sage: phi11, h11 = phi.completions(11,20)[0] sage: phi11s = phi11.p_stabilize() sage: phi11s.is_Tq_eigensymbol(11) # long time True """ else: new_base_ring = alpha.parent() elif alpha ** 2 - ap * alpha + p ** (k + 1) != 0: raise ValueError("alpha must be a root of x^2 - a_p*x + p^(k+1)") raise ValueError("alpha must be a root of x^2 - a_p*x + p^(k+1)")
def completions(self, p, M): r""" If `K` is the base_ring of self, this function takes all maps `K\to \QQ_p` and applies them to self return a list of (modular symbol,map: `K\to \QQ_p`) as map varies over all such maps.
.. NOTE::
This only returns all completions when `p` splits completely in `K`
INPUT:
- ``p`` -- prime
- ``M`` -- precision
OUTPUT:
- A list of tuples (modular symbol,map: `K\to \QQ_p`) as map varies over all such maps
EXAMPLES::
sage: from sage.modular.pollack_stevens.space import ps_modsym_from_simple_modsym_space sage: D = ModularSymbols(67,2,1).cuspidal_submodule().new_subspace().decomposition()[1] sage: f = ps_modsym_from_simple_modsym_space(D) sage: S = f.completions(41,10); S [(Modular symbol of level 67 with values in Sym^0 Q_41^2, Ring morphism: From: Number Field in alpha with defining polynomial x^2 + 3*x + 1 To: 41-adic Field with capped relative precision 10 Defn: alpha |--> 5 + 22*41 + 19*41^2 + 10*41^3 + 28*41^4 + 22*41^5 + 9*41^6 + 25*41^7 + 40*41^8 + 8*41^9 + O(41^10)), (Modular symbol of level 67 with values in Sym^0 Q_41^2, Ring morphism: From: Number Field in alpha with defining polynomial x^2 + 3*x + 1 To: 41-adic Field with capped relative precision 10 Defn: alpha |--> 33 + 18*41 + 21*41^2 + 30*41^3 + 12*41^4 + 18*41^5 + 31*41^6 + 15*41^7 + 32*41^9 + O(41^10))] sage: TestSuite(S[0][0]).run(skip=['_test_category']) """ f = x - 1 else: L = Qp(p, M).extension(f, names='a') # a = L.gen() V = self.parent().change_ring(L) Dist = V.coefficient_module() psi = K.hom([K.gen()], L) embedded_sym = self.parent().element_class(self._map.apply(psi, codomain=Dist, to_moments=True), V, construct=True) ans = [embedded_sym, psi] return ans else:
def lift(self, p=None, M=None, alpha=None, new_base_ring=None, algorithm = None, eigensymbol=False, check=True): r""" Return a (`p`-adic) overconvergent modular symbol with `M` moments which lifts self up to an Eisenstein error
Here the Eisenstein error is a symbol whose system of Hecke eigenvalues equals `\ell+1` for `T_\ell` when `\ell` does not divide `Np` and 1 for `U_q` when `q` divides `Np`.
INPUT:
- ``p`` -- prime
- ``M`` -- integer equal to the number of moments
- ``alpha`` -- `U_p` eigenvalue
- ``new_base_ring`` -- change of base ring
- ``algorithm`` -- 'stevens' or 'greenberg' (default 'stevens')
- ``eigensymbol`` -- if True, lifts to Hecke eigensymbol (self must be a `p`-ordinary eigensymbol)
(Note: ``eigensymbol = True`` does *not* just indicate to the code that self is an eigensymbol; it solves a wholly different problem, lifting an eigensymbol to an eigensymbol.)
OUTPUT:
An overconvergent modular symbol whose specialization equals self, up to some Eisenstein error if ``eigensymbol`` is False. If ``eigensymbol = True`` then the output will be an overconvergent Hecke eigensymbol (and it will lift the input exactly, the Eisenstein error disappears).
EXAMPLES::
sage: E = EllipticCurve('11a') sage: f = E.pollack_stevens_modular_symbol() sage: g = f.lift(11,4,algorithm='stevens',eigensymbol=True) sage: g.is_Tq_eigensymbol(2) True sage: g.Tq_eigenvalue(3) 10 + 10*11 + 10*11^2 + 10*11^3 + O(11^4) sage: g.Tq_eigenvalue(11) 1 + O(11^4)
We check that lifting and then specializing gives back the original symbol::
sage: g.specialize() == f True
Another example, which showed precision loss in an earlier version of the code::
sage: E = EllipticCurve('37a') sage: p = 5 sage: prec = 4 sage: phi = E.pollack_stevens_modular_symbol() sage: Phi = phi.p_stabilize_and_lift(p,prec, algorithm='stevens', eigensymbol=True) # long time sage: Phi.Tq_eigenvalue(5,M = 4) # long time 3 + 2*5 + 4*5^2 + 2*5^3 + O(5^4)
Another example::
sage: from sage.modular.pollack_stevens.padic_lseries import pAdicLseries sage: E = EllipticCurve('37a') sage: p = 5 sage: prec = 6 sage: phi = E.pollack_stevens_modular_symbol() sage: Phi = phi.p_stabilize_and_lift(p=p,M=prec,alpha=None,algorithm='stevens',eigensymbol=True) #long time sage: L = pAdicLseries(Phi) # long time sage: L.symbol() is Phi # long time True
Examples using Greenberg's algorithm::
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: Phi = phi.lift(11,8,algorithm='greenberg',eigensymbol=True) sage: Phi2 = phi.lift(11,8,algorithm='stevens',eigensymbol=True) sage: Phi == Phi2 True
An example in higher weight::
sage: from sage.modular.pollack_stevens.space import ps_modsym_from_simple_modsym_space sage: f = ps_modsym_from_simple_modsym_space(Newforms(7, 4)[0].modular_symbols(1)) sage: fs = f.p_stabilize(5) sage: FsG = fs.lift(M=6, eigensymbol=True,algorithm='greenberg') # long time sage: FsG.values()[0] # long time 5^-1 * (2*5 + 5^2 + 3*5^3 + 4*5^4 + O(5^7), O(5^6), 2*5^2 + 3*5^3 + O(5^5), O(5^4), 5^2 + O(5^3), O(5^2)) sage: FsS = fs.lift(M=6, eigensymbol=True,algorithm='stevens') # long time sage: FsS == FsG # long time True """ p = self.parent().prime() if p == 0: raise ValueError("must specify a prime") raise ValueError("inconsistent prime") M = self.parent().precision_cap() + 1 raise ValueError("M must be at least 2") else: else: # We may need extra precision in solving the difference equation else: # should eventually be a completion # The default algorithm is Greenberg's, if possible. raise ValueError("Greenberg's algorithm only works" " for eigensymbols. Try 'stevens'") raise ValueError("algorithm %s not recognized" % algorithm) # We need some extra precision due to the fact that solving # the difference equation can give denominators. else:
def _lift_to_OMS(self, p, M, new_base_ring, algorithm = 'greenberg'): r""" Return a (`p`-adic) overconvergent modular symbol with `M` moments which lifts self up to an Eisenstein error
Here the Eisenstein error is a symbol whose system of Hecke eigenvalues equals `\ell+1` for `T_\ell` when `\ell` does not divide `Np` and 1 for `U_q` when `q` divides `Np`.
INPUT:
- ``p`` -- prime
- ``M`` -- integer equal to the number of moments
- ``new_base_ring`` -- new base ring
- ``algorithm`` -- (default: 'greenberg') a string, either 'greenberg' or 'stevens', specifying whether to use the lifting algorithm of M.Greenberg or that of Pollack--Stevens. The latter one solves the difference equation, which is not needed. The option to use Pollack--Stevens' algorithm here is just for historical reasons.
OUTPUT:
- An overconvergent modular symbol whose specialization equals self up to some Eisenstein error.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: f = E.pollack_stevens_modular_symbol() sage: f._lift_to_OMS(11,4,Qp(11,4)) Modular symbol of level 11 with values in Space of 11-adic distributions with k=0 action and precision cap 4 """ # See [PS] section 4.1 # See [PS] section 4.1 else: # no two or three torsion
## This loops adds up around the boundary of fundamental ## domain except the two vertical lines else: ## t now should be sum Phi(D_i) | (gamma_i - 1) - sum ## Phi(D'_i) - sum Phi(D''_i)
## (Here I'm using the opposite sign convention of [PS1] ## regarding D'_i and D''_i)
else: raise NotImplementedError
def _find_aq(self, p, M, check): r""" Helper function for finding Hecke eigenvalue `aq` for a prime `q` not equal to `p`. This is called in the case when `alpha = 1 (mod p^M)` (with `alpha` a `U_p`-eigenvalue), which creates the need to use other Hecke eigenvalues (and `alpha`s), because of division by `(alpha - 1)`.
INPUT:
- ``p`` -- working prime
- ``M`` -- precision
- ``check`` -- checks that ``self`` is a `T_q` eigensymbol
OUTPUT:
Tuple ``(q, aq, eisenloss)``, with
- ``q`` -- a prime not equal to `p`
- ``aq`` -- Hecke eigenvalue at `q`
- ``eisenloss`` -- the `p`-adic valuation of `a_q - q^{k+1} - 1`
EXAMPLES::
sage: E = EllipticCurve('11a') sage: f = E.pollack_stevens_modular_symbol() sage: f._find_aq(5,10,True) (2, -2, 1) """ q = next_prime(q) aq = self.Tq_eigenvalue(q, check=check) if q != p: eisenloss = (aq - q ** (k + 1) - 1).valuation(p) else: eisenloss = (aq - 1).valuation(p) raise ValueError("The symbol appears to be eisenstein -- " "not implemented yet")
def _find_extraprec(self, p, M, alpha, check): r""" Find the extra precision needed to account for:
1) The denominators in the Hecke eigenvalue 2) the denominators appearing when solving the difference equation, 3) those denominators who might be also present in self.
INPUT :
- ``p`` -- working prime - ``M`` -- precision - ``alpha`` -- the Up-eigenvalue - ``check`` -- whether to check that ``self`` is a `T_q` eigensymbol
OUTPUT :
A tuple (newM, eisenloss, q, aq), where ``newM`` is the new precision, `q` is a prime different from `p`, and ``aq`` is the eigenvalue of `T_q` of the eigensymbol. The value ``eisenloss`` is the loss of precision accounted for in the denominators of the Hecke eigenvalue.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: p = 5 sage: M = 10 sage: k = 0 sage: phi = E.pollack_stevens_modular_symbol() sage: alpha = phi.Tq_eigenvalue(p) sage: phi._find_extraprec(p,M,alpha,True) (13, 1, 2, -2) """ # We also need to add precision to account for denominators appearing while solving the difference equation. eplog = (newM + eplog).exact_log(p) verbose("M = %s, newM = %s, eplog=%s" % (M, newM, eplog), level=2)
# We also need to add precision to account for denominators that might be present in self
def p_stabilize_and_lift(self, p, M, alpha=None, ap=None, new_base_ring=None, ordinary=True, algorithm='greenberg', eigensymbol=False, check=True): """ `p`-stabilize and lift self
INPUT:
- ``p`` -- prime, not dividing the level of self
- ``M`` -- precision
- ``alpha`` -- (default: None) the `U_p` eigenvalue, if known
- ``ap`` -- (default: None) the Hecke eigenvalue at p (before stabilizing), if known
- ``new_base_ring`` -- (default: None) if specified, force the resulting eigensymbol to take values in the given ring
- ``ordinary`` -- (default: True) whether to return the ordinary (at ``p``) eigensymbol.
- ``algorithm`` -- (default: 'greenberg') a string, either 'greenberg' or 'stevens', specifying whether to use the lifting algorithm of M.Greenberg or that of Pollack--Stevens. The latter one solves the difference equation, which is not needed. The option to use Pollack--Stevens' algorithm here is just for historical reasons.
- ``eigensymbol`` -- (default: False) if True, return an overconvergent eigensymbol. Otherwise just perform a naive lift
- ``check`` -- (default: True) whether to perform extra sanity checks
OUTPUT:
`p`-stabilized and lifted version of self.
EXAMPLES::
sage: E = EllipticCurve('11a') sage: f = E.pollack_stevens_modular_symbol() sage: g = f.p_stabilize_and_lift(3,10) # long time sage: g.Tq_eigenvalue(5) # long time 1 + O(3^10) sage: g.Tq_eigenvalue(7) # long time 1 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + O(3^10) sage: g.Tq_eigenvalue(3) # long time 2 + 3^2 + 2*3^3 + 2*3^4 + 2*3^6 + 3^8 + 2*3^9 + O(3^10) """ # alpha will be the eigenvalue of Up new_base_ring = alpha.parent() raise ValueError("Not enough precision in new base ring")
# Now we can stabilize new_base_ring=new_base_ring, check=check) # And use the standard lifting function for eigensymbols
class PSModularSymbolElement_dist(PSModularSymbolElement):
def reduce_precision(self, M): r""" Only hold on to `M` moments of each value of self
EXAMPLES::
sage: D = OverconvergentDistributions(0, 5, 10) sage: M = PollackStevensModularSymbols(Gamma0(5), coefficients=D) sage: f = M(1) sage: f.reduce_precision(1) Modular symbol of level 5 with values in Space of 5-adic distributions with k=0 action and precision cap 10 """ construct=True)
def precision_relative(self): r""" Return the number of moments of each value of self
EXAMPLES::
sage: D = OverconvergentDistributions(0, 5, 10) sage: M = PollackStevensModularSymbols(Gamma0(5), coefficients=D) sage: f = M(1) sage: f.precision_relative() 1 """
def specialize(self, new_base_ring=None): r""" Return the underlying classical symbol of weight `k` - i.e., applies the canonical map `D_k \to Sym^k` to all values of self.
EXAMPLES::
sage: D = OverconvergentDistributions(0, 5, 10); M = PollackStevensModularSymbols(Gamma0(5), coefficients=D); M Space of overconvergent modular symbols for Congruence Subgroup Gamma0(5) with sign 0 and values in Space of 5-adic distributions with k=0 action and precision cap 10 sage: f = M(1) sage: f.specialize() Modular symbol of level 5 with values in Sym^0 Z_5^2 sage: f.specialize().values() [1 + O(5), 1 + O(5), 1 + O(5)] sage: f.values() [1 + O(5), 1 + O(5), 1 + O(5)] sage: f.specialize().parent() Space of modular symbols for Congruence Subgroup Gamma0(5) with sign 0 and values in Sym^0 Z_5^2 sage: f.specialize().parent().coefficient_module() Sym^0 Z_5^2 sage: f.specialize().parent().coefficient_module().is_symk() True sage: f.specialize(Qp(5,20)) Modular symbol of level 5 with values in Sym^0 Q_5^2 """ self.parent()._specialize_parent_space(new_base_ring), construct=True)
def padic_lseries(self,*args, **kwds): """ Return the `p`-adic L-series of this modular symbol.
EXAMPLES::
sage: E = EllipticCurve('37a') sage: phi = E.pollack_stevens_modular_symbol() sage: L = phi.lift(37, M=6, eigensymbol=True).padic_lseries(); L # long time 37-adic L-series of Modular symbol of level 37 with values in Space of 37-adic distributions with k=0 action and precision cap 7 sage: L.series(2) # long time O(37^6) + (4 + 37 + 36*37^2 + 19*37^3 + 21*37^4 + O(37^5))*T + O(T^2) """ |