def show_ecnf1(nf): if nf == "1.1.1.1": return redirect(url_for("ec.rational_elliptic_curves", **request.args)) if request.args: return elliptic_curve_search(data=request.args) start = 0 count = 50 try: nf_label = nf_string_to_label(nf) except ValueError: return search_input_error() query = {'field_label': nf_label} cursor = db_ecnf().find(query) nres = cursor.count() if (start >= nres): start -= (1 + (start - nres) / count) * count if (start < 0): start = 0 res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC), ('conductor_label', ASC), ('iso_nlabel', ASC), ('number', ASC)]).skip(start).limit(count) bread = [('Elliptic Curves', url_for(".index")), (nf_label, url_for('.show_ecnf1', nf=nf_label))] res = list(res) for e in res: e['field_knowl'] = nf_display_knowl(e['field_label'], getDBConnection(), field_pretty(e['field_label'])) info = {} info['field'] = nf_label info['query'] = query info['curves'] = res # [ECNF(e) for e in res] info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs #don't risk recomputing all the ecnf stats just to show curves for a single number field #if nf_label: #info['stats'] = ecnf_field_summary(nf_label) if nres == 1: info['report'] = 'unique match' 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 = 'Elliptic Curves over %s' % field_pretty(nf_label) return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t, learnmore=learnmore_list())
def show_ecnf1(nf): if nf == "1.1.1.1": return redirect(url_for("ec.rational_elliptic_curves", **request.args)) if request.args: return elliptic_curve_search(data=request.args) start = 0 count = 50 try: nf_label = nf_string_to_label(nf) except ValueError: return search_input_error() query = {'field_label': nf_label} cursor = db_ecnf().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC), ('conductor_label', ASC), ('iso_nlabel', ASC), ('number', ASC)]).skip(start).limit(count) bread = [('Elliptic Curves', url_for(".index")), (nf_label, url_for('.show_ecnf1', nf=nf_label))] res = list(res) for e in res: e['field_knowl'] = nf_display_knowl(e['field_label'], getDBConnection(), field_pretty(e['field_label'])) info = {} info['field'] = nf_label info['query'] = query info['curves'] = res # [ECNF(e) for e in res] info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs #don't risk recomputing all the ecnf stats just to show curves for a single number field #if nf_label: #info['stats'] = ecnf_field_summary(nf_label) if nres == 1: info['report'] = 'unique match' 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 = 'Elliptic Curves over %s' % field_pretty(nf_label) return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t, learnmore=learnmore_list())
def make_torsion_growth(self): try: tor_gro = self.tor_gro self.torsion_growth_data_exists = True except AttributeError: self.torsion_growth_data_exists = False return self.tg = tg = {} tg['data'] = tgextra = [] # find all base-changes of this curve in the database, if any from lmfdb.ecnf.WebEllipticCurve import db_ecnf bcs = [ res['label'] for res in db_ecnf().find({'base_change': self.lmfdb_label}, projection={ 'label': True, '_id': False }) ] bcfs = [lab.split("-")[0] for lab in bcs] for F, T in tor_gro.items(): tg1 = {} tg1['bc'] = "Not in database" if ":" in F: F = F.replace(":", ".") field_data = nf_display_knowl(F, getDBConnection(), field_pretty(F)) deg = int(F.split(".")[0]) bcc = [x for x, y in zip(bcs, bcfs) if y == F] if bcc: from lmfdb.ecnf.main import split_full_label F, NN, I, C = split_full_label(bcc[0]) tg1['bc'] = bcc[0] tg1['bc_url'] = url_for('ecnf.show_ecnf', nf=F, conductor_label=NN, class_label=I, number=C) else: field_data = web_latex_split_on_pm( coeff_to_poly(string2list(F))) deg = F.count(",") tg1['d'] = deg tg1['f'] = field_data tg1['t'] = '\(' + ' \\times '.join( ['\Z/{}\Z'.format(n) for n in T.split(",")]) + '\)' tg1['m'] = 0 tgextra.append(tg1) tgextra.sort(key=lambda x: x['d']) tg['n'] = len(tgextra) lastd = 1 for tg1 in tgextra: d = tg1['d'] if d != lastd: tg1['m'] = len([x for x in tgextra if x['d'] == d]) lastd = d tg['maxd'] = max(db_ecstats().find_one({'_id': 'torsion_growth'})['degrees'])
def field_display_gen(label, poly, disc=None, self_dual=None, truncate=0): """ This function is used to display a number field knowl. When the field is not in the LMFDB, it uses a dynamic knowl displaying the polynomial and discriminant. Otherwise, it uses the standard LMFDB number field knowl. INPUT: - ``label`` -- the LMFDB label for the field (``None`` if not in the LMFDB) - ``poly`` -- the defining polynomial for the field as a list - ``disc`` -- the discriminant of the field, as a list of (p, e) pairs - ``truncate`` -- an integer, the maximum length of the field label before truncation. If 0, no truncation will occur. """ if label is None: if poly: if self_dual: unit = ZZ(1) else: unit = ZZ(-1)**((len(poly)-1)//2) return polyquo_knowl(poly, disc, unit, 12) else: return '' else: name = field_pretty(label) if truncate and name == label and len(name) > truncate: parts = label.split('.') parts[2] = r'\(\cdots\)' name = '.'.join(parts) return nf_display_knowl(label, name)
def field_label(F, pretty=True, check=False): r""" Returns the LMFDB label of the field F. """ if F.absolute_degree() == 1: p = 'x' else: pp = F.absolute_polynomial() x = pp.parent().gen() p = str(pp).replace(str(x), 'x') l = poly_to_field_label(p) if l is None: if check: return False else: if pretty: return web_latex_split_on_pm(pp) else: return pp else: if check: return True if pretty: return field_pretty(l) else: return l
def field_label(F, pretty = True, check=False): r""" Returns the LMFDB label of the field F. """ if F.absolute_degree() == 1: p = 'x' else: pp = F.absolute_polynomial() x = pp.parent().gen() p = str(pp).replace(str(x), 'x') l = poly_to_field_label(p) if l is None: if check: return False else: if pretty: return web_latex_split_on_pm(pp) else: return pp else: if check: return True if pretty: return field_pretty(l) else: return l
def get_nf_info(lab): r""" extract number field label from string and pretty""" try: label = nf_string_to_label(lab) pretty = field_pretty (label) except ValueError as err: raise ValueError(Markup("<span style='color:black'>%s</span> is not a valid number field label. %s" % (escape(lab),err))) return label, pretty
def get_nf_info(lab): r""" extract number field label from string and pretty""" try: label = nf_string_to_label(lab) pretty = field_pretty (label) except ValueError as err: flash(Markup("Error: <span style='color:black'>%s</span> is not a valid number field. %s" % (lab,err)), "error") raise ValueError return label, pretty
def extend_from_db(self): setattr(self._value, "lmfdb_label", self._db_value) if not self._db_value is None and self._db_value != '': try: url = url_for("number_fields.by_label", label=self._db_value) except RuntimeError: emf_logger.critical("could not set url for the label") url = '' setattr(self._value, "lmfdb_url",url) setattr(self._value, "lmfdb_pretty", field_pretty(self._db_value)) else: if hasattr(self._value,'absolute_polynomial'): setattr(self._value, "lmfdb_pretty", web_latex_split_on_pm(self._value.absolute_polynomial())) elif self._value.absolute_degree()==1: setattr(self._value, "lmfdb_pretty", field_pretty('1.1.1.1')) setattr(self._value, "lmfdb_label", '1.1.1.1') else: emf_logger.critical("could not set lmfdb_pretty for the label")
def index(): # if 'jump' in request.args: # return show_ecnf1(request.args['label']) if len(request.args) > 0: return elliptic_curve_search(data=request.args) bread = get_bread() # the dict data will hold additional information to be displayed on # the main browse and search page data = {} # data['fields'] holds data for a sample of number fields of different # signatures for a general browse: data['fields'] = [] # Rationals data['fields'].append(['the rational field', (('1.1.1.1', [url_for('ec.rational_elliptic_curves'), '$\Q$']),)]) # Real quadratics (only a sample) rqfs = ['2.2.%s.1' % str(d) for d in [5, 89, 229, 497]] data['fields'].append(['real quadratic fields', ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in rqfs)]) # Imaginary quadratics iqfs = ['2.0.%s.1' % str(d) for d in [4, 8, 3, 7, 11]] data['fields'].append(['imaginary quadratic fields', ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in iqfs)]) # Cubics cubics = ['3.1.23.1'] data['fields'].append(['cubic fields', ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in cubics)]) # data['highlights'] holds data (URL and descriptive text) for a # sample of elliptic curves with interesting features: data['highlights'] = [] data['highlights'].append( ['A curve with $C_3\\times C_3$ torsion', url_for('.show_ecnf', nf='2.0.3.1', class_label='a', conductor_label='[2268,36,18]', number=int(1))] ) data['highlights'].append( ['A curve with $C_4\\times C_4$ torsion', url_for('.show_ecnf', nf='2.0.4.1', class_label='b', conductor_label='[5525,870,5]', number=int(9))] ) data['highlights'].append( ['A curve with CM by $\\sqrt{-267}$', url_for('.show_ecnf', nf='2.2.89.1', class_label='a', conductor_label='81.1', number=int(1))] ) data['highlights'].append( ['An isogeny class with isogenies of degree $3$ and $89$ (and $267$)', url_for('.show_ecnf_isoclass', nf='2.2.89.1', class_label='a', conductor_label='81.1')] ) data['highlights'].append( ['A curve with everywhere good reduction, but no global minimal model', url_for('.show_ecnf', nf='2.2.229.1', class_label='a', conductor_label='1.1', number=int(1))] ) return render_template("ecnf-index.html", title="Elliptic Curves over Number Fields", data=data, bread=bread)
def get_nf_info(lab): r""" extract number field label from string and pretty""" try: label = nf_string_to_label(lab) pretty = field_pretty(label) except ValueError as err: flash_error("%s is not a valid number field. %s", lab, err) raise ValueError return label, pretty
def field_display_gen(self, label, poly): if label is None: if poly: return polyquo_knowl(poly) else: return 'Unknown' elif label == u'1.1.1.1': # rationals, special case return nf_display_knowl(label, name=r"\(\Q\)") else: return nf_display_knowl(label, field_pretty(label))
def make_torsion_growth(self): if self.tor_gro is None: self.torsion_growth_data_exists = False return tor_gro = self.tor_gro self.torsion_growth_data_exists = True self.tg = tg = {} tg['data'] = tgextra = [] # find all base-changes of this curve in the database, if any bcs = list( db.ec_nfcurves.search( {'base_change': { '$contains': [self.lmfdb_label] }}, projection='label')) bcfs = [lab.split("-")[0] for lab in bcs] for F, T in tor_gro.items(): tg1 = {} tg1['bc'] = "Not in database" if ":" in F: F = F.replace(":", ".") field_data = nf_display_knowl(F, field_pretty(F)) deg = int(F.split(".")[0]) bcc = [x for x, y in zip(bcs, bcfs) if y == F] if bcc: from lmfdb.ecnf.main import split_full_label F, NN, I, C = split_full_label(bcc[0]) tg1['bc'] = bcc[0] tg1['bc_url'] = url_for('ecnf.show_ecnf', nf=F, conductor_label=NN, class_label=I, number=C) else: field_data = web_latex_split_on_pm( coeff_to_poly(string2list(F))) deg = F.count(",") tg1['d'] = deg tg1['f'] = field_data tg1['t'] = '\(' + ' \\times '.join( ['\Z/{}\Z'.format(n) for n in T.split(",")]) + '\)' tg1['m'] = 0 tgextra.append(tg1) tgextra.sort(key=lambda x: x['d']) tg['n'] = len(tgextra) lastd = 1 for tg1 in tgextra: d = tg1['d'] if d != lastd: tg1['m'] = len([x for x in tgextra if x['d'] == d]) lastd = d ## Hard code for now #tg['maxd'] = max(db.ec_curves.stats.get_oldstat('torsion_growth')['degrees']) tg['maxd'] = 7
def end_field_statement(field_label, poly): if field_label == '1.1.1.1': return """All endomorphisms of the Jacobian are defined over \(\Q\)""" elif field_label != '': pretty = field_pretty(field_label) url = url_for("number_fields.by_label", label=field_label) return """Smallest field over which all endomorphisms are defined:<br> Galois number field \(K = \Q (a) \simeq \) <a href=%s>%s</a> with defining polynomial \(%s\)""" % (url, pretty, poly) else: return """Smallest field over which all endomorphisms are defined:<br> Galois number field \(K = \Q (a)\) with defining polynomial \(%s\)""" % poly
def index(): # if 'jump' in request.args: # return show_ecnf1(request.args['label']) if len(request.args) > 0: return elliptic_curve_search(data=request.args) bread = get_bread() data = {} nfs = db_ecnf().distinct("field_label") nfs = ["2.0.4.1", "2.2.5.1", "3.1.23.1"] data["fields"] = [(nf, field_pretty(nf)) for nf in nfs if int(nf.split(".")[2]) < 200] return render_template("ecnf-index.html", title="Elliptic Curves over Number Fields", data=data, bread=bread)
def show_ecnf1(nf): if nf == "1.1.1.1": return redirect(url_for("ec.rational_elliptic_curves", **request.args)) if request.args: return elliptic_curve_search(data=request.args) start = 0 count = 50 nf_label = parse_field_string(nf) query = {"field_label": nf_label} cursor = db_ecnf().find(query) nres = cursor.count() if start >= nres: start -= (1 + (start - nres) / count) * count if start < 0: start = 0 res = ( cursor.sort( [ ("field_label", ASC), ("conductor_norm", ASC), ("conductor_label", ASC), ("iso_label", ASC), ("number", ASC), ] ) .skip(start) .limit(count) ) bread = [("Elliptic Curves", url_for(".index")), (nf_label, url_for(".show_ecnf1", nf=nf_label))] res = list(res) for e in res: e["field_knowl"] = nf_display_knowl(e["field_label"], getDBConnection(), e["field_label"]) info = {} info["field"] = nf_label info["query"] = query info["curves"] = res # [ECNF(e) for e in res] info["number"] = nres info["start"] = start info["count"] = count info["more"] = int(start + count < nres) info["field_pretty"] = field_pretty info["web_ainvs"] = web_ainvs if nres == 1: info["report"] = "unique match" 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 = "Elliptic Curves over %s" % field_pretty(nf_label) return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
def extend_from_db(self): setattr(self._value, "lmfdb_label", self._db_value) if not self._db_value is None and self._db_value != "": try: url = url_for("number_fields.by_label", label=self._db_value) except RuntimeError: emf_logger.critical("could not set url for the label") url = "" setattr(self._value, "lmfdb_url", url) setattr(self._value, "lmfdb_pretty", field_pretty(self._db_value)) else: setattr(self._value, "lmfdb_pretty", web_latex_split_on_pm(self._value.absolute_polynomial()))
def split_field_statement(is_simple_geom, field_label, poly): if is_simple_geom: return """Simple over \(\overline{\Q}\)""" elif field_label == '1.1.1.1': return """Splits over \(\Q\)""" elif field_label != '': pretty = field_pretty(field_label) url = url_for("number_fields.by_label", label=field_label) return """Splits over the number field \(\Q (b) \simeq \) <a href=%s>%s</a> with defining polynomial:<br> \(%s\)"""\ % (url, pretty, poly) else: return """Splits over the number field \(\Q (b)\) with defining polynomial:<br> \(%s\)""" % poly
def index(): # if 'jump' in request.args: # return show_ecnf1(request.args['label']) info = to_dict(request.args, search_array=ECNFSearchArray(), stats=ECNF_stats()) if request.args: return elliptic_curve_search(info) bread = get_bread() # the dict data will hold additional information to be displayed on # the main browse and search page # info['fields'] holds data for a sample of number fields of different # signatures for a general browse: info['fields'] = [] # Rationals # info['fields'].append(['the rational field', (('1.1.1.1', [url_for('ec.rational_elliptic_curves'), '$\Q$']),)]) # Removed due to ambiguity # Real quadratics (sample) rqfs = ['2.2.{}.1'.format(d) for d in [8, 12, 5, 24, 28, 40, 44, 13, 56, 60]] info['fields'].append(['By <a href="{}">real quadratic field</a>'.format(url_for('.statistics_by_signature', d=2, r=2)), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in rqfs)]) # Imaginary quadratics (sample) iqfs = ['2.0.{}.1'.format(d) for d in [4, 8, 3, 7, 11, 19, 43]] info['fields'].append(['By <a href="{}">imaginary quadratic field</a>'.format(url_for('.statistics_by_signature', d=2, r=0)), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in iqfs)]) # Cubics (sample) cubics = ['3.1.23.1'] + ['3.3.{}.1'.format(d) for d in [49,81,148,169,229,257,316]] info['fields'].append(['By <a href="{}">cubic field</a>'.format(url_for('.statistics_by_degree', d=3)), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in cubics)]) # Quartics (sample) quartics = ['4.4.{}.1'.format(d) for d in [725,1125,1600,1957,2000,2048,2225,2304]] info['fields'].append(['By <a href="{}">totally real quartic field</a>'.format(url_for('.statistics_by_degree', d=4)), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in quartics)]) # Quintics (sample) quintics = ['5.5.{}.1'.format(d) for d in [14641, 24217, 36497, 38569, 65657, 70601, 81509]] info['fields'].append(['By <a href="{}">totally real quintic field</a>'.format(url_for('.statistics_by_degree', d=5)), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in quintics)]) # Sextics (sample) sextics = ['6.6.{}.1'.format(d) for d in [300125, 371293, 434581, 453789, 485125, 592661, 703493]] info['fields'].append(['By <a href="{}">totally real sextic field</a>'.format(url_for('.statistics_by_degree', d=6)), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in sextics)]) return render_template("ecnf-index.html", title="Elliptic curves over number fields", info=info, bread=bread, learnmore=learnmore_list())
def extend_from_db(self): setattr(self._value, "lmfdb_label", self._db_value) if not self._db_value is None and self._db_value != '': try: url = url_for("number_fields.by_label", label=self._db_value) except RuntimeError: emf_logger.critical("could not set url for the label") url = '' setattr(self._value, "lmfdb_url", url) setattr(self._value, "lmfdb_pretty", field_pretty(self._db_value)) else: setattr(self._value, "lmfdb_pretty", web_latex_split_on_pm(self._value.absolute_polynomial()))
def spl_fod_statement(is_simple_geom, spl_fod_label, spl_fod_poly): if is_simple_geom: return """Simple over \(\overline{\Q}\)""" elif spl_fod_label == '1.1.1.1': return """Splits over \(\Q\)""" elif spl_fod_label != '': spl_fod_pretty = field_pretty(spl_fod_label) spl_fod_url = url_for("number_fields.by_label", label=spl_fod_label) return """Splits over the number field \(\Q (b) \cong \) <a href=%s>%s</a> with defining polynomial:<br> \(%s\)"""\ % (spl_fod_url, spl_fod_pretty, spl_fod_poly) else: return """Splits over the number field \(\Q (b)\) with defining polynomialL<br>  %s"""\ % spl_fod_poly
def make_torsion_growth(self): if self.tor_gro is None: self.torsion_growth_data_exists = False return tor_gro = self.tor_gro self.torsion_growth_data_exists = True self.tg = tg = {} tg['data'] = tgextra = [] # find all base-changes of this curve in the database, if any bcs = list(db.ec_nfcurves.search({'base_change': {'$contains': [self.lmfdb_label]}}, projection='label')) bcfs = [lab.split("-")[0] for lab in bcs] for F, T in tor_gro.items(): tg1 = {} tg1['bc'] = "Not in database" if ":" in F: F = F.replace(":",".") field_data = nf_display_knowl(F, field_pretty(F)) deg = int(F.split(".")[0]) bcc = [x for x,y in zip(bcs, bcfs) if y==F] if bcc: from lmfdb.ecnf.main import split_full_label F, NN, I, C = split_full_label(bcc[0]) tg1['bc'] = bcc[0] tg1['bc_url'] = url_for('ecnf.show_ecnf', nf=F, conductor_label=NN, class_label=I, number=C) else: field_data = web_latex_split_on_pm(coeff_to_poly(string2list(F))) deg = F.count(",") tg1['d'] = deg tg1['f'] = field_data tg1['t'] = '\(' + ' \\times '.join(['\Z/{}\Z'.format(n) for n in T.split(",")]) + '\)' tg1['m'] = 0 tgextra.append(tg1) tgextra.sort(key = lambda x: x['d']) tg['n'] = len(tgextra) lastd = 1 for tg1 in tgextra: d = tg1['d'] if d!=lastd: tg1['m'] = len([x for x in tgextra if x['d']==d]) lastd = d ## Hard-code this for now. While something like ## max(db.ec_curves.search({},projection='tor_degs')) might ## work, since 'tor_degs' is in the extra table it is very ## slow. Note that the *only* place where this number is used ## is in the ec-curve template where it says "The number ## fields ... of degree up to {{data.tg.maxd}} such that...". tg['maxd'] = 7
def stats_for_field(self, F): forms = self.forms fields = self.fields # pipeline = [{"$match": {'field_label':F}}, # {"$project" : { 'level_norm' : 1 }}, # {"$group":{"_id":"level_norm", "nforms": {"$sum": 2}, "maxnorm" : {"$max": '$level_norm'}}}] # res = forms.aggregate(pipeline).next() res = [f['level_norm'] for f in forms.find({'field_label':F}, ['level_norm'])] stats = {} stats['nforms'] = len(res) # res['nforms'] stats['maxnorm'] = max(res+[0]) # res['maxnorm'] stats['field_knowl'] = nf_display_knowl(F, lmfdb.base.getDBConnection(), field_pretty(F)) stats['forms'] = url_for('hmf.hilbert_modular_form_render_webpage', field_label=F) return stats
def field_summary(self, field): stats = self.field_normstats[field] ncurves = stats['ncurves'] nclasses = stats['nclasses'] max_norm = stats['max_norm'] ec_knowl = self.ec_knowl if ncurves == 1 else self.ec_knowls iso_knowl = self.iso_knowl if ncurves == 1 else self.iso_knowls nf_knowl = self.nf_knowl if ncurves == 1 else self.nf_knowls cond_knowl = self.cond_knowl if ncurves == 1 else self.cond_knowls s = '' if max_norm == 1 else 'up to ' norm_phrase = ' of norm {}{}.'.format(s, max_norm) return ''.join([ r'The database currently contains {} '.format(ncurves), ec_knowl, r' defined over the ', nf_knowl, r' {}, in {} '.format(field_pretty(field), nclasses), iso_knowl, r', with ', cond_knowl, norm_phrase ])
def ecnf_field_summary(field): stats = get_field_stats(field) s = '' if stats['ncurves'] == 1 else 's' ec_knowl = '<a knowl="ec">elliptic curve%s</a>' % s s = '' if stats['nclasses'] == 1 else 'es' iso_knowl = '<a knowl="ec.isogeny_class">isogeny class%s</a>' % s nf_knowl = '<a knowl="nf">number field</a>' s = '' if stats['maxnorm'] == 1 else 's' cond_knowl = '<a knowl="ec.conductor">conductor%s</a>' % s s = '' if stats['maxnorm'] == 1 else 'up to ' return ''.join([ r'The database currently contains %s ' % stats['ncurves'], ec_knowl, r' defined over the ', nf_knowl, r' %s, in %s ' % (field_pretty(field), stats['nclasses']), iso_knowl, r', with ', cond_knowl, r' of norm %s %s.' % (s, stats['maxnorm']) ])
def make_torsion_growth(self): try: tor_gro = self.tor_gro self.torsion_growth_data_exists = True except AttributeError: self.torsion_growth_data_exists = False return self.tg = tg = {} tg['data'] = tgextra = [] # find all base-changes of this curve in the database, if any from lmfdb.ecnf.WebEllipticCurve import db_ecnf bcs = [res['label'] for res in db_ecnf().find({'base_change': self.lmfdb_label}, projection={'label': True, '_id': False})] bcfs = [lab.split("-")[0] for lab in bcs] for F, T in tor_gro.items(): tg1 = {} tg1['bc'] = "Not in database" if ":" in F: F = F.replace(":",".") field_data = nf_display_knowl(F, getDBConnection(), field_pretty(F)) deg = int(F.split(".")[0]) bcc = [x for x,y in zip(bcs, bcfs) if y==F] if bcc: from lmfdb.ecnf.main import split_full_label F, NN, I, C = split_full_label(bcc[0]) tg1['bc'] = bcc[0] tg1['bc_url'] = url_for('ecnf.show_ecnf', nf=F, conductor_label=NN, class_label=I, number=C) else: field_data = web_latex_split_on_pm(coeff_to_poly(string2list(F))) deg = F.count(",") tg1['d'] = deg tg1['f'] = field_data tg1['t'] = '\(' + ' \\times '.join(['\Z/{}\Z'.format(n) for n in T.split(",")]) + '\)' tg1['m'] = 0 tgextra.append(tg1) tgextra.sort(key = lambda x: x['d']) tg['n'] = len(tgextra) lastd = 1 for tg1 in tgextra: d = tg1['d'] if d!=lastd: tg1['m'] = len([x for x in tgextra if x['d']==d]) lastd = d tg['maxd'] = max(db_ecstats().find_one({'_id': 'torsion_growth'})['degrees'])
def make_torsion_growth(self): if self.tor_gro is None: self.torsion_growth_data_exists = False return tor_gro = self.tor_gro self.torsion_growth_data_exists = True self.tg = tg = {} tg['data'] = tgextra = [] # find all base-changes of this curve in the database, if any bcs = list(db.ec_nfcurves.search({'base_change': {'$contains': [self.lmfdb_label]}}, projection='label')) bcfs = [lab.split("-")[0] for lab in bcs] for F, T in tor_gro.items(): tg1 = {} tg1['bc'] = "Not in database" if ":" in F: F = F.replace(":",".") field_data = nf_display_knowl(F, field_pretty(F)) deg = int(F.split(".")[0]) bcc = [x for x,y in zip(bcs, bcfs) if y==F] if bcc: from lmfdb.ecnf.main import split_full_label F, NN, I, C = split_full_label(bcc[0]) tg1['bc'] = bcc[0] tg1['bc_url'] = url_for('ecnf.show_ecnf', nf=F, conductor_label=NN, class_label=I, number=C) else: field_data = web_latex_split_on_pm(coeff_to_poly(string2list(F))) deg = F.count(",") tg1['d'] = deg tg1['f'] = field_data tg1['t'] = '\(' + ' \\times '.join(['\Z/{}\Z'.format(n) for n in T.split(",")]) + '\)' tg1['m'] = 0 tgextra.append(tg1) tgextra.sort(key = lambda x: x['d']) tg['n'] = len(tgextra) lastd = 1 for tg1 in tgextra: d = tg1['d'] if d!=lastd: tg1['m'] = len([x for x in tgextra if x['d']==d]) lastd = d ## Hard code for now #tg['maxd'] = max(db.ec_curves.stats.get_oldstat('torsion_growth')['degrees']) tg['maxd'] = 7
def ecnf_field_summary(field): stats = get_field_stats(field) s = '' if stats['ncurves']==1 else 's' ec_knowl = '<a knowl="ec">elliptic curve%s</a>' % s s = '' if stats['nclasses']==1 else 'es' iso_knowl = '<a knowl="ec.isogeny_class">isogeny class%s</a>' % s nf_knowl = '<a knowl="nf">number field</a>' s = '' if stats['maxnorm']==1 else 's' cond_knowl = '<a knowl="ec.conductor">conductor%s</a>' % s s = '' if stats['maxnorm']==1 else 'up to ' return ''.join([r'The database currently contains %s ' % stats['ncurves'], ec_knowl, r' defined over the ', nf_knowl, r' %s, in %s ' % (field_pretty(field), stats['nclasses']), iso_knowl, r', with ', cond_knowl, r' of norm %s %s.' % (s,stats['maxnorm'])])
def end_lattice_statement(lattice): statement = '' for ED in lattice: if ED[0][0]: # Add link and prettify if available: statement += """Over subfield \(F \simeq \) <a href=%s>%s</a> with generator \(%s\) with minimal polynomial \(%s\)"""\ % (url_for("number_fields.by_label", label=ED[0][0]), field_pretty(ED[0][0]), strlist_to_nfelt(ED[0][2], 'a'), intlist_to_poly(ED[0][1])) else: statement += """Over subfield \(F\) with generator \(%s\) with minimal polynomial \(%s\)"""\ % (strlist_to_nfelt(ED[0][2], 'a'), intlist_to_poly(ED[0][1])) statement += """:<br>""" statement += end_statement(ED[1], ED[2], field=r'F', ring=ED[3]) statement += """Sato Tate group: %s""" % st_link_by_name(1,4,ED[4]) statement += """<br>""" statement += gl2_simple_statement(ED[1], ED[2]) statement += """<p></p>""" return statement
def ecnf_field_summary(field): data = db.ec_nfcurves.stats.get_oldstat('conductor_norm_by_field')[field] ncurves = data['ncurves'] s = '' if ncurves == 1 else 's' ec_knowl = '<a knowl="ec">elliptic curve{}</a>'.format(s) nclasses = data['nclasses'] s = '' if nclasses == 1 else 'es' iso_knowl = '<a knowl="ec.isogeny_class">isogeny class{}</a>'.format(s) nf_knowl = '<a knowl="nf">number field</a>' max_norm = data['max_norm'] s = '' if max_norm == 1 else 's' cond_knowl = '<a knowl="ec.conductor">conductor{}</a>'.format(s) s = '' if max_norm == 1 else 'up to ' return ''.join([ r'The database currently contains {} '.format(ncurves), ec_knowl, r' defined over the ', nf_knowl, r' {}, in {} '.format(field_pretty(field), nclasses), iso_knowl, r', with ', cond_knowl, r' of norm {} {}.'.format(s, data['max_norm']) ])
def end_lattice_statement(lattice): statement = '' for ED in lattice: if ED[0][0]: # Add link and prettify if available: statement += """Over subfield \(F \simeq \) <a href=%s>%s</a> with generator \(%s\) with minimal polynomial \(%s\)"""\ % (url_for("number_fields.by_label", label=ED[0][0]), field_pretty(ED[0][0]), strlist_to_nfelt(ED[0][2], 'a'), intlist_to_poly(ED[0][1])) else: statement += """Over subfield \(F\) with generator \(%s\) with minimal polynomial \(%s\)"""\ % (strlist_to_nfelt(ED[0][2], 'a'), intlist_to_poly(ED[0][1])) statement += """:<br>""" statement += end_statement(ED[1], ED[2], field=r'F', ring=ED[3]) statement += """Sato Tate group: %s""" % st_link_by_name(1, 4, ED[4]) statement += """<br>""" statement += gl2_simple_statement(ED[1], ED[2]) statement += """<p></p>""" return statement
def field_summary(self, field): stats = self.field_normstats[field] ncurves = stats['ncurves'] nclasses = stats['nclasses'] max_norm = stats['max_norm'] ec_knowl = self.ec_knowl if ncurves==1 else self.ec_knowls iso_knowl = self.iso_knowl if ncurves==1 else self.iso_knowls nf_knowl = self.nf_knowl if ncurves==1 else self.nf_knowls cond_knowl = self.cond_knowl if ncurves==1 else self.cond_knowls s = '' if max_norm==1 else 'up to ' norm_phrase = ' of norm {}{}.'.format(s, max_norm) return ''.join([r'The database currently contains {} '.format(ncurves), ec_knowl, r' defined over the ', nf_knowl, r' {}, in {} '.format(field_pretty(field), nclasses), iso_knowl, r', with ', cond_knowl, norm_phrase])
def ecnf_field_summary(field): data = db_ecnfstats().find_one({'_id':'conductor_norm_by_field'})[field] ncurves = data['ncurves'] s = '' if ncurves==1 else 's' ec_knowl = '<a knowl="ec">elliptic curve{}</a>'.format(s) nclasses = data['nclasses'] s = '' if nclasses==1 else 'es' iso_knowl = '<a knowl="ec.isogeny_class">isogeny class{}</a>'.format(s) nf_knowl = '<a knowl="nf">number field</a>' max_norm = data['max_norm'] s = '' if max_norm==1 else 's' cond_knowl = '<a knowl="ec.conductor">conductor{}</a>'.format(s) s = '' if max_norm==1 else 'up to ' return ''.join([r'The database currently contains {} '.format(ncurves), ec_knowl, r' defined over the ', nf_knowl, r' {}, in {} '.format(field_pretty(field), nclasses), iso_knowl, r', with ', cond_knowl, r' of norm {} {}.'.format(s,data['max_norm'])])
def show_ecnf1(nf): if request.args: return elliptic_curve_search(data=request.args) start = 0 count = 20 query = {'field_label' : nf} cursor = db_ecnf().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC), ('conductor_label', ASC), ('iso_label', ASC), ('number', ASC)]).skip(start).limit(count) bread = [('Elliptic Curves', url_for(".index")), (nf, url_for('.show_ecnf1', nf=nf))] res = list(res) for e in res: e['field_knowl'] = nf_display_knowl(e['field_label'], getDBConnection(), e['field_label']) info = {} info['field'] = nf info['query'] = query info['curves'] = res # [ECNF(e) for e in res] info['number'] = nres info['start'] = start info['count'] = count info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs if nres == 1: info['report'] = 'unique match' 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 = 'Elliptic Curves over %s' % field_pretty(nf) return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
@search_wrap(template="hilbert_modular_form_search.html", table=db.hmf_forms, title='Hilbert modular form search results', err_title='Hilbert modular form search error', per_page=50, shortcuts={'jump': hilbert_modular_form_jump}, projection=[ 'field_label', 'short_label', 'label', 'level_ideal', 'dimension' ], cleaners={ "level_ideal": lambda v: teXify_pol(v['level_ideal']), "field_knowl": lambda e: nf_display_knowl(e['field_label'], field_pretty(e['field_label'])) }, bread=lambda: get_bread("Search results"), learnmore=learnmore_list, url_for_label=url_for_label, credit=lambda: hmf_credit, properties=lambda: []) def hilbert_modular_form_search(info, query): parse_nf_string(info, query, 'field_label', name="Field") parse_ints(info, query, 'deg', name='Field degree') parse_ints(info, query, 'disc', name="Field discriminant") parse_ints(info, query, 'dimension') parse_ints(info, query, 'level_norm', name="Level norm") parse_hmf_weight(info, query, 'weight',
except ValueError: return redirect(url_for(".hilbert_modular_form_render_webpage")) hmf_columns = SearchColumns([ MultiProcessedCol( "label", "mf.hilbert.label", "Label", ["field_label", "label", "short_label"], lambda fld, label, short: '<a href="%s">%s</a>' % (url_for( 'hmf.render_hmf_webpage', field_label=fld, label=label), short), default=True), ProcessedCol("field_label", "nf", "Base field", lambda fld: nf_display_knowl(fld, field_pretty(fld)), default=True), MathCol("deg", "nf.degree", "Field degree"), MathCol("disc", "nf.discriminant", "Field discriminant"), ProcessedCol("level_ideal", "mf.hilbert.level_norm", "Level", teXify_pol, mathmode=True, default=True), MathCol("level_norm", "mf.level_norm", "Level norm"), MathCol("weight", "mf.hilbert.weight_vector", "Weight"), MathCol("dimension", "mf.hilbert.dimension", "Dimension", default=True), ProcessedCol("is_CM", "mf.cm", "CM",
def elliptic_curve_search(**args): info = to_dict(args['data']) if 'download' in info and info['download'] != 0: return download_search(info) if not 'query' in info: info['query'] = {} bread = [('Elliptic Curves', url_for(".index")), ('Search Results', '.')] if 'jump' in info: label = info.get('label', '').replace(" ", "") # This label should be a full isogeny class label or a full # curve label (including the field_label component) try: nf, cond_label, iso_label, number = split_full_label(label.strip()) except ValueError: info['err'] = '' return search_input_error(info, bread) return show_ecnf(nf, cond_label, iso_label, number) query = {} try: parse_ints(info,query,'conductor_norm') parse_noop(info,query,'conductor_label') parse_nf_string(info,query,'field',name="base number field",qfield='field_label') parse_nf_elt(info,query,'jinv',name='j-invariant') parse_ints(info,query,'torsion',name='Torsion order',qfield='torsion_order') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: query['torsion_order'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) except ValueError: return search_input_error(info, bread) if 'include_isogenous' in info and info['include_isogenous'] == 'off': info['number'] = 1 query['number'] = 1 if 'include_base_change' in info and info['include_base_change'] == 'off': query['base_change'] = [] else: info['include_base_change'] = "on" if 'include_Q_curves' in info: if info['include_Q_curves'] == 'exclude': query['q_curve'] = False elif info['include_Q_curves'] == 'only': query['q_curve'] = True if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} info['query'] = query count = parse_count(info, 50) start = parse_start(info) # make the query and trim results according to start/count: cursor = db_ecnf().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC), ('conductor_label', ASC), ('iso_nlabel', ASC), ('number', ASC)]).skip(start).limit(count) res = list(res) for e in res: e['numb'] = str(e['number']) e['field_knowl'] = nf_display_knowl(e['field_label'], getDBConnection(), field_pretty(e['field_label'])) info['curves'] = res # [ECNF(e) for e in res] info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs if nres == 1: info['report'] = 'unique match' 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 = 'Elliptic Curve search results' return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
def elliptic_curve_search(info): if info.get('download') == '1' and info.get('Submit') and info.get( 'query'): return download_search(info) if not 'query' in info: info['query'] = {} bread = info.get('bread', [('Elliptic Curves', url_for(".index")), ('Search Results', '.')]) if 'jump' in info: label = info.get('label', '').replace(" ", "") # This label should be a full isogeny class label or a full # curve label (including the field_label component) try: nf, cond_label, iso_label, number = split_full_label(label.strip()) except ValueError: info['err'] = '' return search_input_error(info, bread) return redirect( url_for(".show_ecnf", nf=nf, conductor_label=cond_label, class_label=iso_label, number=number), 301) query = {} if 'jinv' in info: if info.get('field', '').strip() == '2.2.5.1': info['jinv'] = info['jinv'].replace('phi', 'a') if info.get('field', '').strip() == '2.0.4.1': info['jinv'] = info['jinv'].replace('i', 'a') try: parse_ints(info, query, 'conductor_norm') parse_noop(info, query, 'conductor_label') parse_nf_string(info, query, 'field', name="base number field", qfield='field_label') parse_nf_elt(info, query, 'jinv', name='j-invariant') parse_ints(info, query, 'torsion', name='Torsion order', qfield='torsion_order') parse_bracketed_posints(info, query, 'torsion_structure', maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: query['torsion_order'] = reduce( mul, [int(n) for n in query['torsion_structure']], 1) parse_ints(info, query, field='isodeg', qfield='isogeny_degrees') except (TypeError, ValueError): return search_input_error(info, bread) if query.get('jinv'): query['jinv'] = ','.join(query['jinv']) if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) if 'include_isogenous' in info and info['include_isogenous'] == 'off': info['number'] = 1 query['number'] = 1 if 'include_base_change' in info and info['include_base_change'] == 'off': query['base_change'] = [] else: info['include_base_change'] = "on" if 'include_Q_curves' in info: if info['include_Q_curves'] == 'exclude': query['q_curve'] = False elif info['include_Q_curves'] == 'only': query['q_curve'] = True if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne': 0} info['query'] = query count = parse_count(info, 50) start = parse_start(info) # make the query and trim results according to start/count: cursor = db_ecnf().find(query) nres = cursor.count() if (start >= nres): start -= (1 + (start - nres) / count) * count if (start < 0): start = 0 res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC), ('conductor_label', ASC), ('iso_nlabel', ASC), ('number', ASC)]).skip(start).limit(count) res = list(res) for e in res: e['numb'] = str(e['number']) e['field_knowl'] = nf_display_knowl(e['field_label'], getDBConnection(), field_pretty(e['field_label'])) info['curves'] = res # [ECNF(e) for e in res] info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs if nres == 1: info['report'] = 'unique match' 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 Curve search results') return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
raise ValueError("A CM discriminant must be a fundamental discriminant of an imaginary quadratic field.") cm_list += [-el for el in cm_list] return cm_list @search_parser def parse_cm_list(inp, query, qfield): query[qfield] = {'$in': make_cm_query(inp)} ecnf_columns = SearchColumns([ MultiProcessedCol("label", "ec.curve_label", "Label", ["short_label", "field_label", "conductor_label", "iso_label", "number"], lambda label, field, conductor, iso, number: '<a href="%s">%s</a>' % ( url_for('.show_ecnf', nf=field, conductor_label=conductor, class_label=iso, number=number), label), default=True, align="center"), ProcessedCol("field_label", "nf", "Base field", lambda field: nf_display_knowl(field, field_pretty(field)), default=True, align="center"), MultiProcessedCol("conductor", "ec.conductor_label", "Conductor", ["field_label", "conductor_label"], lambda field, conductor: '<a href="%s">%s</a>' %( url_for('.show_ecnf_conductor', nf=field, conductor_label=conductor), conductor), default=True, align="center"), MultiProcessedCol("iso_class", "ec.isogeny_class", "Isogeny class", ["field_label", "conductor_label", "iso_label", "short_class_label"], lambda field, conductor, iso, short_class_label: '<a href="%s">%s</a>' % ( url_for('.show_ecnf_isoclass', nf=field, conductor_label=conductor, class_label=iso), short_class_label), default=True, align="center"), MultiProcessedCol("ainvs", "ec.weierstrass_coeffs", "Weierstrass coefficients", ["field_label", "conductor_label", "iso_label", "number", "ainvs"], lambda field, conductor, iso, number, ainvs: '<a href="%s">%s</a>' % (
def index(): # if 'jump' in request.args: # return show_ecnf1(request.args['label']) if len(request.args) > 0: return elliptic_curve_search(to_dict(request.args)) bread = get_bread() # the dict data will hold additional information to be displayed on # the main browse and search page data = {} # data['fields'] holds data for a sample of number fields of different # signatures for a general browse: ecnfstats = db_ecnfstats() fields_by_deg = ecnfstats.find_one({'_id':'fields_by_degree'}) fields_by_sig = ecnfstats.find_one({'_id':'fields_by_signature'}) data['fields'] = [] # Rationals data['fields'].append(['the rational field', (('1.1.1.1', [url_for('ec.rational_elliptic_curves'), '$\Q$']),)]) # Real quadratics (sample) rqfs = ['2.2.{}.1'.format(d) for d in [5, 89, 229, 497]] niqfs = len(fields_by_sig['0,1']) nrqfs = len(fields_by_sig['2,0']) data['fields'].append(['{} real quadratic fields, including'.format(nrqfs), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in rqfs)]) # Imaginary quadratics (sample) iqfs = ['2.0.{}.1'.format(d) for d in [4, 8, 3, 7, 11]] data['fields'].append(['{} imaginary quadratic fields, including'.format(niqfs), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in iqfs)]) # Cubics (sample) cubics = ['3.1.23.1'] + ['3.3.{}.1'.format(d) for d in [49,148,1957]] ncubics = len(fields_by_deg['3']) data['fields'].append(['{} cubic fields, including'.format(ncubics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in cubics)]) # Quartics (sample) quartics = ['4.4.{}.1'.format(d) for d in [725,2777,9909,19821]] nquartics = len(fields_by_deg['4']) data['fields'].append(['{} totally real quartic fields, including'.format(nquartics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in quartics)]) # Quintics (sample) quintics = ['5.5.{}.1'.format(d) for d in [14641, 24217, 36497, 38569, 65657]] nquintics = len(fields_by_deg['5']) data['fields'].append(['{} totally real quintic fields, including'.format(nquintics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in quintics)]) # Sextics (sample) sextics = ['6.6.{}.1'.format(d) for d in [300125, 371293, 434581, 453789, 485125]] nsextics = len(fields_by_deg['6']) data['fields'].append(['{} totally real sextic fields, including'.format(nsextics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in sextics)]) data['degrees'] = sorted([int(d) for d in fields_by_deg.keys() if d!='_id']) # data['highlights'] holds data (URL and descriptive text) for a # sample of elliptic curves with interesting features: data['highlights'] = [] data['highlights'].append( ['A curve with $C_3\\times C_3$ torsion', url_for('.show_ecnf', nf='2.0.3.1', class_label='a', conductor_label='2268.36.18', number=int(1))] ) data['highlights'].append( ['A curve with $C_4\\times C_4$ torsion', url_for('.show_ecnf', nf='2.0.4.1', class_label='b', conductor_label='5525.870.5', number=int(9))] ) data['highlights'].append( ['A curve with CM by $\\sqrt{-267}$', url_for('.show_ecnf', nf='2.2.89.1', class_label='a', conductor_label='81.1', number=int(1))] ) data['highlights'].append( ['An isogeny class with isogenies of degree $3$ and $89$ (and $267$)', url_for('.show_ecnf_isoclass', nf='2.2.89.1', class_label='a', conductor_label='81.1')] ) data['highlights'].append( ['A curve with everywhere good reduction, but no global minimal model', url_for('.show_ecnf', nf='2.2.229.1', class_label='a', conductor_label='1.1', number=int(1))] ) return render_template("ecnf-index.html", title="Elliptic Curves over Number Fields", data=data, bread=bread, learnmore=learnmore_list_remove('Completeness'))
def end_statement(factorsQQ, factorsRR, field='', ring=None): # field is a latex string describing the basechange field (default is empty) # ring is optional, if unspecified only endomorphism algebra is described statement = '<table style="margin-left: 10px; margin-top: -12px">' factorsQQ_number = len(factorsQQ) factorsQQ_pretty = [field_pretty(fac[0]) for fac in factorsQQ if fac[0]] # endomorphism ring is an invariant of the curve but not the isogeny class, so we make it optional if ring: # First row: description of the endomorphism ring as an order in the endomorphism algebra statement += r"<tr><td>\(\End (J_{%s})\)</td><td>\(\simeq\)</td><td>" % field # First the case of a maximal order: if ring[0] == 1: # Single factor: if factorsQQ_number == 1: # Number field or not: if factorsQQ[0][2] == -1: # Prettify in quadratic case: if len(factorsQQ[0][1]) in [2, 3]: statement += r"\(%s\)" % ring_pretty( factorsQQ[0][1], 1) else: statement += r"the maximal order of \(\End (J_{%s}) \otimes \Q\)" % field else: # Use M_2 over integers if this applies: if factorsQQ[0][2] == 1 and factorsQQ[0][0] == '1.1.1.1': statement += r"\(\mathrm{M}_2 (\Z)\)" # TODO: Add flag that indicates whether we are over a PID, in # which case we can use the following lines: #if factorsQQ[0][2] == 1: # statement += (r"\(\mathrm{M}_2 (%s)\)" # % ring_pretty(factorsQQ[0][1], 1)) else: statement += r"a maximal order of \(\End (J_{%s}) \otimes \Q\)" % field # If there are two factors, then they are both at most quadratic # and we can prettify them else: statement += r'\(' + r' \times '.join( [ring_pretty(factorQQ[1], 1) for factorQQ in factorsQQ]) + r'\)' # Then the case where there is still a single factor: elif factorsQQ_number == 1: # Number field case: if factorsQQ[0][2] == -1: # Prettify in quadratic case: if len(factorsQQ[0][1]) in [2, 3]: statement += r"\(%s\)" % ring_pretty( factorsQQ[0][1], ring[0]) else: statement += r"an order of conductor of norm \(%s\) in \(\End (J_{%s}) \otimes \Q\)" % ( ring[0], field) # Otherwise mention whether the order is Eichler: elif ring[1] == 1: statement += r"an Eichler order of index \(%s\) in a maximal order of \(\End (J_{%s}) \otimes \Q\)" % ( ring[0], field) else: statement += r"a non-Eichler order of index \(%s\) in a maximal order of \(\End (J_{%s}) \otimes \Q\)" % ( ring[0], field) # Finally the case of two factors. We can prettify to some extent, since we # can describe the maximal order here else: statement += r"an order of index \(%s\) in \(%s\)" % ( ring[0], r' \times '.join( [ring_pretty(factorQQ[1], 1) for factorQQ in factorsQQ])) # End of first row: statement += "</td></tr>" # Second row: description of endomorphism algebra factors (this is the first row if ring=None) statement += r"<tr><td>\(\End (J_{%s}) \otimes \Q \)</td><td>\(\simeq\)</td><td>" % field # In the case of only one factor we either get a number field or a # quaternion algebra: if factorsQQ_number == 1: # First we deal with the number field case, # in which we have set the discriminant to be -1 if factorsQQ[0][2] == -1: # Prettify if labels available, otherwise return defining polynomial: if factorsQQ_pretty: statement += "<a href=%s>%s</a>" % (url_for( "number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0]) else: statement += r"the number field with defining polynomial \(%s\)" % intlist_to_poly( factorsQQ[0][1]) # Detect CM by presence of a quartic polynomial: if len(factorsQQ[0][1]) == 5: statement += " (CM)" # TODO: Get the following line to work #statement += " ({{ KNOWL('ag.complex_multiplication', title='CM') }})" # Up next is the case of a matrix ring (trivial disciminant), with # labels and full prettification always available: elif factorsQQ[0][2] == 1: statement += r"\(\mathrm{M}_2(\)<a href=%s>%s</a>\()\)" % (url_for( "number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0]) # And finally we deal with quaternion algebras over the rationals: else: statement += ( "the quaternion algebra over <a href=%s>%s</a> of discriminant %s" % (url_for("number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0], factorsQQ[0][2])) # If there are two factors, then we get two at most quadratic fields: else: statement += (r"<a href=%s>%s</a> \(\times\) <a href=%s>%s</a>" % (url_for("number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0], url_for("number_fields.by_label", label=factorsQQ[1][0]), factorsQQ_pretty[1])) # End of second row: statement += "</td></tr>" # Third row: description of algebra tensored with RR (this is the second row if ring=None) statement += r"<tr><td>\(\End (J_{%s}) \otimes \R\)</td><td>\(\simeq\)</td> <td>\(%s\)</td></tr>" % ( field, factorsRR_raw_to_pretty(factorsRR)) # End of statement: statement += "</table>" return statement
def make_object(self, curve, endo, tama, ratpts, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = curve['Lhash'] data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex(factor(int(data['cond']))) data['analytic_rank'] = ZZ(curve['analytic_rank']) data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1,4,data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ(curve['disc_key'][3:]) # use disc_key rather than abs_disc (will work when abs_disc > 2^63) data['disc'] = curve['disc_sign'] * curve['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = list_to_min_eqn(data['min_eqn']) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['igusa_clebsch'] = [ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv'])] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [web_latex(zfactor(i)) for i in data['igusa_clebsch']] data['igusa_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa'] ] data['aut_grp_id'] = curve['aut_grp_id'] data['geom_aut_grp_id'] = curve['geom_aut_grp_id'] data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['has_square_sha'] = "square" if curve['has_square_sha'] else "twice a square" P = curve['non_solvable_places'] if len(P): sz = "except over " sz += ", ".join([QpName(p) for p in P]) last = " and" if len(P) > 2: last = ", and" sz = last.join(sz.rsplit(",",1)) else: sz = "everywhere" data['non_solvable_places'] = sz data['torsion_order'] = curve['torsion_order'] data['torsion_factors'] = [ ZZ(a) for a in literal_eval(curve['torsion_subgroup']) ] if len(data['torsion_factors']) == 0: data['torsion_subgroup'] = '\mathrm{trivial}' else: data['torsion_subgroup'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in data['torsion_factors'] ]) data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] data['tama'] = '' for i in range(tama.count()): item = tama.next() if item['tamagawa_number'] > 0: tamgwnr = str(item['tamagawa_number']) else: tamgwnr = 'N/A' data['tama'] += tamgwnr + ' (p = ' + str(item['p']) + ')' if (i+1 < tama.count()): data['tama'] += ', ' if ratpts: if len(ratpts['rat_pts']): data['rat_pts'] = ', '.join(web_latex('(' +' : '.join(P) + ')') for P in ratpts['rat_pts']) data['rat_pts_v'] = 2 if ratpts['rat_pts_v'] else 1 # data['mw_rank'] = ratpts['mw_rank'] # data['mw_rank_v'] = ratpts['mw_rank_v'] else: data['rat_pts_v'] = 0 if curve['two_torsion_field'][0]: data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], getDBConnection(), field_pretty(curve['two_torsion_field'][0])) else: t = curve['two_torsion_field'] data['two_torsion_field_knowl'] = """splitting field of \(%s\) with Galois group %s"""%(intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1],getDBConnection())) else: # invariants specific to isogeny class curves_data = g2c_db_curves().find({"class" : curve['class']},{'_id':int(0),'label':int(1),'eqn':int(1),'disc_key':int(1)}).sort([("disc_key", ASCENDING), ("label", ASCENDING)]) if not curves_data: raise KeyError("No curves found in database for isogeny class %s of genus 2 curve %s." %(curve['class'],curve['label'])) data['curves'] = [ {"label" : c['label'], "equation_formatted" : list_to_min_eqn(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ] lfunc_data = g2c_db_lfunction_by_hash(curve['Lhash']) if not lfunc_data: raise KeyError("No Lfunction found in database for isogeny class of genus 2 curve %s." %curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [[nth_prime(n+1),lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n+1) < 30 and (data['cond'] % nth_prime(n+1))] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors']] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base(endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = """Endomorphism %s over \(\Q\):<br>""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement(data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base(data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = """Endomorphism %s over \(\overline{\Q}\):""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None) data['real_geom_end_alg_name'] = end_alg_name(curve['real_geom_end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement(data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement(data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len(endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'], data['rat_pts'].split(',') if 'rat_pts' in data else [])) plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot) properties += [ (None, plot_link), ('Conductor',str(data['cond'])), ('Discriminant', str(data['disc'])), ] properties += [ ('Sato-Tate group', data['st_group_link']), ('\(\\End(J_{\\overline{\\Q}}) \\otimes \\R\)', '\(%s\)' % data['real_geom_end_alg_name']), ('\(\\overline{\\Q}\)-simple', bool_pretty(data['is_simple_geom'])), ('\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [('L-function', data['lfunc_url'])] if is_curve: friends.append(('Isogeny class %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) for friend in g2c_db_lfunction_instances().find({'Lhash':data['Lhash']},{'_id':False,'url':True}): if 'url' in friend: add_friend (friends, lfunction_friend_from_url(friend['url'])) if 'urls' in friend: for url in friends['urls']: add_friend (friends, lfunction_friend_from_url(friend['url'])) if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: add_friend (friends, ("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: add_friend (friends, ("EC isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label))) if is_curve: friends.append(('Twists', url_for(".index_Q", g20 = str(data['g2'][0]), g21 = str(data['g2'][1]), g22 = str(data['g2'][2])))) # Breadcrumbs self.bread = bread = [ ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1])) ] if is_curve: bread += [ ('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3])) ] # Title self.title = "Genus 2 " + ("Curve " if is_curve else "Isogeny Class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage':'','magma':''} # use default show names code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))'%(data['min_eqn'][0],data['min_eqn'][1]), 'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(data['min_eqn'][0],data['min_eqn'][1])} if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]' else: magma_cond_option = '' code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option} code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'} code['igusa_clebsch'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma':'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];'} code['igusa'] = {'magma':'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];'} code['g2'] = {'magma':'G2Invariants(C);'} code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'} code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'} if ratpts: code['rat_pts'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in ratpts['rat_pts']]) + '];' } code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'} code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'} code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
def quad_field_knowl(disc): r = 2 if disc > 0 else 0 field_label = "2.%d.%d.1" % (r, abs(disc)) field_name = field_pretty(field_label) return nf_display_knowl(field_label, field_name)
return redirect(url_for("ecnf.index")) def url_for_label(label): if label == 'random': return url_for(".random") nf, cond_label, iso_label, number = split_full_label(label.strip()) return url_for(".show_ecnf", nf=nf, conductor_label=cond_label, class_label=iso_label, number=number) @search_wrap(template="ecnf-search-results.html", table=db.ec_nfcurves, title='Elliptic curve search results', err_title='Elliptic curve search input error', shortcuts={'jump':elliptic_curve_jump, 'download':download_search}, cleaners={'numb':lambda e: str(e['number']), 'field_knowl':lambda e: nf_display_knowl(e['field_label'], field_pretty(e['field_label']))}, url_for_label=url_for_label, learnmore=learnmore_list, bread=lambda:[('Elliptic curves', url_for(".index")), ('Search results', '.')]) def elliptic_curve_search(info, query): parse_nf_string(info,query,'field',name="base number field",qfield='field_label') if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) parse_ints(info,query,'conductor_norm') parse_noop(info,query,'conductor_label') parse_ints(info,query,'rank') parse_ints(info,query,'torsion',name='Torsion order',qfield='torsion_order') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: t_o = 1
def set_info_for_web_newform(level=None, weight=None, character=None, label=None, **kwds): r""" Set the info for on modular form. """ info = to_dict(kwds) info['level'] = level info['weight'] = weight info['character'] = character info['label'] = label if level is None or weight is None or character is None or label is None: s = "In set info for one form but do not have enough args!" s += "level={0},weight={1},character={2},label={3}".format( level, weight, character, label) emf_logger.critical(s) emf_logger.debug("In set_info_for_one_mf: info={0}".format(info)) prec = my_get(info, 'prec', default_prec, int) bprec = my_get(info, 'bprec', default_display_bprec, int) emf_logger.debug("PREC: {0}".format(prec)) emf_logger.debug("BITPREC: {0}".format(bprec)) try: WNF = WebNewForm_cached(level=level, weight=weight, character=character, label=label, prec=prec) emf_logger.debug("defined webnewform for rendering!") except IndexError as e: WNF = None info['error'] = e.message url1 = url_for("emf.render_elliptic_modular_forms") url2 = url_for("emf.render_elliptic_modular_forms", level=level) url3 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight) url4 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character) bread = [(EMF_TOP, url1)] bread.append(("Level %s" % level, url2)) bread.append(("Weight %s" % weight, url3)) if int(character) == 0: bread.append(("Trivial Character", url4)) else: bread.append(("Character \( %s \)" % (WNF.character.latex_name), url4)) bread.append( ("Newform %d.%d.%d.%s" % (level, weight, int(character), label), '')) info['bread'] = bread properties2 = list() friends = list() space_url = url_for('emf.render_elliptic_modular_forms', level=level, weight=weight, character=character) friends.append( ('\( S_{%s}(%s, %s)\)' % (WNF.weight, WNF.level, WNF.character.latex_name), space_url)) if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url: friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty, WNF.base_ring.lmfdb_url)) if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_label: friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_url)) friends = uniq(friends) friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)", WNF.character.url())) if WNF.dimension == 0: info['error'] = "This space is empty!" info['title'] = 'Newform ' + WNF.hecke_orbit_label info['learnmore'] = [('History of Modular forms', url_for('holomorphic_mf_history'))] if 'error' in info: return info ## Until we have figured out how to do the embeddings correctly we don't display the Satake ## parameters for non-trivial characters.... ## Example to illustrate the different cases ## base = CyclotomicField(n) -- of degree phi(n) ## coefficient_field = NumberField( p(x)) for some p in base['x'] of degree m ## we would then have cdeg = m*phi(n) and bdeg = phi(n) ## and rdeg = m ## Unfortunately, for e.g. base = coefficient_field = CyclotomicField(6) ## we get coefficient_field.relative_degree() == 2 although it should be 1 cdeg = WNF.coefficient_field.absolute_degree() bdeg = WNF.base_ring.absolute_degree() if cdeg == 1: rdeg = 1 else: ## just setting rdeg = WNF.coefficient_field.relative_degree() does not give correct result... ## rdeg = QQ(cdeg) / QQ(bdeg) cf_is_QQ = (cdeg == 1) br_is_QQ = (bdeg == 1) if cf_is_QQ: info['satake'] = WNF.satake if WNF.complexity_of_first_nonvanishing_coefficients( ) > default_max_height: info['qexp'] = "" info['qexp_display'] = '' info['hide_qexp'] = True n, c = WNF.first_nonvanishing_coefficient() info['trace_nv'] = latex(c.trace()) info['norm_nv'] = '\\approx ' + latex(c.norm().n()) info['index_nv'] = n else: info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ') info['qexp_display'] = url_for(".get_qexp_latex", level=level, weight=weight, character=character, label=label) info["hide_qexp"] = False info['max_cn_qexp'] = WNF.q_expansion.prec() ## All combinations should be tested... ## 13/4/4/a -> base ring = coefficient_field = QQ(zeta_6) ## 13/3/8/a -> base_ring = QQ(zeta_4), coefficient_field has poly x^2+(2\zeta_4+2x-3\zeta_$ over base_ring ## 13/4/3/a -> base_ring = coefficient_field = QQ(zeta_3) ## 13/4/1/a -> all rational ## 13/6/1/a/ -> base_ring = QQ, coefficient_field = Q(sqrt(17)) ## These are variables which needs to be set properly below info['polvars'] = {'base_ring': 'x', 'coefficient_field': '\\alpha'} if not cf_is_QQ: if rdeg > 1: # not WNF.coefficient_field == WNF.base_ring: ## Here WNF.base_ring should be some cyclotomic field and we have an extension over this. p1 = WNF.coefficient_field.relative_polynomial() c_pol_ltx = web_latex_poly(p1, '\\alpha') # make the variable \alpha c_pol_ltx_x = web_latex_poly(p1, 'x') zeta = p1.base_ring().gens()[0] # p2 = zeta.minpoly() #this is not used anymore # b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore z1 = zeta.multiplicative_order() info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'), c_pol_ltx_x, z1 ] if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url: info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label ] if z1 == 4: info[ 'polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format( c_pol_ltx) info['polvars']['base_ring'] = 'i' elif z1 <= 2: info[ 'polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format( c_pol_ltx) else: info[ 'polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\) ' % ( c_pol_ltx, z1, z1) info['polvars']['base_ring'] = '\zeta_{{ {0} }}'.format(z1) if z1 == 3: info[ 'polynomial_st'] += 'is a primitive cube root of unity.' else: info[ 'polynomial_st'] += 'is a primitive {0}-th root of unity.'.format( z1) elif not br_is_QQ: ## Now we have base and coefficient field being equal, meaning that since the coefficient field is not QQ it is some cyclotomic field ## generated by some \zeta_n p1 = WNF.coefficient_field.absolute_polynomial() z1 = WNF.coefficient_field.gens()[0].multiplicative_order() c_pol_ltx = web_latex_poly(p1, '\\zeta_{{{0}}}'.format(z1)) c_pol_ltx_x = web_latex_poly(p1, 'x') info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'), c_pol_ltx_x ] if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url: info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label ] if z1 == 4: info[ 'polynomial_st'] = '<div class="where">where \(\zeta_4=e^{{\\frac{{\\pi i}}{{ 2 }} }}=i \).</div>'.format( c_pol_ltx) info['polvars']['coefficient_field'] = 'i' elif z1 <= 2: info['polynomial_st'] = '' else: info[ 'polynomial_st'] = '<div class="where">where \(\zeta_{{{0}}}=e^{{\\frac{{2\\pi i}}{{ {0} }} }}\) '.format( z1) info['polvars']['coefficient_field'] = '\zeta_{{{0}}}'.format( z1) if z1 == 3: info[ 'polynomial_st'] += 'is a primitive cube root of unity.</div>' else: info[ 'polynomial_st'] += 'is a primitive {0}-th root of unity.</div>'.format( z1) else: info['polynomial_st'] = '' if info["hide_qexp"]: info['polynomial_st'] = '' info['degree'] = int(cdeg) if cdeg == 1: info['is_rational'] = 1 info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty ] else: info['is_rational'] = 0 emf_logger.debug("PREC2: {0}".format(prec)) info['embeddings'] = WNF._embeddings[ 'values'] #q_expansion_embeddings(prec, bprec,format='latex') info['embeddings_len'] = len(info['embeddings']) properties2 = [('Level', str(level)), ('Weight', str(weight)), ('Character', '$' + WNF.character.latex_name + '$'), ('Label', WNF.hecke_orbit_label), ('Dimension of Galois orbit', str(WNF.dimension))] if (ZZ(level)).is_squarefree(): info['twist_info'] = WNF.twist_info if isinstance(info['twist_info'], list) and len(info['twist_info']) > 0: info['is_minimal'] = info['twist_info'][0] if (info['twist_info'][0]): s = 'Is minimal<br>' else: s = 'Is a twist of lower level<br>' properties2 += [('Twist info', s)] else: info['twist_info'] = 'Twist info currently not available.' properties2 += [('Twist info', 'not available')] args = list() for x in range(5, 200, 10): args.append({'digits': x}) alev = None CM = WNF._cm_values if CM is not None: if CM.has_key('tau') and len(CM['tau']) != 0: info['CM_values'] = CM info['is_cm'] = WNF.is_cm if WNF.is_cm == 1: info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc) info['cm_disc'] = WNF.cm_disc info['cm_field_knowl'] = nf_display_knowl( info['cm_field'], getDBConnection(), field_pretty(info['cm_field'])) info['cm_field_url'] = url_for("number_fields.by_label", label=info["cm_field"]) if WNF.is_cm is None or WNF.is_cm == -1: s = '- Unknown (insufficient data)<br>' elif WNF.is_cm == 1: s = 'Yes<br>' else: s = 'No<br>' properties2.append(('CM', s)) alev = WNF.atkin_lehner_eigenvalues() info['atkinlehner'] = None if isinstance(alev, dict) and len(alev.keys()) > 0 and level != 1: s1 = " Atkin-Lehner eigenvalues " s2 = "" for Q in alev.keys(): s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q]) properties2.append((s1, s2)) emf_logger.debug("properties={0}".format(properties2)) # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps() # if isinstance(alev,dict) and len(alev.keys())>0: # emf_logger.debug("alev={0}".format(alev)) # info['atkinlehner'] = list() # for Q in alev.keys(): # s = "\(" + latex(c) + "\)" # Q = alev[c][0] # ev = alev[c][1] # info['atkinlehner'].append([Q, c, ev]) if (level == 1): poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6', '') if poly != '': d, monom, coeffs = poly emf_logger.critical("poly={0}".format(poly)) info['explicit_formulas'] = '\(' for i in range(len(coeffs)): c = QQ(coeffs[i]) s = "" if d > 1 and i > 0 and c > 0: s = "+" if c < 0: s = "-" if c.denominator() > 1: cc = "\\frac{{ {0} }}{{ {1} }}".format( abs(c.numerator()), c.denominator()) else: cc = str(abs(c)) s += "{0} \cdot ".format(cc) a = monom[i][0] b = monom[i][1] if a == 0 and b != 0: s += "E_6^{{ {0} }}".format(b) elif b == 0 and a != 0: s += "E_4^{{ {0} }}".format(a) else: s += "E_4^{{ {0} }}E_6^{{ {1} }}".format(a, b) info['explicit_formulas'] += s info['explicit_formulas'] += " \)" cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + \ '&label=' + str(label) if len(WNF.parent.hecke_orbits) > 1: for label_other in WNF.parent.hecke_orbits.keys(): if (label_other != label): s = 'Modular form ' if character: s += newform_label(level, weight, character, label_other) else: s += newform_label(level, weight, 1, label_other) url = url_for('emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label_other) friends.append((s, url)) s = 'L-Function ' if character: s += newform_label(level, weight, character, label) else: s += newform_label(level, weight, 1, label) # url = # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s" # %(level,weight,character,label,0) url = '/L' + url_for('emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label) if WNF.coefficient_field_degree > 1: for h in range(WNF.coefficient_field_degree): s0 = s + ".{0}".format(h) url0 = url + "{0}/".format(h) friends.append((s0, url0)) else: friends.append((s, url)) # if there is an elliptic curve over Q associated to self we also list that if WNF.weight == 2 and WNF.coefficient_field_degree == 1: llabel = str(level) + '.' + label s = 'Elliptic curve isogeny class ' + llabel url = '/EllipticCurve/Q/' + llabel friends.append((s, url)) info['properties2'] = properties2 info['friends'] = friends info['max_cn'] = WNF.max_available_prec() return info
def index(): # if 'jump' in request.args: # return show_ecnf1(request.args['label']) if len(request.args) > 0: return elliptic_curve_search(to_dict(request.args)) bread = get_bread() # the dict data will hold additional information to be displayed on # the main browse and search page data = {} # data['fields'] holds data for a sample of number fields of different # signatures for a general browse: ecnfstats = db_ecnfstats() fields_by_deg = ecnfstats.find_one({'_id': 'fields_by_degree'}) fields_by_sig = ecnfstats.find_one({'_id': 'fields_by_signature'}) data['fields'] = [] # Rationals data['fields'].append([ 'the rational field', (('1.1.1.1', [url_for('ec.rational_elliptic_curves'), '$\Q$']), ) ]) # Real quadratics (sample) rqfs = ['2.2.{}.1'.format(d) for d in [5, 89, 229, 497]] niqfs = len(fields_by_sig['0,1']) nrqfs = len(fields_by_sig['2,0']) data['fields'].append([ '{} real quadratic fields, including'.format(nrqfs), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in rqfs) ]) # Imaginary quadratics (sample) iqfs = ['2.0.{}.1'.format(d) for d in [4, 8, 3, 7, 11]] data['fields'].append([ '{} imaginary quadratic fields, including'.format(niqfs), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in iqfs) ]) # Cubics (sample) cubics = ['3.1.23.1'] + ['3.3.{}.1'.format(d) for d in [49, 148, 1957]] ncubics = len(fields_by_deg['3']) data['fields'].append([ '{} cubic fields, including'.format(ncubics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in cubics) ]) # Quartics (sample) quartics = ['4.4.{}.1'.format(d) for d in [725, 2777, 9909, 19821]] nquartics = len(fields_by_deg['4']) data['fields'].append([ '{} totally real quartic fields, including'.format(nquartics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in quartics) ]) # Quintics (sample) quintics = [ '5.5.{}.1'.format(d) for d in [14641, 24217, 36497, 38569, 65657] ] nquintics = len(fields_by_deg['5']) data['fields'].append([ '{} totally real quintic fields, including'.format(nquintics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in quintics) ]) # Sextics (sample) sextics = [ '6.6.{}.1'.format(d) for d in [300125, 371293, 434581, 453789, 485125] ] nsextics = len(fields_by_deg['6']) data['fields'].append([ '{} totally real sextic fields, including'.format(nsextics), ((nf, [url_for('.show_ecnf1', nf=nf), field_pretty(nf)]) for nf in sextics) ]) data['degrees'] = sorted( [int(d) for d in fields_by_deg.keys() if d != '_id']) # data['highlights'] holds data (URL and descriptive text) for a # sample of elliptic curves with interesting features: data['highlights'] = [] data['highlights'].append([ 'A curve with $C_3\\times C_3$ torsion', url_for('.show_ecnf', nf='2.0.3.1', class_label='a', conductor_label='2268.36.18', number=int(1)) ]) data['highlights'].append([ 'A curve with $C_4\\times C_4$ torsion', url_for('.show_ecnf', nf='2.0.4.1', class_label='b', conductor_label='5525.870.5', number=int(9)) ]) data['highlights'].append([ 'A curve with CM by $\\sqrt{-267}$', url_for('.show_ecnf', nf='2.2.89.1', class_label='a', conductor_label='81.1', number=int(1)) ]) data['highlights'].append([ 'An isogeny class with isogenies of degree $3$ and $89$ (and $267$)', url_for('.show_ecnf_isoclass', nf='2.2.89.1', class_label='a', conductor_label='81.1') ]) data['highlights'].append([ 'A curve with everywhere good reduction, but no global minimal model', url_for('.show_ecnf', nf='2.2.229.1', class_label='a', conductor_label='1.1', number=int(1)) ]) return render_template("ecnf-index.html", title="Elliptic Curves over Number Fields", data=data, bread=bread, learnmore=learnmore_list_remove('Completeness'))
def set_info_for_web_newform(level=None, weight=None, character=None, label=None, **kwds): r""" Set the info for on modular form. """ info = to_dict(kwds) info['level'] = level info['weight'] = weight info['character'] = character info['label'] = label if level is None or weight is None or character is None or label is None: s = "In set info for one form but do not have enough args!" s += "level={0},weight={1},character={2},label={3}".format(level, weight, character, label) emf_logger.critical(s) emf_logger.debug("In set_info_for_one_mf: info={0}".format(info)) prec = my_get(info, 'prec', default_prec, int) bprec = my_get(info, 'bprec', default_display_bprec, int) emf_logger.debug("PREC: {0}".format(prec)) emf_logger.debug("BITPREC: {0}".format(bprec)) try: WNF = WebNewForm_cached(level=level, weight=weight, character=character, label=label) emf_logger.critical("defined webnewform for rendering!") # if info.has_key('download') and info.has_key('tempfile'): # WNF._save_to_file(info['tempfile']) # info['filename']=str(weight)+'-'+str(level)+'-'+str(character)+'-'+label+'.sobj' # return info except IndexError as e: WNF = None info['error'] = e.message url1 = url_for("emf.render_elliptic_modular_forms") url2 = url_for("emf.render_elliptic_modular_forms", level=level) url3 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight) url4 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character) bread = [(EMF_TOP, url1)] bread.append(("of level %s" % level, url2)) bread.append(("weight %s" % weight, url3)) if int(character) == 0: bread.append(("trivial character", url4)) else: bread.append(("\( %s \)" % (WNF.character.latex_name), url4)) info['bread'] = bread properties2 = list() friends = list() space_url = url_for('emf.render_elliptic_modular_forms',level=level, weight=weight, character=character) friends.append(('\( S_{%s}(%s, %s)\)'%(WNF.weight, WNF.level, WNF.character.latex_name), space_url)) if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url: friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty, WNF.base_ring.lmfdb_url)) if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_label: friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_url)) friends = uniq(friends) friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)", WNF.character.url())) if WNF.dimension==0: info['error'] = "This space is empty!" # emf_logger.debug("WNF={0}".format(WNF)) #info['name'] = name info['title'] = 'Modular Form ' + WNF.hecke_orbit_label if 'error' in info: return info # info['name']=WNF._name ## Until we have figured out how to do the embeddings correctly we don't display the Satake ## parameters for non-trivial characters.... ## Example to illustrate the different cases ## base = CyclotomicField(n) -- of degree phi(n) ## coefficient_field = NumberField( p(x)) for some p in base['x'] of degree m ## we would then have cdeg = m*phi(n) and bdeg = phi(n) ## and rdeg = m ## Unfortunately, for e.g. base = coefficient_field = CyclotomicField(6) ## we get coefficient_field.relative_degree() == 2 although it should be 1 cdeg = WNF.coefficient_field.absolute_degree() bdeg = WNF.base_ring.absolute_degree() if cdeg == 1: rdeg = 1 else: ## just setting rdeg = WNF.coefficient_field.relative_degree() does not give correct result... ## rdeg = QQ(cdeg)/QQ(bdeg) cf_is_QQ = (cdeg == 1) br_is_QQ = (bdeg == 1) if cf_is_QQ: info['satake'] = WNF.satake info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ') info['qexp_display'] = url_for(".get_qexp_latex", level=level, weight=weight, character=character, label=label) info['max_cn_qexp'] = WNF.q_expansion.prec() ## All combinations should be tested... ## 13/4/4/a -> base ring = coefficient_field = QQ(zeta_6) ## 13/3/8/a -> base_ring = QQ(zeta_4), coefficient_field has poly x^2+(2\zeta_4+2x-3\zeta_$ over base_ring ## 13/4/3/a -> base_ring = coefficient_field = QQ(zeta_3) ## 13/4/1/a -> all rational ## 13/6/1/a/ -> base_ring = QQ, coefficient_field = Q(sqrt(17)) ## These are variables which needs to be set properly below info['polvars'] = {'base_ring':'x','coefficient_field':'\\alpha'} if not cf_is_QQ: if rdeg>1: # not WNF.coefficient_field == WNF.base_ring: ## Here WNF.base_ring should be some cyclotomic field and we have an extension over this. p1 = WNF.coefficient_field.relative_polynomial() c_pol_ltx = web_latex_poly(p1, '\\alpha') # make the variable \alpha c_pol_ltx_x = web_latex_poly(p1, 'x') zeta = p1.base_ring().gens()[0] # p2 = zeta.minpoly() #this is not used anymore # b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore z1 = zeta.multiplicative_order() info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'),c_pol_ltx_x, z1] if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url: info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label] if z1==4: info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format(c_pol_ltx) info['polvars']['base_ring']='i' elif z1<=2: info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(c_pol_ltx) else: info['polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\) '%(c_pol_ltx, z1,z1) info['polvars']['base_ring']='\zeta_{{ {0} }}'.format(z1) if z1==3: info['polynomial_st'] += 'is a primitive cube root of unity.' else: info['polynomial_st'] += 'is a primitive {0}-th root of unity.'.format(z1) elif not br_is_QQ: ## Now we have base and coefficient field being equal, meaning that since the coefficient field is not QQ it is some cyclotomic field ## generated by some \zeta_n p1 = WNF.coefficient_field.absolute_polynomial() z1 = WNF.coefficient_field.gens()[0].multiplicative_order() c_pol_ltx = web_latex_poly(p1, '\\zeta_{{{0}}}'.format(z1)) c_pol_ltx_x = web_latex_poly(p1, 'x') info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'), c_pol_ltx_x] if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url: info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label] if z1==4: info['polynomial_st'] = '<div class="where">where \(\zeta_4=e^{{\\frac{{\\pi i}}{{ 2 }} }}=i \).</div>'.format(c_pol_ltx) info['polvars']['coefficient_field']='i' elif z1<=2: info['polynomial_st'] = '' else: info['polynomial_st'] = '<div class="where">where \(\zeta_{{{0}}}=e^{{\\frac{{2\\pi i}}{{ {0} }} }}\) '.format(z1) info['polvars']['coefficient_field']='\zeta_{{{0}}}'.format(z1) if z1==3: info['polynomial_st'] += 'is a primitive cube root of unity.</div>' else: info['polynomial_st'] += 'is a primitive {0}-th root of unity.</div>'.format(z1) else: info['polynomial_st'] = '' info['degree'] = int(cdeg) if cdeg==1: info['is_rational'] = 1 info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty ] else: info['is_rational'] = 0 # info['q_exp_embeddings'] = WNF.print_q_expansion_embeddings() # if(int(info['degree'])>1 and WNF.dimension()>1): # s = 'One can embed it into \( \mathbb{C} \) as:' # bprec = 26 # print s # info['embeddings'] = ajax_more2(WNF.print_q_expansion_embeddings,{'prec':[5,10,25,50],'bprec':[26,53,106]},text=['more coeffs.','higher precision']) # elif(int(info['degree'])>1): # s = 'There are '+str(info['degree'])+' embeddings into \( \mathbb{C} \):' # bprec = 26 # print s # info['embeddings'] = ajax_more2(WNF.print_q_expansion_embeddings,{'prec':[5,10,25,50],'bprec':[26,53,106]},text=['more coeffs.','higher precision']) # else: # info['embeddings'] = '' emf_logger.debug("PREC2: {0}".format(prec)) info['embeddings'] = WNF._embeddings['values'] #q_expansion_embeddings(prec, bprec,format='latex') info['embeddings_len'] = len(info['embeddings']) properties2 = [] if (ZZ(level)).is_squarefree(): info['twist_info'] = WNF.twist_info if isinstance(info['twist_info'], list) and len(info['twist_info'])>0: info['is_minimal'] = info['twist_info'][0] if(info['twist_info'][0]): s = 'Is minimal<br>' else: s = 'Is a twist of lower level<br>' properties2 = [('Twist info', s)] else: info['twist_info'] = 'Twist info currently not available.' properties2 = [('Twist info', 'not available')] args = list() for x in range(5, 200, 10): args.append({'digits': x}) alev = None CM = WNF._cm_values if CM is not None: if CM.has_key('tau') and len(CM['tau']) != 0: info['CM_values'] = CM info['is_cm'] = WNF.is_cm if WNF.is_cm == 1: info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc) info['cm_disc'] = WNF.cm_disc info['cm_field_knowl'] = nf_display_knowl(info['cm_field'], getDBConnection(), field_pretty(info['cm_field'])) info['cm_field_url'] = url_for("number_fields.by_label", label=info["cm_field"]) if WNF.is_cm is None or WNF.is_cm==-1: s = '- Unknown (insufficient data)<br>' elif WNF.is_cm == 1: s = 'Is a CM-form<br>' else: s = 'Is not a CM-form<br>' properties2.append(('CM info', s)) alev = WNF.atkin_lehner_eigenvalues() info['atkinlehner'] = None if isinstance(alev,dict) and len(alev.keys())>0 and level != 1: s1 = " Atkin-Lehner eigenvalues " s2 = "" for Q in alev.keys(): s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q]) properties2.append((s1, s2)) emf_logger.debug("properties={0}".format(properties2)) # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps() # if isinstance(alev,dict) and len(alev.keys())>0: # emf_logger.debug("alev={0}".format(alev)) # info['atkinlehner'] = list() # for Q in alev.keys(): # s = "\(" + latex(c) + "\)" # Q = alev[c][0] # ev = alev[c][1] # info['atkinlehner'].append([Q, c, ev]) if(level == 1): poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6','') if poly != '': d,monom,coeffs = poly emf_logger.critical("poly={0}".format(poly)) info['explicit_formulas'] = '\(' for i in range(len(coeffs)): c = QQ(coeffs[i]) s = "" if d>1 and i >0 and c>0: s="+" if c<0: s="-" if c.denominator()>1: cc = "\\frac{{ {0} }}{{ {1} }}".format(abs(c.numerator()),c.denominator()) else: cc = str(abs(c)) s += "{0} \cdot ".format(cc) a = monom[i][0]; b = monom[i][1] if a == 0 and b != 0: s+="E_6^{{ {0} }}".format(b) elif b ==0 and a != 0: s+="E_4^{{ {0} }}".format(a) else: s+="E_4^{{ {0} }}E_6^{{ {1} }}".format(a,b) info['explicit_formulas'] += s info['explicit_formulas'] += " \)" cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + \ '&label=' + str(label) if len(WNF.parent.hecke_orbits) > 1: for label_other in WNF.parent.hecke_orbits.keys(): if(label_other != label): s = 'Modular form ' if character: s = s + str(level) + '.' + str(weight) + '.' + str(character) + str(label_other) else: s = s + str(level) + '.' + str(weight) + str(label_other) url = url_for('emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label_other) friends.append((s, url)) s = 'L-Function ' if character: s = s + str(level) + '.' + str(weight) + '.' + str(character) + str(label) else: s = s + str(level) + '.' + str(weight) + str(label) # url = # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s" # %(level,weight,character,label,0) url = '/L' + url_for( 'emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label) if WNF.coefficient_field_degree > 1: for h in range(WNF.coefficient_field_degree): s0 = s + ".{0}".format(h) url0 = url + "{0}/".format(h) friends.append((s0, url0)) else: friends.append((s, url)) # if there is an elliptic curve over Q associated to self we also list that if WNF.weight == 2 and WNF.coefficient_field_degree == 1: llabel = str(level) + '.' + label s = 'Elliptic curve isogeny class ' + llabel url = '/EllipticCurve/Q/' + llabel friends.append((s, url)) info['properties2'] = properties2 info['friends'] = friends info['max_cn'] = WNF.max_cn() return info
def render_sample_page(family, sam, args, bread): info = { 'args': to_dict(args), 'sam': sam, 'latex': latex, 'type':sam.type(), 'name':sam.name(), 'full_name': sam.full_name(), 'weight':sam.weight(), 'fdeg':sam.degree_of_field(), 'is_eigenform':sam.is_eigenform(), 'field_poly': sam.field_poly()} if sam.is_integral() != None: info['is_integral'] = sam.is_integral() if 'Sp4Z' in sam.collection(): info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=0) if 'Sp4Z_2' in sam.collection(): info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=2) info['space'] = '$'+family.latex_name.replace('k', '{' + str(sam.weight()) + '}')+'$' if 'space_url' in info: bread.append((info['space'], info['space_url'])) info['space_href'] = '<a href="%s">%s</d>'%(info['space_url'],info['space']) if 'space_url' in info else info['space'] if info['field_poly'].disc() < 10**10: label = poly_to_field_label(info['field_poly']) if label: info['field_label'] = label info['field_url'] = url_for('number_fields.by_label', label=label) info['field_href'] = '<a href="%s">%s</a>'%(info['field_url'], field_pretty(label)) bread.append((info['name'], '')) title='Siegel modular forms sample ' + info['full_name'] properties = [('Space', info['space_href']), ('Name', info['name']), ('Type', '<br>'.join(info['type'].split(','))), ('Weight', str(info['weight'])), ('Hecke eigenform', str(info['is_eigenform'])), ('Field degree', str(info['fdeg']))] try: evs_to_show = parse_ints_to_list_flash(args.get('ev_index'), 'list of $l$') fcs_to_show = parse_ints_to_list_flash(args.get('fc_det'), 'list of $\\det(F)$') except ValueError: evs_to_show = [] fcs_to_show = [] info['evs_to_show'] = sorted([n for n in (evs_to_show if len(evs_to_show) else sam.available_eigenvalues()[:10])]) info['fcs_to_show'] = sorted([n for n in (fcs_to_show if len(fcs_to_show) else sam.available_Fourier_coefficients()[1:6])]) info['evs_avail'] = [n for n in sam.available_eigenvalues()] info['fcs_avail'] = [n for n in sam.available_Fourier_coefficients()] # Do not attempt to constuct a modulus ideal unless the field has a reasonably small discriminant # otherwise sage may not even be able to factor the discriminant info['field'] = sam.field() if info['field_poly'].disc() < 10**80: null_ideal = sam.field().ring_of_integers().ideal(0) info['modulus'] = null_ideal modulus = args.get('modulus','').strip() m = 0 if modulus: try: O = sam.field().ring_of_integers() m = O.ideal([O(str(b)) for b in modulus.split(',')]) except Exception: info['error'] = True flash_error("Unable to construct modulus ideal from specified generators %s.", modulus) if m == 1: info['error'] = True flash_error("The ideal %s is the unit ideal, please specify a different modulus.", '('+modulus+')') m = 0 info['modulus'] = m # Hack to reduce polynomials and to handle non integral stuff def redc(c): return m.reduce(c*c.denominator())/m.reduce(c.denominator()) def redp(f): c = f.dict() return f.parent()(dict((e,redc(c[e])) for e in c)) def safe_reduce(f): if not m: return latex(f) try: if f in sam.field(): return latex(redc(f)) else: return latex(redp(f)) except ZeroDivisionError: return '\\textrm{Unable to reduce} \\bmod\\mathfrak{m}' info['reduce'] = safe_reduce else: info['reduce'] = latex # check that explicit formula is not ridiculously big if sam.explicit_formula(): info['explicit_formula_bytes'] = len(sam.explicit_formula()) if len(sam.explicit_formula()) < 100000: info['explicit_formula'] = sam.explicit_formula() return render_template("ModularForm_GSp4_Q_sample.html", title=title, bread=bread, properties2=properties, info=info)
def render_sample_page(family, sam, args, bread): info = { 'args': to_dict(args), 'sam': sam, 'latex': latex, 'type': sam.type(), 'name': sam.name(), 'full_name': sam.full_name(), 'weight': sam.weight(), 'fdeg': sam.degree_of_field(), 'is_eigenform': sam.is_eigenform(), 'field_poly': sam.field_poly() } if sam.is_integral() != None: info['is_integral'] = sam.is_integral() if 'Sp4Z' in sam.collection(): info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=0) if 'Sp4Z_2' in sam.collection(): info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=2) info['space'] = '$' + family.latex_name.replace( 'k', '{' + str(sam.weight()) + '}') + '$' if 'space_url' in info: bread.append((info['space'], info['space_url'])) info['space_href'] = '<a href="%s">%s</d>' % ( info['space_url'], info['space']) if 'space_url' in info else info['space'] if info['field_poly'].disc() < 10**10: label = poly_to_field_label(info['field_poly']) if label: info['field_label'] = label info['field_url'] = url_for('number_fields.by_label', label=label) info['field_href'] = '<a href="%s">%s</a>' % (info['field_url'], field_pretty(label)) bread.append((info['name'], '')) title = 'Siegel modular forms sample ' + info['full_name'] properties = [('Space', info['space_href']), ('Name', info['name']), ('Type', '<br>'.join(info['type'].split(','))), ('Weight', str(info['weight'])), ('Hecke eigenform', str(info['is_eigenform'])), ('Field degree', str(info['fdeg']))] try: evs_to_show = parse_ints_to_list_flash(args.get('ev_index'), 'list of $l$') fcs_to_show = parse_ints_to_list_flash(args.get('fc_det'), 'list of $\\det(F)$') except ValueError: evs_to_show = [] fcs_to_show = [] info['evs_to_show'] = sorted([ n for n in (evs_to_show if len(evs_to_show) else sam.available_eigenvalues()[:10]) ]) info['fcs_to_show'] = sorted([ n for n in (fcs_to_show if len(fcs_to_show) else sam. available_Fourier_coefficients()[1:6]) ]) info['evs_avail'] = [n for n in sam.available_eigenvalues()] info['fcs_avail'] = [n for n in sam.available_Fourier_coefficients()] # Do not attempt to constuct a modulus ideal unless the field has a reasonably small discriminant # otherwise sage may not even be able to factor the discriminant info['field'] = sam.field() if info['field_poly'].disc() < 10**80: null_ideal = sam.field().ring_of_integers().ideal(0) info['modulus'] = null_ideal modulus = args.get('modulus', '').strip() m = 0 if modulus: try: O = sam.field().ring_of_integers() m = O.ideal([O(str(b)) for b in modulus.split(',')]) except Exception: info['error'] = True flash_error( "Unable to construct modulus ideal from specified generators %s.", modulus) if m == 1: info['error'] = True flash_error( "The ideal %s is the unit ideal, please specify a different modulus.", '(' + modulus + ')') m = 0 info['modulus'] = m # Hack to reduce polynomials and to handle non integral stuff def redc(c): return m.reduce(c * c.denominator()) / m.reduce(c.denominator()) def redp(f): c = f.dict() return f.parent()(dict((e, redc(c[e])) for e in c)) def safe_reduce(f): if not m: return latex(f) try: if f in sam.field(): return latex(redc(f)) else: return latex(redp(f)) except ZeroDivisionError: return '\\textrm{Unable to reduce} \\bmod\\mathfrak{m}' info['reduce'] = safe_reduce else: info['reduce'] = latex # check that explicit formula is not ridiculously big if sam.explicit_formula(): info['explicit_formula_bytes'] = len(sam.explicit_formula()) if len(sam.explicit_formula()) < 100000: info['explicit_formula'] = sam.explicit_formula() return render_template("ModularForm_GSp4_Q_sample.html", title=title, bread=bread, properties2=properties, info=info)
try: nf, cond_label, iso_label, number = split_full_label(label.strip()) except ValueError: info['err'] = '' return redirect(url_for("ecnf.index")) return redirect(url_for(".show_ecnf", nf=nf, conductor_label=cond_label, class_label=iso_label, number=number), 301) @search_wrap(template="ecnf-search-results.html", table=db.ec_nfcurves, title='Elliptic Curve Search Results', err_title='Elliptic Curve Search Input Error', shortcuts={'jump':elliptic_curve_jump, 'download':download_search}, cleaners={'numb':lambda e: str(e['number']), 'field_knowl':lambda e: nf_display_knowl(e['field_label'], field_pretty(e['field_label']))}, bread=lambda:[('Elliptic Curves', url_for(".index")), ('Search Results', '.')], credit=lambda:ecnf_credit) def elliptic_curve_search(info, query): parse_nf_string(info,query,'field',name="base number field",qfield='field_label') if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) parse_ints(info,query,'conductor_norm') parse_noop(info,query,'conductor_label') parse_ints(info,query,'torsion',name='Torsion order',qfield='torsion_order') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: query['torsion_order'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) parse_ints(info,query,field='isodeg',qfield='isogeny_degrees')
def make_object(self, curve, endo, tama, ratpts, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = str(curve['Lhash']) data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex(factor(int( data['cond']))).replace(r"-1 \cdot", "-") data['analytic_rank'] = ZZ(curve['analytic_rank']) data['mw_rank'] = ZZ(0) if curve.get('mw_rank') is None else ZZ( curve['mw_rank']) # 0 will be marked as a lower bound data['mw_rank_proved'] = curve['mw_rank_proved'] data['analytic_rank_proved'] = curve['analytic_rank_proved'] data['hasse_weil_proved'] = curve['hasse_weil_proved'] data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1, 4, data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [(c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ(curve['abs_disc']) data['disc'] = curve['disc_sign'] * data['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = min_eqns_pretty(data['min_eqn']) data['disc_factor_latex'] = web_latex(factor( data['disc'])).replace(r"-1 \cdot", "-") data['igusa_clebsch'] = [ ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv']) ] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [ web_latex(zfactor(i)).replace(r"-1 \cdot", "-") for i in data['igusa_clebsch'] ] data['igusa_factor_latex'] = [ web_latex(zfactor(j)).replace(r"-1 \cdot", "-") for j in data['igusa'] ] data['aut_grp'] = small_group_label_display_knowl( '%d.%d' % tuple(literal_eval(curve['aut_grp_id']))) data['geom_aut_grp'] = small_group_label_display_knowl( '%d.%d' % tuple(literal_eval(curve['geom_aut_grp_id']))) data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['has_square_sha'] = "square" if curve[ 'has_square_sha'] else "twice a square" P = curve['non_solvable_places'] if len(P): sz = "except over " sz += ", ".join([QpName(p) for p in P]) last = " and" if len(P) > 2: last = ", and" sz = last.join(sz.rsplit(",", 1)) else: sz = "everywhere" data['non_solvable_places'] = sz data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['torsion_order'] = curve['torsion_order'] data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] data['real_period'] = decimal_pretty(str(curve['real_period'])) data['regulator'] = decimal_pretty( str(curve['regulator'] )) if curve['regulator'] > -0.5 else 'unknown' if data['mw_rank'] == 0 and data['mw_rank_proved']: data['regulator'] = '1' # display an exact 1 when we know this data['tamagawa_product'] = ZZ( curve['tamagawa_product']) if curve.get( 'tamagawa_product') else 0 data['analytic_sha'] = ZZ( curve['analytic_sha']) if curve.get('analytic_sha') else 0 data['leading_coeff'] = decimal_pretty( str(curve['leading_coeff'] )) if curve['leading_coeff'] else 'unknown' data['rat_pts'] = ratpts['rat_pts'] data['rat_pts_v'] = ratpts['rat_pts_v'] data['rat_pts_table'] = ratpts_table(ratpts['rat_pts'], ratpts['rat_pts_v']) data['mw_gens_v'] = ratpts['mw_gens_v'] lower = len([n for n in ratpts['mw_invs'] if n == 0]) upper = data['analytic_rank'] invs = ratpts[ 'mw_invs'] if data['mw_gens_v'] or lower >= upper else [ 0 for n in range(upper - lower) ] + ratpts['mw_invs'] if len(invs) == 0: data['mw_group'] = 'trivial' else: data['mw_group'] = r'\(' + r' \times '.join([ (r'\Z' if n == 0 else r'\Z/{%s}\Z' % n) for n in invs ]) + r'\)' if lower >= upper: data['mw_gens_table'] = mw_gens_table(ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts']) if curve['two_torsion_field'][0]: data['two_torsion_field_knowl'] = nf_display_knowl( curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0])) else: t = curve['two_torsion_field'] data[ 'two_torsion_field_knowl'] = r"splitting field of \(%s\) with Galois group %s" % ( intlist_to_poly( t[1]), group_display_knowl(t[2][0], t[2][1])) tamalist = [[item['p'], item['tamagawa_number']] for item in tama] data['local_table'] = local_table(data['abs_disc'], data['cond'], tamalist, data['bad_lfactors_pretty']) else: # invariants specific to isogeny class curves_data = list( db.g2c_curves.search({"class": curve['class']}, ['label', 'eqn'])) if not curves_data: raise KeyError( "No curves found in database for isogeny class %s of genus 2 curve %s." % (curve['class'], curve['label'])) data['curves'] = [{ "label": c['label'], "equation_formatted": min_eqn_pretty(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label']) } for c in curves_data] lfunc_data = db.lfunc_lfunctions.lucky( {'Lhash': str(curve['Lhash'])}) if not lfunc_data: raise KeyError( "No Lfunction found in database for isogeny class of genus 2 curve %s." % curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [ [nth_prime(n + 1), lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n + 1) < 30 and (data['cond'] % nth_prime(n + 1)) ] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors'] ] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base( endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = ( r"Endomorphism %s over \(\Q\):<br>" % ("ring" if is_curve else "algebra") + end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None)) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement( data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base( data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = ( r"Endomorphism %s over \(\overline{\Q}\):" % ("ring" if is_curve else "algebra") + end_statement( data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None)) data['real_geom_end_alg_name'] = real_geom_end_alg_name( curve['real_geom_end_alg']) data['geom_end_alg_name'] = geom_end_alg_name(curve['geom_end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement( data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement( data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len( endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: plot_from_db = db.g2c_plots.lucky({"label": curve['label']}) if (plot_from_db is None): self.plot = encode_plot( eqn_list_to_curve_plot( data['min_eqn'], ratpts['rat_pts'] if ratpts else [])) else: self.plot = plot_from_db['plot'] plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format( self.plot) properties += [ (None, plot_link), ('Conductor', str(data['cond'])), ('Discriminant', str(data['disc'])), ] if data['mw_rank_proved']: properties += [('Mordell-Weil group', data['mw_group'])] properties += [ ('Sato-Tate group', data['st_group_link']), (r'\(\End(J_{\overline{\Q}}) \otimes \R\)', r'\(%s\)' % data['real_geom_end_alg_name']), (r'\(\End(J_{\overline{\Q}}) \otimes \Q\)', r'\(%s\)' % data['geom_end_alg_name']), (r'\(\overline{\Q}\)-simple', bool_pretty(data['is_simple_geom'])), (r'\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [] if is_curve: friends.append(('Isogeny class %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) # first deal with EC ecs = [] if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: ecs.append(("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: ecs.append( ("Isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label))) ecs.sort(key=lambda x: key_for_numerically_sort(x[0])) # then again EC from lfun instances = [] for elt in db.lfunc_instances.search( { 'Lhash': data['Lhash'], 'type': 'ECQP' }, 'url'): instances.extend(elt.split('|')) # and then the other isogeny friends instances.extend([ elt['url'] for elt in get_instances_by_Lhash_and_trace_hash( data["Lhash"], 4, int(data["Lhash"])) ]) exclude = { elt[1].rstrip('/').lstrip('/') for elt in self.friends if elt[1] } exclude.add(data['lfunc_url'].lstrip('/L/').rstrip('/')) for elt in ecs + names_and_urls(instances, exclude=exclude): # because of the splitting we must use G2C specific code add_friend(friends, elt) if is_curve: friends.append(('Twists', url_for(".index_Q", g20=str(data['g2'][0]), g21=str(data['g2'][1]), g22=str(data['g2'][2])))) friends.append(('L-function', data['lfunc_url'])) # Breadcrumbs self.bread = bread = [('Genus 2 Curves', url_for(".index")), (r'$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))] if is_curve: bread += [('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3]))] # Title self.title = "Genus 2 " + ("Curve " if is_curve else "Isogeny Class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage': '', 'magma': ''} # use default show names f, h = fh = data['min_eqn'] g = simplify_hyperelliptic(fh) code['curve'] = { 'sage': 'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));' % (f, h), 'magma': 'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);' % (f, h) } code['simple_curve'] = { 'sage': 'X = HyperellipticCurve(R(%s))' % (g), 'magma': 'X,pi:= SimplifiedModel(C);' } if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation(' + str( data['cond']) + ',2),R!' + str(bad2) + '>*]' else: magma_cond_option = '' code['cond'] = { 'magma': 'Conductor(LSeries(C%s)); Factorization($1);' % magma_cond_option } code['disc'] = { 'magma': 'Discriminant(C); Factorization(Integers()!$1);' } code['geom_inv'] = { 'sage': 'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma': 'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);' } code['aut'] = {'magma': 'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = { 'magma': 'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);' } code['num_rat_wpts'] = { 'magma': '#Roots(HyperellipticPolynomials(SimplifiedModel(C)));' } if ratpts: code['rat_pts'] = { 'magma': '[' + ','.join([ "C![%s,%s,%s]" % (p[0], p[1], p[2]) for p in ratpts['rat_pts'] ]) + '];' } code['mw_group'] = {'magma': 'MordellWeilGroupGenus2(Jacobian(C));'} code['two_selmer'] = { 'magma': 'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);' } code['has_square_sha'] = {'magma': 'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = { 'magma': 'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);' } code['torsion_subgroup'] = { 'magma': 'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);' }
def make_torsion_growth(self): try: tor_gro = self.tor_gro except AttributeError: # for curves with norsion growth data tor_gro = None if tor_gro is None: self.torsion_growth_data_exists = False return self.torsion_growth_data_exists = True self.tg = tg = {} tg['data'] = tgextra = [] # find all base-changes of this curve in the database, if any bcs = list( db.ec_nfcurves.search( {'base_change': { '$contains': [self.lmfdb_label] }}, projection='label')) bcfs = [lab.split("-")[0] for lab in bcs] for F, T in tor_gro.items(): tg1 = {} tg1['bc'] = "Not in database" # mongo did not allow "." in a dict key so we changed (e.g.) '3.1.44.1' to '3:1:44:1' # Here we change it back (but this code also works in case the fields already use ".") F = F.replace(":", ".") if "." in F: field_data = nf_display_knowl(F, field_pretty(F)) deg = int(F.split(".")[0]) bcc = [x for x, y in zip(bcs, bcfs) if y == F] if bcc: from lmfdb.ecnf.main import split_full_label F, NN, I, C = split_full_label(bcc[0]) tg1['bc'] = bcc[0] tg1['bc_url'] = url_for('ecnf.show_ecnf', nf=F, conductor_label=NN, class_label=I, number=C) else: field_data = web_latex(coeff_to_poly(string2list(F))) deg = F.count(",") tg1['d'] = deg tg1['f'] = field_data tg1['t'] = '\(' + ' \\times '.join( ['\Z/{}\Z'.format(n) for n in T.split(",")]) + '\)' tg1['m'] = 0 tgextra.append(tg1) tgextra.sort(key=lambda x: x['d']) tg['n'] = len(tgextra) lastd = 1 for tg1 in tgextra: d = tg1['d'] if d != lastd: tg1['m'] = len([x for x in tgextra if x['d'] == d]) lastd = d ## Hard-code this for now. While something like ## max(db.ec_curves.search({},projection='tor_degs')) might ## work, since 'tor_degs' is in the extra table it is very ## slow. Note that the *only* place where this number is used ## is in the ec-curve template where it says "The number ## fields ... of degree up to {{data.tg.maxd}} such that...". tg['maxd'] = 7
def end_statement(factorsQQ, factorsRR, field='', ring=None): # field is a latex string describing the basechange field (default is empty) # ring is optional, if unspecified only endomorphism algebra is described statement = """<table class="g2">""" factorsQQ_number = len(factorsQQ) factorsQQ_pretty = [ field_pretty(fac[0]) for fac in factorsQQ if fac[0] ] # endomorphism ring is an invariant of the curve but not the isogeny class, so we make it optional if ring: # First row: description of the endomorphism ring as an order in the endomorphism algebra statement += """<tr><td>\(\End (J_{%s})\)</td><td>\(\simeq\)</td><td>""" % field # First the case of a maximal order: if ring[0] == 1: # Single factor: if factorsQQ_number == 1: # Number field or not: if factorsQQ[0][2] == -1: # Prettify in quadratic case: if len(factorsQQ[0][1]) in [2, 3]: statement += """\(%s\)""" % ring_pretty(factorsQQ[0][1], 1) else: statement += """the maximal order of \(\End (J_{%s}) \otimes \Q\)""" % field else: # Use M_2 over integers if this applies: if factorsQQ[0][2] == 1 and factorsQQ[0][0] == '1.1.1.1': statement += """\(\mathrm{M}_2 (\Z)\)""" # TODO: Add flag that indicates whether we are over a PID, in # which case we can use the following lines: #if factorsQQ[0][2] == 1: # statement += """\(\mathrm{M}_2 (%s)\)"""\ # % ring_pretty(factorsQQ[0][1], 1) else: statement += """a maximal order of \(\End (J_{%s}) \otimes \Q\)""" % field # If there are two factors, then they are both at most quadratic # and we can prettify them else: statement += r'\(' + ' \\times '.join([ ring_pretty(factorQQ[1], 1) for factorQQ in factorsQQ ]) + r'\)' # Then the case where there is still a single factor: elif factorsQQ_number == 1: # Number field case: if factorsQQ[0][2] == -1: # Prettify in quadratic case: if len(factorsQQ[0][1]) in [2, 3]: statement += """\(%s\)""" % ring_pretty(factorsQQ[0][1], ring[0]) else: statement += """an order of conductor of norm \(%s\) in \(\End (J_{%s}) \otimes \Q\)""" % (ring[0], field) # Otherwise mention whether the order is Eichler: elif ring[1] == 1: statement += """an Eichler order of index \(%s\) in a maximal order of \(\End (J_{%s}) \otimes \Q\)""" % (ring[0], field) else: statement += """a non-Eichler order of index \(%s\) in a maximal order of \(\End (J_{%s}) \otimes \Q\)""" % (ring[0], field) # Finally the case of two factors. We can prettify to some extent, since we # can describe the maximal order here else: statement += """an order of index \(%s\) in \(%s\)""" % (ring[0], ' \\times '.join([ ring_pretty(factorQQ[1], 1) for factorQQ in factorsQQ ])) # End of first row: statement += """</td></tr>""" # Second row: description of endomorphism algebra factors (this is the first row if ring=None) statement += """<tr><td>\(\End (J_{%s}) \otimes \Q \)</td><td>\(\simeq\)</td><td>""" % field # In the case of only one factor we either get a number field or a # quaternion algebra: if factorsQQ_number == 1: # First we deal with the number field case, # in which we have set the discriminant to be -1 if factorsQQ[0][2] == -1: # Prettify if labels available, otherwise return defining polynomial: if factorsQQ_pretty: statement += """<a href=%s>%s</a>""" % (url_for("number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0]) else: statement += """the number field with defining polynomial \(%s\)""" % intlist_to_poly(factorsQQ[0][1]) # Detect CM by presence of a quartic polynomial: if len(factorsQQ[0][1]) == 5: statement += """ (CM)""" # TODO: Get the following line to work #statement += """ ({{ KNOWL('ag.complex_multiplication', title='CM') }})""" # Up next is the case of a matrix ring (trivial disciminant), with # labels and full prettification always available: elif factorsQQ[0][2] == 1: statement += """\(\mathrm{M}_2(\)<a href=%s>%s</a>\()\)""" % (url_for("number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0]) # And finally we deal with quaternion algebras over the rationals: else: statement += """the quaternion algebra over <a href=%s>%s</a> of discriminant %s"""\ % (url_for("number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0], factorsQQ[0][2]) # If there are two factors, then we get two at most quadratic fields: else: statement += """<a href=%s>%s</a> \(\\times\) <a href=%s>%s</a>"""\ % (url_for("number_fields.by_label", label=factorsQQ[0][0]), factorsQQ_pretty[0], url_for("number_fields.by_label", label=factorsQQ[1][0]), factorsQQ_pretty[1]) # End of second row: statement += """</td></tr>""" # Third row: description of algebra tensored with RR (this is the second row if ring=None) statement += """<tr><td>\(\End (J_{%s}) \otimes \R\)</td><td>\(\simeq\)</td> <td>\(%s\)</td></tr>""" % (field, factorsRR_raw_to_pretty(factorsRR)) # End of statement: statement += """</table>""" return statement
def make_object(self, curve, endo, tama, ratpts, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = str(curve['Lhash']) data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex(factor(int(data['cond']))) data['analytic_rank'] = ZZ(curve['analytic_rank']) data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1, 4, data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [(c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ(curve['abs_disc']) data['disc'] = curve['disc_sign'] * data['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = list_to_min_eqn(data['min_eqn']) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['igusa_clebsch'] = [ ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv']) ] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [ web_latex(zfactor(i)) for i in data['igusa_clebsch'] ] data['igusa_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa'] ] data['aut_grp_id'] = curve['aut_grp_id'] data['geom_aut_grp_id'] = curve['geom_aut_grp_id'] data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['has_square_sha'] = "square" if curve[ 'has_square_sha'] else "twice a square" P = curve['non_solvable_places'] if len(P): sz = "except over " sz += ", ".join([QpName(p) for p in P]) last = " and" if len(P) > 2: last = ", and" sz = last.join(sz.rsplit(",", 1)) else: sz = "everywhere" data['non_solvable_places'] = sz data['torsion_order'] = curve['torsion_order'] data['torsion_factors'] = [ ZZ(a) for a in literal_eval(curve['torsion_subgroup']) ] if len(data['torsion_factors']) == 0: data['torsion_subgroup'] = '\mathrm{trivial}' else: data['torsion_subgroup'] = ' \\times '.join( ['\Z/{%s}\Z' % n for n in data['torsion_factors']]) data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] data['tama'] = '' for item in tama: if item['tamagawa_number'] > 0: tamgwnr = str(item['tamagawa_number']) else: tamgwnr = 'N/A' data['tama'] += tamgwnr + ' (p = ' + str(item['p']) + '), ' data['tama'] = data['tama'][:-2] # trim last ", " if ratpts: if len(ratpts['rat_pts']): data['rat_pts'] = ', '.join( web_latex('(' + ' : '.join(map(str, P)) + ')') for P in ratpts['rat_pts']) data['rat_pts_v'] = 2 if ratpts['rat_pts_v'] else 1 # data['mw_rank'] = ratpts['mw_rank'] # data['mw_rank_v'] = ratpts['mw_rank_v'] else: data['rat_pts_v'] = 0 if curve['two_torsion_field'][0]: data['two_torsion_field_knowl'] = nf_display_knowl( curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0])) else: t = curve['two_torsion_field'] data[ 'two_torsion_field_knowl'] = """splitting field of \(%s\) with Galois group %s""" % ( intlist_to_poly( t[1]), group_display_knowl(t[2][0], t[2][1])) else: # invariants specific to isogeny class curves_data = list( db.g2c_curves.search({"class": curve['class']}, ['label', 'eqn'])) if not curves_data: raise KeyError( "No curves found in database for isogeny class %s of genus 2 curve %s." % (curve['class'], curve['label'])) data['curves'] = [{ "label": c['label'], "equation_formatted": list_to_min_eqn(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label']) } for c in curves_data] lfunc_data = db.lfunc_lfunctions.lucky( {'Lhash': str(curve['Lhash'])}) if not lfunc_data: raise KeyError( "No Lfunction found in database for isogeny class of genus 2 curve %s." % curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [ [nth_prime(n + 1), lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n + 1) < 30 and (data['cond'] % nth_prime(n + 1)) ] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors'] ] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base( endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = """Endomorphism %s over \(\Q\):<br>""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement( data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base( data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = """Endomorphism %s over \(\overline{\Q}\):""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None) data['real_geom_end_alg_name'] = end_alg_name( curve['real_geom_end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement( data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement( data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len( endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: self.plot = encode_plot( eqn_list_to_curve_plot( data['min_eqn'], data['rat_pts'].split(',') if 'rat_pts' in data else [])) plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format( self.plot) properties += [ (None, plot_link), ('Conductor', str(data['cond'])), ('Discriminant', str(data['disc'])), ] properties += [ ('Sato-Tate group', data['st_group_link']), ('\(\\End(J_{\\overline{\\Q}}) \\otimes \\R\)', '\(%s\)' % data['real_geom_end_alg_name']), ('\(\\overline{\\Q}\)-simple', bool_pretty(data['is_simple_geom'])), ('\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [('L-function', data['lfunc_url'])] if is_curve: friends.append(('Isogeny class %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) for friend_url in db.lfunc_instances.search({'Lhash': data['Lhash']}, 'url'): if '|' in friend_url: for url in friend_url.split('|'): add_friend(friends, lfunction_friend_from_url(url)) else: add_friend(friends, lfunction_friend_from_url(friend_url)) if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: add_friend(friends, ("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: add_friend( friends, ("EC isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label))) if is_curve: friends.append(('Twists', url_for(".index_Q", g20=str(data['g2'][0]), g21=str(data['g2'][1]), g22=str(data['g2'][2])))) # Breadcrumbs self.bread = bread = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))] if is_curve: bread += [('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3]))] # Title self.title = "Genus 2 " + ("Curve " if is_curve else "Isogeny Class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage': '', 'magma': ''} # use default show names code['curve'] = { 'sage': 'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))' % (data['min_eqn'][0], data['min_eqn'][1]), 'magma': 'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);' % (data['min_eqn'][0], data['min_eqn'][1]) } if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation(' + str( data['cond']) + ',2),R!' + str(bad2) + '>*]' else: magma_cond_option = '' code['cond'] = { 'magma': 'Conductor(LSeries(C%s)); Factorization($1);' % magma_cond_option } code['disc'] = { 'magma': 'Discriminant(C); Factorization(Integers()!$1);' } code['igusa_clebsch'] = { 'sage': 'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma': 'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];' } code['igusa'] = { 'magma': 'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];' } code['g2'] = {'magma': 'G2Invariants(C);'} code['aut'] = {'magma': 'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = { 'magma': 'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);' } code['num_rat_wpts'] = { 'magma': '#Roots(HyperellipticPolynomials(SimplifiedModel(C)));' } if ratpts: code['rat_pts'] = { 'magma': '[' + ','.join([ "C![%s,%s,%s]" % (p[0], p[1], p[2]) for p in ratpts['rat_pts'] ]) + '];' } code['two_selmer'] = { 'magma': 'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);' } code['has_square_sha'] = {'magma': 'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = { 'magma': 'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);' } code['torsion_subgroup'] = { 'magma': 'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);' }