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 [PS2011].
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)]
- class sage.modular.pollack_stevens.modsym.PSModSymAction(actor, MSspace)¶
Bases:
sage.categories.action.Action
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
- class sage.modular.pollack_stevens.modsym.PSModularSymbolElement(map_data, parent, construct=False)¶
Bases:
sage.structure.element.ModuleElement
Initialize a modular symbol
EXAMPLES:
sage: E = EllipticCurve('37a') sage: phi = E.pollack_stevens_modular_symbol()
- Tq_eigenvalue(q, p=None, M=None, check=True)¶
Eigenvalue of \(T_q\) modulo \(p^M\)
INPUT:
q
– prime of the Hecke operatorp
– prime we are working modulo (default: None)M
– degree of accuracy of approximation (default: None)check
– check thatself
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
- diagonal_valuation(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
- dict()¶
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
- evaluate_twisted(a, chi)¶
Return \(\Phi_{\chi}(\{a/p\}-\{\infty\})\) where \(\Phi\) is
self
and \(\chi\) is a quadratic characterINPUT:
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))
- hecke(ell, algorithm='prep')¶
Return self | \(T_{\ell}\) by making use of the precomputations in self.prep_hecke()
INPUT:
ell
– a primealgorithm
– 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
- is_Tq_eigensymbol(q, p=None, M=None)¶
Determine if self is an eigenvector for \(T_q\) modulo \(p^M\)
INPUT:
q
– prime of the Hecke operatorp
– prime we are working moduloM
– 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
- is_ordinary(p=None, P=None)¶
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
- minus_part()¶
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
- plus_part()¶
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
- valuation(p=None)¶
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
- values()¶
Return the values of the symbol
self
on our chosen generators.The generators are listed in
self.dict()
.EXAMPLES:
sage: E = EllipticCurve('11a') sage: phi = E.pollack_stevens_modular_symbol() sage: phi.values() [-1/5, 1, 0] sage: sorted(phi.dict()) [ [-1 -1] [ 0 -1] [1 0] [ 3 2], [ 1 3], [0 1] ] sage: sorted(phi.values()) == sorted(phi.dict().values()) True
- weight()¶
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
- class sage.modular.pollack_stevens.modsym.PSModularSymbolElement_dist(map_data, parent, construct=False)¶
Bases:
sage.modular.pollack_stevens.modsym.PSModularSymbolElement
- padic_lseries(*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)
- precision_relative()¶
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
- reduce_precision(M)¶
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
- specialize(new_base_ring=None)¶
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
- class sage.modular.pollack_stevens.modsym.PSModularSymbolElement_symk(map_data, parent, construct=False)¶
Bases:
sage.modular.pollack_stevens.modsym.PSModularSymbolElement
- completions(p, M)¶
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
– primeM
– 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'])
- lift(p=None, M=None, alpha=None, new_base_ring=None, algorithm=None, eigensymbol=False, check=True)¶
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
– primeM
– integer equal to the number of momentsalpha
– \(U_p\) eigenvaluenew_base_ring
– change of base ringalgorithm
– ‘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. Ifeigensymbol = 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_stabilize(p=None, M=20, alpha=None, ap=None, new_base_ring=None, ordinary=True, check=True)¶
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 selfM
– (default: 20) precision of \(\QQ_p\)alpha
– \(U_p\) eigenvalueap
– Hecke eigenvaluenew_base_ring
– change of base ringordinary
– (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
- p_stabilize_and_lift(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 selfM
– precisionalpha
– (default: None) the \(U_p\) eigenvalue, if knownap
– (default: None) the Hecke eigenvalue at p (before stabilizing), if knownnew_base_ring
– (default: None) if specified, force the resulting eigensymbol to take values in the given ringordinary
– (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 liftcheck
– (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)