def upper_bound_on_elliptic_factors(self, p=None, ellmax=2): r""" Return an upper bound (provably correct) on the number of elliptic curves of conductor equal to the level of this supersingular module. INPUT: - ``p`` - (default: 997) prime to work modulo ALGORITHM: Currently we only use `T_2`. Function will be extended to use more Hecke operators later. The prime p is replaced by the smallest prime that doesn't divide the level. EXAMPLE:: sage: SupersingularModule(37).upper_bound_on_elliptic_factors() 2 (There are 4 elliptic curves of conductor 37, but only 2 isogeny classes.) """ # NOTE: The heuristic runtime is *very* roughly `p^2/(2\cdot 10^6)`. #ellmax -- (default: 2) use Hecke operators T_ell with ell <= ellmax if p is None: p = 997 while self.level() % p == 0: p = rings.next_prime(p) ell = 2 t = self.hecke_matrix(ell).change_ring(rings.GF(p)) # TODO: temporarily try using sparse=False # turn this off when sparse rank is optimized. t = t.dense_matrix() B = 2 * math.sqrt(ell) bnd = 0 lower = -int(math.floor(B)) upper = int(math.floor(B)) + 1 for a in range(lower, upper): tm = verbose("computing T_%s - %s" % (ell, a)) if a == lower: c = a else: c = 1 for i in range(t.nrows()): t[i, i] += c tm = verbose("computing kernel", tm) #dim = t.kernel().dimension() dim = t.nrows() - t.rank() bnd += dim verbose('got dimension = %s; new bound = %s' % (dim, bnd), tm) return bnd
def upper_bound_on_elliptic_factors(self, p=None, ellmax=2): r""" Return an upper bound (provably correct) on the number of elliptic curves of conductor equal to the level of this supersingular module. INPUT: - ``p`` - (default: 997) prime to work modulo ALGORITHM: Currently we only use `T_2`. Function will be extended to use more Hecke operators later. The prime p is replaced by the smallest prime that doesn't divide the level. EXAMPLE:: sage: SupersingularModule(37).upper_bound_on_elliptic_factors() 2 (There are 4 elliptic curves of conductor 37, but only 2 isogeny classes.) """ # NOTE: The heuristic runtime is *very* roughly `p^2/(2\cdot 10^6)`. # ellmax -- (default: 2) use Hecke operators T_ell with ell <= ellmax if p is None: p = 997 while self.level() % p == 0: p = rings.next_prime(p) ell = 2 t = self.hecke_matrix(ell).change_ring(rings.GF(p)) # TODO: temporarily try using sparse=False # turn this off when sparse rank is optimized. t = t.dense_matrix() B = 2 * math.sqrt(ell) bnd = 0 lower = -int(math.floor(B)) upper = int(math.floor(B)) + 1 for a in range(lower, upper): tm = verbose("computing T_%s - %s" % (ell, a)) if a == lower: c = a else: c = 1 for i in range(t.nrows()): t[i, i] += c tm = verbose("computing kernel", tm) # dim = t.kernel().dimension() dim = t.nrows() - t.rank() bnd += dim verbose("got dimension = %s; new bound = %s" % (dim, bnd), tm) return bnd
def next_prime_not_dividing(P, I): while True: p = P.smallest_integer() if p == 1: Q = F.ideal(2) elif p % 5 in [2,3]: # inert Q = F.primes_above(next_prime(p))[0] elif p == 5: Q = F.ideal(7) else: # p split A = F.primes_above(p) if A[0] == P: Q = A[1] else: Q = F.primes_above(next_prime(p))[0] if not Q.divides(I): return Q else: P = Q # try again
def max_det_prime(n): """ Return the largest prime so that it is reasonably efficiency to compute modulo that prime with n x n matrices in LinBox. INPUT: n -- a positive integer OUTPUT: a prime number EXAMPLES: sage: from sage.matrix.matrix_integer_dense_hnf import max_det_prime sage: max_det_prime(10000) 524309 sage: max_det_prime(1000) 2097169 sage: max_det_prime(10) 16777259 """ k = int(26 - math.ceil(math.log(n)*0.7213475205)) return next_prime(2**k)
def modular_symbols_from_curve(C, N, num_factors=3): """ Find the modular symbols spaces that shoudl correspond to the Jacobian of the given hyperelliptic curve, up to the number of factors we consider. INPUT: - C -- a hyperelliptic curve over QQ - N -- a positive integer - num_factors -- number of Euler factors to verify match up; this is important, because if, e.g., there is only one factor of degree g(C), we don't want to just immediately conclude that Jac(C) = A_f. OUTPUT: - list of all sign 1 simple modular symbols factor of level N that correspond to a simple modular abelian A_f that is isogenous to Jac(C). EXAMPLES:: sage: from psage.modform.rational.unfiled import modular_symbols_from_curve sage: R.<x> = ZZ[] sage: f = x^7+4*x^6+5*x^5+x^4-3*x^3-2*x^2+1 sage: C1 = HyperellipticCurve(f) sage: modular_symbols_from_curve(C1, 284) [Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 39 for Gamma_0(284) of weight 2 with sign 1 over Rational Field] sage: f = x^7-7*x^5-11*x^4+5*x^3+18*x^2+4*x-11 sage: C2 = HyperellipticCurve(f) sage: modular_symbols_from_curve(C2, 284) [Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 39 for Gamma_0(284) of weight 2 with sign 1 over Rational Field] """ # We will use the Eichler-Shimura relation and David Harvey's # p-adic point counting hypellfrob. Harvey's code has the # constraint: p > (2*g + 1)*(2*prec - 1). # So, find the smallest p not dividing N that satisfies the # above constraint, for our given choice of prec. f, f2 = C.hyperelliptic_polynomials() if f2 != 0: raise NotImplementedError, "curve must be of the form y^2 = f(x)" if f.degree() % 2 == 0: raise NotImplementedError, "curve must be of the form y^2 = f(x) with f(x) odd" prec = 1 g = C.genus() B = (2 * g + 1) * (2 * prec - 1) from sage.rings.all import next_prime p = B # We use that if F(X) is the characteristic polynomial of the # Hecke operator T_p, then X^g*F(X+p/X) is the characteristic # polynomial of Frob_p, because T_p = Frob_p + p/Frob_p, according # to Eichler-Shimura. Use this to narrow down the factors. from sage.all import ModularSymbols, Integers, get_verbose D = ModularSymbols( N, sign=1).cuspidal_subspace().new_subspace().decomposition() D = [A for A in D if A.dimension() == g] from sage.schemes.hyperelliptic_curves.hypellfrob import hypellfrob while num_factors > 0: p = next_prime(p) while N % p == 0: p = next_prime(p) R = Integers(p**prec)['X'] X = R.gen() D2 = [] # Compute the charpoly of Frobenius using hypellfrob M = hypellfrob(p, 1, f) H = R(M.charpoly()) for A in D: F = R(A.hecke_polynomial(p)) # Compute charpoly of Frobenius from F(X) G = R(F.parent()(X**g * F(X + p / X))) if get_verbose(): print(p, G, H) if G == H: D2.append(A) D = D2 num_factors -= 1 return D
def next_prime_of_characteristic_coprime_to(P, I): p = next_prime(P.smallest_integer()) N = ZZ(I.norm()) while N%p == 0: p = next_prime(p) return F.primes_above(p)[0]
def modular_symbols_from_curve(C, N, num_factors=3): """ Find the modular symbols spaces that shoudl correspond to the Jacobian of the given hyperelliptic curve, up to the number of factors we consider. INPUT: - C -- a hyperelliptic curve over QQ - N -- a positive integer - num_factors -- number of Euler factors to verify match up; this is important, because if, e.g., there is only one factor of degree g(C), we don't want to just immediately conclude that Jac(C) = A_f. OUTPUT: - list of all sign 1 simple modular symbols factor of level N that correspond to a simple modular abelian A_f that is isogenous to Jac(C). EXAMPLES:: sage: from psage.modform.rational.unfiled import modular_symbols_from_curve sage: R.<x> = ZZ[] sage: f = x^7+4*x^6+5*x^5+x^4-3*x^3-2*x^2+1 sage: C1 = HyperellipticCurve(f) sage: modular_symbols_from_curve(C1, 284) [Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 39 for Gamma_0(284) of weight 2 with sign 1 over Rational Field] sage: f = x^7-7*x^5-11*x^4+5*x^3+18*x^2+4*x-11 sage: C2 = HyperellipticCurve(f) sage: modular_symbols_from_curve(C2, 284) [Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 39 for Gamma_0(284) of weight 2 with sign 1 over Rational Field] """ # We will use the Eichler-Shimura relation and David Harvey's # p-adic point counting hypellfrob. Harvey's code has the # constraint: p > (2*g + 1)*(2*prec - 1). # So, find the smallest p not dividing N that satisfies the # above constraint, for our given choice of prec. f, f2 = C.hyperelliptic_polynomials() if f2 != 0: raise NotImplementedError, "curve must be of the form y^2 = f(x)" if f.degree() % 2 == 0: raise NotImplementedError, "curve must be of the form y^2 = f(x) with f(x) odd" prec = 1 g = C.genus() B = (2*g + 1)*(2*prec - 1) from sage.rings.all import next_prime p = B # We use that if F(X) is the characteristic polynomial of the # Hecke operator T_p, then X^g*F(X+p/X) is the characteristic # polynomial of Frob_p, because T_p = Frob_p + p/Frob_p, according # to Eichler-Shimura. Use this to narrow down the factors. from sage.all import ModularSymbols, Integers, get_verbose D = ModularSymbols(N,sign=1).cuspidal_subspace().new_subspace().decomposition() D = [A for A in D if A.dimension() == g] from sage.schemes.hyperelliptic_curves.hypellfrob import hypellfrob while num_factors > 0: p = next_prime(p) while N % p == 0: p = next_prime(p) R = Integers(p**prec)['X'] X = R.gen() D2 = [] # Compute the charpoly of Frobenius using hypellfrob M = hypellfrob(p, 1, f) H = R(M.charpoly()) for A in D: F = R(A.hecke_polynomial(p)) # Compute charpoly of Frobenius from F(X) G = R(F.parent()(X**g * F(X + p/X))) if get_verbose(): print (p, G, H) if G == H: D2.append(A) D = D2 num_factors -= 1 return D