def weil_representation_kernel(self): r""" Compute a scalar `r` and a group `\Gamma` which contains the translation `T` so that `\diag(1, 1/r) \Gamma \diag(1, r) \subseteq \ker( \rho_D )`. OUTPUT: - A pair of an integer and an arithmetic group. """ if self._L == matrix( 2, [2, 1, 1, 2]) or self._L == -matrix(2, [2, 1, 1, 2]): return (ZZ(3), GammaH(9, [4])) if self._L == matrix( 2, [2, 0, 0, 2]) or self._L == -matrix(2, [2, 0, 0, 2]): return (ZZ(4), GammaH(16, [5])) if self._L == matrix( 2, [2, 0, 0, 4]) or self._L == -matrix(2, [2, 0, 0, 4]): return (ZZ(8), GammaH(64, [57])) level = 2 * self._L.inverse().denominator() return (level, GammaH(level**2, filter(lambda n: n % level == 1, range(level**2))))
def JH(N, H): """ Return the Jacobian `J_H(N)` of the modular curve `X_H(N)`. EXAMPLES:: sage: JH(389,[16]) Abelian variety JH(389,[16]) of dimension 64 """ key = 'JH(%s,%s)' % (N, H) try: return _get(key) except ValueError: from sage.modular.arithgroup.all import GammaH return _saved(key, GammaH(N, H).modular_abelian_variety())
def group(self): r""" Return a `\Gamma_H` group which is the level of all of the relevant twists of `f`. EXAMPLE:: sage: from sage.modular.local_comp.type_space import example_type_space sage: example_type_space().group() Congruence Subgroup Gamma_H(98) with H generated by [57] """ p = self.prime() r = self.conductor() d = max(self.character_conductor(), r // 2) n = self.tame_level() chi = self.form().character() tame_H = [i for i in chi.kernel() if (i % p**r) == 1] wild_H = [crt(1 + p**d, 1, p**r, n)] return GammaH(n * p**r, tame_H + wild_H)
def group(self): r""" Return a `\Gamma_H` group which is the level of all of the relevant twists of `f`. EXAMPLES:: sage: from sage.modular.local_comp.type_space import example_type_space sage: example_type_space().group() Congruence Subgroup Gamma_H(98) with H generated by [15, 29, 43] """ # Implementation here is not the most efficient but this is heavily not # time-critical, and getting it wrong can lead to subtle bugs. p = self.prime() r = self.conductor() d = max(self.character_conductor(), r // 2) n = self.tame_level() chi = self.form().character() tame_H = [i for i in chi.kernel() if (i % p**r) == 1] wild_H = [crt(x, 1, p**r, n) for x in range(p**r) if x % (p**d) == 1] return GammaH(n * p**r, tame_H + wild_H)
def __init__(self, index=20, index_max=50, odd_probability=0.5): r""" Create an arithmetic subgroup testing object. INPUT: - ``index`` - the index of random subgroup to test - ``index_max`` - the maximum index for congruence subgroup to test EXAMPLES:: sage: from sage.modular.arithgroup.tests import Test sage: Test() Arithmetic subgroup testing class """ self.congroups = [] i = 1 self.odd_probability = odd_probability if index % 4: self.odd_probability = 0 while Gamma(i).index() < index_max: self.congroups.append(Gamma(i)) i += 1 i = 1 while Gamma0(i).index() < index_max: self.congroups.append(Gamma0(i)) i += 1 i = 2 while Gamma1(i).index() < index_max: self.congroups.append(Gamma1(i)) M = Zmod(i) U = [x for x in M if x.is_unit()] for j in range(1, len(U) - 1): self.congroups.append(GammaH(i, prandom.sample(U, j))) i += 1 self.index = index
def hecke_stable_subspace(chi, aux_prime=ZZ(2)): r""" Compute a q-expansion basis for S_1(chi). Results are returned as q-expansions to a certain fixed (and fairly high) precision. If more precision is required this can be obtained with :func:`modular_ratio_to_prec`. EXAMPLES:: sage: from sage.modular.modform.weight1 import hecke_stable_subspace sage: hecke_stable_subspace(DirichletGroup(59, QQ).0) [q - q^3 + q^4 - q^5 - q^7 - q^12 + q^15 + q^16 + 2*q^17 - q^19 - q^20 + q^21 + q^27 - q^28 - q^29 + q^35 + O(q^40)] """ # Deal quickly with the easy cases. if chi(-1) == 1: return [] N = chi.modulus() H = chi.kernel() G = GammaH(N, H) try: if ArithmeticSubgroup.dimension_cusp_forms(G, 1) == 0: verbose("no wt 1 cusp forms for N=%s, chi=%s by Riemann-Roch" % (N, chi._repr_short_()), level=1) return [] except NotImplementedError: pass from sage.modular.modform.constructor import EisensteinForms chi = chi.minimize_base_ring() K = chi.base_ring() # Auxiliary prime for Hecke stability method l = aux_prime while l.divides(N): l = l.next_prime() verbose("Auxiliary prime: %s" % l, level=1) # Compute working precision R = l * Gamma0(N).sturm_bound(l + 2) t = verbose("Computing modular ratio space", level=1) mrs = modular_ratio_space(chi) t = verbose("Computing modular ratios to precision %s" % R, level=1) qexps = [modular_ratio_to_prec(chi, f, R) for f in mrs] verbose("Done", t=t, level=1) # We want to compute the largest subspace of I stable under T_l. To do # this, we compute I intersect T_l(I) modulo q^(R/l), and take its preimage # under T_l, which is then well-defined modulo q^R. from sage.modular.modform.hecke_operator_on_qexp import hecke_operator_on_qexp t = verbose("Computing Hecke-stable subspace", level=1) A = PowerSeriesRing(K, 'q') r = R // l V = K**R W = K**r Tl_images = [hecke_operator_on_qexp(f, l, 1, chi) for f in qexps] qvecs = [V(x.padded_list(R)) for x in qexps] qvecs_trunc = [W(x.padded_list(r)) for x in qexps] Tvecs = [W(x.padded_list(r)) for x in Tl_images] I = V.submodule(qvecs) Iimage = W.span(qvecs_trunc) TlI = W.span(Tvecs) Jimage = Iimage.intersection(TlI) J = I.Hom(W)(Tvecs).inverse_image(Jimage) verbose("Hecke-stable subspace is %s-dimensional" % J.dimension(), t=t, level=1) if J.rank() == 0: return [] # The theory does not guarantee that J is exactly S_1(chi), just that it is # intermediate between S_1(chi) and M_1(chi). In every example I know of, # it is equal to S_1(chi), but just for honesty, we check this anyway. t = verbose("Checking cuspidality", level=1) JEis = V.span( V(x.padded_list(R)) for x in EisensteinForms(chi, 1).q_echelon_basis(prec=R)) D = JEis.intersection(J) if D.dimension() != 0: raise ArithmeticError("Got non-cuspidal form!") verbose("Done", t=t, level=1) qexps = Sequence(A(x.list()).add_bigoh(R) for x in J.gens()) return qexps