def elliptic_curve_search(info, query): 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, 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_element_of(info, query, field='isodeg', qfield='isogeny_degrees', split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes', mode=mode, radical='nonmax_rad') if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 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])
def random_curve(): label = db.ec_curvedata.random(projection='lmfdb_label') cond, iso, num = split_lmfdb_label(label) return url_for(".by_triple_label", conductor=cond, iso_label=iso, number=num)
def by_label(label): """ Searches for a specific elliptic curve isogeny class in the curves collection by its label, which can be either a curve label (e.g. "11.a1") or a class label (e.g. "11.a") in either LMFDB or Cremona format. """ #print "label = %s" % label try: N, iso, number = split_lmfdb_label(label) if number: data = db_ec().find_one({"lmfdb_label" : label}) else: data = db_ec().find_one({"lmfdb_label" : label+"1"}) except AttributeError: try: N, iso, number = split_cremona_label(label) if number: data = db_ec().find_one({"label" : label}) else: data = db_ec().find_one({"label" : label+"1"}) except AttributeError: return "Invalid label" # caller must catch this and raise an error if data: return ECisog_class(data) return "Class not found" # caller must catch this and raise an error
def download_EC_all(label): try: N, iso, number = split_lmfdb_label(label) except (ValueError,AttributeError): return elliptic_curve_jump_error(label, {}) CDB = db_ec() if number: data = CDB.find_one({'lmfdb_label': label}) if data is None: return elliptic_curve_jump_error(label, {}) data_list = [data] else: data_list = sorted(list(CDB.find({'lmfdb_iso': label})), key=lambda E: E['number']) if len(data_list) == 0: return elliptic_curve_jump_error(label, {}) # For each curve we will output all data fields except the '_id': # (This should also be possible by adding projection={'_id':False} # to the find() call but on testing that timed out.) for data in data_list: data.pop('_id') import json response = make_response('\n\n'.join(json.dumps(d) for d in data_list)) response.headers['Content-type'] = 'text/plain' return response
def url_for_ec_class(ec_label): if not '-' in ec_label: (cond, iso, num) = split_lmfdb_label(ec_label) return url_for('ec.by_double_iso_label', conductor=cond, iso_label=iso) else: (nf, cond, iso, num) = split_full_label(ec_label) return url_for('ecnf.show_ecnf_isoclass', nf=nf, conductor_label=cond, class_label=iso)
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p print "label = %s; p = %s" % (label,p) N, iso, number = split_lmfdb_label(label) # print N, iso, number if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({'lmfdb_iso': N + '.' + iso}) data = C.elliptic_curves.padic_db.find_one({'lmfdb_iso': N + '.' + iso, 'p': p}) info['data'] = data if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = sage.all.Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("padic_data.html", info=info)
def by_ec_label(label): ec_logger.debug(label) try: N, iso, number = split_lmfdb_label(label) except AttributeError: ec_logger.debug("%s not a valid lmfdb label, trying cremona") try: N, iso, number = split_cremona_label(label) except AttributeError: ec_logger.debug("%s not a valid cremona label either, trying Weierstrass") eqn = label.replace(" ","") if weierstrass_eqn_regex.match(eqn) or short_weierstrass_eqn_regex.match(eqn): return by_weierstrass(eqn) else: return elliptic_curve_jump_error(label, {}) # We permanently redirect to the lmfdb label if number: data = db_ec().find_one({'label': label}) if data is None: return elliptic_curve_jump_error(label, {}) ec_logger.debug(url_for(".by_ec_label", label=data['lmfdb_label'])) return redirect(url_for(".by_ec_label", label=data['lmfdb_label']), 301) else: data = db_ec().find_one({'iso': label}) if data is None: return elliptic_curve_jump_error(label, {}) ec_logger.debug(url_for(".by_ec_label", label=data['lmfdb_label'])) return redirect(url_for(".by_ec_label", label=data['lmfdb_iso']), 301) if number: return redirect(url_for(".by_triple_label", conductor=N, iso_label=iso, number=number)) else: return redirect(url_for(".by_double_iso_label", conductor=N, iso_label=iso))
def by_label(label): """ Searches for a specific elliptic curve isogeny class in the curves collection by its label, which can be either a curve label (e.g. "11.a1") or a class label (e.g. "11.a") in either LMFDB or Cremona format. """ try: N, iso, number = split_lmfdb_label(label) if number: label = ".".join([N,iso]) data = db.ec_curves.lucky({"lmfdb_iso" : label, 'number':1}) data['label_type'] = 'LMFDB' except AttributeError: try: N, iso, number = split_cremona_label(label) if number: label = "".join([N,iso]) data = db.ec_curves.lucky({"iso" : label, 'number':1}) data['label_type'] = 'Cremona' except AttributeError: return "Invalid label" # caller must catch this and raise an error if data: return ECisog_class(data) return "Class not found" # caller must catch this and raise an error
def by_label(label): """ Searches for a specific elliptic curve isogeny class in the curves collection by its label, which can be either a curve label (e.g. "11.a1") or a class label (e.g. "11.a") in either LMFDB or Cremona format. """ try: N, iso, number = split_lmfdb_label(label) if number: label = ".".join([N, iso]) data = db.ec_curves.lucky({"lmfdb_iso": label, 'number': 1}) data['label_type'] = 'LMFDB' except AttributeError: try: N, iso, number = split_cremona_label(label) if number: label = "".join([N, iso]) data = db.ec_curves.lucky({"iso": label, 'number': 1}) data['label_type'] = 'Cremona' except AttributeError: return "Invalid label" # caller must catch this and raise an error if data: return ECisog_class(data) return "Class not found" # caller must catch this and raise an error
def by_label(label): """ Searches for a specific elliptic curve isogeny class in the curves collection by its label, which can be either a curve label (e.g. "11.a1") or a class label (e.g. "11.a") in either LMFDB or Cremona format. """ #print "label = %s" % label try: N, iso, number = split_lmfdb_label(label) if number: data = db_ec().find_one({"lmfdb_label": label}) else: data = db_ec().find_one({"lmfdb_label": label + "1"}) except AttributeError: try: N, iso, number = split_cremona_label(label) if number: data = db_ec().find_one({"label": label}) else: data = db_ec().find_one({"label": label + "1"}) except AttributeError: return "Invalid label" # caller must catch this and raise an error if data: return ECisog_class(data) return "Class not found" # caller must catch this and raise an error
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p N, iso, number = split_lmfdb_label(label) if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({'lmfdb_iso': N + '.' + iso}) data = C.elliptic_curves.padic_db.find_one({ 'lmfdb_iso': N + '.' + iso, 'p': p }) info['data'] = data if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = sage.all.Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("ec-padic-data.html", info=info)
def download_EC_qexp(label, limit): N, iso, number = split_lmfdb_label(label) if number: ainvs = db.ec_curves.lookup(label, 'ainvs', 'lmfdb_label') else: ainvs = db.ec_curves.lookup(label, 'ainvs', 'lmfdb_iso') E = EllipticCurve(ainvs) response = make_response(','.join(str(an) for an in E.anlist(int(limit), python_ints=True))) response.headers['Content-type'] = 'text/plain' return response
def download_EC_qexp(label, limit): CDB = db_ec() N, iso, number = split_lmfdb_label(label) if number: data = CDB.find_one({'lmfdb_label': label}) else: data = CDB.find_one({'lmfdb_iso': label}) E = EllipticCurve(parse_ainvs(data['ainvs'])) response = make_response(','.join(str(an) for an in E.anlist(int(limit), python_ints=True))) response.headers['Content-type'] = 'text/plain' return response
def EC_data(label): bread = get_bread([(label, url_for_label(label)), ("Data", " ")]) if match_lmfdb_label(label): conductor, iso_class, number = split_lmfdb_label(label) if not number: # isogeny class return datapage(label, ["ec_classdata", "ec_padic"], bread=bread, label_col="lmfdb_iso", sorts=[[], ["p"]]) iso_label = class_lmfdb_label(conductor, iso_class) labels = [label] * 8 label_cols = ["lmfdb_label"] * 8 labels[1] = labels[7] = iso_label label_cols[1] = label_cols[7] = "lmfdb_iso" sorts = [[], [], [], [], ["degree", "field"], ["prime"], ["prime"], ["p"]] return datapage(labels, ["ec_curvedata", "ec_classdata", "ec_mwbsd", "ec_iwasawa", "ec_torsion_growth", "ec_localdata", "ec_galrep", "ec_padic"], title=f"Elliptic curve data - {label}", bread=bread, label_cols=label_cols, sorts=sorts) return abort(404, f"Invalid label {label}")
def by_ec_label(label): ec_logger.debug(label) # First see if we have an LMFDB label of a curve or class: try: N, iso, number = split_lmfdb_label(label) if number: return redirect( url_for(".by_triple_label", conductor=N, iso_label=iso, number=number)) else: return redirect( url_for(".by_double_iso_label", conductor=N, iso_label=iso)) except AttributeError: ec_logger.debug("%s not a valid lmfdb label, trying cremona") # Next see if we have a Cremona label of a curve or class: try: N, iso, number = split_cremona_label(label) except AttributeError: ec_logger.debug( "%s not a valid cremona label either, trying Weierstrass") eqn = label.replace(" ", "") if weierstrass_eqn_regex.match( eqn) or short_weierstrass_eqn_regex.match(eqn): return by_weierstrass(eqn) else: return elliptic_curve_jump_error(label, {}) if number: # it's a curve label_type = 'label' else: label_type = 'iso' data = db_ec().find_one({label_type: label}) if data is None: return elliptic_curve_jump_error(label, {}) ec_logger.debug(url_for(".by_ec_label", label=data['lmfdb_label'])) iso = data['lmfdb_iso'].split(".")[1] if number: return redirect( url_for(".by_triple_label", conductor=N, iso_label=iso, number=data['lmfdb_number'])) else: return redirect( url_for(".by_double_iso_label", conductor=N, iso_label=iso))
def download_EC_qexp(label, limit): ec_logger.debug(label) CDB = lmfdb.base.getDBConnection().elliptic_curves.curves N, iso, number = split_lmfdb_label(label) if number: data = CDB.find_one({'lmfdb_label': label}) else: data = CDB.find_one({'lmfdb_iso': label}) ainvs = data['ainvs'] ec_logger.debug(ainvs) E = EllipticCurve([int(a) for a in ainvs]) response = make_response(','.join(str(an) for an in E.anlist(int(limit), python_ints=True))) response.headers['Content-type'] = 'text/plain' return response
def download_EC_qexp(label, limit): try: N, iso, number = split_lmfdb_label(label) except (ValueError,AttributeError): return elliptic_curve_jump_error(label, {}) if number: ainvs = db.ec_curvedata.lookup(label, 'ainvs', 'lmfdb_label') else: ainvs = db.ec_curvedata.lookup(label, 'ainvs', 'lmfdb_iso') if ainvs is None: return elliptic_curve_jump_error(label, {}) if limit > 100000: return redirect(url_for('.download_EC_qexp',label=label,limit=10000), 301) E = EllipticCurve(ainvs) response = make_response(','.join(str(an) for an in E.anlist(int(limit), python_ints=True))) response.headers['Content-type'] = 'text/plain' return response
def download_EC_all(label): try: N, iso, number = split_lmfdb_label(label) except (ValueError,AttributeError): return elliptic_curve_jump_error(label, {}) if number: data = db.ec_curves.lookup(label, label_col='lmfdb_label') if data is None: return elliptic_curve_jump_error(label, {}) data_list = [data] else: data_list = list(db.ec_curves.search({'lmfdb_iso': label}, projection=2, sort=['number'])) if len(data_list) == 0: return elliptic_curve_jump_error(label, {}) response = make_response('\n\n'.join(Json.dumps(d) for d in data_list)) response.headers['Content-type'] = 'text/plain' return response
def download_EC_all(label): try: N, iso, number = split_lmfdb_label(label) except (ValueError,AttributeError): return elliptic_curve_jump_error(label, {}) if number: data = db.ec_curvedata.lookup(label, label_col='lmfdb_label') if data is None: return elliptic_curve_jump_error(label, {}) data_list = [data] else: data_list = list(db.ec_curvedata.search({'lmfdb_iso': label}, sort=['lmfdb_number'])) if not data_list: return elliptic_curve_jump_error(label, {}) response = make_response('\n\n'.join(Json.dumps(d) for d in data_list)) response.headers['Content-type'] = 'text/plain' return response
def by_ec_label(label): ec_logger.debug(label) try: N, iso, number = split_lmfdb_label(label) except AttributeError: ec_logger.debug("%s not a valid lmfdb label, trying cremona") try: N, iso, number = split_cremona_label(label) except AttributeError: ec_logger.debug( "%s not a valid cremona label either, trying Weierstrass") eqn = label.replace(" ", "") if weierstrass_eqn_regex.match( eqn) or short_weierstrass_eqn_regex.match(eqn): return by_weierstrass(eqn) else: return elliptic_curve_jump_error(label, {}) # We permanently redirect to the lmfdb label if number: # it's a curve data = db_ec().find_one({'label': label}) if data is None: return elliptic_curve_jump_error(label, {}) ec_logger.debug(url_for(".by_ec_label", label=data['lmfdb_label'])) #return redirect(url_for(".by_ec_label", label=data['lmfdb_label']), 301) return render_curve_webpage_by_label(data['label']) else: # it's an isogeny class data = db_ec().find_one({'iso': label}) if data is None: return elliptic_curve_jump_error(label, {}) ec_logger.debug(url_for(".by_ec_label", label=data['lmfdb_label'])) #return redirect(url_for(".by_ec_label", label=data['iso']), 301) return render_isogeny_class(data['iso']) if number: return redirect( url_for(".by_triple_label", conductor=N, iso_label=iso, number=number)) else: return redirect( url_for(".by_double_iso_label", conductor=N, iso_label=iso))
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p N, iso, number = split_lmfdb_label(label) if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': data = db.ec_padic.lucky({'lmfdb_iso': N + '.' + iso, 'p': p}) if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = sage.all.Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("ec-padic-data.html", info=info)
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p N, iso, number = split_lmfdb_label(label) if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': data = db.ec_padic.lucky({'lmfdb_iso': N + '.' + iso, 'p': p}) if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("ec-padic-data.html", info=info)
def padic_data(label, p): try: N, iso, number = split_lmfdb_label(label) except AttributeError: return abort(404) info = {'p': p} if db.ec_curvedata.lookup(label, label_col='lmfdb_label', projection="rank") == 0: info['reg'] = 1 elif number == '1': data = db.ec_padic.lucky({'lmfdb_iso': N + '.' + iso, 'p': p}) if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("ec-padic-data.html", info=info)
def download_EC_all(label): CDB = lmfdb.base.getDBConnection().elliptic_curves.curves N, iso, number = split_lmfdb_label(label) if number: data = CDB.find_one({'lmfdb_label': label}) if data is None: return elliptic_curve_jump_error(label, {}) data_list = [data] else: data_list = sorted(list(CDB.find({'lmfdb_iso': label})), key=lambda E: E['number']) if len(data_list) == 0: return elliptic_curve_jump_error(label, {}) # titles of all entries of curves dump_data = [] titles = [str(c) for c in data_list[0]] titles = [t for t in titles if t[0] != '_'] titles.sort() dump_data.append(titles) for data in data_list: data1 = [] for t in titles: d = data[t] if t == 'ainvs': data1.append(format_ainvs(d)) elif t in ['torsion_generators', 'torsion_structure']: data1.append([eval(g) for g in d]) elif t == 'x-coordinates_of_integral_points': data1.append(parse_list(d)) elif t == 'gens': data1.append(parse_points(d)) elif t in ['iso', 'label', 'lmfdb_iso', 'lmfdb_label']: data1.append(str(d)) else: data1.append(d) dump_data.append(data1) response = make_response('\n'.join(str(an) for an in dump_data)) response.headers['Content-type'] = 'text/plain' return response
def by_ec_label(label): ec_logger.debug(label) # First see if we have an LMFDB label of a curve or class: try: N, iso, number = split_lmfdb_label(label) if number: return redirect(url_for(".by_triple_label", conductor=N, iso_label=iso, number=number)) else: return redirect(url_for(".by_double_iso_label", conductor=N, iso_label=iso)) except AttributeError: ec_logger.debug("%s not a valid lmfdb label, trying cremona") # Next see if we have a Cremona label of a curve or class: try: N, iso, number = split_cremona_label(label) except AttributeError: ec_logger.debug("%s not a valid cremona label either, trying Weierstrass") eqn = label.replace(" ","") if weierstrass_eqn_regex.match(eqn) or short_weierstrass_eqn_regex.match(eqn): return by_weierstrass(eqn) else: return elliptic_curve_jump_error(label, {}) if number: # it's a curve label_type = 'label' else: label_type = 'iso' data = db.ec_curves.lucky({label_type: label}, projection=1) if data is None: return elliptic_curve_jump_error(label, {}, wellformed_label=True, missing_curve=True) ec_logger.debug(url_for(".by_ec_label", label=data['lmfdb_label'])) iso = data['lmfdb_iso'].split(".")[1] if number: return render_curve_webpage_by_label(label) #return redirect(url_for(".by_triple_label", conductor=N, iso_label=iso, number=data['lmfdb_number'])) else: return render_isogeny_class(label)
def download_EC_all(label): CDB = lmfdb.base.getDBConnection().elliptic_curves.curves N, iso, number = split_lmfdb_label(label) if number: data = CDB.find_one({"lmfdb_label": label}) if data is None: return elliptic_curve_jump_error(label, {}) data_list = [data] else: data_list = sorted(list(CDB.find({"lmfdb_iso": label})), key=lambda E: E["number"]) if len(data_list) == 0: return elliptic_curve_jump_error(label, {}) # titles of all entries of curves dump_data = [] titles = [str(c) for c in data_list[0]] titles = [t for t in titles if t[0] != "_"] titles.sort() dump_data.append(titles) for data in data_list: data1 = [] for t in titles: d = data[t] if t == "ainvs": data1.append(format_ainvs(d)) elif t in ["torsion_generators", "torsion_structure"]: data1.append([eval(g) for g in d]) elif t == "x-coordinates_of_integral_points": data1.append(split_list(d)) elif t == "gens": data1.append(parse_points(d)) elif t in ["iso", "label", "lmfdb_iso", "lmfdb_label"]: data1.append(str(d)) else: data1.append(d) dump_data.append(data1) response = make_response("\n".join(str(an) for an in dump_data)) response.headers["Content-type"] = "text/plain" return response
def padic_data(): info = {} label = request.args["label"] p = int(request.args["p"]) info["p"] = p N, iso, number = split_lmfdb_label(label) if request.args["rank"] == "0": info["reg"] = 1 elif number == "1": C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({"lmfdb_iso": N + "." + iso}) data = C.elliptic_curves.padic_db.find_one({"lmfdb_iso": N + "." + iso, "p": p}) info["data"] = data if data is None: info["reg"] = "no data" else: val = int(data["val"]) aprec = data["prec"] reg = sage.all.Qp(p, aprec)(int(data["unit"]), aprec - val) << val info["reg"] = web_latex(reg) else: info["reg"] = "no data" return render_template("padic_data.html", info=info)
def elliptic_curve_search(info, query): 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_ints(info, query, 'num_int_pts', 'num_int_pts') parse_floats(info, query, 'regulator', 'regulator') parse_bool(info, query, 'semistable', 'semistable') parse_bracketed_posints(info, query, 'torsion_structure', maxlength=2, 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='cm_disc',qfield='cm') if 'cm_disc' in info: query['cm'] = info['cm_disc'] parse_element_of(info, query, field='isodeg', qfield='isogeny_degrees', split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='exclude') parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes', mode=info.get('surj_quantifier'), radical='nonmax_rad') parse_primes(info, query, 'bad_primes', name='bad primes', qfield='bad_primes', mode=info.get('bad_quantifier')) # The button which used to be labelled Optimal only no/yes" # (default no) has been renamed "Curves per isogeny class all/one" # (default one) but the only change in behavious is that we no # longer treat class 990h (where the optial curve is #3 not #1) as # special: the "one" option just restricts to curves whose # 'number' is 1. if 'optimal' in info and info['optimal'] == 'on': query.update({'number': 1}) # Old behaviour was as follows: # For all isogeny classes except 990h the optimal curve is number 1, while for class 990h it is number 3. # So setting query['number'] = 1 is nearly correct, but fails on 990h3. # Instead, we use this more complicated query: # query.update({"$or":[{'iso':'990h', 'number':3}, {'iso':{'$ne':'990h'},'number':1}]}) info['curve_ainvs'] = lambda dbc: str([ZZ(ai) for ai in dbc['ainvs']]) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label( dbc['lmfdb_iso'])[1]) info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['label']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['iso'])
def random_curve(): label = db.ec_curves.random(projection=1)['lmfdb_label'] cond, iso, num = split_lmfdb_label(label) return redirect( url_for(".by_triple_label", conductor=cond, iso_label=iso, number=num))
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 random_curve(): label = db.ec_curves.random(projection=1)['lmfdb_label'] cond, iso, num = split_lmfdb_label(label) return redirect(url_for(".by_triple_label", conductor=cond, iso_label=iso, number=num))
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 make_form(self): # To start with the data fields of self are just those from # the database. We need to reformat these and compute some # further (easy) data about it. # from lmfdb.ecnf.WebEllipticCurve import FIELD self.field = FIELD(self.field_label) pretty_field = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, getDBConnection(), pretty_field) try: dims = db_dims().find_one({'field_label':self.field_label, 'level_label':self.level_label})['gl2_dims'] self.newspace_dimension = dims[str(self.weight)]['new_dim'] except TypeError: self.newspace_dimension = 'not available' self.newspace_label = "-".join([self.field_label,self.level_label]) self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label) K = self.field.K() if self.dimension>1: Qx = PolynomialRing(QQ,'x') self.hecke_poly = Qx(str(self.hecke_poly)) F = NumberField(self.hecke_poly,'z') self.hecke_poly = web_latex(self.hecke_poly) def conv(ap): if '?' in ap: return 'not known' else: return F(str(ap)) self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs] self.nap = len(self.hecke_eigs) self.nap0 = min(50, self.nap) self.hecke_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])] level = ideal_from_label(K,self.level_label) self.level_ideal2 = web_latex(level) badp = level.prime_factors() self.have_AL = self.AL_eigs[0]!='?' if self.have_AL: self.AL_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(badp, self.AL_eigs)] self.sign = 'not determined' if self.sfe == 1: self.sign = "+1" elif self.sfe == -1: self.sign = "-1" if self.Lratio == '?': self.Lratio = "not determined" self.anrank = "not determined" else: self.Lratio = QQ(self.Lratio) self.anrank = "\(0\)" if self.Lratio!=0 else "odd" if self.sfe==-1 else "\(\ge2\), even" self.properties2 = [('Base field', pretty_field), ('Weight', str(self.weight)), ('Level norm', str(self.level_norm)), ('Level', self.level_ideal2), ('Label', self.label), ('Dimension', str(self.dimension)) ] if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' self.properties2.append(('CM', str(self.CM))) self.bc_extra = '' self.bcd = 0 self.bct = self.bc!='?' and self.bc!=0 if self.bc == '?': self.bc = 'not determined' elif self.bc == 0: self.bc = 'no' elif self.bc == 1: self.bcd = self.bc self.bc = 'yes' elif self.bc >1: self.bcd = self.bc self.bc = 'yes' self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)' elif self.bc < -1: self.bcd = -self.bc self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' self.properties2.append(('Base-change', str(self.bc))) curve = db_ecnf().find_one({'class_label':self.label}) if curve: self.ec_status = 'exists' self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix) curve_bc = curve['base_change'] curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc] bc_urls = [url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso) for cond, iso, num in curve_bc_parts] bc_labels = [newform_label(cond,2,1,iso) for cond,iso,num in curve_bc_parts] bc_exists = [is_newform_in_db(lab) for lab in bc_labels] self.bc_forms = [{'exists':ex, 'label':lab, 'url':url} for ex,lab,url in zip(bc_exists, bc_labels, bc_urls)] else: self.bc_forms = [] if self.bct: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties2.append(('Sign', self.sign)) self.properties2.append(('Analytic rank', self.anrank)) self.friends = [] if self.dimension==1: if self.ec_status == 'exists': self.friends += [('Elliptic curve isogeny class {}'.format(self.label), self.ec_url)] elif self.ec_status == 'missing': self.friends += [('Elliptic curve {} missing'.format(self.label), "")] else: self.friends += [('No elliptic curve', "")] self.friends += [ ('Newspace {}'.format(self.newspace_label),self.newspace_url)] self.friends += [ ('L-function not available','')]
def make_class(self): self.ainvs_str = self.ainvs self.ainvs = [int(a) for a in self.ainvs_str] self.E = EllipticCurve(self.ainvs) self.CM = self.E.has_cm() try: # Extract the isogeny degree matrix from the database size = len(self.isogeny_matrix) from sage.matrix.all import Matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) except AttributeError: # Failsafe: construct it from scratch self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix() size = self.isogeny_matrix.nrows() self.ncurves = size # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img # Create a list of the curves in the class from the database self.db_curves = [self.E] self.optimal_flags = [False] * size self.degrees = [0] * size if self.degree: self.degrees[0] = self.degree else: try: self.degrees[0] = self.E.modular_degree() except RuntimeError: pass # Fill in the curves in the class by looking each one up in the db: self.cremona_labels = [self.label] + [0] * (size - 1) if self.number == 1: self.optimal_flags[0] = True for i in range(2, size + 1): Edata = db_ec().find_one({"lmfdb_label": self.lmfdb_iso + str(i)}) Ei = EllipticCurve([int(a) for a in Edata["ainvs"]]) self.cremona_labels[i - 1] = Edata["label"] if Edata["number"] == 1: self.optimal_flags[i - 1] = True if "degree" in Edata: self.degrees[i - 1] = Edata["degree"] else: try: self.degrees[i - 1] = Ei.modular_degree() except RuntimeError: pass self.db_curves.append(Ei) if self.iso == "990h": # this isogeny class is labeled wrong in Cremona's tables self.optimal_flags = [False, False, True, False] self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) N, iso, number = split_lmfdb_label(self.lmfdb_iso) self.newform = web_latex(self.E.q_eigenform(10)) self.newform_label = newform_label(N, 2, 1, iso) self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso) newform_exists_in_db = is_newform_in_db(self.newform_label) self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso) self.curves = [ dict( [ ("label", self.lmfdb_iso + str(i + 1)), ("url", url_for(".by_triple_label", conductor=N, iso_label=iso, number=i + 1)), ("cremona_label", self.cremona_labels[i]), ("ainvs", str(list(c.ainvs()))), ("torsion", c.torsion_order()), ("degree", self.degrees[i]), ("optimal", self.optimal_flags[i]), ] ) for i, c in enumerate(self.db_curves) ] self.friends = [("L-function", self.lfunction_link)] if not self.CM: self.friends += [ ( "Symmetric square L-function", url_for("l_functions.l_function_ec_sym_page", power="2", label=self.lmfdb_iso), ), ( "Symmetric 4th power L-function", url_for("l_functions.l_function_ec_sym_page", power="4", label=self.lmfdb_iso), ), ] if newform_exists_in_db: self.friends += [("Modular form " + self.newform_label, self.newform_link)] self.properties = [ ("Label", self.lmfdb_iso), ("Number of curves", str(self.ncurves)), ("Conductor", "\(%s\)" % N), ("CM", "%s" % self.CM), ("Rank", "\(%s\)" % self.rank), ("Graph", ""), (None, self.graph_link), ] self.downloads = [ ("Download coefficients of newform", url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=100)), ("Download stored data for all curves", url_for(".download_EC_all", label=self.lmfdb_iso)), ] if self.lmfdb_iso == self.iso: self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso else: self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso) self.bread = [ ("Elliptic Curves", url_for("ecnf.index")), ("$\Q$", url_for(".rational_elliptic_curves")), ("%s" % N, url_for(".by_conductor", conductor=N)), ("%s" % iso, " "), ]
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 random_curve(): label = random_object_from_collection( db_ec() )['lmfdb_label'] cond, iso, num = split_lmfdb_label(label) return redirect(url_for(".by_triple_label", conductor=cond, iso_label=iso, number=num))
def make_class(self): self.ainvs_str = self.ainvs self.ainvs = [int(a) for a in self.ainvs_str] self.E = EllipticCurve(self.ainvs) self.CM = self.E.has_cm() try: # Extract the isogeny degree matrix from the database size = len(self.isogeny_matrix) from sage.matrix.all import Matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) except AttributeError: # Failsafe: construct it from scratch self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix() size = self.isogeny_matrix.nrows() self.ncurves = size # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img # Create a list of the curves in the class from the database self.db_curves = [self.E] self.optimal_flags = [False] * size self.degrees = [0] * size if self.degree: self.degrees[0] = self.degree else: try: self.degrees[0] = self.E.modular_degree() except RuntimeError: pass # Fill in the curves in the class by looking each one up in the db: self.cremona_labels = [self.label] + [0] * (size - 1) if self.number == 1: self.optimal_flags[0] = True for i in range(2, size + 1): Edata = db_ec().find_one({'lmfdb_label': self.lmfdb_iso + str(i)}) Ei = EllipticCurve([int(a) for a in Edata['ainvs']]) self.cremona_labels[i - 1] = Edata['label'] if Edata['number'] == 1: self.optimal_flags[i - 1] = True if 'degree' in Edata: self.degrees[i - 1] = Edata['degree'] else: try: self.degrees[i - 1] = Ei.modular_degree() except RuntimeError: pass self.db_curves.append(Ei) if self.iso == '990h': # this isogeny class is labeled wrong in Cremona's tables self.optimal_flags = [False, False, True, False] self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) N, iso, number = split_lmfdb_label(self.lmfdb_iso) self.newform = web_latex(self.E.q_eigenform(10)) self.newform_label = newform_label(N,2,1,iso) self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso) self.newform_exists_in_db = is_newform_in_db(self.newform_label) self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso) self.curves = [dict([('label',self.lmfdb_iso + str(i + 1)), ('url',url_for(".by_triple_label", conductor=N, iso_label=iso, number=i+1)), ('cremona_label',self.cremona_labels[i]), ('ainvs',str(list(c.ainvs()))), ('torsion',c.torsion_order()), ('degree',self.degrees[i]), ('optimal',self.optimal_flags[i])]) for i, c in enumerate(self.db_curves)] self.friends = [('L-function', self.lfunction_link)] if not self.CM: if int(N)<=300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso))] if int(N)<=50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', label=self.lmfdb_iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.properties = [('Label', self.lmfdb_iso), ('Number of curves', str(self.ncurves)), ('Conductor', '\(%s\)' % N), ('CM', '%s' % self.CM), ('Rank', '\(%s\)' % self.rank), ('Graph', ''),(None, self.graph_link) ] self.downloads = [('Download coefficients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)), ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))] if self.lmfdb_iso == self.iso: self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso else: self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')] self.code = {} self.code['show'] = {'sage':''} # use default show names self.code['class'] = {'sage':'E = EllipticCurve("%s1")\n'%(self.lmfdb_iso) + 'E.isogeny_class()\n'} self.code['curves'] = {'sage':'E.isogeny_class().curves'} self.code['rank'] = {'sage':'E.rank()'} self.code['q_eigenform'] = {'sage':'E.q_eigenform(10)'} self.code['matrix'] = {'sage':'E.isogeny_class().matrix()'} self.code['plot'] = {'sage':'E.isogeny_graph().plot(edge_labels=True)'}
def make_form(self, nap0=50): # To start with the data fields of self are just those from # the database. We need to reformat these and compute some # further (easy) data about it. # from lmfdb.ecnf.WebEllipticCurve import FIELD self.field = FIELD(self.field_label) pretty_field = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, pretty_field) try: dims = db.bmf_dims.lucky( { 'field_label': self.field_label, 'level_label': self.level_label }, projection='gl2_dims') self.newspace_dimension = dims[str(self.weight)]['new_dim'] except TypeError: self.newspace_dimension = 'not available' self.newspace_label = "-".join([self.field_label, self.level_label]) self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label) K = self.field.K() # 'hecke_poly_obj' is the non-LaTeX version of hecke_poly self.hecke_poly_obj = self.hecke_poly if self.dimension > 1: Qx = PolynomialRing(QQ, 'x') self.hecke_poly = Qx(str(self.hecke_poly)) F = NumberField(self.hecke_poly, 'z') self.hecke_poly = web_latex(self.hecke_poly) def conv(ap): if '?' in ap: return 'not known' else: return F(str(ap)) self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs] self.level = ideal_from_label(K, self.level_label) self.level_ideal2 = web_latex(self.level) badp = self.level.prime_factors() self.nap = len(self.hecke_eigs) self.nap0 = min(nap0, self.nap) self.neigs = self.nap0 + len(badp) self.hecke_table = [[ web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap) ] for p, ap in zip(primes_iter(K), self.hecke_eigs[:self.neigs]) if not p in badp] self.have_AL = self.AL_eigs[0] != '?' if self.have_AL: self.AL_table = [[ web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap) ] for p, ap in zip(badp, self.AL_eigs)] # The following helps to create Sage download data self.AL_table_data = [[p.gens_reduced(), ap] for p, ap in zip(badp, self.AL_eigs)] self.sign = 'not determined' try: if self.sfe == 1: self.sign = "$+1$" elif self.sfe == -1: self.sign = "$-1$" except AttributeError: self.sfe = '?' if self.Lratio == '?': self.Lratio = "not determined" self.anrank = "not determined" else: self.Lratio = QQ(self.Lratio) self.anrank = r"\(0\)" if self.Lratio != 0 else "odd" if self.sfe == -1 else r"\(\ge2\), even" self.properties = [('Label', self.label), ('Base field', pretty_field), ('Weight', prop_int_pretty(self.weight)), ('Level norm', prop_int_pretty(self.level_norm)), ('Level', self.level_ideal2), ('Dimension', prop_int_pretty(self.dimension))] try: if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' else: if int(self.CM) % 4 in [2, 3]: self.CM = 4 * int(self.CM) self.CM = "$%s$" % self.CM except AttributeError: self.CM = 'not determined' self.properties.append(('CM', str(self.CM))) self.bc_extra = '' self.bcd = 0 self.bct = self.bc != '?' and self.bc != 0 if self.bc == '?': self.bc = 'not determined' elif self.bc == 0: self.bc = 'no' elif self.bc == 1: self.bcd = self.bc self.bc = 'yes' elif self.bc > 1: self.bcd = self.bc self.bc = 'yes' self.bc_extra = r', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str( self.bcd) + r'})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = r', but is a twist of the base change of a form over \(\mathbb{Q}\)' elif self.bc < -1: self.bcd = -self.bc self.bc = 'no' self.bc_extra = r', but is a twist of the base change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str( self.bcd) + r'})\)' self.properties.append(('Base change', str(self.bc))) curve_bc = db.ec_nfcurves.lucky({'class_label': self.label}, projection="base_change") if curve_bc is not None: if curve_bc and "." not in curve_bc[0]: curve_bc = [ cremona_label_to_lmfdb_label(lab) for lab in curve_bc ] self.ec_status = 'exists' self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix) curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc] bc_urls = [ url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) for cond, iso, num in curve_bc_parts ] bc_labels = [ ".".join([str(cond), str(2), 'a', iso]) for cond, iso, _ in curve_bc_parts ] bc_exists = [db.mf_newforms.label_exists(lab) for lab in bc_labels] self.bc_forms = [{ 'exists': ex, 'label': lab, 'url': url } for ex, lab, url in zip(bc_exists, bc_labels, bc_urls)] else: self.bc_forms = [] if self.bct or self.label in bmfs_with_no_curve: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties.append(('Sign', self.sign)) self.properties.append(('Analytic rank', self.anrank)) self.friends = [] self.friends += [('Newspace {}'.format(self.newspace_label), self.newspace_url)] url = 'ModularForm/GL2/ImaginaryQuadratic/{}'.format( self.label.replace('-', '/')) Lfun = get_lfunction_by_url(url) if Lfun: instances = get_instances_by_Lhash_and_trace_hash( Lfun['Lhash'], Lfun['degree'], Lfun['trace_hash']) # This will also add the EC/G2C, as this how the Lfun was computed # and not add itself self.friends = names_and_urls(instances, exclude={url}) self.friends.append(('L-function', '/L/' + url)) else: # old code if self.dimension == 1: if self.ec_status == 'exists': self.friends += [('Isogeny class {}'.format(self.label), self.ec_url)] elif self.ec_status == 'missing': self.friends += [ ('Isogeny class {} missing'.format(self.label), "") ] else: self.friends += [('No elliptic curve', "")] self.friends += [('L-function not available', '')]
def make_form(self): # To start with the data fields of self are just those from # the database. We need to reformat these and compute some # further (easy) data about it. # from lmfdb.ecnf.WebEllipticCurve import FIELD self.field = FIELD(self.field_label) pretty_field = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, pretty_field) try: dims = db.bmf_dims.lucky({'field_label':self.field_label, 'level_label':self.level_label}, projection='gl2_dims') self.newspace_dimension = dims[str(self.weight)]['new_dim'] except TypeError: self.newspace_dimension = 'not available' self.newspace_label = "-".join([self.field_label,self.level_label]) self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label) K = self.field.K() if self.dimension>1: Qx = PolynomialRing(QQ,'x') self.hecke_poly = Qx(str(self.hecke_poly)) F = NumberField(self.hecke_poly,'z') self.hecke_poly = web_latex(self.hecke_poly) def conv(ap): if '?' in ap: return 'not known' else: return F(str(ap)) self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs] self.nap = len(self.hecke_eigs) self.nap0 = min(50, self.nap) self.hecke_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])] level = ideal_from_label(K,self.level_label) self.level_ideal2 = web_latex(level) badp = level.prime_factors() self.have_AL = self.AL_eigs[0]!='?' if self.have_AL: self.AL_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(badp, self.AL_eigs)] self.sign = 'not determined' try: if self.sfe == 1: self.sign = "+1" elif self.sfe == -1: self.sign = "-1" except AttributeError: self.sfe = '?' if self.Lratio == '?': self.Lratio = "not determined" self.anrank = "not determined" else: self.Lratio = QQ(self.Lratio) self.anrank = "\(0\)" if self.Lratio!=0 else "odd" if self.sfe==-1 else "\(\ge2\), even" self.properties2 = [('Base field', pretty_field), ('Weight', str(self.weight)), ('Level norm', str(self.level_norm)), ('Level', self.level_ideal2), ('Label', self.label), ('Dimension', str(self.dimension)) ] try: if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' else: if self.CM%4 in [2,3]: self.CM = 4*self.CM except AttributeError: self.CM = 'not determined' self.properties2.append(('CM', str(self.CM))) self.bc_extra = '' self.bcd = 0 self.bct = self.bc!='?' and self.bc!=0 if self.bc == '?': self.bc = 'not determined' elif self.bc == 0: self.bc = 'no' elif self.bc == 1: self.bcd = self.bc self.bc = 'yes' elif self.bc >1: self.bcd = self.bc self.bc = 'yes' self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)' elif self.bc < -1: self.bcd = -self.bc self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' self.properties2.append(('Base-change', str(self.bc))) curve_bc = db.ec_nfcurves.lucky({'class_label':self.label}, projection="base_change") if curve_bc is not None: self.ec_status = 'exists' self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix) curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc] bc_urls = [url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) for cond, iso, num in curve_bc_parts] bc_labels = [".".join( [str(cond), str(2), 'a', iso] ) for cond,iso,_ in curve_bc_parts] bc_exists = [db.mf_newforms.label_exists(lab) for lab in bc_labels] self.bc_forms = [{'exists':ex, 'label':lab, 'url':url} for ex,lab,url in zip(bc_exists, bc_labels, bc_urls)] else: self.bc_forms = [] if self.bct: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties2.append(('Sign', self.sign)) self.properties2.append(('Analytic rank', self.anrank)) self.friends = [] self.friends += [('Newspace {}'.format(self.newspace_label),self.newspace_url)] url = 'ModularForm/GL2/ImaginaryQuadratic/{}'.format( self.label.replace('-', '/')) Lfun = get_lfunction_by_url(url) if Lfun: # first by Lhash instances = get_instances_by_Lhash(Lfun['Lhash']) # then by trace_hash instances += get_instances_by_trace_hash(Lfun['degree'], Lfun['trace_hash']) # This will also add the EC/G2C, as this how the Lfun was computed self.friends = names_and_urls(instances) # remove itself self.friends.remove( ('Bianchi modular form {}'.format(self.label), '/' + url)) self.friends.append(('L-function', '/L/'+url)) else: # old code if self.dimension == 1: if self.ec_status == 'exists': self.friends += [('Isogeny class {}'.format(self.label), self.ec_url)] elif self.ec_status == 'missing': self.friends += [('Isogeny class {} missing'.format(self.label), "")] else: self.friends += [('No elliptic curve', "")] self.friends += [ ('L-function not available','')]
def make_form(self): # To start with the data fields of self are just those from # the database. We need to reformat these and compute some # further (easy) data about it. # from lmfdb.ecnf.WebEllipticCurve import FIELD self.field = FIELD(self.field_label) pretty_field = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, pretty_field) try: dims = db.bmf_dims.lucky( { 'field_label': self.field_label, 'level_label': self.level_label }, projection='gl2_dims') self.newspace_dimension = dims[str(self.weight)]['new_dim'] except TypeError: self.newspace_dimension = 'not available' self.newspace_label = "-".join([self.field_label, self.level_label]) self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label) K = self.field.K() if self.dimension > 1: Qx = PolynomialRing(QQ, 'x') self.hecke_poly = Qx(str(self.hecke_poly)) F = NumberField(self.hecke_poly, 'z') self.hecke_poly = web_latex(self.hecke_poly) def conv(ap): if '?' in ap: return 'not known' else: return F(str(ap)) self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs] self.nap = len(self.hecke_eigs) self.nap0 = min(50, self.nap) self.hecke_table = [[ web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap) ] for p, ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])] level = ideal_from_label(K, self.level_label) self.level_ideal2 = web_latex(level) badp = level.prime_factors() self.have_AL = self.AL_eigs[0] != '?' if self.have_AL: self.AL_table = [[ web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap) ] for p, ap in zip(badp, self.AL_eigs)] self.sign = 'not determined' if self.sfe == 1: self.sign = "+1" elif self.sfe == -1: self.sign = "-1" if self.Lratio == '?': self.Lratio = "not determined" self.anrank = "not determined" else: self.Lratio = QQ(self.Lratio) self.anrank = "\(0\)" if self.Lratio != 0 else "odd" if self.sfe == -1 else "\(\ge2\), even" self.properties2 = [('Base field', pretty_field), ('Weight', str(self.weight)), ('Level norm', str(self.level_norm)), ('Level', self.level_ideal2), ('Label', self.label), ('Dimension', str(self.dimension))] if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' self.properties2.append(('CM', str(self.CM))) self.bc_extra = '' self.bcd = 0 self.bct = self.bc != '?' and self.bc != 0 if self.bc == '?': self.bc = 'not determined' elif self.bc == 0: self.bc = 'no' elif self.bc == 1: self.bcd = self.bc self.bc = 'yes' elif self.bc > 1: self.bcd = self.bc self.bc = 'yes' self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str( self.bcd) + '})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)' elif self.bc < -1: self.bcd = -self.bc self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str( self.bcd) + '})\)' self.properties2.append(('Base-change', str(self.bc))) curve_bc = db.ec_nfcurves.lucky({'class_label': self.label}, projection="base_change") if curve_bc is not None: self.ec_status = 'exists' self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix) curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc] bc_urls = [ url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso) for cond, iso, num in curve_bc_parts ] bc_labels = [ newform_label(cond, 2, 1, iso) for cond, iso, num in curve_bc_parts ] bc_exists = [is_newform_in_db(lab) for lab in bc_labels] self.bc_forms = [{ 'exists': ex, 'label': lab, 'url': url } for ex, lab, url in zip(bc_exists, bc_labels, bc_urls)] else: self.bc_forms = [] if self.bct: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties2.append(('Sign', self.sign)) self.properties2.append(('Analytic rank', self.anrank)) self.friends = [] if self.dimension == 1: if self.ec_status == 'exists': self.friends += [ ('Elliptic curve isogeny class {}'.format(self.label), self.ec_url) ] elif self.ec_status == 'missing': self.friends += [ ('Elliptic curve {} missing'.format(self.label), "") ] else: self.friends += [('No elliptic curve', "")] self.friends += [('Newspace {}'.format(self.newspace_label), self.newspace_url)] self.friends += [('L-function not available', '')]
def elliptic_curve_search(info, query): parse_rational_to_list(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_ints(info,query,'num_int_pts','num_int_pts') parse_ints(info,query,'class_size','class_size') parse_ints(info,query,'class_deg','class_deg') parse_floats(info,query,'regulator','regulator') parse_bool(info,query,'semistable','semistable') parse_bool(info,query,'potential_good_reduction','potential_good_reduction') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,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='cm_disc',qfield='cm') parse_element_of(info,query,'isogeny_degrees',split_interval=1000,contained_in=get_stats().isogeny_degrees) parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='exclude') parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes',mode=info.get('surj_quantifier'), radical='nonmax_rad') parse_primes(info, query, 'bad_primes', name='bad primes', qfield='bad_primes',mode=info.get('bad_quantifier')) parse_primes(info, query, 'sha_primes', name='sha primes', qfield='sha_primes',mode=info.get('sha_quantifier')) # The button which used to be labelled Optimal only no/yes" # (default: no) has been renamed "Curves per isogeny class # all/one" (default: all). When this option is "one" we only list # one curve in each class, currently choosing the curve with # minimal Faltings heights, which is conjecturally the # Gamma_1(N)-optimal curve. if 'optimal' in info and info['optimal'] == 'on': query.update({'lmfdb_number':1}) info['curve_ainvs'] = lambda dbc: str([ZZ(ai) for ai in dbc['ainvs']]) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['cremona_bound'] = CREMONA_BOUND info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['Clabel']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['Ciso'])
def make_class(self): # Extract the size of the isogeny class from the database classdata = db.ec_classdata.lucky({'lmfdb_iso': self.lmfdb_iso}) self.class_size = ncurves = classdata['class_size'] # Create a list of the curves in the class from the database number_key = 'Cnumber' if self.label_type == 'Cremona' else 'lmfdb_number' self.curves = [ db.ec_curvedata.lucky({ 'lmfdb_iso': self.lmfdb_iso, number_key: i + 1 }) for i in range(ncurves) ] # Set optimality flags. The optimal curve is conditionally # number 1 except in one case which is labeled differently in # the Cremona tables. We know which curve is optimal iff the # optimality code for curve #1 is 1 (except for class 990h). # Note that self is actually an elliptic curve, with number=1. # The code here allows us to update the display correctly by # changing one line in this file (defining OPTIMALITY_BOUND) # without changing the data. self.cremona_bound = CREMONA_BOUND self.optimality_bound = OPTIMALITY_BOUND self.optimality_known = (self.conductor < OPTIMALITY_BOUND) or ( (self.conductor < CREMONA_BOUND) and ((self.optimality == 1) or (self.Ciso == '990h'))) self.optimal_label = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label if self.conductor < OPTIMALITY_BOUND: for c in self.curves: c['optimal'] = (c['Cnumber'] == (3 if self.Ciso == '990h' else 1)) c['optimality_known'] = True elif self.conductor < CREMONA_BOUND: for c in self.curves: c['optimal'] = (c['optimality'] > 0 ) # this curve possibly optimal c['optimality_known'] = (c['optimality'] == 1 ) # this curve certainly optimal else: for c in self.curves: c['optimal'] = None c['optimality_known'] = False for c in self.curves: c['ai'] = c['ainvs'] c['curve_url_lmfdb'] = url_for(".by_triple_label", conductor=self.conductor, iso_label=self.iso_label, number=c['lmfdb_number']) c['curve_url_cremona'] = url_for( ".by_ec_label", label=c['Clabel']) if self.conductor < CREMONA_BOUND else "N/A" if self.label_type == 'Cremona': c['curve_label'] = c['Clabel'] _, c_iso, c_number = split_cremona_label(c['Clabel']) else: c['curve_label'] = c['lmfdb_label'] _, c_iso, c_number = split_lmfdb_label(c['lmfdb_label']) c['short_label'] = "{}{}".format(c_iso, c_number) from sage.matrix.all import Matrix M = classdata['isogeny_matrix'] # permute rows/cols to match labelling: the rows/cols in the # ec_classdata table are with respect to LMFDB ordering. if self.label_type == 'Cremona': perm = lambda i: next(c for c in self.curves if c['Cnumber'] == i + 1)['lmfdb_number'] - 1 M = [[M[perm(i)][perm(j)] for i in range(ncurves)] for j in range(ncurves)] M = Matrix(M) self.isogeny_matrix_str = latex(M) # Create isogeny graph with appropriate vertex labels: self.graph = make_graph(M, [c['short_label'] for c in self.curves]) P = self.graph.plot(edge_labels=True, vertex_size=1000) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.newform = raw_typeset( PowerSeriesRing(QQ, 'q')(classdata['anlist'], 20, check=True)) self.newform_label = ".".join( [str(self.conductor), str(2), 'a', self.iso_label]) self.newform_exists_in_db = db.mf_newforms.label_exists( self.newform_label) if self.newform_exists_in_db: char_orbit, hecke_orbit = self.newform_label.split('.')[2:] self.newform_link = url_for("cmf.by_url_newform_label", level=self.conductor, weight=2, char_orbit_label=char_orbit, hecke_orbit=hecke_orbit) self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label=self.conductor, isogeny_class_label=self.iso_label) self.friends = [('L-function', self.lfunction_link)] if self.cm: # set CM field for Properties box. D = ZZ(self.cm).squarefree_part() coeffs = [(1 - D) // 4, -1, 1] if D % 4 == 1 else [-D, 0, 1] lab = db.nf_fields.lucky({'coeffs': coeffs}, projection='label') self.CMfield = field_pretty(lab) else: self.CMfield = "no" if self.conductor <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=self.conductor, isogeny=self.iso_label))] if self.conductor <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=self.conductor, isogeny=self.iso_label))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] if self.label_type == 'Cremona': self.title = "Elliptic curve isogeny class with Cremona label {} (LMFDB label {})".format( self.Ciso, self.lmfdb_iso) elif self.conductor < CREMONA_BOUND: self.title = "Elliptic curve isogeny class with LMFDB label {} (Cremona label {})".format( self.lmfdb_iso, self.Ciso) else: self.title = "Elliptic curve isogeny class with LMFDB label {}".format( self.lmfdb_iso) self.properties = [ ('Label', self.Ciso if self.label_type == 'Cremona' else self.lmfdb_iso), ('Number of curves', prop_int_pretty(ncurves)), ('Conductor', prop_int_pretty(self.conductor)), ('CM', '%s' % self.CMfield), ('Rank', prop_int_pretty(self.rank)) ] if ncurves > 1: self.properties += [('Graph', ''), (None, self.graph_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.iso_label, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.iso_label))] self.bread = [('Elliptic curves', url_for("ecnf.index")), (r'$\Q$', url_for(".rational_elliptic_curves")), ('%s' % self.conductor, url_for(".by_conductor", conductor=self.conductor)), ('%s' % self.iso_label, ' ')] self.code = {} self.code['show'] = {'sage': ''} # use default show names self.code['class'] = { 'sage': 'E = EllipticCurve("%s1")\n' % (self.iso_label) + 'E.isogeny_class()\n' } self.code['curves'] = {'sage': 'E.isogeny_class().curves'} self.code['rank'] = {'sage': 'E.rank()'} self.code['q_eigenform'] = {'sage': 'E.q_eigenform(10)'} self.code['matrix'] = {'sage': 'E.isogeny_class().matrix()'} self.code['plot'] = { 'sage': 'E.isogeny_graph().plot(edge_labels=True)' }
def elliptic_curve_search(info, query): 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,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_element_of(info,query,field='isodeg',qfield='isogeny_degrees',split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes',mode=mode, radical='nonmax_rad') if 'optimal' in info and info['optimal'] == 'on': # For all isogeny classes except 990h the optimal curve is number 1, while for class 990h it is number 3. # So setting query['number'] = 1 is nearly correct, but fails on 990h3. # Instead, we use this more complicated query: query.update({"$or":[{'iso':'990h', 'number':3}, {'iso':{'$ne':'990h'},'number':1}]}) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['label']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['iso'])
def make_class(self): self.CM = self.cm N, iso, number = split_lmfdb_label(self.lmfdb_iso) # Extract the size of the isogeny class from the database ncurves = self.class_size # Create a list of the curves in the class from the database self.curves = [db_ec().find_one({'iso':self.iso, 'lmfdb_number': i+1}) for i in range(ncurves)] # Set optimality flags. The optimal curve is number 1 except # in one case which is labeled differently in the Cremona tables for c in self.curves: c['optimal'] = (c['number']==(3 if self.label == '990h' else 1)) c['ai'] = parse_ainvs(c['xainvs']) c['url'] = url_for(".by_triple_label", conductor=N, iso_label=iso, number=c['lmfdb_number']) from sage.matrix.all import Matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.newform = web_latex(PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True)) self.newform_label = newform_label(N,2,1,iso) self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso) self.newform_exists_in_db = is_newform_in_db(self.newform_label) self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label = N, isogeny_class_label = iso) self.friends = [('L-function', self.lfunction_link)] if not self.CM: self.CM = "no" if int(N)<=300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor = N, isogeny = iso))] if int(N)<=50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor = N, isogeny = iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.properties = [('Label', self.lmfdb_iso), ('Number of curves', str(ncurves)), ('Conductor', '\(%s\)' % N), ('CM', '%s' % self.CM), ('Rank', '\(%s\)' % self.rank), ('Graph', ''),(None, self.graph_link) ] self.downloads = [('Download coefficients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)), ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))] if self.lmfdb_iso == self.iso: self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso else: self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')] self.code = {} self.code['show'] = {'sage':''} # use default show names self.code['class'] = {'sage':'E = EllipticCurve("%s1")\n'%(self.lmfdb_iso) + 'E.isogeny_class()\n'} self.code['curves'] = {'sage':'E.isogeny_class().curves'} self.code['rank'] = {'sage':'E.rank()'} self.code['q_eigenform'] = {'sage':'E.q_eigenform(10)'} self.code['matrix'] = {'sage':'E.isogeny_class().matrix()'} self.code['plot'] = {'sage':'E.isogeny_graph().plot(edge_labels=True)'}
def make_class(self): self.CM = self.cm N, iso, number = split_lmfdb_label(self.lmfdb_iso) self.conductor = int(N) # Extract the size of the isogeny class from the database self.ncurves = ncurves = self.class_size # Create a list of the curves in the class from the database number_key = 'number' if self.label_type == 'Cremona' else 'lmfdb_number' self.curves = [ db.ec_curves.lucky({ 'iso': self.iso, number_key: i + 1 }) for i in range(ncurves) ] # Set optimality flags. The optimal curve is number 1 except # in one case which is labeled differently in the Cremona tables self.optimality_known = (self.ncurves == 1) or (self.conductor < OPTIMALITY_BOUND) self.optimality_bound = OPTIMALITY_BOUND for c in self.curves: c['optimal'] = (c['number'] == (3 if self.iso == '990h' else 1)) c['ai'] = c['ainvs'] c['curve_url_lmfdb'] = url_for(".by_triple_label", conductor=N, iso_label=iso, number=c['lmfdb_number']) c['curve_url_cremona'] = url_for(".by_ec_label", label=c['label']) if self.label_type == 'Cremona': c['curve_label'] = c['label'] _, c_iso, c_number = split_cremona_label(c['label']) else: c['curve_label'] = c['lmfdb_label'] _, c_iso, c_number = split_lmfdb_label(c['lmfdb_label']) c['short_label'] = "{}{}".format(c_iso, c_number) from sage.matrix.all import Matrix if self.label_type == 'Cremona': # permute rows/cols perm = lambda i: (c for c in self.curves if c['number'] == i + 1 ).next()['lmfdb_number'] - 1 self.isogeny_matrix = [[ self.isogeny_matrix[perm(i)][perm(j)] for i in range(ncurves) ] for j in range(ncurves)] self.isogeny_matrix = Matrix(self.isogeny_matrix) self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) # Create isogeny graph with appropriate vertex labels: self.graph = make_graph(self.isogeny_matrix, [c['short_label'] for c in self.curves]) P = self.graph.plot(edge_labels=True, vertex_size=1000) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.newform = web_latex( PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True)) self.newform_label = db.mf_newforms.lucky( { 'level': N, 'weight': 2, 'related_objects': { '$contains': 'EllipticCurve/Q/%s/%s' % (N, iso) } }, 'label') self.newform_exists_in_db = self.newform_label is not None if self.newform_label is not None: char_orbit, hecke_orbit = self.newform_label.split('.')[2:] self.newform_link = url_for("cmf.by_url_newform_label", level=N, weight=2, char_orbit_label=char_orbit, hecke_orbit=hecke_orbit) self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label=N, isogeny_class_label=iso) self.friends = [('L-function', self.lfunction_link)] if not self.CM: self.CM = "no" if int(N) <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=N, isogeny=iso))] if int(N) <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=N, isogeny=iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] if self.label_type == 'Cremona': self.title = "Elliptic Curve Isogeny Class with Cremona label {} (LMFDB label {})".format( self.iso, self.lmfdb_iso) self.iso_label = self.iso else: self.title = "Elliptic Curve Isogeny Class with LMFDB label {} (Cremona label {})".format( self.lmfdb_iso, self.iso) self.iso_label = self.lmfdb_iso self.properties = [ ('Label', self.iso if self.label_type == 'Cremona' else self.lmfdb_iso), ('Number of curves', str(ncurves)), ('Conductor', '%s' % N), ('CM', '%s' % self.CM), ('Rank', '%s' % self.rank) ] if self.ncurves > 1: self.properties += [('Graph', ''), (None, self.graph_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.lmfdb_iso))] self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')] self.code = {} self.code['show'] = {'sage': ''} # use default show names self.code['class'] = { 'sage': 'E = EllipticCurve("%s1")\n' % (self.lmfdb_iso) + 'E.isogeny_class()\n' } self.code['curves'] = {'sage': 'E.isogeny_class().curves'} self.code['rank'] = {'sage': 'E.rank()'} self.code['q_eigenform'] = {'sage': 'E.q_eigenform(10)'} self.code['matrix'] = {'sage': 'E.isogeny_class().matrix()'} self.code['plot'] = { 'sage': 'E.isogeny_graph().plot(edge_labels=True)' }
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(info, query): 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,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_element_of(info,query,field='isodeg',qfield='isogeny_degrees',split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes',mode=mode, radical='nonmax_rad') if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 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])
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 make_class(self): self.ainvs_str = self.ainvs self.ainvs = [int(a) for a in self.ainvs_str] self.E = EllipticCurve(self.ainvs) self.CM = self.E.has_cm() try: # Extract the isogeny degree matrix from the database size = len(self.isogeny_matrix) from sage.matrix.all import Matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) except AttributeError: # Failsafe: construct it from scratch self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix() size = self.isogeny_matrix.nrows() self.ncurves = size # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img # Create a list of the curves in the class from the database self.db_curves = [self.E] self.optimal_flags = [False] * size self.degrees = [0] * size if self.degree: self.degrees[0] = self.degree else: try: self.degrees[0] = self.E.modular_degree() except RuntimeError: pass # Fill in the curves in the class by looking each one up in the db: self.cremona_labels = [self.label] + [0] * (size - 1) if self.number == 1: self.optimal_flags[0] = True for i in range(2, size + 1): Edata = db_ec().find_one({'lmfdb_label': self.lmfdb_iso + str(i)}) Ei = EllipticCurve([int(a) for a in Edata['ainvs']]) self.cremona_labels[i - 1] = Edata['label'] if Edata['number'] == 1: self.optimal_flags[i - 1] = True if 'degree' in Edata: self.degrees[i - 1] = Edata['degree'] else: try: self.degrees[i - 1] = Ei.modular_degree() except RuntimeError: pass self.db_curves.append(Ei) if self.iso == '990h': # this isogeny class is labeled wrong in Cremona's tables self.optimal_flags = [False, False, True, False] self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) N, iso, number = split_lmfdb_label(self.lmfdb_iso) self.newform = web_latex(self.E.q_eigenform(10)) self.newform_label = newform_label(N, 2, 1, iso) self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso) newform_exists_in_db = is_newform_in_db(self.newform_label) self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso) self.curves = [ dict([('label', self.lmfdb_iso + str(i + 1)), ('url', url_for(".by_triple_label", conductor=N, iso_label=iso, number=i + 1)), ('cremona_label', self.cremona_labels[i]), ('ainvs', str(list(c.ainvs()))), ('torsion', c.torsion_order()), ('degree', self.degrees[i]), ('optimal', self.optimal_flags[i])]) for i, c in enumerate(self.db_curves) ] self.friends = [('L-function', self.lfunction_link)] if not self.CM: if int(N) <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso))] if int(N) <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', label=self.lmfdb_iso))] if newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.properties = [('Label', self.lmfdb_iso), ('Number of curves', str(self.ncurves)), ('Conductor', '\(%s\)' % N), ('CM', '%s' % self.CM), ('Rank', '\(%s\)' % self.rank), ('Graph', ''), (None, self.graph_link)] self.downloads = [('Download coefficients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=100)), ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))] if self.lmfdb_iso == self.iso: self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso else: self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % ( self.lmfdb_iso, self.iso) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')]
def make_class(self): self.CM = self.cm N, iso, number = split_lmfdb_label(self.lmfdb_iso) # Extract the size of the isogeny class from the database ncurves = self.class_size # Create a list of the curves in the class from the database self.curves = [db.ec_curves.lucky({'iso':self.iso, 'lmfdb_number': i+1}) for i in range(ncurves)] # Set optimality flags. The optimal curve is number 1 except # in one case which is labeled differently in the Cremona tables for c in self.curves: c['optimal'] = (c['number']==(3 if self.label == '990h' else 1)) c['ai'] = c['ainvs'] c['url'] = url_for(".by_triple_label", conductor=N, iso_label=iso, number=c['lmfdb_number']) from sage.matrix.all import Matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.newform = web_latex(PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True)) self.newform_label = db.mf_newforms.lucky({'level':N, 'weight':2, 'related_objects':{'$contains':'EllipticCurve/Q/%s/%s' % (N, iso)}},'label') self.newform_exists_in_db = self.newform_label is not None if self.newform_label is not None: char_orbit, hecke_orbit = self.newform_label.split('.')[2:] self.newform_link = url_for("cmf.by_url_newform_label", level=N, weight=2, char_orbit_label=char_orbit, hecke_orbit=hecke_orbit) self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label = N, isogeny_class_label = iso) self.friends = [('L-function', self.lfunction_link)] if not self.CM: self.CM = "no" if int(N)<=300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor = N, isogeny = iso))] if int(N)<=50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor = N, isogeny = iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.properties = [('Label', self.lmfdb_iso), ('Number of curves', str(ncurves)), ('Conductor', '\(%s\)' % N), ('CM', '%s' % self.CM), ('Rank', '\(%s\)' % self.rank), ('Graph', ''),(None, self.graph_link) ] self.downloads = [('Download q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)), ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))] if self.lmfdb_iso == self.iso: self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso else: self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')] self.code = {} self.code['show'] = {'sage':''} # use default show names self.code['class'] = {'sage':'E = EllipticCurve("%s1")\n'%(self.lmfdb_iso) + 'E.isogeny_class()\n'} self.code['curves'] = {'sage':'E.isogeny_class().curves'} self.code['rank'] = {'sage':'E.rank()'} self.code['q_eigenform'] = {'sage':'E.q_eigenform(10)'} self.code['matrix'] = {'sage':'E.isogeny_class().matrix()'} self.code['plot'] = {'sage':'E.isogeny_graph().plot(edge_labels=True)'}
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)