def _possible_normalizers(E, SA): r"""Find a list containing all primes `l` such that the Galois image at `l` is contained in the normalizer of a Cartan subgroup, such that the corresponding quadratic character is ramified only at the given primes. INPUT: - ``E`` - EllipticCurve - over a number field K. - ``SA`` - list - a list of primes of K. OUTPUT: - list - A list of primes, which contains all primes `l` such that the Galois image at `l` is contained in the normalizer of a Cartan subgroup, such that the corresponding quadratic character is ramified only at primes in SA. - If `E` has geometric CM that is not defined over its ground field, a ValueError is raised. EXAMPLES:: sage: E = EllipticCurve([0,0,0,-56,4848]) sage: 5 in sage.schemes.elliptic_curves.gal_reps_number_field._possible_normalizers(E, [ZZ.ideal(2)]) True """ E = _over_numberfield(E) K = E.base_field() SA = [K.ideal(I.gens()) for I in SA] x = K['x'].gen() selmer_group = K.selmer_group(SA, 2) # Generators of the selmer group. if selmer_group == []: return [] V = VectorSpace(GF(2), len(selmer_group)) # We think of this as the character group of the selmer group. traces_list = [] W = V.zero_subspace() deg_one_primes = K.primes_of_degree_one_iter() while W.dimension() < V.dimension() - 1: P = deg_one_primes.next() k = P.residue_field() defines_valid_character = True # A prime P defines a quadratic residue character # on the Selmer group. This variable will be set # to zero if any elements of the selmer group are # zero mod P (i.e. the character is ramified). splitting_vector = [] # This will be the values of this # character on the generators of the Selmer group. for a in selmer_group: abar = k(a) if abar == 0: # Ramification. defines_valid_character = False break if abar.is_square(): splitting_vector.append(GF(2)(0)) else: splitting_vector.append(GF(2)(1)) if not defines_valid_character: continue if splitting_vector in W: continue try: Etilde = E.change_ring(k) except ArithmeticError: # Bad reduction. continue tr = Etilde.trace_of_frobenius() if tr == 0: continue traces_list.append(tr) W = W + V.span([splitting_vector]) bad_primes = set([]) for i in traces_list: for p in i.prime_factors(): bad_primes.add(p) # We find the unique vector v in V orthogonal to W: v = W.matrix().transpose().kernel().basis()[0] # We find the element a of the selmer group corresponding to v: a = 1 for i in xrange(len(selmer_group)): if v[i] == 1: a *= selmer_group[i] # Since we've already included the above bad primes, we can assume # that the quadratic character corresponding to the exceptional primes # we're looking for is given by mapping into Gal(K[\sqrt{a}]/K). patience = 5 * K.degree() # Number of Frobenius elements to check before suspecting that E # has CM and computing the set of CM j-invariants of K to check. # TODO: Is this the best value for this parameter? while True: P = deg_one_primes.next() k = P.residue_field() if not k(a).is_square(): try: tr = E.change_ring(k).trace_of_frobenius() except ArithmeticError: # Bad reduction. continue if tr == 0: patience -= 1 if patience == 0: # We suspect E has CM, so we check: if E.j_invariant() in cm_j_invariants(K): raise ValueError("The curve E should not have CM.") else: for p in tr.prime_factors(): bad_primes.add(p) bad_primes = sorted(bad_primes) return bad_primes
def _possible_normalizers(E, SA): r"""Find a list containing all primes `l` such that the Galois image at `l` is contained in the normalizer of a Cartan subgroup, such that the corresponding quadratic character is ramified only at the given primes. INPUT: - ``E`` - EllipticCurve - over a number field K. - ``SA`` - list - a list of primes of K. OUTPUT: - list - A list of primes, which contains all primes `l` such that the Galois image at `l` is contained in the normalizer of a Cartan subgroup, such that the corresponding quadratic character is ramified only at primes in SA. - If `E` has geometric CM that is not defined over its ground field, a ValueError is raised. EXAMPLES:: sage: E = EllipticCurve([0,0,0,-56,4848]) sage: 5 in sage.schemes.elliptic_curves.gal_reps_number_field._possible_normalizers(E, [ZZ.ideal(2)]) True """ E = _over_numberfield(E) K = E.base_field() SA = [K.ideal(I.gens()) for I in SA] x = K['x'].gen() selmer_group = K.selmer_group(SA, 2) # Generators of the selmer group. if selmer_group == []: return [] V = VectorSpace(GF(2), len(selmer_group)) # We think of this as the character group of the selmer group. traces_list = [] W = V.zero_subspace() deg_one_primes = K.primes_of_degree_one_iter() while W.dimension() < V.dimension() - 1: P = next(deg_one_primes) k = P.residue_field() defines_valid_character = True # A prime P defines a quadratic residue character # on the Selmer group. This variable will be set # to zero if any elements of the selmer group are # zero mod P (i.e. the character is ramified). splitting_vector = [] # This will be the values of this # character on the generators of the Selmer group. for a in selmer_group: abar = k(a) if abar == 0: # Ramification. defines_valid_character = False break if abar.is_square(): splitting_vector.append(GF(2)(0)) else: splitting_vector.append(GF(2)(1)) if not defines_valid_character: continue if splitting_vector in W: continue try: Etilde = E.change_ring(k) except ArithmeticError: # Bad reduction. continue tr = Etilde.trace_of_frobenius() if tr == 0: continue traces_list.append(tr) W = W + V.span([splitting_vector]) bad_primes = set([]) for i in traces_list: for p in i.prime_factors(): bad_primes.add(p) # We find the unique vector v in V orthogonal to W: v = W.matrix().transpose().kernel().basis()[0] # We find the element a of the selmer group corresponding to v: a = 1 for i in xrange(len(selmer_group)): if v[i] == 1: a *= selmer_group[i] # Since we've already included the above bad primes, we can assume # that the quadratic character corresponding to the exceptional primes # we're looking for is given by mapping into Gal(K[\sqrt{a}]/K). patience = 5 * K.degree() # Number of Frobenius elements to check before suspecting that E # has CM and computing the set of CM j-invariants of K to check. # TODO: Is this the best value for this parameter? while True: P = next(deg_one_primes) k = P.residue_field() if not k(a).is_square(): try: tr = E.change_ring(k).trace_of_frobenius() except ArithmeticError: # Bad reduction. continue if tr == 0: patience -= 1 if patience == 0: # We suspect E has CM, so we check: if E.j_invariant() in cm_j_invariants(K): raise ValueError("The curve E should not have CM.") else: for p in tr.prime_factors(): bad_primes.add(p) bad_primes = sorted(bad_primes) return bad_primes
def _semistable_reducible_primes(E): r"""Find a list containing all semistable primes l unramified in K/QQ for which the Galois image for E could be reducible. INPUT: - ``E`` - EllipticCurve - over a number field. OUTPUT: list - A list of primes, which contains all primes l unramified in K/QQ, such that E is semistable at all primes lying over l, and the Galois image at l is reducible. If E has CM defined over its ground field, a ValueError is raised. EXAMPLES:: sage: E = EllipticCurve([0, -1, 1, -10, -20]) # X_0(11) sage: 5 in sage.schemes.elliptic_curves.gal_reps_number_field._semistable_reducible_primes(E) True """ E = _over_numberfield(E) K = E.base_field() deg_one_primes = K.primes_of_degree_one_iter() bad_primes = set([]) # This will store the output. # We find two primes (of distinct residue characteristics) which are # of degree 1, unramified in K/Q, and at which E has good reduction. # Both of these primes will give us a nontrivial divisibility constraint # on the exceptional primes l. For both of these primes P, we precompute # a generator and the trace of Frob_P^12. precomp = [] last_char = 0 # The residue characteristic of the most recent prime. while len(precomp) < 2: P = deg_one_primes.next() if not P.is_principal(): continue det = P.norm() if det == last_char: continue if P.ramification_index() != 1: continue try: tr = E.change_ring(P.residue_field()).trace_of_frobenius() except ArithmeticError: # Bad reduction at P. continue x = P.gens_reduced()[0] precomp.append((x, _tr12(tr, det))) last_char = det x, tx = precomp[0] y, ty = precomp[1] Kgal = K.galois_closure('b') maps = K.embeddings(Kgal) for i in xrange(2 ** (K.degree() - 1)): ## We iterate through all possible characters. ## # Here, if i = i_{l-1} i_{l-2} cdots i_1 i_0 in binary, then i # corresponds to the character prod sigma_j^{i_j}. phi1x = 1 phi2x = 1 phi1y = 1 phi2y = 1 # We compute the two algebraic characters at x and y: for j in xrange(K.degree()): if i % 2 == 1: phi1x *= maps[j](x) phi1y *= maps[j](y) else: phi2x *= maps[j](x) phi2y *= maps[j](y) i = int(i/2) # Any prime with reducible image must divide both of: gx = phi1x**12 + phi2x**12 - tx gy = phi1y**12 + phi2y**12 - ty if (gx != 0) or (gy != 0): for prime in Integer(Kgal.ideal([gx, gy]).norm()).prime_factors(): bad_primes.add(prime) continue ## It is possible that our curve has CM. ## # Our character must be of the form Nm^K_F for an imaginary # quadratic subfield F of K (which is the CM field if E has CM). # We compute F: a = (Integer(phi1x + phi2x)**2 - 4 * x.norm()).squarefree_part() y = QQ['y'].gen() F = NumberField(y**2 - a, 'a') # Next, we turn K into relative number field over F. K = K.relativize(F.embeddings(K)[0], 'b') E = E.change_ring(K.structure()[1]) ## We try to find a nontrivial divisibility condition. ## patience = 5 * K.absolute_degree() # Number of Frobenius elements to check before suspecting that E # has CM and computing the set of CM j-invariants of K to check. # TODO: Is this the best value for this parameter? while True: P = deg_one_primes.next() if not P.is_principal(): continue try: tr = E.change_ring(P.residue_field()).trace_of_frobenius() except ArithmeticError: # Bad reduction at P. continue x = P.gens_reduced()[0].norm(F) div = (x**12).trace() - _tr12(tr, x.norm()) patience -= 1 if div != 0: # We found our divisibility constraint. for prime in Integer(div).prime_factors(): bad_primes.add(prime) # Turn K back into an absolute number field. E = E.change_ring(K.structure()[0]) K = K.structure()[0].codomain() break if patience == 0: # We suspect that E has CM, so we check: f = K.structure()[0] if f(E.j_invariant()) in cm_j_invariants(f.codomain()): raise ValueError("The curve E should not have CM.") L = sorted(bad_primes) return L
def _semistable_reducible_primes(E): r"""Find a list containing all semistable primes l unramified in K/QQ for which the Galois image for E could be reducible. INPUT: - ``E`` - EllipticCurve - over a number field. OUTPUT: A list of primes, which contains all primes `l` unramified in `K/\mathbb{QQ}`, such that `E` is semistable at all primes lying over `l`, and the Galois image at `l` is reducible. If `E` has CM defined over its ground field, a ``ValueError`` is raised. EXAMPLES:: sage: E = EllipticCurve([0, -1, 1, -10, -20]) # X_0(11) sage: 5 in sage.schemes.elliptic_curves.gal_reps_number_field._semistable_reducible_primes(E) True """ E = _over_numberfield(E) K = E.base_field() deg_one_primes = K.primes_of_degree_one_iter() bad_primes = set([]) # This will store the output. # We find two primes (of distinct residue characteristics) which are # of degree 1, unramified in K/Q, and at which E has good reduction. # Both of these primes will give us a nontrivial divisibility constraint # on the exceptional primes l. For both of these primes P, we precompute # a generator and the trace of Frob_P^12. precomp = [] last_char = 0 # The residue characteristic of the most recent prime. while len(precomp) < 2: P = next(deg_one_primes) if not P.is_principal(): continue det = P.norm() if det == last_char: continue if P.ramification_index() != 1: continue try: tr = E.change_ring(P.residue_field()).trace_of_frobenius() except ArithmeticError: # Bad reduction at P. continue x = P.gens_reduced()[0] precomp.append((x, _tr12(tr, det))) last_char = det x, tx = precomp[0] y, ty = precomp[1] Kgal = K.galois_closure('b') maps = K.embeddings(Kgal) for i in xrange(2**(K.degree() - 1)): ## We iterate through all possible characters. ## # Here, if i = i_{l-1} i_{l-2} cdots i_1 i_0 in binary, then i # corresponds to the character prod sigma_j^{i_j}. phi1x = 1 phi2x = 1 phi1y = 1 phi2y = 1 # We compute the two algebraic characters at x and y: for j in xrange(K.degree()): if i % 2 == 1: phi1x *= maps[j](x) phi1y *= maps[j](y) else: phi2x *= maps[j](x) phi2y *= maps[j](y) i = int(i / 2) # Any prime with reducible image must divide both of: gx = phi1x**12 + phi2x**12 - tx gy = phi1y**12 + phi2y**12 - ty if (gx != 0) or (gy != 0): for prime in Integer(Kgal.ideal([gx, gy]).norm()).prime_factors(): bad_primes.add(prime) continue ## It is possible that our curve has CM. ## # Our character must be of the form Nm^K_F for an imaginary # quadratic subfield F of K (which is the CM field if E has CM). # We compute F: a = (Integer(phi1x + phi2x)**2 - 4 * x.norm()).squarefree_part() y = QQ['y'].gen() F = NumberField(y**2 - a, 'a') # Next, we turn K into relative number field over F. K = K.relativize(F.embeddings(K)[0], 'b') E = E.change_ring(K.structure()[1]) ## We try to find a nontrivial divisibility condition. ## patience = 5 * K.absolute_degree() # Number of Frobenius elements to check before suspecting that E # has CM and computing the set of CM j-invariants of K to check. # TODO: Is this the best value for this parameter? while True: P = next(deg_one_primes) if not P.is_principal(): continue try: tr = E.change_ring(P.residue_field()).trace_of_frobenius() except ArithmeticError: # Bad reduction at P. continue x = P.gens_reduced()[0].norm(F) div = (x**12).trace() - _tr12(tr, x.norm()) patience -= 1 if div != 0: # We found our divisibility constraint. for prime in Integer(div).prime_factors(): bad_primes.add(prime) # Turn K back into an absolute number field. E = E.change_ring(K.structure()[0]) K = K.structure()[0].codomain() break if patience == 0: # We suspect that E has CM, so we check: f = K.structure()[0] if f(E.j_invariant()) in cm_j_invariants(f.codomain()): raise ValueError("The curve E should not have CM.") L = sorted(bad_primes) return L