def fix1_qcurve_flag(ec, verbose=False): """ Update ec structure (from nfcurves collection) with the correct q_curves flag. For degree >2 at present we only do trivial tests here which do not require any computation. """ if ec['q_curve']: # keep old True values return ec # Easy sufficient tests in all degrees qc = False if ec['cm']: qc = True elif all(c == '0' for c in ec['jinv'].split(",")[1:]): qc = True if qc: # then we have just set it to True if ec['q_curve'] != qc: if verbose: print("{}: changing q_curve flag from {} to {}".format( ec['label'], ec['q_curve'], qc)) ec['q_curve'] = qc return ec # else if degree != 2 just replace possibly false negatives with '?' if ec['degree'] > 2: qc = '?' # if ec['q_curve'] != qc: # print("{}: changing q_curve flag from {} to {}".format(ec['label'],ec['q_curve'],qc)) ec['q_curve'] = qc return ec # else (degree 2 only for now) do the work (knowing that E does # not have CM and j(E) is not in Q) K = FIELD(ec['field_label']) sigma = K.K().galois_group()[1] # Compute the Q-curve flag from scratch N = ideal_from_string(K.K(), ec['conductor_ideal']) if sigma(N) != N: qc = False else: # construct and check the curve ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) qc = is_Q_curve(E) if ec['q_curve'] != qc: if verbose: print("{}: changing q_curve flag from {} to {}".format( ec['label'], ec['q_curve'], qc)) ec['q_curve'] = qc return ec
def curves(line, verbose=False): r""" Parses one line from a curves file. Returns the label and a dict containing fields with keys 'field_label', 'degree', 'signature', 'abs_disc', 'label', 'short_label', conductor_label', 'conductor_ideal', 'conductor_norm', 'iso_label', 'iso_nlabel', 'number', 'ainvs', 'jinv', 'cm', 'q_curve', 'base_change', 'torsion_order', 'torsion_structure', 'torsion_gens'; and (added May 2016): 'equation', 'local_data', 'non_min_p', 'minD' Input line fields (13): field_label conductor_label iso_label number conductor_ideal conductor_norm a1 a2 a3 a4 a6 cm base_change Sample input line: 2.0.4.1 65.18.1 a 1 [65,18,1] 65 1,1 1,1 0,1 -1,1 -1,0 0 0 """ # Parse the line and form the full label: data = split(line) if len(data) != 13: print "line %s does not have 13 fields, skipping" % line field_label = data[0] # string IQF_flag = field_label.split(".")[:2] == ['2', '0'] K = nf_lookup(field_label) if IQF_flag else None conductor_label = data[1] # string # convert label (does nothing except for imaginary quadratic) conductor_label = convert_conductor_label(field_label, conductor_label) iso_label = data[2] # string iso_nlabel = numerify_iso_label(iso_label) # int number = int(data[3]) # int short_class_label = "%s-%s" % (conductor_label, iso_label) short_label = "%s%s" % (short_class_label, str(number)) class_label = "%s-%s" % (field_label, short_class_label) label = "%s-%s" % (field_label, short_label) conductor_ideal = data[4] # string conductor_norm = int(data[5]) # int ainvs = ";".join(data[6:11]) # one string joining 5 NFelt strings cm = data[11] # int or '?' if cm != '?': cm = int(cm) # Create the field and curve to compute the j-invariant: dummy, deg, sig, abs_disc = field_data(field_label) K = nf_lookup(field_label) #print("Field %s created, gen_name = %s" % (field_label,str(K.gen()))) ainvsK = parse_ainvs(K, ainvs) # list of K-elements E = EllipticCurve(ainvsK) #print("{} created with disc = {}, N(disc)={}".format(E,K.ideal(E.discriminant()).factor(),E.discriminant().norm().factor())) j = E.j_invariant() jinv = NFelt(j) if cm == '?': cm = get_cm(j) if cm: print "cm=%s for j=%s" % (cm, j) q_curve = data[12] # 0, 1 or ?. If unknown we'll determine this below. if q_curve in ['0', '1']: # already set -- easy q_curve = bool(int(q_curve)) else: try: q_curve = is_Q_curve(E) except NotImplementedError: q_curve = '?' # Here we should check that the conductor of the constructed curve # agrees with the input conductor. N = ideal_from_string(K, conductor_ideal) NE = E.conductor() if N == "wrong" or N != NE: print( "Wrong conductor ideal {} for label {}, using actual conductor {} instead" .format(conductor_ideal, label, NE)) conductor_ideal = ideal_to_string(NE) N = NE # get torsion order, structure and generators: torgroup = E.torsion_subgroup() ntors = int(torgroup.order()) torstruct = [int(n) for n in list(torgroup.invariants())] torgens = [point_string(P.element()) for P in torgroup.gens()] # get label of elliptic curve over Q for base_change cases (a # subset of Q-curves) if True: # q_curve: now we have not precomputed Q-curve status # but still want to test for base change! if verbose: print("testing {} for base-change...".format(label)) E1list = E.descend_to(QQ) if len(E1list): base_change = [cremona_to_lmfdb(E1.label()) for E1 in E1list] if verbose: print "%s is base change of %s" % (label, base_change) else: base_change = [] # print "%s is a Q-curve, but not base-change..." % label else: base_change = [] # NB if this is not a global minimal model then local_data may # include a prime at which we have good reduction. This causes no # problems except that the bad_reduction_type is then None which # cannot be converted to an integer. The bad reduction types are # coded as (Sage) integers in {-1,0,1}. local_data = [{ 'p': ideal_to_string(ld.prime()), 'normp': str(ld.prime().norm()), 'ord_cond': int(ld.conductor_valuation()), 'ord_disc': int(ld.discriminant_valuation()), 'ord_den_j': int(max(0, -(E.j_invariant().valuation(ld.prime())))), 'red': None if ld.bad_reduction_type() == None else int(ld.bad_reduction_type()), 'kod': web_latex(ld.kodaira_symbol()).replace('$', ''), 'cp': int(ld.tamagawa_number()) } for ld in E.local_data()] non_minimal_primes = [ideal_to_string(P) for P in E.non_minimal_primes()] minD = ideal_to_string(E.minimal_discriminant_ideal()) edata = { 'field_label': field_label, 'degree': deg, 'signature': sig, 'abs_disc': abs_disc, 'class_label': class_label, 'short_class_label': short_class_label, 'label': label, 'short_label': short_label, 'conductor_label': conductor_label, 'conductor_ideal': conductor_ideal, 'conductor_norm': conductor_norm, 'iso_label': iso_label, 'iso_nlabel': iso_nlabel, 'number': number, 'ainvs': ainvs, 'jinv': jinv, 'cm': cm, 'q_curve': q_curve, 'base_change': base_change, 'torsion_order': ntors, 'torsion_structure': torstruct, 'torsion_gens': torgens, 'equation': web_latex(E), 'local_data': local_data, 'minD': minD, 'non_min_p': non_minimal_primes, } return label, edata
def check_Q_curves(field_label='2.2.5.1', min_norm=0, max_norm=None, fix=False, verbose=False): """Given a (quadratic) field label test all curves E over that field for being Q-curves. """ query = {} query['field_label'] = field_label query['conductor_norm'] = {'$gte': int(min_norm)} if max_norm: query['conductor_norm']['$lte'] = int(max_norm) else: max_norm = 'infinity' cursor = nfcurves.find(query) # keep the curves and re-find them, else the cursor times out. curves = [ec['label'] for ec in cursor] ncurves = len(curves) print("Checking {} curves over field {}".format(ncurves, field_label)) K = FIELD(field_label) sigma = K.K().galois_group()[1] bad1 = [] bad2 = [] count = 0 for label in curves: count += 1 if count % 1000 == 0: print("checked {} curves ({}%)".format(count, 100.0 * count / ncurves)) ec = nfcurves.find_one({'label': label}) assert label == ec['label'] method = None # first check that j(E) is rational (no computation needed) jinv = ec['jinv'] if all(c == '0' for c in jinv.split(",")[1:]): if verbose: print("{}: j in QQ".format(label)) qc = True method = "j in Q" elif ec['cm']: if verbose: print("{}: CM".format(label)) qc = True method = "CM" else: # construct and check the conductor if verbose: print("{}: checking conductor".format(label)) N = ideal_from_string(K.K(), ec['conductor_ideal']) if sigma(N) != N: qc = False method = "conductor" else: # construct and check the curve if verbose: print("{}: checking isogenies".format(label)) ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) qc = is_Q_curve(E) method = "isogenies" db_qc = ec['q_curve'] if qc and not db_qc: print("Curve {} is a Q-curve (using {}) but database thinks not". format(label, method)) bad1 += [label] elif db_qc and not qc: print( "Curve {} is not a Q-curve (using {}) but database thinks it is" .format(label, method)) bad2 += [label] else: if verbose: print("Curve {} OK (using {})".format(label, method)) print( "{} curves in the database are incorrectly labelled as being Q-curves". format(len(bad2))) print( "{} curves in the database are incorrectly labelled as NOT being Q-curves" .format(len(bad1))) return bad1, bad2