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