def add_heights(data, verbose=False): r""" If data holds the data fields for a curve this returns the same with the heights of the points included as a new field with key 'heights'. It is more convenient to do this separately than while parsing the input files since curves() knows tha a-invariants but not the gens and curve_data() vice versa. """ if 'heights' in data and 'reg' in data: return data ngens = data.get('ngens', 0) if ngens == 0: data['heights'] = [] data['reg'] = float(1) return data # Now there is work to do K = nf_lookup(data['field_label']) if 'ainvs' in data: ainvs = data['ainvs'] else: ainvs = nfcurves.find_one({'label': data['label']})['ainvs'] ainvsK = parse_ainvs(K, ainvs) # list of K-elements E = EllipticCurve(ainvsK) gens = [E(parse_point(K, x)) for x in data['gens']] data['heights'] = [float(P.height()) for P in gens] data['reg'] = float(E.regulator_of_points(gens)) if verbose: print("added heights %s and regulator %s to %s" % (data['heights'], data['reg'], data['label'])) return data
def genus1_lookup_equation_nf(rec): assert rec['g'] == 1 # make base field nf_matches = list(db.nf_fields.search({'coeffs': rec['base_field']})) if len(nf_matches) == 0: return None else: nf_rec = nf_matches[0] # make curve f, h = curve_string_parser(rec) ainvs = hyperelliptic_polys_to_ainvs(f, h) E = EllipticCurve(ainvs) K = E.base_field() j = E.j_invariant() j_str = NFelt(j) j_matches = list( db.ec_nfcurves.search({ "field_label": nf_rec['label'], "jinv": j_str })) for r in j_matches: ainvs2 = parse_ainvs(K, r['ainvs']) E2 = EllipticCurve(ainvs2) assert E.base_field() == E2.base_field() if E.is_isomorphic(E2): return r['label'] #print("Curve not found in database") return None
def add_heights(data, verbose = False): r""" If data holds the data fields for a curve this returns the same with the heights of the points included as a new field with key 'heights'. It is more convenient to do this separately than while parsing the input files since curves() knows tha a-invariants but not the gens and curve_data() vice versa. """ if 'heights' in data and 'reg' in data: return data ngens = data.get('ngens', 0) if ngens == 0: data['heights'] = [] data['reg'] = float(1) return data # Now there is work to do K = nf_lookup(data['field_label']) if 'ainvs' in data: ainvs = data['ainvs'] else: ainvs = nfcurves.find_one({'label':data['label']})['ainvs'] ainvsK = parse_ainvs(K, ainvs) # list of K-elements E = EllipticCurve(ainvsK) gens = [E(parse_point(K,x)) for x in data['gens']] data['heights'] = [float(P.height()) for P in gens] data['reg'] = float(E.regulator_of_points(gens)) if verbose: print("added heights %s and regulator %s to %s" % (data['heights'],data['reg'], data['label'])) return data
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 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
def find_curves(field_label='2.2.5.1', min_norm=0, max_norm=None, label=None, outfilename=None, verbose=False, effort=500): r""" Go through all Hilbert Modular Forms with the given field label, assumed totally real, for level norms in the given range, test whether an elliptic curve exists with the same label; if not, find the curves using Magma; output these to a file. """ print("Checking forms over {}, norms from {} to {}".format(field_label,min_norm,max_norm)) if outfilename: print("Output of curves found to {}".format(outfilename)) else: print("No curve search or output, just checking") query = {} query['field_label'] = field_label if fields.find({'label': field_label}).count() == 0: if verbose: print("No HMF data for field %s" % field_label) return None query['dimension'] = 1 # only look at rational newforms if label: print("looking for {} only".format(label)) query['short_label'] = label # e.g. '91.1-a' else: query['level_norm'] = {'$gte': int(min_norm)} if max_norm: query['level_norm']['$lte'] = int(max_norm) cursor = forms.find(query) cursor.sort([('level_norm', pymongo.ASCENDING)]) labels = [f['label'] for f in cursor] nfound = 0 nnotfound = 0 nok = 0 missing_curves = [] K = HilbertNumberField(field_label) primes = [P['ideal'] for P in K.primes_iter(1000)] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Step 1: look at all newforms, check that there is an elliptic # curve of the same label, and if so compare ap-lists. The # dicts curve_ap and form_ap store these when there is # disagreement: e.g. curve_ap[conductor_label][iso_label] = # aplist. for curve_label in labels: # We find the forms again since otherwise the cursor might timeout during the loop. f = forms.find_one({'label': curve_label}) ec = nfcurves.find_one({'field_label': field_label, 'class_label': curve_label, 'number': 1}) if ec: if verbose: print("curve with label %s found in the database" % curve_label) nfound += 1 ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] aplist = [E.reduction(P).trace_of_frobenius() for P in good_primes] f_aplist = [int(a) for a in f['hecke_eigenvalues']] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag] nap = min(len(aplist), len(f_aplist)) if aplist[:nap] == f_aplist[:nap]: nok += 1 if verbose: print("Curve {} and newform agree! (checked {} ap)".format(ec['short_label'],nap)) else: print("Curve {} does NOT agree with newform".format(ec['short_label'])) if verbose: for P,aPf,aPc in zip(good_primes[:nap], f_aplist[:nap], aplist[:nap]): if aPf!=aPc: print("P = {} with norm {}".format(P,P.norm().factor())) print("ap from curve: %s" % aPc) print("ap from form: %s" % aPf) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No curve with label %s found in the database!" % curve_label) missing_curves.append(f['short_label']) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print("Out of %s newforms, %s curves were found in the database and %s were not found" % (n, nfound, nnotfound)) else: print("Out of %s newforms, all %s had curves with the same label and ap" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) if nnotfound: print("%s missing curves" % len(missing_curves)) else: return # Step 2: for each newform for which there was no curve, call interface to Magma's EllipticCurveSearch() # (unless outfilename is None in which case just dump the missing labels to a file) if outfilename: outfile = file(outfilename, mode="w") else: t = file("curves_missing.{}".format(field_label), mode="w") for c in missing_curves: t.write(c) t.write("\n") t.close() return def output(L): if outfilename: outfile.write(L) if verbose: sys.stdout.write(L) bad_p = [] #if field_label=='4.4.1600.1': bad_p = [7**2,13**2,29**2] if field_label=='4.4.2304.1': bad_p = [19**2,29**2] if field_label=='4.4.4225.1': bad_p = [17**2,23**2] if field_label=='4.4.7056.1': bad_p = [29**2,31**2] if field_label=='4.4.7168.1': bad_p = [29**2] if field_label=='4.4.9248.1': bad_p = [23**2] if field_label=='4.4.11025.1': bad_p = [17**2,37**2,43**2] if field_label=='4.4.13824.1': bad_p = [19**2] if field_label=='4.4.12400.1': bad_p = [23**2] if field_label=='4.4.180769.1': bad_p = [23**2] if field_label=='6.6.905177.1': bad_p = [2**3] bad_p = [] effort0 = effort for nf_label in missing_curves: if verbose: print("Curve %s is missing from the database..." % nf_label) form = forms.find_one({'field_label': field_label, 'short_label': nf_label}) if not form: print("... form %s not found!" % nf_label) else: if verbose: print("... found form, calling Magma search") print("Conductor = %s" % form['level_ideal'].replace(" ","")) N = K.ideal(form['level_label']) neigs = len(form['hecke_eigenvalues']) Plist = [P['ideal'] for P in K.primes_iter(neigs)] goodP = [(i, P) for i, P in enumerate(Plist) if not P.divides(N) and not P.norm() in bad_p and P.residue_class_degree()==1] aplist = [int(form['hecke_eigenvalues'][i]) for i, P in goodP] Plist = [P for i,P in goodP] nap = len(Plist) neigs0 = min(nap,100) effort=effort0 if verbose: print("Using %s ap from Hilbert newform and effort %s" % (neigs0,effort)) if bad_p: print("( excluding primes with norms {})".format(bad_p)) #inds = list(set([randint(0,nap-1) for _ in range(neigs0)])) inds = range(neigs0) Plist0 = [Plist[i] for i in inds] aplist0 = [aplist[i] for i in inds] curves = EllipticCurveSearch(K.K(), Plist0, N, aplist0, effort) # rep = 0 allrep=0 while not curves and allrep<10: allrep += 1 effort*=2 # if rep<2: # rep += 1 # else: # rep = 1 # effort *=2 if verbose: print("No curves found by Magma, trying again with effort %s..." % effort) curves = EllipticCurveSearch(K.K(), Plist0, N, aplist0, effort) if verbose: if curves: print("Success!") else: print("Still no success") E = None if curves: E = curves[0] print("%s curves for %s found, first is %s" % (len(curves),nf_label,E.ainvs())) else: print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") print("!!! No curves for %s found (using %s ap) !!!" % (nf_label,len(aplist))) print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") if E!=None: ec = {} ec['field_label'] = field_label ec['conductor_label'] = form['level_label'] ec['iso_label'] = form['label_suffix'] ec['number'] = int(1) ec['conductor_ideal'] = form['level_ideal'].replace(" ","") ec['conductor_norm'] = form['level_norm'] ai = E.ainvs() ec['ainvs'] = ";".join([",".join([str(c) for c in list(a)]) for a in ai]) #print ec['ainvs'] ec['cm'] = '?' ec['base_change'] = [] output(make_curves_line(ec) + "\n") if outfilename: outfile.flush()
def find_curve_labels(field_label='2.2.5.1', min_norm=0, max_norm=None, outfilename=None, verbose=False, effort=1000): r""" Go through all Hilbert Modular Forms with the given field label, assumed totally real, for level norms in the given range, test whether an elliptic curve exists with the same label. """ query = {} query['field_label'] = field_label if fields.find({'label': field_label}).count() == 0: if verbose: print("No HMF data for field %s" % field_label) return None query['dimension'] = 1 # only look at rational newforms query['level_norm'] = {'$gte': int(min_norm)} if max_norm: query['level_norm']['$lte'] = int(max_norm) else: max_norm = 'infinity' cursor = forms.find(query) cursor.sort([('level_norm', pymongo.ASCENDING)]) labels = [f['label'] for f in cursor] nfound = 0 nnotfound = 0 nok = 0 missing_curves = [] K = HilbertNumberField(field_label) primes = [P['ideal'] for P in K.primes_iter()] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Step 1: look at all newforms, check that there is an elliptic # curve of the same label, and if so compare ap-lists. The # dicts curve_ap and form_ap store these when there is # disagreement: e.g. curve_ap[conductor_label][iso_label] = # aplist. for curve_label in labels: # We find the forms again since otherwise the cursor might timeout during the loop. f = forms.find_one({'label': curve_label}) ec = nfcurves.find_one({'field_label': field_label, 'class_label': curve_label, 'number': 1}) if ec: if verbose: print("curve with label %s found" % curve_label) nfound += 1 ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] aplist = [E.reduction(P).trace_of_frobenius() for P in good_primes[:30]] f_aplist = [int(a) for a in f['hecke_eigenvalues'][:40]] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag][:30] if aplist == f_aplist: nok += 1 if verbose: print("Curve %s and newform agree!" % ec['short_label']) else: print("Curve %s does NOT agree with newform" % ec['short_label']) if verbose: print("ap from curve: %s" % aplist) print("ap from form: %s" % f_aplist) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No curve with label %s found!" % curve_label) missing_curves.append(f['short_label']) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print("Out of %s newforms, %s curves were found and %s were not found" % (n, nfound, nnotfound)) else: print("Out of %s newforms, all %s had curves with the same label and ap" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) if nnotfound: print("Missing curves: %s" % missing_curves) else: return if outfilename==None: return # Step 2: for each newform for which there was no curve, create a # Magma file containing code to search for such a curve. # First output Magma code to define the field and primes: output_magma_field(field_label, K.K(), primes, outfilename) if verbose: print("...output definition of field and primes finished") for nf_label in missing_curves: if verbose: print("Curve %s is missing..." % nf_label) form = forms.find_one({'field_label': field_label, 'short_label': nf_label}) if not form: print("... form %s not found!" % nf_label) else: if verbose: print("... found form, outputting Magma search code") output_magma_curve_search(K, form, outfilename, verbose=verbose, effort=effort)
def make_curve(dbCurve): nf = nf_lookup(dbCurve['field_label']) ainvs = parse_ainvs(nf, dbCurve['ainvs']) return EllipticCurve(ainvs)
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) q_curve = (data[12] == '1') # bool # 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) # 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 find_curves(field_label='2.2.5.1', min_norm=0, max_norm=None, label=None, outfilename=None, verbose=False, effort=500): r""" Go through all Hilbert Modular Forms with the given field label, assumed totally real, for level norms in the given range, test whether an elliptic curve exists with the same label; if not, find the curves using Magma; output these to a file. """ print("Checking forms over {}, norms from {} to {}".format( field_label, min_norm, max_norm)) if outfilename: print("Output of curves found to {}".format(outfilename)) else: print("No curve search or output, just checking") query = {} query['field_label'] = field_label if fields.find({'label': field_label}).count() == 0: if verbose: print("No HMF data for field %s" % field_label) return None query['dimension'] = 1 # only look at rational newforms if label: print("looking for {} only".format(label)) query['short_label'] = label # e.g. '91.1-a' else: query['level_norm'] = {'$gte': int(min_norm)} if max_norm: query['level_norm']['$lte'] = int(max_norm) cursor = forms.find(query) cursor.sort([('level_norm', pymongo.ASCENDING)]) labels = [f['label'] for f in cursor] nfound = 0 nnotfound = 0 nok = 0 missing_curves = [] K = HilbertNumberField(field_label) primes = [P['ideal'] for P in K.primes_iter(1000)] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Step 1: look at all newforms, check that there is an elliptic # curve of the same label, and if so compare ap-lists. The # dicts curve_ap and form_ap store these when there is # disagreement: e.g. curve_ap[conductor_label][iso_label] = # aplist. for curve_label in labels: # We find the forms again since otherwise the cursor might timeout during the loop. f = forms.find_one({'label': curve_label}) ec = nfcurves.find_one({ 'field_label': field_label, 'class_label': curve_label, 'number': 1 }) if ec: if verbose: print("curve with label %s found in the database" % curve_label) nfound += 1 ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] aplist = [E.reduction(P).trace_of_frobenius() for P in good_primes] f_aplist = [int(a) for a in f['hecke_eigenvalues']] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag] nap = min(len(aplist), len(f_aplist)) if aplist[:nap] == f_aplist[:nap]: nok += 1 if verbose: print("Curve {} and newform agree! (checked {} ap)".format( ec['short_label'], nap)) else: print("Curve {} does NOT agree with newform".format( ec['short_label'])) if verbose: for P, aPf, aPc in zip(good_primes[:nap], f_aplist[:nap], aplist[:nap]): if aPf != aPc: print("P = {} with norm {}".format( P, P.norm().factor())) print("ap from curve: %s" % aPc) print("ap from form: %s" % aPf) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No curve with label %s found in the database!" % curve_label) missing_curves.append(f['short_label']) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print( "Out of %s newforms, %s curves were found in the database and %s were not found" % (n, nfound, nnotfound)) else: print( "Out of %s newforms, all %s had curves with the same label and ap" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) if nnotfound: print("%s missing curves" % len(missing_curves)) else: return # Step 2: for each newform for which there was no curve, call interface to Magma's EllipticCurveSearch() # (unless outfilename is None in which case just dump the missing labels to a file) if outfilename: outfile = file(outfilename, mode="w") else: t = file("curves_missing.{}".format(field_label), mode="w") for c in missing_curves: t.write(c) t.write("\n") t.close() return def output(L): if outfilename: outfile.write(L) if verbose: sys.stdout.write(L) bad_p = [] #if field_label=='4.4.1600.1': bad_p = [7**2,13**2,29**2] if field_label == '4.4.2304.1': bad_p = [19**2, 29**2] if field_label == '4.4.4225.1': bad_p = [17**2, 23**2] if field_label == '4.4.7056.1': bad_p = [29**2, 31**2] if field_label == '4.4.7168.1': bad_p = [29**2] if field_label == '4.4.9248.1': bad_p = [23**2] if field_label == '4.4.11025.1': bad_p = [17**2, 37**2, 43**2] if field_label == '4.4.13824.1': bad_p = [19**2] if field_label == '4.4.12400.1': bad_p = [23**2] if field_label == '4.4.180769.1': bad_p = [23**2] if field_label == '6.6.905177.1': bad_p = [2**3] bad_p = [] effort0 = effort for nf_label in missing_curves: if verbose: print("Curve %s is missing from the database..." % nf_label) form = forms.find_one({ 'field_label': field_label, 'short_label': nf_label }) if not form: print("... form %s not found!" % nf_label) else: if verbose: print("... found form, calling Magma search") print("Conductor = %s" % form['level_ideal'].replace(" ", "")) N = K.ideal(form['level_label']) neigs = len(form['hecke_eigenvalues']) Plist = [P['ideal'] for P in K.primes_iter(neigs)] goodP = [(i, P) for i, P in enumerate(Plist) if not P.divides(N) and not P.norm() in bad_p and P.residue_class_degree() == 1] aplist = [int(form['hecke_eigenvalues'][i]) for i, P in goodP] Plist = [P for i, P in goodP] nap = len(Plist) neigs0 = min(nap, 100) effort = effort0 if verbose: print("Using %s ap from Hilbert newform and effort %s" % (neigs0, effort)) if bad_p: print("( excluding primes with norms {})".format(bad_p)) #inds = list(set([randint(0,nap-1) for _ in range(neigs0)])) inds = range(neigs0) Plist0 = [Plist[i] for i in inds] aplist0 = [aplist[i] for i in inds] curves = EllipticCurveSearch(K.K(), Plist0, N, aplist0, effort) # rep = 0 allrep = 0 while not curves and allrep < 10: allrep += 1 effort *= 2 # if rep<2: # rep += 1 # else: # rep = 1 # effort *=2 if verbose: print( "No curves found by Magma, trying again with effort %s..." % effort) curves = EllipticCurveSearch(K.K(), Plist0, N, aplist0, effort) if verbose: if curves: print("Success!") else: print("Still no success") E = None if curves: E = curves[0] print("%s curves for %s found, first is %s" % (len(curves), nf_label, E.ainvs())) else: print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") print("!!! No curves for %s found (using %s ap) !!!" % (nf_label, len(aplist))) print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") if E != None: ec = {} ec['field_label'] = field_label ec['conductor_label'] = form['level_label'] ec['iso_label'] = form['label_suffix'] ec['number'] = int(1) ec['conductor_ideal'] = form['level_ideal'].replace(" ", "") ec['conductor_norm'] = form['level_norm'] ai = E.ainvs() ec['ainvs'] = ";".join( [",".join([str(c) for c in list(a)]) for a in ai]) #print ec['ainvs'] ec['cm'] = '?' ec['base_change'] = [] output(make_curves_line(ec) + "\n") if outfilename: outfile.flush()
def find_curve_labels(field_label='2.2.5.1', min_norm=0, max_norm=None, outfilename=None, verbose=False, effort=1000): r""" Go through all Hilbert Modular Forms with the given field label, assumed totally real, for level norms in the given range, test whether an elliptic curve exists with the same label. """ query = {} query['field_label'] = field_label if fields.find({'label': field_label}).count() == 0: if verbose: print("No HMF data for field %s" % field_label) return None query['dimension'] = 1 # only look at rational newforms query['level_norm'] = {'$gte': int(min_norm)} if max_norm: query['level_norm']['$lte'] = int(max_norm) else: max_norm = 'infinity' cursor = forms.find(query) cursor.sort([('level_norm', pymongo.ASCENDING)]) labels = [f['label'] for f in cursor] nfound = 0 nnotfound = 0 nok = 0 missing_curves = [] K = HilbertNumberField(field_label) primes = [P['ideal'] for P in K.primes_iter()] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Step 1: look at all newforms, check that there is an elliptic # curve of the same label, and if so compare ap-lists. The # dicts curve_ap and form_ap store these when there is # disagreement: e.g. curve_ap[conductor_label][iso_label] = # aplist. for curve_label in labels: # We find the forms again since otherwise the cursor might timeout during the loop. f = forms.find_one({'label': curve_label}) ec = nfcurves.find_one({ 'field_label': field_label, 'class_label': curve_label, 'number': 1 }) if ec: if verbose: print("curve with label %s found" % curve_label) nfound += 1 ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] aplist = [ E.reduction(P).trace_of_frobenius() for P in good_primes[:30] ] f_aplist = [int(a) for a in f['hecke_eigenvalues'][:40]] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag][:30] if aplist == f_aplist: nok += 1 if verbose: print("Curve %s and newform agree!" % ec['short_label']) else: print("Curve %s does NOT agree with newform" % ec['short_label']) if verbose: print("ap from curve: %s" % aplist) print("ap from form: %s" % f_aplist) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No curve with label %s found!" % curve_label) missing_curves.append(f['short_label']) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print( "Out of %s newforms, %s curves were found and %s were not found" % (n, nfound, nnotfound)) else: print( "Out of %s newforms, all %s had curves with the same label and ap" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) if nnotfound: print("Missing curves: %s" % missing_curves) else: return if outfilename == None: return # Step 2: for each newform for which there was no curve, create a # Magma file containing code to search for such a curve. # First output Magma code to define the field and primes: output_magma_field(field_label, K.K(), primes, outfilename) if verbose: print("...output definition of field and primes finished") for nf_label in missing_curves: if verbose: print("Curve %s is missing..." % nf_label) form = forms.find_one({ 'field_label': field_label, 'short_label': nf_label }) if not form: print("... form %s not found!" % nf_label) else: if verbose: print("... found form, outputting Magma search code") output_magma_curve_search(K, form, outfilename, verbose=verbose, effort=effort)
def check_curve_labels(field_label='2.2.5.1', min_norm=0, max_norm=None, fix=False, verbose=False): r""" Go through all curves with the given field label, assumed totally real, test whether a Hilbert Modular Form exists with the same label. """ query = {} query['field_label'] = field_label query['number'] = 1 # only look at first curve in each isogeny class 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) nfound = 0 nnotfound = 0 nok = 0 bad_curves = [] K = HilbertNumberField(field_label) primes = [P['ideal'] for P in K.primes_iter(30)] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Step 1: look at all curves (one per isogeny class), check that # there is a Hilbert newform of the same label, and if so compare # ap-lists. The dicts curve_ap and form_ap store these when # there is disagreement: # e.g. curve_ap[conductor_label][iso_label] = aplist. for ec in cursor: hmf_label = "-".join( [ec['field_label'], ec['conductor_label'], ec['iso_label']]) f = forms.find_one({'field_label': field_label, 'label': hmf_label}) if f: if verbose: print("hmf with label %s found" % hmf_label) nfound += 1 ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] aplist = [ E.reduction(P).trace_of_frobenius() for P in good_primes[:10] ] f_aplist = [int(a) for a in f['hecke_eigenvalues'][:30]] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag][:10] if aplist == f_aplist: nok += 1 if verbose: print("Curve %s and newform agree!" % ec['short_label']) else: bad_curves.append(ec['short_label']) print("Curve %s does NOT agree with newform" % ec['short_label']) if verbose: print("ap from curve: %s" % aplist) print("ap from form: %s" % f_aplist) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No hmf with label %s found!" % hmf_label) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print("Out of %s forms, %s were found and %s were not found" % (n, nfound, nnotfound)) else: print( "Out of %s classes of curve, all %s had newforms with the same label" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) # print("Bad curves: %s" % bad_curves) # Step 2: for each conductor_label for which there was a # discrepancy, create a dict giving the permutation curve --> # newform, so remap[conductor_label][iso_label] = form_label remap = {} for level in curve_ap.keys(): remap[level] = {} c_dat = curve_ap[level] f_dat = form_ap[level] for a in c_dat.keys(): aplist = c_dat[a] for b in f_dat.keys(): if aplist == f_dat[b]: remap[level][a] = b break if verbose: print("remap: %s" % remap) # Step 3, for through all curves with these bad conductors and # create new labels for them, update the database with these (if # fix==True) for level in remap.keys(): perm = remap[level] print("Fixing iso labels for conductor %s using map %s" % (level, perm)) query = {} query['field_label'] = field_label query['conductor_label'] = level cursor = nfcurves.find(query) for ec in cursor: iso = ec['iso_label'] if iso in perm: new_iso = perm[iso] if verbose: print("--mapping class %s to class %s" % (iso, new_iso)) num = str(ec['number']) newlabeldata = {} newlabeldata['iso_label'] = new_iso newlabeldata['short_class_label'] = '-'.join([level, new_iso]) newlabeldata['class_label'] = '-'.join( [field_label, newlabeldata['short_class_label']]) newlabeldata['short_label'] = ''.join( [newlabeldata['short_class_label'], num]) newlabeldata['label'] = '-'.join( [field_label, newlabeldata['short_label']]) if verbose: print("new data fields: %s" % newlabeldata) if fix: nfcurves.update({'_id': ec['_id']}, {"$set": newlabeldata}, upsert=True)
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
def check_curve_labels(field_label='2.2.5.1', min_norm=0, max_norm=None, fix=False, verbose=False): r""" Go through all curves with the given field label, assumed totally real, test whether a Hilbert Modular Form exists with the same label. """ query = {} query['field_label'] = field_label query['number'] = 1 # only look at first curve in each isogeny class 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) nfound = 0 nnotfound = 0 nok = 0 bad_curves = [] K = HilbertNumberField(field_label) primes = [P['ideal'] for P in K.primes_iter(30)] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Step 1: look at all curves (one per isogeny class), check that # there is a Hilbert newform of the same label, and if so compare # ap-lists. The dicts curve_ap and form_ap store these when # there is disagreement: # e.g. curve_ap[conductor_label][iso_label] = aplist. for ec in cursor: hmf_label = "-".join([ec['field_label'], ec['conductor_label'], ec['iso_label']]) f = forms.find_one({'field_label': field_label, 'label': hmf_label}) if f: if verbose: print("hmf with label %s found" % hmf_label) nfound += 1 ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] aplist = [E.reduction(P).trace_of_frobenius() for P in good_primes[:10]] f_aplist = [int(a) for a in f['hecke_eigenvalues'][:30]] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag][:10] if aplist == f_aplist: nok += 1 if verbose: print("Curve %s and newform agree!" % ec['short_label']) else: bad_curves.append(ec['short_label']) print("Curve %s does NOT agree with newform" % ec['short_label']) if verbose: print("ap from curve: %s" % aplist) print("ap from form: %s" % f_aplist) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No hmf with label %s found!" % hmf_label) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print("Out of %s forms, %s were found and %s were not found" % (n, nfound, nnotfound)) else: print("Out of %s classes of curve, all %s had newforms with the same label" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) # print("Bad curves: %s" % bad_curves) # Step 2: for each conductor_label for which there was a # discrepancy, create a dict giving the permutation curve --> # newform, so remap[conductor_label][iso_label] = form_label remap = {} for level in curve_ap.keys(): remap[level] = {} c_dat = curve_ap[level] f_dat = form_ap[level] for a in c_dat.keys(): aplist = c_dat[a] for b in f_dat.keys(): if aplist == f_dat[b]: remap[level][a] = b break if verbose: print("remap: %s" % remap) # Step 3, for through all curves with these bad conductors and # create new labels for them, update the database with these (if # fix==True) for level in remap.keys(): perm = remap[level] print("Fixing iso labels for conductor %s using map %s" % (level, perm)) query = {} query['field_label'] = field_label query['conductor_label'] = level cursor = nfcurves.find(query) for ec in cursor: iso = ec['iso_label'] if iso in perm: new_iso = perm[iso] if verbose: print("--mapping class %s to class %s" % (iso, new_iso)) num = str(ec['number']) newlabeldata = {} newlabeldata['iso_label'] = new_iso newlabeldata['short_class_label'] = '-'.join([level, new_iso]) newlabeldata['class_label'] = '-'.join([field_label, newlabeldata['short_class_label']]) newlabeldata['short_label'] = ''.join([newlabeldata['short_class_label'], num]) newlabeldata['label'] = '-'.join([field_label, newlabeldata['short_label']]) if verbose: print("new data fields: %s" % newlabeldata) if fix: nfcurves.update({'_id': ec['_id']}, {"$set": newlabeldata}, upsert=True)
def check_curves(field_label='2.0.4.1', min_norm=0, max_norm=None, label=None, check_ap=False, verbose=False): r"""Go through all Bianchi Modular Forms with the given field label, assumed imaginary quadratic (i.e. '2.0.d.1' with d in {4,8,3,7,11}), check whether an elliptic curve exists with the same label. If so, and if check_ap is True, check that the a_P agree. """ if field_label not in fields: print("No BMF data available for field {}".format(field_label)) return else: K = field_from_label(field_label) print("Checking forms over {}, norms from {} to {}".format( field_label, min_norm, max_norm)) query = {} query['field_label'] = field_label query['dimension'] = 1 # only look at rational newforms if label: print("looking for {} only".format(label)) query['short_label'] = label # e.g. '91.1-a' else: query['level_norm'] = {'$gte': int(min_norm)} if max_norm: query['level_norm']['$lte'] = int(max_norm) cursor = forms.search(query, sort=['level_norm']) labels = [f['short_label'] for f in cursor] nforms = len(labels) print("found {} newforms".format(nforms)) labels = [lab for lab in labels if lab not in false_curves[field_label]] nforms = len(labels) print( " of which {} should have associated curves (not false ones)".format( nforms)) nfound = 0 nnotfound = 0 nok = 0 missing_curves = [] mismatches = [] primes = list(primes_iter(K, maxnorm=1000)) if check_ap else [] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Now look at all newforms, check that there is an elliptic # curve of the same label, and if so compare ap-lists. The # dicts curve_ap and form_ap store these when there is # disagreement: e.g. curve_ap[conductor_label][iso_label] = # aplist. print("checking {} newforms".format(nforms)) n = 0 for curve_label in labels: n += 1 if n % 100 == 0: perc = 100.0 * n / nforms print("{} forms checked ({}%)".format(n, perc)) # We find the forms again since otherwise the cursor might timeout during the loop. label = "-".join([field_label, curve_label]) if verbose: print("newform and isogeny class label {}".format(label)) f = forms.lucky({'label': label}) if f: if verbose: print("found newform with label {}".format(label)) else: print("no newform in database has label {}!".format(label)) continue ec = nfcurves.lucky({'class_label': label, 'number': 1}) if ec: if verbose: print("curve with label %s found in the database" % curve_label) nfound += 1 if not check_ap: continue ainvsK = parse_ainvs(K, ec['ainvs']) if verbose: print("E = {}".format(ainvsK)) E = EllipticCurve(ainvsK) if verbose: print("constructed elliptic curve {}".format(E.ainvs())) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] if verbose: print("{} good primes".format(len(good_primes))) f_aplist = f['hecke_eigs'] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag] nap = len(f_aplist) if verbose: print("recovered {} ap from BMF".format(nap)) aplist = [ E.reduction(P).trace_of_frobenius() for P in good_primes[:nap] ] if verbose: print("computed {} ap from elliptic curve".format(nap)) if aplist[:nap] == f_aplist[:nap]: nok += 1 if verbose: print("Curve {} and newform agree! (checked {} ap)".format( ec['short_label'], nap)) else: print("Curve {} does NOT agree with newform".format( ec['short_label'])) mismatches.append(label) if verbose: for P, aPf, aPc in zip(good_primes[:nap], f_aplist[:nap], aplist[:nap]): if aPf != aPc: print("P = {} with norm {}".format( P, P.norm().factor())) print("ap from curve: %s" % aPc) print("ap from form: %s" % aPf) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No curve with label %s found in the database!" % curve_label) missing_curves.append(f['short_label']) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print( "Out of %s newforms, %s curves were found in the database and %s were not found" % (n, nfound, nnotfound)) else: print( "Out of %s newforms, all %s had curves with the same label and ap" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) if nnotfound: print("%s missing curves" % len(missing_curves)) else: pass if mismatches: print("{} form-curve pairs had inconsistent ap:".format( len(mismatches))) print(mismatches)
def make_curve(dbCurve): nf = nf_lookup(dbCurve['field_label']) ainvs = parse_ainvs(nf,dbCurve['ainvs']) return EllipticCurve(ainvs)