def make_extra_data(label, number, ainvs, gens): """Given a curve label (and number, as some data is only stored wih curve number 1 in each class) and its ainvs and gens, returns a dict with which to update the entry. Extra items computed here: 'equation': latex string of curve's equation 'signD': sign of discriminant 'local_data': list of dicts, one item for each bad prime 'min_quad_twist': dict holding curve's min quadratic twist and the twisting discriminant 'heights': list of heights of gens and for curve #1 in a class only: 'aplist': list of a_p for p<100 'anlist': list of a_n for n<=20 """ E = EllipticCurve(parse_ainvs(ainvs)) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{ 'p': int(ld.prime().gen()), 'ord_cond': int(ld.conductor_valuation()), 'ord_disc': int(ld.discriminant_valuation()), 'ord_den_j': int(max(0, -(E.j_invariant().valuation(ld.prime().gen())))), 'red': int(ld.bad_reduction_type()), 'rootno': int(E.root_number(ld.prime().gen())), 'kod': web_latex(ld.kodaira_symbol()).replace('$', ''), 'cp': int(ld.tamagawa_number()) } for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor() == E.conductor(): data['min_quad_twist'] = {'label': label, 'disc': int(1)} else: minq_ainvs = ''.join(['['] + [str(c) for c in Etw.ainvs()] + [']']) r = curves.find_one({ 'jinv': str(E.j_invariant()), 'ainvs': minq_ainvs }) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label': minq_label, 'disc': int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number == 1: data['aplist'] = E.aplist(100, python_ints=True) data['anlist'] = E.anlist(20, python_ints=True) return data
def test1(B=10**4): from sage.all import polygen, primes, QQ, EllipticCurve import psage.libs.smalljac.wrapper x = polygen(QQ, 'x') J = psage.libs.smalljac.wrapper.SmallJac(x**3 + 17 * x + 3) E = EllipticCurve([17, 3]) N = E.conductor() for p in primes(B): if N % p: assert E.ap(p) == J.ap(p)
def get_congruent_number_data(n): info = {'n': n} info['rank'] = rank = int(get_CN_data('rank', n)[1]) info['is_congruent'] = cong = rank > 0 ainvs = [0, 0, 0, -n * n, 0] E = EllipticCurve(ainvs) info['E'] = E gens_string = get_CN_data('MWgroup', n)[1] gens = [E(g) for g in parse_gens_string(gens_string)] info['gens'] = ", ".join([str(g) for g in gens]) info['missing_generator'] = len(gens) < rank # better typesetting of points info['gens'] = [raw_typeset(P.xy()) for P in gens] if len(gens) == 1: info['gen'] = info['gens'][0] info['conductor'] = N = int(get_CN_data('conductor', n)[1]) assert N == E.conductor() info['triangle'] = None if cong: P = 2 * gens[0] x, y = P.xy() Z = 2 * x.sqrt() XplusY = 2 * (x + n).sqrt() XminusY = 2 * (x - n).sqrt() X = (XplusY + XminusY) / 2 Y = XplusY - X assert X * X + Y * Y == Z * Z assert X * Y == 2 * n assert X > 0 and Y > 0 and Z > 0 if X > Y: X, Y = Y, X info['triangle'] = {'X': X, 'Y': Y, 'Z': Z} res = db.ec_curvedata.search({'ainvs': ainvs}) try: res = next(res) info['in_db'] = 'exact' except StopIteration: res = db.ec_curvedata.search({'jinv': [1728, 1], 'conductor': N}) try: res = next(res) info['in_db'] = 'isomorphic' except StopIteration: info['in_db'] = False if info['in_db']: info['label'] = label = res['lmfdb_label'] if res else None info['url'] = url_for(".by_ec_label", label=label) return info
def test1(B=10 ** 4): from sage.all import polygen, primes, QQ, EllipticCurve import psage.libs.smalljac.wrapper x = polygen(QQ, "x") J = psage.libs.smalljac.wrapper.SmallJac(x ** 3 + 17 * x + 3) E = EllipticCurve([17, 3]) N = E.conductor() for p in primes(B): if N % p: assert E.ap(p) == J.ap(p)
def make_extra_data(label, number, ainvs, gens): """ C is a database elliptic curve entry. Returns a dict with which to update the entry. Data fields needed in C already: 'ainvs', 'lmfdb_label', 'gens', 'number' """ E = EllipticCurve([int(a) for a in ainvs]) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['xainvs'] = ''.join(['[', ','.join(ainvs), ']']) data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{ 'p': int(ld.prime().gen()), 'ord_cond': int(ld.conductor_valuation()), 'ord_disc': int(ld.discriminant_valuation()), 'ord_den_j': int(max(0, -(E.j_invariant().valuation(ld.prime().gen())))), 'red': int(ld.bad_reduction_type()), 'rootno': int(E.root_number(ld.prime().gen())), 'kod': web_latex(ld.kodaira_symbol()).replace('$', ''), 'cp': int(ld.tamagawa_number()) } for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor() == E.conductor(): data['min_quad_twist'] = {'label': label, 'disc': int(1)} else: # Later this should be changed to look for xainvs but now all curves have ainvs minq_ainvs = [str(c) for c in Etw.ainvs()] r = curves.find_one({ 'jinv': str(E.j_invariant()), 'ainvs': minq_ainvs }) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label': minq_label, 'disc': int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number == 1: data['aplist'] = E.aplist(100, python_ints=True) data['anlist'] = E.anlist(20, python_ints=True) return data
def make_hash_SW(plist, N1=0, N2=999, nq=30, tate=False): """Here N1 and N2 are in [0..999] and refer to the batch number, where batch n has curves of conductor between n*10^5 and (n+1)*10^5 plist is a list of primes so we can make several hash tables in parallel If tate=True then ignore curves unless ord_p(j(E))=-1 """ # Compute the first nq primes greater than the largest conductor: qlist = [next_prime((N2 + 1) * 10**5)] while len(qlist) < nq: qlist.append(next_prime(qlist[-1])) # Initialize hash tables for each p: hashtabs = dict([(p, dict()) for p in plist]) nc = 0 for N in range(N1, N2 + 1): print("Batch {}".format(N)) for dat in SteinWatkinsAllData(N): nc += 1 NE = dat.conductor E = EllipticCurve(dat.curves[0][0]) assert E.conductor() == NE if tate and all(E.j_invariant().valuation(p) >= 0 for p in plist): continue lab = SW_label(E) if nc % 10000 == 0: print(lab) # if nc>10000: # break h = hash1many(plist, E, qlist) for p in plist: if tate and E.j_invariant().valuation(p) >= 0: continue hp = h[p] if hp in hashtabs[p]: hashtabs[p][hp].append(lab) print("p={}, new set {}".format(p, hashtabs[p][hp])) else: hashtabs[p][hp] = [lab] ns = dict([(p, len([v for v in hashtabs[p].values() if len(v) > 1])) for p in plist]) for p in plist: print("p={}: {} nontrivial sets of congruent curves".format(p, ns[p])) return hashtabs
def by_weierstrass(eqn): w = weierstrass_eqn_regex.match(eqn) if not w: w = short_weierstrass_eqn_regex.match(eqn) if not w: return elliptic_curve_jump_error(eqn, {}) try: ainvs = [ZZ(ai) for ai in w.groups()] except TypeError: return elliptic_curve_jump_error(eqn, {}) E = EllipticCurve(ainvs).global_minimal_model() N = E.conductor() data = db_ec().find_one({'xainvs': EC_ainvs(E)}) if data is None: return elliptic_curve_jump_error(eqn, {'conductor':N}, missing_curve=True) return redirect(url_for(".by_ec_label", label=data['lmfdb_label']), 301)
def by_weierstrass(eqn): w = weierstrass_eqn_regex.match(eqn) if not w: w = short_weierstrass_eqn_regex.match(eqn) if not w: return elliptic_curve_jump_error(eqn, {}) try: ainvs = [ZZ(ai) for ai in w.groups()] except TypeError: return elliptic_curve_jump_error(eqn, {}) E = EllipticCurve(ainvs).global_minimal_model() label = db.ec_curvedata.lucky({'ainvs': EC_ainvs(E)},'lmfdb_label') if label is None: N = E.conductor() return elliptic_curve_jump_error(eqn, {'conductor':N}, missing_curve=True) return redirect(url_for(".by_ec_label", label=label), 301)
def by_weierstrass(eqn): w = weierstrass_eqn_regex.match(eqn) if not w: w = short_weierstrass_eqn_regex.match(eqn) if not w: return elliptic_curve_jump_error(eqn, {}) try: ainvs = [ZZ(ai) for ai in w.groups()] except TypeError: return elliptic_curve_jump_error(eqn, {}) E = EllipticCurve(ainvs).global_minimal_model() label = db.ec_curves.lucky({'ainvs': EC_ainvs(E)},'lmfdb_label') if label is None: N = E.conductor() return elliptic_curve_jump_error(eqn, {'conductor':N}, missing_curve=True) return redirect(url_for(".by_ec_label", label=label), 301)
def make_extra_data(label,number,ainvs,gens): """Given a curve label (and number, as some data is only stored wih curve number 1 in each class) and its ainvs and gens, returns a dict with which to update the entry. Extra items computed here: 'equation': latex string of curve's equation 'signD': sign of discriminant 'local_data': list of dicts, one item for each bad prime 'min_quad_twist': dict holding curve's min quadratic twist and the twisting discriminant 'heights': list of heights of gens and for curve #1 in a class only: 'aplist': list of a_p for p<100 'anlist': list of a_n for n<=20 """ E = EllipticCurve(parse_ainvs(ainvs)) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{'p': int(ld.prime().gen()), 'ord_cond':int(ld.conductor_valuation()), 'ord_disc':int(ld.discriminant_valuation()), 'ord_den_j':int(max(0,-(E.j_invariant().valuation(ld.prime().gen())))), 'red':int(ld.bad_reduction_type()), 'rootno':int(E.root_number(ld.prime().gen())), 'kod':web_latex(ld.kodaira_symbol()).replace('$',''), 'cp':int(ld.tamagawa_number())} for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor()==E.conductor(): data['min_quad_twist'] = {'label':label, 'disc':int(1)} else: minq_ainvs = ''.join(['['] + [str(c) for c in Etw.ainvs()] + [']']) r = curves.find_one({'jinv':str(E.j_invariant()), 'ainvs':minq_ainvs}) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label':minq_label, 'disc':int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number==1: data['aplist'] = E.aplist(100,python_ints=True) data['anlist'] = E.anlist(20,python_ints=True) return data
def test1(B=50): """ Tests that the functions all run without crashing over a specific number field. Does not test that the output is correct. That should be in another test. """ from sage.all import polygen, QQ, NumberField, EllipticCurve x = polygen(QQ,'x') F = NumberField(x**2 - x - 1,'a'); a = F.gen() E = EllipticCurve([1,a+1,a,a,0]) ap(E,F.ideal(3)) primes_of_bounded_norm(F,B) ap_list(E,B) assert len(ap_list(E,B,primes=True)) == 2 apd = ap_dict(E,B) reduced_rep(F.ideal(3)) assert an_dict(E,B) == an_dict_from_ap(apd, E.conductor(), B)
def elliptic_curve_jump(info): label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s', '', label) lab = re.sub(r'^\[', '', lab) lab = re.sub(r']$', '', lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec).minimal_model() # Now we do have a valid curve over Q, but it might # not be in the database. lmfdb_label = db.ec_curves.lucky({'ainvs': EC_ainvs(E)}, 'lmfdb_label') if lmfdb_label is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(lmfdb_label) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: return elliptic_curve_jump_error('', info)
def by_weierstrass(eqn): w = weierstrass_eqn_regex.match(eqn) if not w: w = short_weierstrass_eqn_regex.match(eqn) if not w: return elliptic_curve_jump_error(eqn, {}) try: ainvs = [ZZ(ai) for ai in w.groups()] except TypeError: return elliptic_curve_jump_error(eqn, {}) E = EllipticCurve(ainvs).global_minimal_model() N = E.conductor() ainvs = [str(ai) for ai in E.ainvs()] data = db_ec().find_one({'ainvs': ainvs}) if data is None: return elliptic_curve_jump_error(eqn, {'conductor':N}, missing_curve=True) return redirect(url_for(".by_ec_label", label=data['lmfdb_label']), 301)
def elliptic_curve_jump(info): label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec).minimal_model() # Now we do have a valid curve over Q, but it might # not be in the database. lmfdb_label = db.ec_curves.lucky({'ainvs': EC_ainvs(E)}, 'lmfdb_label') if lmfdb_label is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(lmfdb_label) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: return elliptic_curve_jump_error('', info)
def make_extra_data(label,number,ainvs,gens): """ C is a database elliptic curve entry. Returns a dict with which to update the entry. Data fields needed in C already: 'ainvs', 'lmfdb_label', 'gens', 'number' """ E = EllipticCurve([int(a) for a in ainvs]) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['xainvs'] = ''.join(['[',','.join(ainvs),']']) data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{'p': int(ld.prime().gen()), 'ord_cond':int(ld.conductor_valuation()), 'ord_disc':int(ld.discriminant_valuation()), 'ord_den_j':int(max(0,-(E.j_invariant().valuation(ld.prime().gen())))), 'red':int(ld.bad_reduction_type()), 'rootno':int(E.root_number(ld.prime().gen())), 'kod':web_latex(ld.kodaira_symbol()).replace('$',''), 'cp':int(ld.tamagawa_number())} for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor()==E.conductor(): data['min_quad_twist'] = {'label':label, 'disc':int(1)} else: # Later this should be changed to look for xainvs but now all curves have ainvs minq_ainvs = [str(c) for c in Etw.ainvs()] r = curves.find_one({'jinv':str(E.j_invariant()), 'ainvs':minq_ainvs}) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label':minq_label, 'disc':int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number==1: data['aplist'] = E.aplist(100,python_ints=True) data['anlist'] = E.anlist(20,python_ints=True) return data
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 elliptic_curve_search(info): if info.get('download') == '1' and info.get('Submit') and info.get('query'): return download_search(info) if 'SearchAgain' in info: return rational_elliptic_curves() query = {} bread = info.get('bread',[('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')]) if 'jump' in info: label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) # Now we do have a valid curve over Q, but it might # not be in the database. ainvs = [str(c) for c in E.minimal_model().ainvs()] xainvs = ''.join(['[',','.join(ainvs),']']) data = db_ec().find_one({'xainvs': xainvs}) if data is None: data = db_ec().find_one({'ainvs': ainvs}) if data is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data['lmfdb_label']) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' try: parse_rational(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion if 'torsion_structure' in query and not 'torsion' in query: query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='surjective primes', qfield='non-maximal_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes', qfield='non-maximal_primes',mode=mode) except ValueError as err: info['err'] = str(err) return search_input_error(info, bread) count = parse_count(info,100) start = parse_start(info) if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 info['query'] = query cursor = db_ec().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING)]).skip(start).limit(count) info['curves'] = res info['format_ainvs'] = format_ainvs info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number']) info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres #credit = 'John Cremona' #if 'non-surjective_primes' in query or 'non-maximal_primes' in query: # credit += ' and Andrew Sutherland' t = info.get('title','Elliptic Curves search results') return render_template("ec-search-results.html", info=info, credit=ec_credit(), bread=bread, title=t)
def elliptic_curve_search(**args): info = to_dict(args) if "download" in info and info["download"] != "0": return download_search(info) query = {} bread = [ ("Elliptic Curves", url_for("ecnf.index")), ("$\Q$", url_for(".rational_elliptic_curves")), ("Search Results", "."), ] if "SearchAgain" in args: return rational_elliptic_curves() if "jump" in args: label = info.get("label", "").replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r"\s", "", label) lab = re.sub(r"^\[", "", lab) lab = re.sub(r"]$", "", lab) try: labvec = lab.split(",") labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) # Now we do have a valid curve over Q, but it might # not be in the database. ainvs = [str(c) for c in E.minimal_model().ainvs()] data = db_ec().find_one({"ainvs": ainvs}) if data is None: info["conductor"] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data["lmfdb_label"]) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query["label"] = "" try: parse_rational(info, query, "jinv", "j-invariant") parse_ints(info, query, "conductor") parse_ints(info, query, "torsion", "torsion order") parse_ints(info, query, "rank") parse_ints(info, query, "sha", "analytic order of Ш") parse_bracketed_posints( info, query, "torsion_structure", maxlength=2, process=str, check_divisibility="increasing" ) parse_primes( info, query, "surj_primes", name="surjective primes", qfield="non-surjective_primes", mode="complement" ) if info.get("surj_quantifier") == "exactly": mode = "exact" else: mode = "append" parse_primes( info, query, "nonsurj_primes", name="non-surjective primes", qfield="non-surjective_primes", mode=mode ) except ValueError as err: info["err"] = str(err) return search_input_error(info, bread) count = parse_count(info, 100) start = parse_start(info) if "optimal" in info and info["optimal"] == "on": # fails on 990h3 query["number"] = 1 info["query"] = query cursor = db_ec().find(query) nres = cursor.count() if start >= nres: start -= (1 + (start - nres) / count) * count if start < 0: start = 0 res = ( cursor.sort([("conductor", ASCENDING), ("iso_nlabel", ASCENDING), ("lmfdb_number", ASCENDING)]) .skip(start) .limit(count) ) info["curves"] = res info["format_ainvs"] = format_ainvs info["curve_url"] = lambda dbc: url_for( ".by_triple_label", conductor=dbc["conductor"], iso_label=split_lmfdb_label(dbc["lmfdb_iso"])[1], number=dbc["lmfdb_number"], ) info["iso_url"] = lambda dbc: url_for( ".by_double_iso_label", conductor=dbc["conductor"], iso_label=split_lmfdb_label(dbc["lmfdb_iso"])[1] ) info["number"] = nres info["start"] = start info["count"] = count info["more"] = int(start + count < nres) if nres == 1: info["report"] = "unique match" elif nres == 2: info["report"] = "displaying both matches" else: if nres > count or start != 0: info["report"] = "displaying matches %s-%s of %s" % (start + 1, min(nres, start + count), nres) else: info["report"] = "displaying all %s matches" % nres credit = "John Cremona" if "non-surjective_primes" in query: credit += "and Andrew Sutherland" t = "Elliptic Curves search results" return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
def allgens(line): r""" Parses one line from an allgens file. Returns the label and a dict containing fields with keys 'conductor', 'iso', 'number', 'ainvs', 'jinv', 'cm', 'rank', 'gens', 'torsion_order', 'torsion_structure', 'torsion_generators', all values being strings or ints, and more. Input line fields: conductor iso number ainvs rank torsion_structure gens torsion_gens Sample input line: 20202 i 2 [1,0,0,-298389,54947169] 1 [2,4] [-570:6603:1] [-622:311:1] [834:19239:1] """ global lmfdb_label_to_label global label_to_lmfdb_label data = split(line) iso = data[0] + data[1] label = iso + data[2] try: lmfdb_label = label_to_lmfdb_label[label] except AttributeError: print("Label {} not found in label_to_lmfdb_label dict!".format(label)) lmfdb_label = "" global nallgens nallgens += 1 if nallgens % 100 == 0: print("processing allgens for {} (#{})".format(label, nallgens)) rank = int(data[4]) t = data[5] tor_struct = [] if t == '[]' else t[1:-1].split(",") torsion = int(prod([int(ti) for ti in tor_struct], 1)) ainvs = parse_ainvs(data[3]) E = EllipticCurve(ainvs) jinv = text_type(E.j_invariant()) if E.has_cm(): cm = int(E.cm_discriminant()) else: cm = int(0) N = E.conductor() bad_p = N.prime_factors() # will be sorted num_bad_p = len(bad_p) local_data = [{ 'p': int(ld.prime().gen()), 'ord_cond': int(ld.conductor_valuation()), 'ord_disc': int(ld.discriminant_valuation()), 'ord_den_j': int(max(0, -(E.j_invariant().valuation(ld.prime().gen())))), 'red': int(ld.bad_reduction_type()), 'rootno': int(E.root_number(ld.prime().gen())), 'kod': web_latex(ld.kodaira_symbol()).replace('$', ''), 'cp': int(ld.tamagawa_number()) } for ld in E.local_data()] semistable = all([ld['ord_cond'] == 1 for ld in local_data]) gens = [ gen.replace("[", "(").replace("]", ")") for gen in data[6:6 + rank] ] tor_gens = ["%s" % parse_tgens(tgens[1:-1]) for tgens in data[6 + rank:]] from lmfdb.elliptic_curves.web_ec import parse_points heights = [float(E(P).height()) for P in parse_points(gens)] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor() == N: min_quad_twist = { 'label': label, 'lmfdb_label': lmfdb_label, 'disc': int(1) } else: minq_ainvs = Etw.ainvs() r = curves.lucky({ 'jinv': str(E.j_invariant()), 'ainvs': minq_ainvs }, projection=['label', 'lmfdb_label']) min_quad_twist = { 'label': r['label'], 'lmfdb_label': r['lmfdb_label'], 'disc': int(Dtw) } trace_hash = TraceHashClass(iso, E) return label, { 'conductor': int(data[0]), 'iso': iso, 'number': int(data[2]), 'ainvs': ainvs, 'jinv': jinv, 'cm': cm, 'rank': rank, 'gens': gens, 'torsion': torsion, 'torsion_structure': tor_struct, 'torsion_generators': tor_gens, 'trace_hash': trace_hash, 'equation': web_latex(E), 'bad_primes': bad_p, 'num_bad_primes': num_bad_p, 'local_data': local_data, 'semistable': semistable, 'signD': int(E.discriminant().sign()), 'heights': heights, 'aplist': E.aplist(100, python_ints=True), 'anlist': E.anlist(20, python_ints=True), 'min_quad_twist': min_quad_twist, }
def elliptic_curve_search(**args): info = to_dict(args) query = {} bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')] if 'SearchAgain' in args: return rational_elliptic_curves() if 'jump' in args: label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) # Now we do have a valid curve over Q, but it might # not be in the database. ainvs = [str(c) for c in E.minimal_model().ainvs()] data = db_ec().find_one({'ainvs': ainvs}) if data is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data['lmfdb_label']) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' if info.get('jinv'): j = clean_input(info['jinv']) j = j.replace('+', '') if not QQ_RE.match(j): info['err'] = 'Error parsing input for the j-invariant. It needs to be a rational number.' return search_input_error(info, bread) query['jinv'] = str(QQ(j)) # to simplify e.g. 1728/1 for field in ['conductor', 'torsion', 'rank', 'sha']: if info.get(field): info[field] = clean_input(info[field]) ran = info[field] ran = ran.replace('..', '-').replace(' ', '') if not LIST_RE.match(ran): names = {'conductor': 'conductor', 'torsion': 'torsion order', 'rank': 'rank', 'sha': 'analytic order of Ш'} info['err'] = 'Error parsing input for the %s. It needs to be an integer (such as 25), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 4,9,16 or 4-25, 81-121).' % names[field] return search_input_error(info, bread) # Past input check tmp = parse_range2(ran, field) # work around syntax for $or # we have to foil out multiple or conditions if tmp[0] == '$or' and '$or' in query: newors = [] for y in tmp[1]: oldors = [dict.copy(x) for x in query['$or']] for x in oldors: x.update(y) newors.extend(oldors) tmp[1] = newors query[tmp[0]] = tmp[1] if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 if 'torsion_structure' in info and info['torsion_structure']: res = parse_torsion_structure(info['torsion_structure']) if 'Error' in res: info['err'] = res return search_input_error(info, bread) #update info for repeat searches info['torsion_structure'] = str(res).replace(' ','') query['torsion_structure'] = [str(r) for r in res] if info.get('surj_primes'): info['surj_primes'] = clean_input(info['surj_primes']) format_ok = LIST_POSINT_RE.match(info['surj_primes']) if format_ok: surj_primes = [int(p) for p in info['surj_primes'].split(',')] format_ok = all([ZZ(p).is_prime(proof=False) for p in surj_primes]) if format_ok: query['non-surjective_primes'] = {"$nin": surj_primes} else: info['err'] = 'Error parsing input for surjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) if info.get('nonsurj_primes'): info['nonsurj_primes'] = clean_input(info['nonsurj_primes']) format_ok = LIST_POSINT_RE.match(info['nonsurj_primes']) if format_ok: nonsurj_primes = [int(p) for p in info['nonsurj_primes'].split(',')] format_ok = all([ZZ(p).is_prime(proof=False) for p in nonsurj_primes]) if format_ok: if info['surj_quantifier'] == 'exactly': nonsurj_primes.sort() query['non-surjective_primes'] = nonsurj_primes else: if 'non-surjective_primes' in query: query['non-surjective_primes'] = { "$nin": surj_primes, "$all": nonsurj_primes } else: query['non-surjective_primes'] = { "$all": nonsurj_primes } else: info['err'] = 'Error parsing input for nonsurjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) if 'download' in info and info['download'] != '0': res = db_ec().find(query).sort([ ('conductor', ASCENDING), ('lmfdb_iso', ASCENDING), ('lmfdb_number', ASCENDING) ]) return download_search(info, res) count_default = 100 if info.get('count'): try: count = int(info['count']) except: count = count_default else: count = count_default info['count'] = count start_default = 0 if info.get('start'): try: start = int(info['start']) if(start < 0): start += (1 - (start + 1) / count) * count except: start = start_default else: start = start_default cursor = db_ec().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('conductor', ASCENDING), ('lmfdb_iso', ASCENDING), ('lmfdb_number', ASCENDING) ]).skip(start).limit(count) info['curves'] = res info['format_ainvs'] = format_ainvs info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number']) info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['number'] = nres info['start'] = start if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres credit = 'John Cremona' if 'non-surjective_primes' in query: credit += 'and Andrew Sutherland' t = 'Elliptic Curves search results' return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
def elliptic_curve_search(**args): info = to_dict(args) if 'download' in info and info['download'] != '0': return download_search(info) query = {} bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')] if 'SearchAgain' in args: return rational_elliptic_curves() if 'jump' in args: label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) # Now we do have a valid curve over Q, but it might # not be in the database. ainvs = [str(c) for c in E.minimal_model().ainvs()] data = db_ec().find_one({'ainvs': ainvs}) if data is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data['lmfdb_label']) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' try: parse_rational(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing') if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_primes(info, query, 'surj_primes', name='surjective primes', qfield='non-surjective_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes', qfield='non-surjective_primes',mode=mode) except ValueError as err: info['err'] = str(err) return search_input_error(info, bread) count = parse_count(info,100) start = parse_start(info) if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 info['query'] = query cursor = db_ec().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING)]).skip(start).limit(count) info['curves'] = res info['format_ainvs'] = format_ainvs info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number']) info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres credit = 'John Cremona' if 'non-surjective_primes' in query: credit += 'and Andrew Sutherland' t = 'Elliptic Curves search results' return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
def elliptic_curve_search(**args): info = to_dict(args) query = {} bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')] if 'SearchAgain' in args: return rational_elliptic_curves() if 'jump' in args: label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) # Now we do have a valid curve over Q, but it might # not be in the database. ainvs = [str(c) for c in E.minimal_model().ainvs()] data = db_ec().find_one({'ainvs': ainvs}) if data is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data['lmfdb_label']) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' if info.get('jinv'): j = clean_input(info['jinv']) j = j.replace('+', '') if not QQ_RE.match(j): info['err'] = 'Error parsing input for the j-invariant. It needs to be a rational number.' return search_input_error(info, bread) query['jinv'] = str(QQ(j)) # to simplify e.g. 1728/1 for field in ['conductor', 'torsion', 'rank', 'sha']: if info.get(field): info[field] = clean_input(info[field]) ran = info[field] ran = ran.replace('..', '-').replace(' ', '') if not LIST_RE.match(ran): names = {'conductor': 'conductor', 'torsion': 'torsion order', 'rank': 'rank', 'sha': 'analytic order of Ш'} info['err'] = 'Error parsing input for the %s. It needs to be an integer (such as 25), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 4,9,16 or 4-25, 81-121).' % names[field] return search_input_error(info, bread) # Past input check tmp = parse_range2(ran, field) # work around syntax for $or # we have to foil out multiple or conditions if tmp[0] == '$or' and '$or' in query: newors = [] for y in tmp[1]: oldors = [dict.copy(x) for x in query['$or']] for x in oldors: x.update(y) newors.extend(oldors) tmp[1] = newors query[tmp[0]] = tmp[1] if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 if 'torsion_structure' in info and info['torsion_structure']: res = parse_torsion_structure(info['torsion_structure'],2) if 'Error' in res: info['err'] = res return search_input_error(info, bread) #update info for repeat searches info['torsion_structure'] = str(res).replace(' ','') query['torsion_structure'] = [str(r) for r in res] if info.get('surj_primes'): info['surj_primes'] = clean_input(info['surj_primes']) format_ok = LIST_POSINT_RE.match(info['surj_primes']) if format_ok: surj_primes = [int(p) for p in info['surj_primes'].split(',')] format_ok = all([ZZ(p).is_prime(proof=False) for p in surj_primes]) if format_ok: query['non-surjective_primes'] = {"$nin": surj_primes} else: info['err'] = 'Error parsing input for surjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) if info.get('nonsurj_primes'): info['nonsurj_primes'] = clean_input(info['nonsurj_primes']) format_ok = LIST_POSINT_RE.match(info['nonsurj_primes']) if format_ok: nonsurj_primes = [int(p) for p in info['nonsurj_primes'].split(',')] format_ok = all([ZZ(p).is_prime(proof=False) for p in nonsurj_primes]) if format_ok: if info['surj_quantifier'] == 'exactly': nonsurj_primes.sort() query['non-surjective_primes'] = nonsurj_primes else: if 'non-surjective_primes' in query: query['non-surjective_primes'] = { "$nin": surj_primes, "$all": nonsurj_primes } else: query['non-surjective_primes'] = { "$all": nonsurj_primes } else: info['err'] = 'Error parsing input for nonsurjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) if 'download' in info and info['download'] != '0': res = db_ec().find(query).sort([ ('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING) ]) return download_search(info, res) count_default = 100 if info.get('count'): try: count = int(info['count']) except: count = count_default else: count = count_default info['count'] = count start_default = 0 if info.get('start'): try: start = int(info['start']) if(start < 0): start += (1 - (start + 1) / count) * count except: start = start_default else: start = start_default cursor = db_ec().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING) ]).skip(start).limit(count) info['curves'] = res info['format_ainvs'] = format_ainvs info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number']) info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres credit = 'John Cremona' if 'non-surjective_primes' in query: credit += 'and Andrew Sutherland' t = 'Elliptic Curves search results' return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
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 elliptic_curve_search(info): if info.get('download') == '1' and info.get('Submit') and info.get('query'): return download_search(info) if 'SearchAgain' in info: return rational_elliptic_curves() query = {} bread = info.get('bread',[('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')]) if 'jump' in info: label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec).minimal_model() # Now we do have a valid curve over Q, but it might # not be in the database. data = db_ec().find_one({'xainvs': EC_ainvs(E)}) if data is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data['lmfdb_label']) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' try: parse_rational(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion if 'torsion_structure' in query and not 'torsion' in query: query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='surjective primes', qfield='non-maximal_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes', qfield='non-maximal_primes',mode=mode) except ValueError as err: info['err'] = str(err) return search_input_error(info, bread) count = parse_count(info,100) start = parse_start(info) if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 info['query'] = query cursor = db_ec().find(query); cursor = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING)]); # equivalent to # cursor = res # nres = res.count() # if(start >= nres): # start -= (1 + (start - nres) / count) * count # if(start < 0): # start = 0 # res = res.skip(start).limit(count) try: start, nres, res = search_cursor_timeout_decorator(cursor, start, count); except ValueError as err: info['err'] = err; return search_input_error(info, bread) info['curves'] = res info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number']) info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres t = info.get('title','Elliptic Curves search results') return render_template("ec-search-results.html", info=info, credit=ec_credit(), bread=bread, title=t)
def EC_from_SW_label(lab): N, ainvs = lab.split(".") N = ZZ(N) E = EllipticCurve([ZZ(a) for a in ainvs[1:-1].split(",")]) assert E.conductor() == N return N, E