def make_mw(self): mw = self.mw = {} mw['rank'] = self.rank mw['int_points'] = '' if self.xintcoords: a1, a2, a3, a4, a6 = self.ainvs def lift_x(x): f = ((x + a2) * x + a4) * x + a6 b = (a1 * x + a3) d = (b * b + 4 * f).sqrt() return (x, (-b + d) / 2) mw['int_points'] = ', '.join( web_latex(lift_x(ZZ(x))) for x in self.xintcoords) mw['generators'] = '' mw['heights'] = [] if self.gens: mw['generators'] = [ web_latex(tuple(P)) for P in parse_points(self.gens) ] mw['heights'] = self.heights mw['tor_order'] = self.torsion tor_struct = [int(c) for c in self.torsion_structure] if mw['tor_order'] == 1: mw['tor_struct'] = '\mathrm{Trivial}' mw['tor_gens'] = '' else: mw['tor_struct'] = ' \\times '.join( ['\Z/{%s}\Z' % n for n in tor_struct]) mw['tor_gens'] = ', '.join( web_latex(tuple(P)) for P in parse_points(self.torsion_generators))
def make_mw(self): mw = self.mw = {} mw['rank'] = self.rank mw['int_points'] = '' # should import this from import_ec_data.py if self.xintcoords: mw['int_points'] = make_integral_points(self) #mw['int_points'] = ', '.join(web_latex(lift_x(ZZ(x))) for x in self.xintcoords) mw['generators'] = '' mw['heights'] = [] if self.gens: mw['generators'] = [ web_latex(tuple(P)) for P in parse_points(self.gens) ] mw['heights'] = self.heights mw['tor_order'] = self.torsion tor_struct = [int(c) for c in self.torsion_structure] if mw['tor_order'] == 1: mw['tor_struct'] = '\mathrm{Trivial}' mw['tor_gens'] = '' else: mw['tor_struct'] = ' \\times '.join( ['\Z/{%s}\Z' % n for n in tor_struct]) mw['tor_gens'] = ', '.join( web_latex(tuple(P)) for P in parse_points(self.torsion_generators))
def make_mw(self): mw = self.mw = {} mw['rank'] = self.rank mw['int_points'] = '' if self.xintcoords: a1, a2, a3, a4, a6 = self.ainvs def lift_x(x): f = ((x + a2) * x + a4) * x + a6 b = (a1*x + a3) d = (b*b + 4*f).sqrt() return (x, (-b+d)/2) mw['int_points'] = ', '.join(web_latex(lift_x(ZZ(x))) for x in self.xintcoords) mw['generators'] = '' mw['heights'] = [] if self.gens: mw['generators'] = [web_latex(tuple(P)) for P in parse_points(self.gens)] mw['heights'] = self.heights mw['tor_order'] = self.torsion tor_struct = [int(c) for c in self.torsion_structure] if mw['tor_order'] == 1: mw['tor_struct'] = '\mathrm{Trivial}' mw['tor_gens'] = '' else: mw['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct]) mw['tor_gens'] = ', '.join(web_latex(tuple(P)) for P in parse_points(self.torsion_generators))
def make_extra_data(label, number, ainvs, gens): """Given a curve label (and number, as some data is only stored wih curve number 1 in each class) and its ainvs and gens, returns a dict with which to update the entry. Extra items computed here: 'equation': latex string of curve's equation 'signD': sign of discriminant 'local_data': list of dicts, one item for each bad prime 'min_quad_twist': dict holding curve's min quadratic twist and the twisting discriminant 'heights': list of heights of gens and for curve #1 in a class only: 'aplist': list of a_p for p<100 'anlist': list of a_n for n<=20 """ E = EllipticCurve(parse_ainvs(ainvs)) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{ 'p': int(ld.prime().gen()), 'ord_cond': int(ld.conductor_valuation()), 'ord_disc': int(ld.discriminant_valuation()), 'ord_den_j': int(max(0, -(E.j_invariant().valuation(ld.prime().gen())))), 'red': int(ld.bad_reduction_type()), 'rootno': int(E.root_number(ld.prime().gen())), 'kod': web_latex(ld.kodaira_symbol()).replace('$', ''), 'cp': int(ld.tamagawa_number()) } for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor() == E.conductor(): data['min_quad_twist'] = {'label': label, 'disc': int(1)} else: minq_ainvs = ''.join(['['] + [str(c) for c in Etw.ainvs()] + [']']) r = curves.find_one({ 'jinv': str(E.j_invariant()), 'ainvs': minq_ainvs }) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label': minq_label, 'disc': int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number == 1: data['aplist'] = E.aplist(100, python_ints=True) data['anlist'] = E.anlist(20, python_ints=True) return data
def test_web_latex(self): r""" Checking utility: web_latex """ x = var('x') self.assertEqual(web_latex("test string"), "test string") self.assertEqual(web_latex(x**23 + 2*x + 1), '\\( x^{23} + 2 \\, x + 1 \\)')
def test_web_latex(self): r""" Checking utility: web_latex """ x = var('x') self.assertEqual(web_latex("test string"), "test string") self.assertEqual(web_latex(x**23 + 2 * x + 1), '\\( x^{23} + 2 \\, x + 1 \\)') self.assertEqual(web_latex(x**23 + 2 * x + 1, enclose=False), ' x^{23} + 2 \\, x + 1 ')
def make_mwbsd(self): mwbsd = self.mwbsd = db.ec_mwbsd.lookup(self.lmfdb_label) # Some components are in the main table: mwbsd['rank'] = r = self.rank mwbsd['torsion'] = self.torsion mwbsd['reg'] = self.regulator mwbsd['sha'] = self.sha mwbsd['sha2'] = latex_sha(self.sha) # Integral points xintcoords = mwbsd['xcoord_integral_points'] a1, _, a3, _, _ = ainvs = self.ainvs if a1 or a3: int_pts = sum([[(x, y) for y in make_y_coords(ainvs, x)] for x in xintcoords], []) mwbsd['int_points'] = ', '.join(web_latex(P) for P in int_pts) else: int_pts = [(x, make_y_coords(ainvs, x)[0]) for x in xintcoords] mwbsd['int_points'] = ', '.join(pm_pt(P) for P in int_pts) # Generators (mod torsion) and heights: mwbsd['generators'] = [ web_latex(weighted_proj_to_affine_point(P)) for P in mwbsd['gens'] ] if mwbsd['ngens'] else '' # Torsion structure and generators: if mwbsd['torsion'] == 1: mwbsd['tor_struct'] = '' mwbsd['tor_gens'] = '' else: mwbsd['tor_struct'] = r' \times '.join( [r'\Z/{%s}\Z' % n for n in self.torsion_structure]) mwbsd['tor_gens'] = ', '.join( web_latex(weighted_proj_to_affine_point(P)) for P in mwbsd['torsion_generators']) # BSD invariants if r >= 2: mwbsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r) elif r: mwbsd['lder_name'] = "L'(E,1)" else: mwbsd['lder_name'] = "L(E,1)" tamagawa_numbers = [ld['tamagawa_number'] for ld in self.local_data] cp_fac = [ZZ(cp).factor() for cp in tamagawa_numbers] cp_fac = [ latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')' for cp in cp_fac ] mwbsd['tamagawa_factors'] = r'\cdot'.join(cp_fac) mwbsd['tamagawa_product'] = prod(tamagawa_numbers)
def properties(self): nilp_str = f"yes, of class {self.nilpotency_class}" if self.nilpotent else "no" solv_str = f"yes, of length {self.derived_length}" if self.solvable else "no" props = [ ("Label", self.label), ("Order", web_latex(factor(self.order))), ("Exponent", web_latex(factor(self.exponent))), (None, self.image()), ] if self.abelian: props.append(("Abelian", "yes")) if self.simple: props.extend([("Simple", "yes"), (r"#$\operatorname{Aut}(G)$", web_latex(factor(self.aut_order)))]) else: props.append((r"#$\operatorname{Aut}(G)$", web_latex(factor(self.aut_order)))) else: if self.simple: props.append(("Simple", "yes")) else: props.extend([("Nilpotent", nilp_str), ("Solvable", solv_str)]) props.extend([ (r"#$G^{\mathrm{ab}}$", web_latex(self.Gab_order_factor())), ("#$Z(G)$", web_latex(self.cent_order_factor())), (r"#$\operatorname{Aut}(G)$", web_latex(factor(self.aut_order))), (r"#$\operatorname{Out}(G)$", web_latex(factor(self.outer_order))), ]) props.extend([ ("Rank", f"${self.rank}$"), ("Perm deg.", f"${self.transitive_degree}$"), # ("Faith. dim.", str(self.faithful_reps[0][0])), ]) return props
def make_extra_data(label, number, ainvs, gens): """ C is a database elliptic curve entry. Returns a dict with which to update the entry. Data fields needed in C already: 'ainvs', 'lmfdb_label', 'gens', 'number' """ E = EllipticCurve([int(a) for a in ainvs]) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['xainvs'] = ''.join(['[', ','.join(ainvs), ']']) data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{ 'p': int(ld.prime().gen()), 'ord_cond': int(ld.conductor_valuation()), 'ord_disc': int(ld.discriminant_valuation()), 'ord_den_j': int(max(0, -(E.j_invariant().valuation(ld.prime().gen())))), 'red': int(ld.bad_reduction_type()), 'rootno': int(E.root_number(ld.prime().gen())), 'kod': web_latex(ld.kodaira_symbol()).replace('$', ''), 'cp': int(ld.tamagawa_number()) } for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor() == E.conductor(): data['min_quad_twist'] = {'label': label, 'disc': int(1)} else: # Later this should be changed to look for xainvs but now all curves have ainvs minq_ainvs = [str(c) for c in Etw.ainvs()] r = curves.find_one({ 'jinv': str(E.j_invariant()), 'ainvs': minq_ainvs }) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label': minq_label, 'disc': int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number == 1: data['aplist'] = E.aplist(100, python_ints=True) data['anlist'] = E.anlist(20, python_ints=True) return data
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p N, iso, number = lmfdb_label_regex.match(label).groups() # print N, iso, number if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({'lmfdb_iso': N + '.' + iso}) data = C.elliptic_curves.padic_db.find_one({ 'lmfdb_iso': N + '.' + iso, 'p': p }) info['data'] = data if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = sage.all.Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("padic_data.html", info=info)
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p print "label = %s; p = %s" % (label,p) N, iso, number = split_lmfdb_label(label) # print N, iso, number if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({'lmfdb_iso': N + '.' + iso}) data = C.elliptic_curves.padic_db.find_one({'lmfdb_iso': N + '.' + iso, 'p': p}) info['data'] = data if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = sage.all.Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("padic_data.html", info=info)
def make_extra_data(label,number,ainvs,gens): """Given a curve label (and number, as some data is only stored wih curve number 1 in each class) and its ainvs and gens, returns a dict with which to update the entry. Extra items computed here: 'equation': latex string of curve's equation 'signD': sign of discriminant 'local_data': list of dicts, one item for each bad prime 'min_quad_twist': dict holding curve's min quadratic twist and the twisting discriminant 'heights': list of heights of gens and for curve #1 in a class only: 'aplist': list of a_p for p<100 'anlist': list of a_n for n<=20 """ E = EllipticCurve(parse_ainvs(ainvs)) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{'p': int(ld.prime().gen()), 'ord_cond':int(ld.conductor_valuation()), 'ord_disc':int(ld.discriminant_valuation()), 'ord_den_j':int(max(0,-(E.j_invariant().valuation(ld.prime().gen())))), 'red':int(ld.bad_reduction_type()), 'rootno':int(E.root_number(ld.prime().gen())), 'kod':web_latex(ld.kodaira_symbol()).replace('$',''), 'cp':int(ld.tamagawa_number())} for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor()==E.conductor(): data['min_quad_twist'] = {'label':label, 'disc':int(1)} else: minq_ainvs = ''.join(['['] + [str(c) for c in Etw.ainvs()] + [']']) r = curves.find_one({'jinv':str(E.j_invariant()), 'ainvs':minq_ainvs}) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label':minq_label, 'disc':int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number==1: data['aplist'] = E.aplist(100,python_ints=True) data['anlist'] = E.anlist(20,python_ints=True) return data
def primeideal_display(p, prime_ideal): ans = "($ {0} $".format(p) if prime_ideal == ["0"]: ans += ")" return ans else: ans += "," + web_latex(coeff_to_poly(prime_ideal, "pi")) + ")" return ans
def make_integral_points(self): a1, _, a3, _, _ = ainvs = self.ainvs if a1 or a3: int_pts = sum([[(x, y) for y in make_y_coords(ainvs, x)] for x in self.xintcoords], []) return ', '.join(web_latex(P) for P in int_pts) else: int_pts = [(x, make_y_coords(ainvs, x)[0]) for x in self.xintcoords] return ', '.join(pm_pt(P) for P in int_pts)
def ajax_more2(callback, *arg_list, **kwds): r""" Like ajax_more but accepts increase in two directions. Call with ajax_more2(function,{'arg1':[x1,x2,...,],'arg2':[y1,y2,...]},'text1','text2') where function takes two named argument 'arg1' and 'arg2' """ inline = kwds.get('inline', True) text = kwds.get('text', 'more') emf_logger.debug("inline={0}".format(inline)) emf_logger.debug("text={0}".format(text)) text0 = text[0] text1 = text[1] emf_logger.debug("arglist={0}".format(arg_list)) nonce = hex(random.randint(0, 1 << 128)) if inline: args = arg_list[0] emf_logger.debug("args={0}".format(args)) key1, key2 = args.keys() l1 = args[key1] l2 = args[key2] emf_logger.debug("key1={0}".format(key1)) emf_logger.debug("key2={0}".format(key2)) emf_logger.debug("l1={0}".format(l1)) emf_logger.debug("l2={0}".format(l2)) args = {key1: l1[0], key2: l2[0]} l11 = l1[1:] l21 = l2[1:] # arg_list = arg_list[1:] arg_list1 = {key1: l1, key2: l21} arg_list2 = {key1: l11, key2: l2} # emf_logger.debug("arglist1={0}".format(arg_list)) if isinstance(args, tuple): res = callback(*arg_list) elif isinstance(args, dict): res = callback(**args) else: res = callback(args) res = web_latex(res) else: res = '' emf_logger.debug("arg_list1={0}".format(arg_list1)) emf_logger.debug("arg_list2={0}".format(arg_list2)) arg_list1 = (arg_list1,) arg_list2 = (arg_list2,) if arg_list1 or arg_list2: url1 = ajax_url(ajax_more2, callback, *arg_list1, inline=True, text=text) url2 = ajax_url(ajax_more2, callback, *arg_list2, inline=True, text=text) emf_logger.debug("arg_list1={0}".format(url1)) emf_logger.debug("arg_list2={0}".format(url2)) s0 = """<span id='%(nonce)s'>%(res)s """ % locals() s1 = """[<a onclick="$('#%(nonce)s').load('%(url1)s', function() { renderMathInElement($('#%(nonce)s').get(0),katexOpts);}); return false;" href="#">%(text0)s</a>""" % locals() t = """| <a onclick="$('#%(nonce)s').load('%(url2)s', function() { renderMathInElement($('#%(nonce)s').get(0),katexOpts);}); return false;" href="#">%(text1)s</a>]</span>""" % locals() return (s0 + s1 + t) else: return res
def make_integral_points(self): ainvs = self.ainvs xcoord_integral_points = self.xintcoords int_pts = [] for x in xcoord_integral_points: y, d = make_y_coord(ainvs, x) int_pts.append((x, y)) if len(xcoord_integral_points) != 0: int_pts_str = ', '.join(web_latex(el) for el in int_pts) return int_pts_str
def _order_basis_forward(self): basis = [] for i, (num, den) in enumerate(zip(self.hecke_ring_numerators, self.hecke_ring_denominators)): numsize = sum(len(str(c)) for c in num if c) if numsize > 80: num = web_latex_poly(num, self._nu_latex, superscript=True) else: num = web_latex(coeff_to_poly(num, self._nu_var)) betai = r'\(\beta_{%s}\)'%i basis.append((betai, self._make_frac(num, den))) return self._make_table(basis)
def q_expansion(self, prec_max=10): # Display the q-expansion, truncating to precision prec_max. Will be inside \( \). if self.has_exact_qexp: prec = min(self.qexp_prec, prec_max) if self.dim == 1: s = web_latex_split_on_pm(web_latex(coeff_to_power_series([self.qexp[n][0] for n in range(prec)],prec=prec),enclose=False)) else: s = self.eigs_as_seqseq_to_qexp(prec) return s else: return coeff_to_power_series([0,1], prec=2)._latex_()
def _order_basis_forward(self): basis = [] for i, (num, den) in enumerate(zip(self.hecke_ring_numerators, self.hecke_ring_denominators)): numsize = sum(len(str(c)) for c in num if c) if numsize > 80: num = web_latex_poly(num, self._nu_latex, superscript=True, cutoff=8) else: num = web_latex(coeff_to_poly(num, self._nu_var)) betai = r'\(\beta_{%s}\)'%i basis.append((betai, self._make_frac(num, den))) return self._make_table(basis)
def units(self): # fundamental units if self.haskey('units'): return ', '.join(self._data['units']) if self.unit_rank() == 0: return '' if self.haskey('class_number'): K = self.K() units = [web_latex(u) for u in K.unit_group().fundamental_units()] units = ', '.join(units) return units return na_text()
def computation_roots(self): # Write these as p-adic series. Start with helper self.lowered = self.lower_precision() def help_padic(n, p, prec): """ Take an integer n, prime p, and precision prec, and return a prec-tuple of the p-adic coefficients of j """ n = ZZ(n) res = [0 for j in range(prec)] while n < 0: n += p**prec for k in range(prec): res[k] = n % p n = (n - res[k]) / p return res # Second helper, in case some arrays are not extended by 0 def getel(li, j): if j < len(li): return li[j] return 0 myroots = self._data["QpRts"] p = self._data['QpRts-p'] prec = self._data['QpRts-prec'] myroots = [[help_padic(z, p, prec) for z in t] for t in myroots] myroots = [[[ getel(root[j], r) for j in range(len(self._data['QpRts-minpoly']) - 1) ] for r in range(prec)] for root in myroots] myroots = [[coeff_to_poly(x, var='a') for x in root] for root in myroots] # Use power series so degrees increase # Use formal p so we can make a power series PR = PowerSeriesRing(PolynomialRing(QQ, 'a'), 'p') rawrts = [str(PR(x)) + r'+O(p^{})'.format(prec) for x in myroots] rawrts = [z.replace('p', str(p)) for z in rawrts] myroots = [ web_latex(PR(x), enclose=False) + r'+O(p^{' + str(prec) + r'})' for x in myroots ] # change p into its value myroots = [r'\({}\)'.format(z) for z in myroots] myroots = [ re.sub(r'([a)\d]) *p', r'\1\\cdot ' + str(p), z) for z in myroots ] typesetrts = [z.replace('p', str(p)) for z in myroots] return [raw_typeset(z[0], z[1]) for z in zip(rawrts, typesetrts)]
def lf_knowl_guts(label, C): f = C.localfields.fields.find_one({'label':label}) ans = 'Local number field %s<br><br>'% label ans += 'Extension of $\Q_{%s}$ defined by %s<br>'%(str(f['p']),web_latex(coeff_to_poly(f['coeffs']))) GG = f['gal'] ans += 'Degree: %s<br>' % str(GG[0]) ans += 'Ramification index $e$: %s<br>' % str(f['e']) ans += 'Residue field degree $f$: %s<br>' % str(f['f']) ans += 'Discriminant ideal: $(p^{%s})$ <br>' % str(f['c']) ans += 'Galois group $G$: %s<br>' % group_display_knowl(GG[0], GG[1], C) ans += '<div align="right">' ans += '<a href="%s">%s home page</a>' % (str(url_for("local_fields.by_label", label=label)),label) ans += '</div>' return ans
def lf_knowl_guts(label, C): f = C.localfields.fields.find_one({"label": label}) ans = "Local number field %s<br><br>" % label ans += "Extension of $\Q_{%s}$ defined by %s<br>" % (str(f["p"]), web_latex(coeff_to_poly(f["coeffs"]))) GG = f["gal"] ans += "Degree: %s<br>" % str(GG[0]) ans += "Ramification index $e$: %s<br>" % str(f["e"]) ans += "Residue field degree $f$: %s<br>" % str(f["f"]) ans += "Discriminant ideal: $(p^{%s})$ <br>" % str(f["c"]) ans += "Galois group $G$: %s<br>" % group_display_knowl(GG[0], GG[1], C) ans += '<div align="right">' ans += '<a href="%s">%s home page</a>' % (str(url_for("local_fields.by_label", label=label)), label) ans += "</div>" return ans
def lf_knowl_guts(label, C): f = C.localfields.fields.find_one({'label':label}) ans = 'Local number field %s<br><br>'% label ans += 'Extension of $\Q_{%s}$ defined by %s<br>'%(str(f['p']),web_latex(coeff_to_poly(string2list(f['coeffs'])))) GG = f['gal'] ans += 'Degree: %s<br>' % str(GG[0]) ans += 'Ramification index $e$: %s<br>' % str(f['e']) ans += 'Residue field degree $f$: %s<br>' % str(f['f']) ans += 'Discriminant ideal: $(p^{%s})$ <br>' % str(f['c']) ans += 'Galois group $G$: %s<br>' % group_display_knowl(GG[0], GG[1], C) ans += '<div align="right">' ans += '<a href="%s">%s home page</a>' % (str(url_for("local_fields.by_label", label=label)),label) ans += '</div>' return ans
def make_extra_data(label,number,ainvs,gens): """ C is a database elliptic curve entry. Returns a dict with which to update the entry. Data fields needed in C already: 'ainvs', 'lmfdb_label', 'gens', 'number' """ E = EllipticCurve([int(a) for a in ainvs]) data = {} # convert from a list of strings to a single string, e.g. from ['0','0','0','1','1'] to '[0,0,0,1,1]' data['xainvs'] = ''.join(['[',','.join(ainvs),']']) data['equation'] = web_latex(E) data['signD'] = int(E.discriminant().sign()) data['local_data'] = [{'p': int(ld.prime().gen()), 'ord_cond':int(ld.conductor_valuation()), 'ord_disc':int(ld.discriminant_valuation()), 'ord_den_j':int(max(0,-(E.j_invariant().valuation(ld.prime().gen())))), 'red':int(ld.bad_reduction_type()), 'rootno':int(E.root_number(ld.prime().gen())), 'kod':web_latex(ld.kodaira_symbol()).replace('$',''), 'cp':int(ld.tamagawa_number())} for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor()==E.conductor(): data['min_quad_twist'] = {'label':label, 'disc':int(1)} else: # Later this should be changed to look for xainvs but now all curves have ainvs minq_ainvs = [str(c) for c in Etw.ainvs()] r = curves.find_one({'jinv':str(E.j_invariant()), 'ainvs':minq_ainvs}) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label':minq_label, 'disc':int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number==1: data['aplist'] = E.aplist(100,python_ints=True) data['anlist'] = E.anlist(20,python_ints=True) return data
def units(self): # fundamental units res = None if self.haskey('units'): res = ', '.join(self._data['units']) elif self.unit_rank() == 0: res = '' elif self.haskey('class_number'): K = self.K() units = [web_latex(u) for u in K.unit_group().fundamental_units()] units = ', '.join(units) res = units if res: res = res.replace('\\\\', '\\') return res return na_text()
def modular_form_display(label, number): try: number = int(number) except ValueError: number = 10 if number < 10: number = 10 if number > 1000: number = 1000 ainvs = db.ec_curves.lookup(label, 'ainvs', 'lmfdb_label') if ainvs is None: return elliptic_curve_jump_error(label, {}) E = EllipticCurve(ainvs) modform = E.q_eigenform(number) modform_string = web_latex(modform) return modform_string
def local_field_data(label): f = db.lf_fields.lookup(label) nicename = '' if f['n'] < 3: nicename = ' = '+ prettyname(f) ans = 'Local number field %s%s<br><br>'% (label, nicename) ans += 'Extension of $\Q_{%s}$ defined by %s<br>'%(str(f['p']),web_latex(coeff_to_poly(f['coeffs']))) gt = f['gal'] gn = f['n'] ans += 'Degree: %s<br>' % str(gt) ans += 'Ramification index $e$: %s<br>' % str(f['e']) ans += 'Residue field degree $f$: %s<br>' % str(f['f']) ans += 'Discriminant ideal: $(p^{%s})$ <br>' % str(f['c']) ans += 'Galois group $G$: %s<br>' % group_pretty_and_nTj(gn, gt, True) ans += '<div align="right">' ans += '<a href="%s">%s home page</a>' % (str(url_for("local_fields.by_label", label=label)),label) ans += '</div>' return ans
def local_field_data(label): f = db.lf_fields.lookup(label) nicename = '' if f['n'] < 3: nicename = ' = '+ prettyname(f) ans = '$p$-adic field %s%s<br><br>'% (label, nicename) ans += r'Extension of $\Q_{%s}$ defined by %s<br>'%(str(f['p']),web_latex(coeff_to_poly(f['coeffs']))) gt = int(f['galois_label'].split('T')[1]) gn = f['n'] ans += 'Degree: %s<br>' % str(gn) ans += 'Ramification index $e$: %s<br>' % str(f['e']) ans += 'Residue field degree $f$: %s<br>' % str(f['f']) ans += 'Discriminant ideal: $(p^{%s})$ <br>' % str(f['c']) ans += 'Galois group $G$: %s<br>' % group_pretty_and_nTj(gn, gt, True) ans += '<div align="right">' ans += '<a href="%s">%s home page</a>' % (str(url_for("local_fields.by_label", label=label)),label) ans += '</div>' return ans
def padic_data(label, p): try: N, iso, number = split_lmfdb_label(label) except AttributeError: return abort(404) info = {'p': p} if db.ec_curvedata.lookup(label, label_col='lmfdb_label', projection="rank") == 0: info['reg'] = 1 elif number == '1': data = db.ec_padic.lucky({'lmfdb_iso': N + '.' + iso, 'p': p}) if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("ec-padic-data.html", info=info)
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p N, iso, number = split_lmfdb_label(label) if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': data = db.ec_padic.lucky({'lmfdb_iso': N + '.' + iso, 'p': p}) if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = sage.all.Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("ec-padic-data.html", info=info)
def padic_data(): info = {} label = request.args['label'] p = int(request.args['p']) info['p'] = p N, iso, number = split_lmfdb_label(label) if request.args['rank'] == '0': info['reg'] = 1 elif number == '1': data = db.ec_padic.lucky({'lmfdb_iso': N + '.' + iso, 'p': p}) if data is None: info['reg'] = 'no data' else: val = int(data['val']) aprec = data['prec'] reg = Qp(p, aprec)(int(data['unit']), aprec - val) << val info['reg'] = web_latex(reg) else: info['reg'] = "no data" return render_template("ec-padic-data.html", info=info)
def padic_data(): info = {} label = request.args["label"] p = int(request.args["p"]) info["p"] = p N, iso, number = split_lmfdb_label(label) if request.args["rank"] == "0": info["reg"] = 1 elif number == "1": C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({"lmfdb_iso": N + "." + iso}) data = C.elliptic_curves.padic_db.find_one({"lmfdb_iso": N + "." + iso, "p": p}) info["data"] = data if data is None: info["reg"] = "no data" else: val = int(data["val"]) aprec = data["prec"] reg = sage.all.Qp(p, aprec)(int(data["unit"]), aprec - val) << val info["reg"] = web_latex(reg) else: info["reg"] = "no data" return render_template("padic_data.html", info=info)
def display_poly(coeffs): return web_latex(coeff_to_poly(coeffs))
def make_E(self): K = self.field.K() # a-invariants self.ainvs = parse_ainvs(K,self.ainvs) self.latex_ainvs = web_latex(self.ainvs) self.numb = str(self.number) # Conductor, discriminant, j-invariant N = ideal_from_string(K,self.conductor_ideal) self.cond = web_latex(N) self.cond_norm = web_latex(self.conductor_norm) local_data = self.local_data # NB badprimes is a list of primes which divide the # discriminant of this model. At most one of these might # actually be a prime of good reduction, if the curve has no # global minimal model. badprimes = [ideal_from_string(K,ld['p']) for ld in local_data] badnorms = [ZZ(ld['normp']) for ld in local_data] mindisc_ords = [ld['ord_disc'] for ld in local_data] # Assumption: the curve models stored in the database are # either global minimal models or minimal at all but one # prime, so the list here has length 0 or 1: self.non_min_primes = [ideal_from_string(K,P) for P in self.non_min_p] self.is_minimal = (len(self.non_min_primes) == 0) self.has_minimal_model = self.is_minimal disc_ords = [ld['ord_disc'] for ld in local_data] if not self.is_minimal: Pmin = self.non_min_primes[0] P_index = badprimes.index(Pmin) self.non_min_prime = web_latex(Pmin) disc_ords[P_index] += 12 if self.conductor_norm == 1: # since the factorization of (1) displays as "1" self.fact_cond = self.cond self.fact_cond_norm = self.cond else: Nfac = Factorization([(P,ld['ord_cond']) for P,ld in zip(badprimes,local_data)]) self.fact_cond = web_latex_ideal_fact(Nfac) Nnormfac = Factorization([(q,ld['ord_cond']) for q,ld in zip(badnorms,local_data)]) self.fact_cond_norm = web_latex(Nnormfac) # D is the discriminant ideal of the model D = prod([P**e for P,e in zip(badprimes,disc_ords)], K.ideal(1)) self.disc = web_latex(D) Dnorm = D.norm() self.disc_norm = web_latex(Dnorm) if Dnorm == 1: # since the factorization of (1) displays as "1" self.fact_disc = self.disc self.fact_disc_norm = self.disc else: Dfac = Factorization([(P,e) for P,e in zip(badprimes,disc_ords)]) self.fact_disc = web_latex_ideal_fact(Dfac) Dnormfac = Factorization([(q,e) for q,e in zip(badnorms,disc_ords)]) self.fact_disc_norm = web_latex(Dnormfac) if not self.is_minimal: Dmin = ideal_from_string(K,self.minD) self.mindisc = web_latex(Dmin) Dmin_norm = Dmin.norm() self.mindisc_norm = web_latex(Dmin_norm) if Dmin_norm == 1: # since the factorization of (1) displays as "1" self.fact_mindisc = self.mindisc self.fact_mindisc_norm = self.mindisc else: Dminfac = Factorization([(P,e) for P,edd in zip(badprimes,mindisc_ords)]) self.fact_mindisc = web_latex_ideal_fact(Dminfac) Dminnormfac = Factorization([(q,e) for q,e in zip(badnorms,mindisc_ords)]) self.fact_mindisc_norm = web_latex(Dminnormfac) j = self.field.parse_NFelt(self.jinv) # if j: # d = j.denominator() # n = d * j # numerator exists for quadratic fields only! # g = GCD(list(n)) # n1 = n / g # self.j = web_latex(n1) # if d != 1: # if n1 > 1: # # self.j = "("+self.j+")\(/\)"+web_latex(d) # self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d)) # else: # self.j = web_latex(d) # if g > 1: # if n1 > 1: # self.j = web_latex(g) + self.j # else: # self.j = web_latex(g) self.j = web_latex(j) self.fact_j = None # See issue 1258: some j factorizations work but take too long # (e.g. EllipticCurve/6.6.371293.1/1.1/a/1). Note that we do # store the factorization of the denominator of j and display # that, which is the most interesting part. # CM and End(E) self.cm_bool = "no" self.End = "\(\Z\)" if self.cm: self.cm_bool = "yes (\(%s\))" % self.cm if self.cm % 4 == 0: d4 = ZZ(self.cm) // 4 self.End = "\(\Z[\sqrt{%s}]\)" % (d4) else: self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm # The line below will need to change once we have curves over non-quadratic fields # that contain the Hilbert class field of an imaginary quadratic field if self.signature == [0,1] and ZZ(-self.abs_disc*self.cm).is_square(): self.ST = st_link_by_name(1,2,'U(1)') else: self.ST = st_link_by_name(1,2,'N(U(1))') else: self.ST = st_link_by_name(1,2,'SU(2)') # Q-curve / Base change self.qc = "no" try: if self.q_curve: self.qc = "yes" except AttributeError: # in case the db entry does not have this field set pass # Torsion self.ntors = web_latex(self.torsion_order) self.tr = len(self.torsion_structure) if self.tr == 0: self.tor_struct_pretty = "Trivial" if self.tr == 1: self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0] if self.tr == 2: self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure) torsion_gens = [parse_point(K,P) for P in self.torsion_gens] self.torsion_gens = ",".join([web_point(P) for P in torsion_gens]) # Rank or bounds try: self.rk = web_latex(self.rank) except AttributeError: self.rk = "?" try: self.rk_bnds = "%s...%s" % tuple(self.rank_bounds) except AttributeError: self.rank_bounds = [0, Infinity] self.rk_bnds = "not available" # Generators try: gens = [parse_point(K,P) for P in self.gens] self.gens = ", ".join([web_point(P) for P in gens]) if self.rk == "?": self.reg = "not available" else: if gens: try: self.reg = self.reg except AttributeError: self.reg = "not available" pass # self.reg already set else: self.reg = 1 # otherwise we only get 1.00000... except AttributeError: self.gens = "not available" self.reg = "not available" try: if self.rank == 0: self.reg = 1 except AttributeError: pass # Local data for P,ld in zip(badprimes,local_data): ld['p'] = web_latex(P) ld['norm'] = P.norm() ld['kod'] = web_latex(ld['kod']).replace('$', '') # URLs of self and related objects: self.urls = {} # It's useful to be able to use this class out of context, when calling url_for will fail: try: self.urls['curve'] = url_for(".show_ecnf", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number) except RuntimeError: return self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label) self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=quote(self.conductor_label)) self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label) sig = self.signature totally_real = sig[1] == 0 imag_quadratic = sig == [0,1] if totally_real: self.hmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label]) self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label) self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0') if imag_quadratic: self.bmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label]) self.friends = [] self.friends += [('Isogeny class ' + self.short_class_label, self.urls['class'])] self.friends += [('Twists', url_for('ecnf.index', field=self.field_label, jinv=rename_j(j)))] if totally_real: self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])] self.friends += [('L-function', self.urls['Lfunction'])] if imag_quadratic: self.friends += [('Bianchi Modular Form %s not available' % self.bmf_label, '')] self.properties = [ ('Base field', self.field.field_pretty()), ('Label', self.label)] # Plot if K.signature()[0]: self.plot = encode_plot(EC_nf_plot(K,self.ainvs, self.field.generator_name())) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties += [(None, self.plot_link)] self.properties += [ ('Conductor', self.cond), ('Conductor norm', self.cond_norm), # See issue #796 for why this is hidden (can be very large) # ('j-invariant', self.j), ('CM', self.cm_bool)] if self.base_change: self.properties += [('base-change', 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))] else: self.base_change = [] # in case it was False instead of [] self.properties += [('Q-curve', self.qc)] r = self.rk if r == "?": r = self.rk_bnds self.properties += [ ('Torsion order', self.ntors), ('Rank', r), ] for E0 in self.base_change: self.friends += [('Base-change of %s /\(\Q\)' % E0, url_for("ec.by_ec_label", label=E0))] self._code = None # will be set if needed by get_code()
def make_form(self): # To start with the data fields of self are just those from # the database. We need to reformat these and compute some # further (easy) data about it. # from lmfdb.ecnf.WebEllipticCurve import FIELD self.field = FIELD(self.field_label) pretty_field = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, pretty_field) try: dims = db.bmf_dims.lucky({'field_label':self.field_label, 'level_label':self.level_label}, projection='gl2_dims') self.newspace_dimension = dims[str(self.weight)]['new_dim'] except TypeError: self.newspace_dimension = 'not available' self.newspace_label = "-".join([self.field_label,self.level_label]) self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label) K = self.field.K() if self.dimension>1: Qx = PolynomialRing(QQ,'x') self.hecke_poly = Qx(str(self.hecke_poly)) F = NumberField(self.hecke_poly,'z') self.hecke_poly = web_latex(self.hecke_poly) def conv(ap): if '?' in ap: return 'not known' else: return F(str(ap)) self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs] self.nap = len(self.hecke_eigs) self.nap0 = min(50, self.nap) self.hecke_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])] level = ideal_from_label(K,self.level_label) self.level_ideal2 = web_latex(level) badp = level.prime_factors() self.have_AL = self.AL_eigs[0]!='?' if self.have_AL: self.AL_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(badp, self.AL_eigs)] self.sign = 'not determined' try: if self.sfe == 1: self.sign = "+1" elif self.sfe == -1: self.sign = "-1" except AttributeError: self.sfe = '?' if self.Lratio == '?': self.Lratio = "not determined" self.anrank = "not determined" else: self.Lratio = QQ(self.Lratio) self.anrank = "\(0\)" if self.Lratio!=0 else "odd" if self.sfe==-1 else "\(\ge2\), even" self.properties2 = [('Base field', pretty_field), ('Weight', str(self.weight)), ('Level norm', str(self.level_norm)), ('Level', self.level_ideal2), ('Label', self.label), ('Dimension', str(self.dimension)) ] try: if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' else: if self.CM%4 in [2,3]: self.CM = 4*self.CM except AttributeError: self.CM = 'not determined' self.properties2.append(('CM', str(self.CM))) self.bc_extra = '' self.bcd = 0 self.bct = self.bc!='?' and self.bc!=0 if self.bc == '?': self.bc = 'not determined' elif self.bc == 0: self.bc = 'no' elif self.bc == 1: self.bcd = self.bc self.bc = 'yes' elif self.bc >1: self.bcd = self.bc self.bc = 'yes' self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)' elif self.bc < -1: self.bcd = -self.bc self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' self.properties2.append(('Base-change', str(self.bc))) curve_bc = db.ec_nfcurves.lucky({'class_label':self.label}, projection="base_change") if curve_bc is not None: self.ec_status = 'exists' self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix) curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc] bc_urls = [url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) for cond, iso, num in curve_bc_parts] bc_labels = [".".join( [str(cond), str(2), 'a', iso] ) for cond,iso,_ in curve_bc_parts] bc_exists = [db.mf_newforms.label_exists(lab) for lab in bc_labels] self.bc_forms = [{'exists':ex, 'label':lab, 'url':url} for ex,lab,url in zip(bc_exists, bc_labels, bc_urls)] else: self.bc_forms = [] if self.bct: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties2.append(('Sign', self.sign)) self.properties2.append(('Analytic rank', self.anrank)) self.friends = [] self.friends += [('Newspace {}'.format(self.newspace_label),self.newspace_url)] url = 'ModularForm/GL2/ImaginaryQuadratic/{}'.format( self.label.replace('-', '/')) Lfun = get_lfunction_by_url(url) if Lfun: # first by Lhash instances = get_instances_by_Lhash(Lfun['Lhash']) # then by trace_hash instances += get_instances_by_trace_hash(Lfun['degree'], Lfun['trace_hash']) # This will also add the EC/G2C, as this how the Lfun was computed self.friends = names_and_urls(instances) # remove itself self.friends.remove( ('Bianchi modular form {}'.format(self.label), '/' + url)) self.friends.append(('L-function', '/L/'+url)) else: # old code if self.dimension == 1: if self.ec_status == 'exists': self.friends += [('Isogeny class {}'.format(self.label), self.ec_url)] elif self.ec_status == 'missing': self.friends += [('Isogeny class {} missing'.format(self.label), "")] else: self.friends += [('No elliptic curve', "")] self.friends += [ ('L-function not available','')]
def make_mwbsd(self): mwbsd = self.mwbsd = db.ec_mwbsd.lookup(self.lmfdb_label) # Some components are in the main table: mwbsd['analytic_rank'] = r = self.analytic_rank mwbsd['torsion'] = self.torsion tamagawa_numbers = [ld['tamagawa_number'] for ld in self.local_data] mwbsd['tamagawa_product'] = prod(tamagawa_numbers) if mwbsd['tamagawa_product'] > 1: cp_fac = [ZZ(cp).factor() for cp in tamagawa_numbers] cp_fac = [ latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')' for cp in cp_fac ] mwbsd['tamagawa_factors'] = r'\cdot'.join(cp_fac) else: mwbsd['tamagawa_factors'] = None try: mwbsd['rank'] = self.rank mwbsd['reg'] = self.regulator mwbsd['sha'] = self.sha mwbsd['sha2'] = latex_sha(self.sha) except AttributeError: mwbsd['rank'] = '?' mwbsd['reg'] = '?' mwbsd['sha'] = '?' mwbsd['sha2'] = '?' mwbsd['regsha'] = (mwbsd['special_value'] * self.torsion**2) / ( mwbsd['tamagawa_product'] * mwbsd['real_period']) if r <= 1: mwbsd['rank'] = r # Integral points xintcoords = mwbsd['xcoord_integral_points'] a1, _, a3, _, _ = ainvs = self.ainvs if a1 or a3: int_pts = sum([[(x, y) for y in make_y_coords(ainvs, x)] for x in xintcoords], []) mwbsd['int_points'] = raw_typeset( ', '.join(str(P) for P in int_pts), ', '.join(web_latex(P) for P in int_pts)) else: int_pts = [(x, make_y_coords(ainvs, x)[0]) for x in xintcoords] raw_form = sum([[P, (P[0], -P[1])] if P[1] else [P] for P in int_pts], []) raw_form = ', '.join(str(P) for P in raw_form) mwbsd['int_points'] = raw_typeset( raw_form, ', '.join(pm_pt(P) for P in int_pts)) # Generators (mod torsion) and heights: mwbsd['generators'] = [ raw_typeset(weighted_proj_to_affine_point(P)) for P in mwbsd['gens'] ] if mwbsd['ngens'] else '' # Torsion structure and generators: if mwbsd['torsion'] == 1: mwbsd['tor_struct'] = '' mwbsd['tor_gens'] = '' else: mwbsd['tor_struct'] = r' \times '.join( r'\Z/{%s}\Z' % n for n in self.torsion_structure) tor_gens_tmp = [ weighted_proj_to_affine_point(P) for P in mwbsd['torsion_generators'] ] mwbsd['tor_gens'] = raw_typeset( ', '.join(str(P) for P in tor_gens_tmp), ', '.join(web_latex(P) for P in tor_gens_tmp)) # BSD invariants if r >= 2: mwbsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r) elif r: mwbsd['lder_name'] = "L'(E,1)" else: mwbsd['lder_name'] = "L(E,1)"
def pm_pt(P): return r"\(({},\pm {})\)".format(P[0], P[1]) if P[1] else web_latex(P)
def make_passport_object(self, passport): from lmfdb.belyi.main import url_for_belyi_galmap_label # all information about the map 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 = {} for elt in ('plabel', 'abc', 'num_orbits', 'g', 'abc', 'deg', 'maxdegbf'): data[elt] = passport[elt] nt = passport['group'].split('T') data['group'] = group_display_knowl(int(nt[0]), int(nt[1]), getDBConnection()) data['geomtype'] = geomtypelet_to_geomtypename_dict[ passport['geomtype']] data['lambdas'] = [str(c)[1:-1] for c in passport['lambdas']] data['pass_size'] = passport['pass_size'] # Permutation triples galmaps_for_plabel = belyi_db_galmaps().find({ "plabel": passport['plabel'] }).sort([('label_index', ASCENDING)]) galmapdata = [] for galmap in galmaps_for_plabel: # wrap number field nonsense F = belyi_base_field(galmap) # inLMFDB = False; field = {} if F._data == None: field['in_LMFDB'] = False fld_coeffs = galmap['base_field'] pol = PolynomialRing(QQ, 'x')(fld_coeffs) field['base_field'] = latex(pol) field['isQQ'] = False else: field['in_LMFDB'] = True if F.poly().degree() == 1: field['isQQ'] = True F.latex_poly = web_latex(F.poly()) field['base_field'] = F galmapdatum = [ galmap['label'].split('-')[-1], url_for_belyi_galmap_label(galmap['label']), galmap['orbit_size'], field, galmap['triples_cyc'][0][0], galmap['triples_cyc'][0][1], galmap['triples_cyc'][0][2], ] galmapdata.append(galmapdatum) data['galmapdata'] = galmapdata # Properties properties = [('Label', passport['plabel']), ('Group', str(passport['group'])), ('Orders', str(passport['abc'])), ('Genus', str(passport['g'])), ('Size', str(passport['pass_size'])), ('Galois orbits', str(passport['num_orbits']))] self.properties = properties # Friends self.friends = [] # Breadcrumbs groupstr, abcstr, sigma0, sigma1, sigmaoo, gstr = data['plabel'].split( "-") lambdasstr = '%s-%s-%s' % (sigma0, sigma1, sigmaoo) lambdasgstr = lambdasstr + "-" + gstr self.bread = [('Belyi Maps', url_for(".index")), (groupstr, url_for(".by_url_belyi_search_group", group=groupstr)), (abcstr, url_for(".by_url_belyi_search_group_triple", group=groupstr, abc=abcstr)), (lambdasgstr, url_for(".by_url_belyi_passport_label", group=groupstr, abc=abcstr, sigma0=sigma0, sigma1=sigma1, sigmaoo=sigmaoo, g=gstr))] # Title self.title = "Passport " + data['plabel'] # Code snippets (only for curves) self.code = {} return
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 make_curve(self): # To start with the data fields of self are just those from # the database. We need to reformat these, construct the # actual elliptic curve E, and compute some further (easy) # data about it. # # Weierstrass equation data = self.data = {} data['ainvs'] = [int(ai) for ai in self.ainvs] self.E = EllipticCurve(data['ainvs']) data['equation'] = web_latex(self.E) # conductor, j-invariant and discriminant data['conductor'] = N = ZZ(self.conductor) bad_primes = N.prime_factors() try: data['j_invariant'] = QQ(str(self.jinv)) except KeyError: data['j_invariant'] = self.E.j_invariant() data['j_inv_factor'] = latex(0) if data['j_invariant']: data['j_inv_factor'] = latex(data['j_invariant'].factor()) data['j_inv_str'] = unicode(str(data['j_invariant'])) data['j_inv_latex'] = web_latex(data['j_invariant']) data['disc'] = D = self.E.discriminant() data['disc_latex'] = web_latex(data['disc']) data['disc_factor'] = latex(data['disc'].factor()) data['cond_factor'] =latex(N.factor()) data['cond_latex'] = web_latex(N) # CM and endomorphism ring data['CMD'] = self.cm data['CM'] = "no" data['EndE'] = "\(\Z\)" if self.cm: data['CM'] = "yes (\(D=%s\))" % data['CMD'] if data['CMD']%4==0: d4 = ZZ(data['CMD'])//4 data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4 else: data['EndE'] = "\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD'] # modular degree try: data['degree'] = self.degree except AttributeError: try: data['degree'] = self.E.modular_degree() except RuntimeError: data['degree'] # invalid, but will be displayed nicely # Minimal quadratic twist E_pari = self.E.pari_curve() from sage.libs.pari.all import PariError try: minq, minqD = self.E.minimal_quadratic_twist() except PariError: # this does occur with 164411a1 ec.debug("PariError computing minimal quadratic twist of elliptic curve %s" % lmfdb_label) minq = self.E minqD = 1 data['minq_D'] = minqD if self.E == minq: data['minq_label'] = self.lmfdb_label data['minq_info'] = '(itself)' else: minq_ainvs = [str(c) for c in minq.ainvs()] data['minq_label'] = db_ec().find_one({'ainvs': minq_ainvs})['lmfdb_label'] data['minq_info'] = '(by %s)' % minqD minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label']) # rational and integral points mw = self.mw = {} xintpoints_projective = [self.E.lift_x(x) for x in self.xintcoords] xintpoints = [P.xy() for P in xintpoints_projective] mw['int_points'] = ', '.join(web_latex(P) for P in xintpoints) # Generators of infinite order mw['rank'] = self.rank try: self.generators = [self.E(g) for g in parse_points(self.gens)] mw['generators'] = [web_latex(P.xy()) for P in self.generators] mw['heights'] = [P.height() for P in self.generators] except AttributeError: mw['generators'] = '' mw['heights'] = [] # Torsion subgroup: order, structure, generators mw['tor_order'] = self.torsion tor_struct = [int(c) for c in self.torsion_structure] if mw['tor_order'] == 1: mw['tor_struct'] = '\mathrm{Trivial}' mw['tor_gens'] = '' else: mw['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct]) mw['tor_gens'] = ', '.join(web_latex(self.E(g).xy()) for g in parse_points(self.torsion_generators)) # Images of Galois representations try: data['galois_images'] = [trim_galois_image_code(s) for s in self.galois_images] data['non_surjective_primes'] = self.non_surjective_primes except AttributeError: #print "No Galois image data" data['galois_images'] = [] data['non_surjective_primes'] = [] data['galois_data'] = [{'p': p,'image': im } for p,im in zip(data['non_surjective_primes'], data['galois_images'])] if self.twoadic_gens: from sage.matrix.all import Matrix data['twoadic_gen_matrices'] = ','.join([latex(Matrix(2,2,M)) for M in self.twoadic_gens]) data['twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html" # Leading term of L-function & BSD data bsd = self.bsd = {} r = self.rank if r >= 2: bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r,r) elif r: bsd['lder_name'] = "L'(E,1)" else: bsd['lder_name'] = "L(E,1)" bsd['reg'] = self.regulator bsd['omega'] = self.real_period bsd['sha'] = int(0.1+self.sha_an) bsd['lder'] = self.special_value # Optimality (the optimal curve in the class is the curve # whose Cremona label ends in '1' except for '990h' which was # labelled wrongly long ago) if self.iso == '990h': data['Gamma0optimal'] = bool(self.number == 3) else: data['Gamma0optimal'] = bool(self.number == 1) data['p_adic_data_exists'] = False if data['Gamma0optimal']: data['p_adic_data_exists'] = (padic_db().find({'lmfdb_iso': self.lmfdb_iso}).count()) > 0 data['p_adic_primes'] = [p for p in sage.all.prime_range(5, 100) if self.E.is_ordinary(p) and not p.divides(N)] # Local data local_data = self.local_data = [] # if we use E.tamagawa_numbers() it calls E.local_data(p) which # used to crash on some curves e.g. 164411a1 tamagawa_numbers = [] for p in bad_primes: local_info = self.E.local_data(p, algorithm="generic") local_data_p = {} local_data_p['p'] = p local_data_p['tamagawa_number'] = local_info.tamagawa_number() tamagawa_numbers.append(ZZ(local_info.tamagawa_number())) local_data_p['kodaira_symbol'] = web_latex(local_info.kodaira_symbol()).replace('$', '') local_data_p['reduction_type'] = local_info.bad_reduction_type() local_data_p['ord_cond'] = local_info.conductor_valuation() local_data_p['ord_disc'] = local_info.discriminant_valuation() local_data_p['ord_den_j'] = max(0,-self.E.j_invariant().valuation(p)) local_data.append(local_data_p) if len(bad_primes)>1: bsd['tamagawa_factors'] = r' \cdot '.join(str(c.factor()) for c in tamagawa_numbers) else: bsd['tamagawa_factors'] = '' bsd['tamagawa_product'] = sage.misc.all.prod(tamagawa_numbers) cond, iso, num = split_lmfdb_label(self.lmfdb_label) data['newform'] = web_latex(self.E.q_eigenform(10)) self.make_code_snippets() self.friends = [ ('Isogeny class ' + self.lmfdb_iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)), ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_triple_label", conductor=minq_N, iso_label=minq_iso, number=minq_number)), ('All twists ', url_for(".rational_elliptic_curves", jinv=self.jinv)), ('L-function', url_for("l_functions.l_function_ec_page", label=self.lmfdb_label)), ('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso)), ('Symmetric 4th power L-function', url_for("l_functions.l_function_ec_sym_page", power='4', label=self.lmfdb_iso)), ('Modular form ' + self.lmfdb_iso.replace('.', '.2'), url_for("emf.render_elliptic_modular_forms", level=int(N), weight=2, character=0, label=iso))] self.downloads = [('Download coeffients of q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=100)), ('Download all stored data', url_for(".download_EC_all", label=self.lmfdb_label))] self.plot = encode_plot(self.E.plot()) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = [('Label', self.lmfdb_label), (None, self.plot_link), ('Conductor', '\(%s\)' % data['conductor']), ('Discriminant', '\(%s\)' % data['disc']), ('j-invariant', '%s' % data['j_inv_latex']), ('CM', '%s' % data['CM']), ('Rank', '\(%s\)' % mw['rank']), ('Torsion Structure', '\(%s\)' % mw['tor_struct']) ] self.title = "Elliptic Curve %s (Cremona label %s)" % (self.lmfdb_label, self.label) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)), ('%s' % num,' ')]
def render_field_webpage(args): data = None C = base.getDBConnection() info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] # This function should not be called unless label is set. label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(('Search results', ' ')) info['err'] = 'There is no field with label %s in the database' % label info['label'] = args['label_orig'] if 'label_orig' in args else args['label'] return search_input_error(info, bread) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() if len(dirichlet_chars)>0: data['dirichlet_group'] = ['<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for('characters.render_Dirichletwebpage',modulus=data['conductor'], number=j), data['conductor'], j) for j in dirichlet_chars] data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), latex(data['conductor'].factor())) data['galois_group'] = group_display_knowl(n, t, C) data['cclasses'] = cclasses_display_knowl(n, t, C) data['character_table'] = character_table_display_knowl(n, t, C) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() data['coefficients'] = nf.coeffs() nf.make_code_snippets() D = nf.disc() ram_primes = D.prime_factors() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) npr = len(ram_primes) ram_primes = str(ram_primes)[1:-1] if ram_primes == '': ram_primes = r'\textrm{None}' data['frob_data'], data['seeram'] = frobs(nf) data['phrase'] = group_phrase(n, t, C) zk = nf.zk() Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else '' # Short version for properties grh_lab = nf.short_grh_string() if 'Not' in str(data['class_number']): grh_lab='' grh_label='' pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) if nf.degree() > 1: gpK = nf.gpK() rootof1coeff = gpK.nfrootsof1()[2] rootofunity = Ra(str(pari("lift(%s)" % gpK.nfbasistoalg(rootof1coeff))).replace('x','a')) else: rootofunity = Ra('-1') info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(nf.poly()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': web_latex(rootofunity), 'fund_units': nf.units(), 'grh_label': grh_label }) bread.append(('%s' % info['label_raw'], ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): # hide ones that take a lond time to compute on the fly # note that the first degree 4 number field missed the zero of the zeta function if abs(D**n) < 50000000: info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet group', url_for("characters.dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( [str(a) for a in dirichlet_chars]), poly=info['polynomial']))) info['learnmore'] = [('Global number field labels', url_for( ".render_labels_page")), (Completename, url_for(".render_discriminants_page")), ('How data was computed', url_for(".how_computed_page"))] if info['signature'] == [0,1]: info['learnmore'].append(('Quadratic imaginary class groups', url_for(".render_class_group_data"))) # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' properties2 = [('Label', label), ('Degree', '%s' % data['degree']), ('Signature', '$%s$' % data['signature']), ('Discriminant', '$%s$' % data['disc_factor']), ('Ramified ' + primes + '', '$%s$' % ram_primes), ('Class number', '%s %s' % (data['class_number'], grh_lab)), ('Class group', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois Group', group_display_short(data['degree'], t, C)) ] from lmfdb.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs']) v = nf.factor_perm_repn(info["tim_number_field"]) def dopow(m): if m==0: return '' if m==1: return '*' return '*<sup>%d</sup>'% m info["mydecomp"] = [dopow(x) for x in v] except AttributeError: pass # del info['_id'] return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, code=nf.code, friends=info.pop('friends'), learnmore=info.pop('learnmore'), info=info)
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 make_E(self): coeffs = self.ainvs # list of 5 lists of d strings self.ainvs = [self.field.parse_NFelt(x) for x in coeffs] self.latex_ainvs = web_latex(self.ainvs) from sage.schemes.elliptic_curves.all import EllipticCurve self.E = E = EllipticCurve(self.ainvs) self.equn = web_latex(E) self.numb = str(self.number) # Conductor, discriminant, j-invariant N = E.conductor() self.cond = web_latex(N) self.cond_norm = web_latex(N.norm()) if N.norm()==1: # since the factorization of (1) displays as "1" self.fact_cond = self.cond else: self.fact_cond = web_latex_ideal_fact(N.factor()) self.fact_cond_norm = web_latex(N.norm().factor()) D = self.field.K().ideal(E.discriminant()) self.disc = web_latex(D) self.disc_norm = web_latex(D.norm()) if D.norm()==1: # since the factorization of (1) displays as "1" self.fact_disc = self.disc else: self.fact_disc = web_latex_ideal_fact(D.factor()) self.fact_disc_norm = web_latex(D.norm().factor()) # Minimal model? # # All curves in the database should be given # by models which are globally minimal if possible, else # minimal at all but one prime. But we do not rely on this # here, and the display should be correct if either (1) there # exists a global minimal model but this model is not; or (2) # this model is non-minimal at more than one prime. # self.non_min_primes = non_minimal_primes(E) self.is_minimal = (len(self.non_min_primes)==0) self.has_minimal_model = True if not self.is_minimal: self.non_min_prime = ','.join([web_latex(P) for P in self.non_min_primes]) self.has_minimal_model = has_global_minimal_model(E) if not self.is_minimal: Dmin = minimal_discriminant_ideal(E) self.mindisc = web_latex(Dmin) self.mindisc_norm = web_latex(Dmin.norm()) if Dmin.norm()==1: # since the factorization of (1) displays as "1" self.fact_mindisc = self.mindisc else: self.fact_mindisc = web_latex_ideal_fact(Dmin.factor()) self.fact_mindisc_norm = web_latex(Dmin.norm().factor()) j = E.j_invariant() if j: d = j.denominator() n = d*j # numerator exists for quadratic fields only! g = GCD(list(n)) n1 = n/g self.j = web_latex(n1) if d!=1: if n1>1: #self.j = "("+self.j+")\(/\)"+web_latex(d) self.j = web_latex(r"\frac{%s}{%s}" % (self.j,d)) else: self.j = web_latex(d) if g>1: if n1>1: self.j = web_latex(g) + self.j else: self.j = web_latex(g) self.j = web_latex(j) self.fact_j = None if j.is_zero(): self.fact_j = web_latex(j) else: try: self.fact_j = web_latex(j.factor()) except (ArithmeticError,ValueError): # if not all prime ideal factors principal pass # CM and End(E) self.cm_bool = "no" self.End = "\(\Z\)" if self.cm: self.cm_bool = "yes (\(%s\))" % self.cm if self.cm%4==0: d4 = ZZ(self.cm)//4 self.End = "\(\Z[\sqrt{%s}]\)"%(d4) else: self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm # Q-curve / Base change self.qc = "no" try: if self.q_curve: self.qc = "yes" except AttributeError: # in case the db entry does not have this field set pass # Torsion self.ntors = web_latex(self.torsion_order) self.tr = len(self.torsion_structure) if self.tr==0: self.tor_struct_pretty = "Trivial" if self.tr==1: self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0] if self.tr==2: self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure) torsion_gens = [E([self.field.parse_NFelt(x) for x in P]) for P in self.torsion_gens] self.torsion_gens = ",".join([web_latex(P) for P in torsion_gens]) # Rank etc try: self.rk = web_latex(self.rank) except AttributeError: self.rk = "not recorded" # if rank in self: # self.r = web_latex(self.rank) # Local data self.local_data = [] for p in N.prime_factors(): self.local_info = E.local_data(p, algorithm="generic") self.local_data.append({'p': web_latex(p), 'norm': web_latex(p.norm().factor()), 'tamagawa_number': self.local_info.tamagawa_number(), 'kodaira_symbol': web_latex(self.local_info.kodaira_symbol()).replace('$', ''), 'reduction_type': self.local_info.bad_reduction_type(), 'ord_den_j': max(0,-E.j_invariant().valuation(p)), 'ord_mindisc': self.local_info.discriminant_valuation() }) # URLs of self and related objects: self.urls = {} self.urls['curve'] = url_for(".show_ecnf", nf = self.field_label, conductor_label=self.conductor_label, class_label = self.iso_label, number = self.number) self.urls['class'] = url_for(".show_ecnf_isoclass", nf = self.field_label, conductor_label=self.conductor_label, class_label = self.iso_label) self.urls['conductor'] = url_for(".show_ecnf_conductor", nf = self.field_label, conductor_label=self.conductor_label) self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label) if self.field.is_real_quadratic(): self.hmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label]) self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label) if self.field.is_imag_quadratic(): self.bmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label]) self.friends = [] self.friends += [('Isogeny class '+self.short_class_label, self.urls['class'])] self.friends += [('Twists',url_for('ecnf.index',field_label=self.field_label,jinv=self.jinv))] if self.field.is_real_quadratic(): self.friends += [('Hilbert Modular Form '+self.hmf_label, self.urls['hmf'])] if self.field.is_imag_quadratic(): self.friends += [('Bianchi Modular Form %s not yet available' % self.bmf_label, '')] self.properties = [ ('Base field', self.field.field_pretty()), ('Label' , self.label)] # Plot if E.base_field().signature()[0]: self.plot = encode_plot(EC_nf_plot(E,self.field.generator_name())) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties += [(None, self.plot_link)] self.properties += [ ('Conductor' , self.cond), ('Conductor norm' , self.cond_norm), ('j-invariant' , self.j), ('CM' , self.cm_bool)] if self.base_change: self.properties += [('base-change', 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))] else: self.base_change = [] # in case it was False instead of [] self.properties += [('Q-curve' , self.qc)] self.properties += [ ('Torsion order' , self.ntors), ('Rank' , self.rk), ] for E0 in self.base_change: self.friends += [('Base-change of %s /\(\Q\)' % E0 , url_for("ec.by_ec_label", label=E0))]
def render_field_webpage(args): data = None C = base.getDBConnection() info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] if 'label' in args: label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(('Search results', ' ')) label2 = re.sub(r'[<>]', '', args['label']) if 'You need to enter a field' in label2: info['err'] = label2 else: info['err'] = 'No such field: %s in the database' % label2 info['label'] = args['label_orig'] if 'label_orig' in args else args['label'] return search_input_error(info, bread) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() data['dirichlet_group'] = ['<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for("render_Character", arg1=data['conductor'], arg2=j), data['conductor'], j) for j in dirichlet_chars] data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), latex(data['conductor'].factor())) data['galois_group'] = group_display_knowl(n, t, C) data['cclasses'] = cclasses_display_knowl(n, t, C) data['character_table'] = character_table_display_knowl(n, t, C) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() D = nf.disc() ram_primes = D.prime_factors() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) npr = len(ram_primes) ram_primes = str(ram_primes)[1:-1] if ram_primes == '': ram_primes = r'\textrm{None}' data['frob_data'], data['seeram'] = frobs(nf.K()) data['phrase'] = group_phrase(n, t, C) zk = pari(nf.K()).nf_subst('a') zk = list(zk.nf_get_zk()) Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else '' # Short version for properties grh_lab = nf.short_grh_string() pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(nf.K().defining_polynomial()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': web_latex(nf.K().primitive_root_of_unity()), 'fund_units': nf.units(), 'grh_label': grh_label }) bread.append(('%s' % info['label_raw'], ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet group', url_for("dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( [str(a) for a in dirichlet_chars]), poly=info['polynomial']))) info['learnmore'] = [('Global number field labels', url_for( ".render_labels_page")), (Completename, url_for(".render_discriminants_page"))] # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' properties2 = [('Degree:', '%s' % data['degree']), ('Signature:', '$%s$' % data['signature']), ('Discriminant:', '$%s$' % data['disc_factor']), ('Ramified ' + primes + ':', '$%s$' % ram_primes), ('Class number:', '%s %s' % (data['class_number'], grh_lab)), ('Class group:', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois Group:', group_display_short(data['degree'], t, C)) ] from lmfdb.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup.find_one({"label": label}) v = nf.factor_perm_repn(info["tim_number_field"]) info["mydecomp"] = ['*' if x>0 else '' for x in v] except AttributeError: pass # del info['_id'] return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, friends=info.pop('friends'), learnmore=info.pop('learnmore'), info=info)
def render_field_webpage(args): data = None info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] # This function should not be called unless label is set. label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(('Search Results', ' ')) info['err'] = 'There is no field with label %s in the database' % label info['label'] = args['label_orig'] if 'label_orig' in args else args['label'] return search_input_error(info, bread) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number_latex() ram_primes = nf.ramified_primes() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() if len(dirichlet_chars)>0: data['dirichlet_group'] = ['<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for('characters.render_Dirichletwebpage',modulus=data['conductor'], number=j), data['conductor'], j) for j in dirichlet_chars] data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: factored_conductor = factor_base_factor(data['conductor'], ram_primes) factored_conductor = factor_base_factorization_latex(factored_conductor) data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), factored_conductor) data['galois_group'] = group_display_knowl(n, t) data['cclasses'] = cclasses_display_knowl(n, t) data['character_table'] = character_table_display_knowl(n, t) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() data['coefficients'] = nf.coeffs() nf.make_code_snippets() D = nf.disc() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) data['frob_data'], data['seeram'] = frobs(nf) # Bad prime information npr = len(ram_primes) ramified_algebras_data = nf.ramified_algebras_data() if isinstance(ramified_algebras_data,str): loc_alg = '' else: # [label, latex, e, f, c, gal] loc_alg = '' for j in range(npr): if ramified_algebras_data[j] is None: loc_alg += '<tr><td>%s<td colspan="7">Data not computed'%str(ram_primes[j]) else: mydat = ramified_algebras_data[j] p = ram_primes[j] loc_alg += '<tr><td rowspan="%d">$%s$</td>'%(len(mydat),str(p)) mm = mydat[0] myurl = url_for('local_fields.by_label', label=mm[0]) lab = mm[0] if mm[3]*mm[2]==1: lab = r'$\Q_{%s}$'%str(p) loc_alg += '<td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$'%(myurl,lab,mm[1],mm[2],mm[3],mm[4],mm[5],show_slope_content(mm[8],mm[6],mm[7])) for mm in mydat[1:]: lab = mm[0] if mm[3]*mm[2]==1: lab = r'$\Q_{%s}$'%str(p) loc_alg += '<tr><td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$'%(myurl,lab,mm[1],mm[2],mm[3],mm[4],mm[5],show_slope_content(mm[8],mm[6],mm[7])) loc_alg += '</tbody></table>' ram_primes = str(ram_primes)[1:-1] if ram_primes == '': ram_primes = r'\textrm{None}' data['phrase'] = group_phrase(n, t) zk = nf.zk() Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else '' # Short version for properties grh_lab = nf.short_grh_string() if 'Not' in str(data['class_number']): grh_lab='' grh_label='' pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) if nf.degree() > 1: gpK = nf.gpK() rootof1coeff = gpK.nfrootsof1() rootofunityorder = int(rootof1coeff[1]) rootof1coeff = rootof1coeff[2] rootofunity = web_latex(Ra(str(pari("lift(%s)" % gpK.nfbasistoalg(rootof1coeff))).replace('x','a'))) rootofunity += ' (order $%d$)' % rootofunityorder else: rootofunity = web_latex(Ra('-1'))+ ' (order $2$)' info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(nf.poly()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': rootofunity, 'fund_units': nf.units(), 'grh_label': grh_label, 'loc_alg': loc_alg }) bread.append(('%s' % info['label_raw'], ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): # hide ones that take a lond time to compute on the fly # note that the first degree 4 number field missed the zero of the zeta function if abs(D**n) < 50000000: info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet character group', url_for("characters.dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( [str(a) for a in dirichlet_chars]), poly=info['polynomial']))) resinfo=[] galois_closure = nf.galois_closure() if galois_closure[0]>0: if len(galois_closure[1])>0: resinfo.append(('gc', galois_closure[1])) if len(galois_closure[2]) > 0: info['friends'].append(('Galois closure',url_for(".by_label", label=galois_closure[2][0]))) else: resinfo.append(('gc', [dnc])) sextic_twins = nf.sextic_twin() if sextic_twins[0]>0: if len(sextic_twins[1])>0: resinfo.append(('sex', r' $\times$ '.join(sextic_twins[1]))) else: resinfo.append(('sex', dnc)) siblings = nf.siblings() # [degsib list, label list] # first is list of [deg, num expected, list of knowls] if len(siblings[0])>0: for sibdeg in siblings[0]: if len(sibdeg[2]) ==0: sibdeg[2] = dnc else: sibdeg[2] = ', '.join(sibdeg[2]) if len(sibdeg[2])<sibdeg[1]: sibdeg[2] += ', some '+dnc resinfo.append(('sib', siblings[0])) for lab in siblings[1]: if lab != '': labparts = lab.split('.') info['friends'].append(("Degree %s sibling"%labparts[0] ,url_for(".by_label", label=lab))) arith_equiv = nf.arith_equiv() if arith_equiv[0]>0: if len(arith_equiv[1])>0: resinfo.append(('ae', ', '.join(arith_equiv[1]), len(arith_equiv[1]))) for aelab in arith_equiv[2]: info['friends'].append(('Arithmetically equivalent sibling',url_for(".by_label", label=aelab))) else: resinfo.append(('ae', dnc, len(arith_equiv[1]))) info['resinfo'] = resinfo learnmore = learnmore_list() #if info['signature'] == [0,1]: # info['learnmore'].append(('Quadratic imaginary class groups', url_for(".render_class_group_data"))) # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' properties2 = [('Label', label), ('Degree', '$%s$' % data['degree']), ('Signature', '$%s$' % data['signature']), ('Discriminant', '$%s$' % data['disc_factor']), ('Ramified ' + primes + '', '$%s$' % ram_primes), ('Class number', '%s %s' % (data['class_number'], grh_lab)), ('Class group', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois Group', group_display_short(data['degree'], t)) ] downloads = [] for lang in [["Magma","magma"], ["SageMath","sage"], ["Pari/GP", "gp"]]: downloads.append(('Download {} code'.format(lang[0]), url_for(".nf_code_download", nf=label, download_type=lang[1]))) from lmfdb.artin_representations.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs']) v = nf.factor_perm_repn(info["tim_number_field"]) def dopow(m): if m==0: return '' if m==1: return '*' return '*<sup>%d</sup>'% m info["mydecomp"] = [dopow(x) for x in v] except AttributeError: pass return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, code=nf.code, friends=info.pop('friends'), downloads=downloads, learnmore=learnmore, info=info)
def make_curve(self): # To start with the data fields of self are just those from # the database. We need to reformat these. # Old version: required constructing the actual elliptic curve # E, and computing some further data about it. # New version (May 2016): extra data fields now in the # database so we do not have to construct the curve or do any # computation with it on the fly. As a failsafe the old way # is still included. data = self.data = {} data['ainvs'] = [ZZ(ai) for ai in self.ainvs] data['conductor'] = N = ZZ(self.conductor) data['j_invariant'] = QQ(str(self.jinv)) data['j_inv_factor'] = latex(0) if data['j_invariant']: # don't factor 0 data['j_inv_factor'] = latex(data['j_invariant'].factor()) data['j_inv_str'] = unicode(str(data['j_invariant'])) data['j_inv_latex'] = web_latex(data['j_invariant']) # extract data about MW rank, generators, heights and torsion: self.make_mw() # get more data from the database entry data['equation'] = self.equation local_data = self.local_data D = self.signD * prod([ld['p']**ld['ord_disc'] for ld in local_data]) for ld in local_data: ld['kod'] = ld['kod'].replace("\\\\", "\\") data['disc'] = D Nfac = Factorization([(ZZ(ld['p']), ld['ord_cond']) for ld in local_data]) Dfac = Factorization([(ZZ(ld['p']), ld['ord_disc']) for ld in local_data], unit=ZZ(self.signD)) data['minq_D'] = minqD = self.min_quad_twist['disc'] data['minq_label'] = self.min_quad_twist[ 'lmfdb_label'] if self.label_type == 'LMFDB' else self.min_quad_twist[ 'label'] data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format( minqD) if self.degree is None: data['degree'] = 0 # invalid, but will be displayed nicely else: data['degree'] = self.degree try: data['an'] = self.anlist data['ap'] = self.aplist except AttributeError: r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1}) data['an'] = r['anlist'] data['ap'] = r['aplist'] data['disc_factor'] = latex(Dfac) data['cond_factor'] = latex(Nfac) data['disc_latex'] = web_latex(D) data['cond_latex'] = web_latex(N) data['galois_images'] = [ trim_galois_image_code(s) for s in self.mod_p_images ] data['non_maximal_primes'] = self.non_maximal_primes data['galois_data'] = [{ 'p': p, 'image': im } for p, im in zip(data['non_maximal_primes'], data['galois_images'])] data['CMD'] = self.cm data['CM'] = "no" data['EndE'] = "\(\Z\)" if self.cm: data['cm_ramp'] = [ p for p in ZZ(self.cm).support() if not p in self.non_maximal_primes ] data['cm_nramp'] = len(data['cm_ramp']) if data['cm_nramp'] == 1: data['cm_ramp'] = data['cm_ramp'][0] else: data['cm_ramp'] = ", ".join([str(p) for p in data['cm_ramp']]) data['cm_sqf'] = ZZ(self.cm).squarefree_part() data['CM'] = "yes (\(D=%s\))" % data['CMD'] if data['CMD'] % 4 == 0: d4 = ZZ(data['CMD']) // 4 data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4 else: data['EndE'] = "\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD'] data['ST'] = st_link_by_name(1, 2, 'N(U(1))') else: data['ST'] = st_link_by_name(1, 2, 'SU(2)') data['p_adic_primes'] = [ p for i, p in enumerate(prime_range(5, 100)) if (N * data['ap'][i]) % p != 0 ] cond, iso, num = split_lmfdb_label(self.lmfdb_label) self.one_deg = ZZ(self.class_deg).is_prime() isodegs = [str(d) for d in self.isogeny_degrees if d > 1] if len(isodegs) < 3: data['isogeny_degrees'] = " and ".join(isodegs) else: data['isogeny_degrees'] = " and ".join( [", ".join(isodegs[:-1]), isodegs[-1]]) if self.twoadic_gens: from sage.matrix.all import Matrix data['twoadic_gen_matrices'] = ','.join( [latex(Matrix(2, 2, M)) for M in self.twoadic_gens]) data[ 'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html" # Leading term of L-function & other BSD data self.make_bsd() # Optimality (the optimal curve in the class is the curve # whose Cremona label ends in '1' except for '990h' which was # labelled wrongly long ago): this is proved for N up to # OPTIMALITY_BOUND (and when there is only one curve in an # isogeny class, obviously) and expected for all N. # Column 'optimality' is 1 for certainly optimal curves, 0 for # certainly non-optimal curves, and is n>1 if the curve is one # of n in the isogeny class which may be optimal given current # knowledge. # Column "manin_constant' is the correct Manin constant # assuming that the optimal curve in the class is known, or # otherwise if it is the curve with (Cremona) number 1. # The code here allows us to update the display correctly by # changing one line in this file (defining OPTIMALITY_BOUND) # without changing the data. data['optimality_bound'] = OPTIMALITY_BOUND data[ 'manin_constant'] = self.manin_constant # (conditional on data['optimality_known']) if N < OPTIMALITY_BOUND: data['optimality_code'] = int( self.number == (3 if self.iso == '990h' else 1)) data['optimality_known'] = True data['manin_known'] = True if self.label_type == 'Cremona': data[ 'optimal_label'] = '990h3' if self.iso == '990h' else self.iso + '1' else: data[ 'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1' else: data['optimality_code'] = self.optimality data['optimality_known'] = (self.optimality < 2) if self.optimality == 1: data['manin_known'] = True data[ 'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label else: if self.number == 1: data['manin_known'] = False data[ 'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label else: # find curve #1 in this class and its optimailty code: opt_curve = db.ec_curves.lucky( { 'iso': self.iso, 'number': 1 }, projection=['label', 'lmfdb_label', 'optimality']) data['manin_known'] = (opt_curve['optimality'] == 1) data['optimal_label'] = opt_curve[ 'label' if self.label_type == 'Cremona' else 'lmfdb_label'] data['p_adic_data_exists'] = False if data['optimality_code'] == 1: data['p_adic_data_exists'] = db.ec_padic.exists( {'lmfdb_iso': self.lmfdb_iso}) # Iwasawa data (where present) self.make_iwasawa() # Torsion growth data (where present) self.make_torsion_growth() data['newform'] = web_latex( PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)) data['newform_label'] = self.newform_label = ".".join( [str(cond), str(2), 'a', iso]) self.newform_link = url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) self.newform_exists_in_db = db.mf_newforms.label_exists( self.newform_label) self._code = None if self.label_type == 'Cremona': self.class_url = url_for(".by_ec_label", label=self.iso) self.class_name = self.iso else: self.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso) self.class_name = self.lmfdb_iso data['class_name'] = self.class_name data['number'] = self.number self.friends = [('Isogeny class ' + self.class_name, self.class_url), ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_ec_label", label=data['minq_label'])), ('All twists ', url_for(".rational_elliptic_curves", jinv=self.jinv))] lfun_url = url_for("l_functions.l_function_ec_page", conductor_label=N, isogeny_class_label=iso) origin_url = lfun_url.lstrip('/L/').rstrip('/') if db.lfunc_instances.exists({'url': origin_url}): self.friends += [('L-function', lfun_url)] else: self.friends += [('L-function not available', "")] if not self.cm: if N <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=N, isogeny=iso))] if N <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=N, isogeny=iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.lmfdb_label)), ('Code to Magma', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')), ('Code to SageMath', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')), ('Code to GP', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='gp'))] try: self.plot = encode_plot(self.E.plot()) except AttributeError: self.plot = encode_plot(EllipticCurve(data['ainvs']).plot()) self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format( self.plot) self.properties = [ ('Label', self.label if self.label_type == 'Cremona' else self.lmfdb_label), (None, self.plot_link), ('Conductor', '%s' % data['conductor']), ('Discriminant', '%s' % data['disc']), ('j-invariant', '%s' % data['j_inv_latex']), ('CM', '%s' % data['CM']), ('Rank', '%s' % self.mw['rank']), ('Torsion Structure', '\(%s\)' % self.mw['tor_struct']) ] if self.label_type == 'Cremona': self.title = "Elliptic Curve with Cremona label {} (LMFDB label {})".format( self.label, self.lmfdb_label) else: self.title = "Elliptic Curve with LMFDB label {} (Cremona label {})".format( self.lmfdb_label, self.label) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)), ('%s' % num, ' ')]
def make_form(self): # To start with the data fields of self are just those from # the database. We need to reformat these and compute some # further (easy) data about it. # from lmfdb.ecnf.WebEllipticCurve import FIELD self.field = FIELD(self.field_label) pretty_field = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, getDBConnection(), pretty_field) try: dims = db_dims().find_one({'field_label':self.field_label, 'level_label':self.level_label})['gl2_dims'] self.newspace_dimension = dims[str(self.weight)]['new_dim'] except TypeError: self.newspace_dimension = 'not available' self.newspace_label = "-".join([self.field_label,self.level_label]) self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label) K = self.field.K() if self.dimension>1: Qx = PolynomialRing(QQ,'x') self.hecke_poly = Qx(str(self.hecke_poly)) F = NumberField(self.hecke_poly,'z') self.hecke_poly = web_latex(self.hecke_poly) def conv(ap): if '?' in ap: return 'not known' else: return F(str(ap)) self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs] self.nap = len(self.hecke_eigs) self.nap0 = min(50, self.nap) self.hecke_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])] level = ideal_from_label(K,self.level_label) self.level_ideal2 = web_latex(level) badp = level.prime_factors() self.have_AL = self.AL_eigs[0]!='?' if self.have_AL: self.AL_table = [[web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap)] for p,ap in zip(badp, self.AL_eigs)] self.sign = 'not determined' if self.sfe == 1: self.sign = "+1" elif self.sfe == -1: self.sign = "-1" if self.Lratio == '?': self.Lratio = "not determined" self.anrank = "not determined" else: self.Lratio = QQ(self.Lratio) self.anrank = "\(0\)" if self.Lratio!=0 else "odd" if self.sfe==-1 else "\(\ge2\), even" self.properties2 = [('Base field', pretty_field), ('Weight', str(self.weight)), ('Level norm', str(self.level_norm)), ('Level', self.level_ideal2), ('Label', self.label), ('Dimension', str(self.dimension)) ] if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' self.properties2.append(('CM', str(self.CM))) self.bc_extra = '' self.bcd = 0 self.bct = self.bc!='?' and self.bc!=0 if self.bc == '?': self.bc = 'not determined' elif self.bc == 0: self.bc = 'no' elif self.bc == 1: self.bcd = self.bc self.bc = 'yes' elif self.bc >1: self.bcd = self.bc self.bc = 'yes' self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)' elif self.bc < -1: self.bcd = -self.bc self.bc = 'no' self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' self.properties2.append(('Base-change', str(self.bc))) curve = db_ecnf().find_one({'class_label':self.label}) if curve: self.ec_status = 'exists' self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix) curve_bc = curve['base_change'] curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc] bc_urls = [url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso) for cond, iso, num in curve_bc_parts] bc_labels = [newform_label(cond,2,1,iso) for cond,iso,num in curve_bc_parts] bc_exists = [is_newform_in_db(lab) for lab in bc_labels] self.bc_forms = [{'exists':ex, 'label':lab, 'url':url} for ex,lab,url in zip(bc_exists, bc_labels, bc_urls)] else: self.bc_forms = [] if self.bct: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties2.append(('Sign', self.sign)) self.properties2.append(('Analytic rank', self.anrank)) self.friends = [] if self.dimension==1: if self.ec_status == 'exists': self.friends += [('Elliptic curve isogeny class {}'.format(self.label), self.ec_url)] elif self.ec_status == 'missing': self.friends += [('Elliptic curve {} missing'.format(self.label), "")] else: self.friends += [('No elliptic curve', "")] self.friends += [ ('Newspace {}'.format(self.newspace_label),self.newspace_url)] self.friends += [ ('L-function not available','')]
def web_ainvs(field_label, ainvs): K = make_field(field_label).K() return web_latex(parse_ainvs(K,ainvs))
def make_galmap_object(self, galmap): from lmfdb.belyi.main import url_for_belyi_passport_label # all information about the map 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 = {} # the stuff that does not need to be polished for elt in ('label', 'plabel', 'triples_cyc', 'orbit_size', 'g', 'abc', 'deg'): data[elt] = galmap[elt] nt = galmap['group'].split('T') data['group'] = group_display_knowl(int(nt[0]), int(nt[1]), getDBConnection()) data['geomtype'] = geomtypelet_to_geomtypename_dict[galmap['geomtype']] data['lambdas'] = [str(c)[1:-1] for c in galmap['lambdas']] data['isQQ'] = False data['in_LMFDB'] = False F = belyi_base_field(galmap) if F._data == None: fld_coeffs = galmap['base_field'] pol = PolynomialRing(QQ, 'x')(fld_coeffs) data['base_field'] = latex(pol) else: data['in_LMFDB'] = True if F.poly().degree() == 1: data['isQQ'] = True F.latex_poly = web_latex(F.poly()) data['base_field'] = F crv_str = galmap['curve'] if crv_str == 'PP1': data['curve'] = '\mathbb{P}^1' else: data['curve'] = make_curve_latex(crv_str) # change pairs of floats to complex numbers embeds = galmap['embeddings'] embed_strs = [] for el in embeds: if el[1] < 0: el_str = str(el[0]) + str(el[1]) + "\sqrt{-1}" else: el_str = str(el[0]) + "+" + str(el[1]) + "\sqrt{-1}" embed_strs.append(el_str) data['map'] = make_map_latex(galmap['map']) data['embeddings_and_triples'] = [] if data['isQQ']: for i in range(0, len(data['triples_cyc'])): triple_cyc = data['triples_cyc'][i] data['embeddings_and_triples'].append([ "\\text{not applicable (over $\mathbb{Q}$)}", triple_cyc[0], triple_cyc[1], triple_cyc[2] ]) else: for i in range(0, len(data['triples_cyc'])): triple_cyc = data['triples_cyc'][i] data['embeddings_and_triples'].append([ embed_strs[i], triple_cyc[0], triple_cyc[1], triple_cyc[2] ]) data['lambdas'] = [str(c)[1:-1] for c in galmap['lambdas']] # Properties properties = [ ('Label', galmap['label']), ('Group', str(galmap['group'])), ('Orders', str(galmap['abc'])), ('Genus', str(galmap['g'])), ('Size', str(galmap['orbit_size'])), ] self.properties = properties # Friends self.friends = [('Passport', url_for_belyi_passport_label(galmap['plabel']))] # Breadcrumbs groupstr, abcstr, sigma0, sigma1, sigmaoo, gstr, letnum = data[ 'label'].split("-") lambdasstr = '%s-%s-%s' % (sigma0, sigma1, sigmaoo) lambdasgstr = lambdasstr + "-" + gstr self.bread = [ ('Belyi Maps', url_for(".index")), (groupstr, url_for(".by_url_belyi_search_group", group=groupstr)), (abcstr, url_for(".by_url_belyi_search_group_triple", group=groupstr, abc=abcstr)), (lambdasgstr, url_for(".by_url_belyi_passport_label", group=groupstr, abc=abcstr, sigma0=sigma0, sigma1=sigma1, sigmaoo=sigmaoo, g=gstr)), (letnum, url_for(".by_url_belyi_galmap_label", group=groupstr, abc=abcstr, sigma0=sigma0, sigma1=sigma1, sigmaoo=sigmaoo, g=gstr, letnum=letnum)), ] # Title self.title = "Belyi map " + data['label'] # Code snippets (only for curves) self.code = {} return
def generator_name(self): #Add special case code for the generator if desired: if self.gen_name=='phi': return '\phi' else: return web_latex(self.gen_name)
def FIELD(label): nf = WebNumberField(label, gen_name=special_names.get(label, 'a')) nf.parse_NFelt = lambda s: nf.K()([QQ(c.encode()) for c in s.split(",")]) nf.latex_poly = web_latex(nf.poly()) return nf
def render_field_webpage(args): data = None info = {} if 'label' in args: label = clean_input(args['label']) data = lfdb().find_one({'label': label}) if data is None: bread = get_bread([("Search error", ' ')]) info['err'] = "Field " + label + " was not found in the database." info['label'] = label return search_input_error(info, bread) title = 'Local Number Field ' + label polynomial = coeff_to_poly(string2list(data['coeffs'])) p = data['p'] e = data['e'] f = data['f'] cc = data['c'] GG = data['gal'] gn = GG[0] gt = GG[1] the_gal = WebGaloisGroup.from_nt(gn,gt) isgal = ' Galois' if the_gal.order() == gn else ' not Galois' abelian = ' and abelian' if the_gal.is_abelian() else '' galphrase = 'This field is'+isgal+abelian+' over $\Q_{%d}$.'%p autstring = r'\Gal' if the_gal.order() == gn else r'\Aut' prop2 = [ ('Label', label), ('Base', '\(\Q_{%s}\)' % p), ('Degree', '\(%s\)' % data['n']), ('e', '\(%s\)' % e), ('f', '\(%s\)' % f), ('c', '\(%s\)' % cc), ('Galois group', group_display_short(gn, gt, db())), ] Pt = PolynomialRing(QQ, 't') Pyt = PolynomialRing(Pt, 'y') eisenp = Pyt(str(data['eisen'])) unramp = Pyt(str(data['unram'])) # Look up the unram poly so we can link to it unramdata = lfdb().find_one({'p': p, 'n': f, 'c': 0}) if unramdata is not None: unramfriend = "/LocalNumberField/%s" % unramdata['label'] else: logger.fatal("Cannot find unramified field!") unramfriend = '' rfdata = lfdb().find_one({'p': p, 'n': {'$in': [1, 2]}, 'rf': data['rf']}) if rfdata is None: logger.fatal("Cannot find discriminant root field!") rffriend = '' else: rffriend = "/LocalNumberField/%s" % rfdata['label'] gsm = data['gsm'] if gsm == '0': gsm = 'Not computed' elif gsm == '-1': gsm = 'Does not exist' else: gsm = web_latex(coeff_to_poly(string2list(gsm))) info.update({ 'polynomial': web_latex(polynomial), 'n': data['n'], 'p': p, 'c': data['c'], 'e': data['e'], 'f': data['f'], 't': data['t'], 'u': data['u'], 'rf': printquad(data['rf'], p), 'hw': data['hw'], 'slopes': show_slopes(data['slopes']), 'gal': group_display_knowl(gn, gt, db()), 'gt': gt, 'inertia': group_display_inertia(data['inertia'], db()), 'unram': web_latex(unramp), 'eisen': web_latex(eisenp), 'gms': data['gms'], 'gsm': gsm, 'galphrase': galphrase, 'autstring': autstring, 'subfields': format_subfields(data['subfields'],p), 'aut': data['aut'], }) friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))] if unramfriend != '': friends.append(('Unramified subfield', unramfriend)) if rffriend != '': friends.append(('Discriminant root field', rffriend)) bread = get_bread([(label, ' ')]) learnmore = [('Completeness of the data', url_for(".completeness_page")), ('Source of the data', url_for(".how_computed_page")), ('Local field labels', url_for(".labels_page"))] return render_template("lf-show-field.html", credit=LF_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends, learnmore=learnmore)
def make_curve(self): data = self.data = {} lmfdb_label = self.lmfdb_label # Some data fields of self are just those from the database. # These only need some reformatting. data['ainvs'] = self.ainvs data['conductor'] = N = self.conductor data['j_invariant'] = QQ(tuple(self.jinv)) data['j_inv_factor'] = latex(0) if data['j_invariant']: # don't factor 0 data['j_inv_factor'] = latex(data['j_invariant'].factor()) data['j_inv_latex'] = web_latex(data['j_invariant']) # retrieve local reduction data from table ec_localdata: self.local_data = local_data = list( db.ec_localdata.search({"lmfdb_label": lmfdb_label})) for ld in local_data: if ld['kodaira_symbol'] <= -14: # Work around bug in Sage's latex ld['kod'] = 'I_{%s}^{*}' % (-ld['kodaira_symbol'] - 4) else: ld['kod'] = latex(KodairaSymbol(ld['kodaira_symbol'])) Nfac = Factorization([(ZZ(ld['prime']), ld['conductor_valuation']) for ld in local_data]) Dfac = Factorization([(ZZ(ld['prime']), ld['discriminant_valuation']) for ld in local_data], unit=ZZ(self.signD)) data['disc_factor'] = latex(Dfac) data['disc'] = D = Dfac.value() data['cond_factor'] = latex(Nfac) data['disc_latex'] = web_latex(D) data['cond_latex'] = web_latex(N) # retrieve data about MW rank, generators, heights and # torsion, leading term of L-function & other BSD data from # table ec_mwbsd: self.make_mwbsd() # latex equation: latexeqn = latex_equation(self.ainvs) data['equation'] = raw_typeset(unlatex(latexeqn), latexeqn) # minimal quadratic twist: data['minq_D'] = minqD = self.min_quad_twist_disc data['minq_label'] = db.ec_curvedata.lucky( {'ainvs': self.min_quad_twist_ainvs}, projection='lmfdb_label' if self.label_type == 'LMFDB' else 'Clabel') data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format( minqD) # modular degree: try: data['degree'] = ZZ(self.degree) # convert None to 0 except AttributeError: # if not computed, db has Null and the attribute is missing data['degree'] = 0 # invalid, but will be displayed nicely # coefficients of modular form / L-series: classdata = db.ec_classdata.lookup(self.lmfdb_iso) data['an'] = classdata['anlist'] data['ap'] = classdata['aplist'] # mod-p Galois images: data['galois_data'] = list( db.ec_galrep.search({'lmfdb_label': lmfdb_label})) for gd in data[ 'galois_data']: # remove the prime prefix from each image code gd['image'] = trim_galois_image_code(gd['image']) # CM and Endo ring: data['CMD'] = self.cm data['CM'] = "no" data['EndE'] = r"\(\Z\)" if self.cm: data['cm_ramp'] = [ p for p in ZZ(self.cm).support() if not p in self.nonmax_primes ] data['cm_nramp'] = len(data['cm_ramp']) if data['cm_nramp'] == 1: data['cm_ramp'] = data['cm_ramp'][0] else: data['cm_ramp'] = ", ".join(str(p) for p in data['cm_ramp']) data['cm_sqf'] = ZZ(self.cm).squarefree_part() data['CM'] = r"yes (\(D=%s\))" % data['CMD'] if data['CMD'] % 4 == 0: d4 = ZZ(data['CMD']) // 4 data['EndE'] = r"\(\Z[\sqrt{%s}]\)" % d4 else: data['EndE'] = r"\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD'] data['ST'] = st_link_by_name(1, 2, 'N(U(1))') else: data['ST'] = st_link_by_name(1, 2, 'SU(2)') # Isogeny degrees: cond, iso, num = split_lmfdb_label(lmfdb_label) self.class_deg = classdata['class_deg'] self.one_deg = ZZ(self.class_deg).is_prime() isodegs = [str(d) for d in self.isogeny_degrees if d > 1] if len(isodegs) < 3: data['isogeny_degrees'] = " and ".join(isodegs) else: data['isogeny_degrees'] = " and ".join( [", ".join(isodegs[:-1]), isodegs[-1]]) self.make_twoadic_data() # Optimality # The optimal curve in the class is the curve whose Cremona # label ends in '1' except for '990h' which was labelled # wrongly long ago. This is proved for N up to # OPTIMALITY_BOUND (and when there is only one curve in an # isogeny class, obviously) and expected for all N. # Column 'optimality' is 1 for certainly optimal curves, 0 for # certainly non-optimal curves, and is n>1 if the curve is one # of n in the isogeny class which may be optimal given current # knowledge. # Column "manin_constant' is the correct Manin constant # assuming that the optimal curve in the class is known, or # otherwise if it is the curve with (Cremona) number 1. # The code here allows us to update the display correctly by # changing one line in this file (defining OPTIMALITY_BOUND) # without changing the data. data['optimality_bound'] = OPTIMALITY_BOUND self.cremona_bound = CREMONA_BOUND if N < CREMONA_BOUND: data[ 'manin_constant'] = self.manin_constant # (conditional on data['optimality_known']) else: data['manin_constant'] = 0 # (meaning not available) if N < OPTIMALITY_BOUND: data['optimality_code'] = int( self.Cnumber == (3 if self.Ciso == '990h' else 1)) data['optimality_known'] = True data['manin_known'] = True if self.label_type == 'Cremona': data[ 'optimal_label'] = '990h3' if self.Ciso == '990h' else self.Ciso + '1' else: data[ 'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1' elif N < CREMONA_BOUND: data['optimality_code'] = self.optimality data['optimality_known'] = (self.optimality < 2) if self.optimality == 1: data['manin_known'] = True data[ 'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label else: if self.Cnumber == 1: data['manin_known'] = False data[ 'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label else: # find curve #1 in this class and its optimailty code: opt_curve = db.ec_curvedata.lucky( { 'Ciso': self.Ciso, 'Cnumber': 1 }, projection=['Clabel', 'lmfdb_label', 'optimality']) data['manin_known'] = (opt_curve['optimality'] == 1) data['optimal_label'] = opt_curve[ 'Clabel' if self.label_type == 'Cremona' else 'lmfdb_label'] else: data['optimality_code'] = None data['optimality_known'] = False data['manin_known'] = False data['optimal_label'] = '' # p-adic data: data['p_adic_primes'] = [ p for i, p in enumerate(prime_range(5, 100)) if (N * data['ap'][i]) % p != 0 ] data['p_adic_data_exists'] = False if data['optimality_code'] == 1: data['p_adic_data_exists'] = db.ec_padic.exists( {'lmfdb_iso': self.lmfdb_iso}) # Iwasawa data (where present) self.make_iwasawa() # Torsion growth data (where present) self.make_torsion_growth() # Newform rawnewform = str(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)) data['newform'] = raw_typeset( rawnewform, web_latex(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))) data['newform_label'] = self.newform_label = ".".join( [str(cond), str(2), 'a', iso]) self.newform_link = url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) self.newform_exists_in_db = db.mf_newforms.label_exists( self.newform_label) self._code = None if self.label_type == 'Cremona': self.class_url = url_for(".by_ec_label", label=self.Ciso) self.class_name = self.Ciso else: self.class_url = url_for(".by_ec_label", label=self.lmfdb_iso) self.class_name = self.lmfdb_iso data['class_name'] = self.class_name data['Cnumber'] = self.Cnumber if N < CREMONA_BOUND else None self.friends = [('Isogeny class ' + self.class_name, self.class_url), ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_ec_label", label=data['minq_label'])), ('All twists ', url_for(".rational_elliptic_curves", jinv=data['j_invariant']))] lfun_url = url_for("l_functions.l_function_ec_page", conductor_label=N, isogeny_class_label=iso) origin_url = lfun_url.lstrip('/L/').rstrip('/') if db.lfunc_instances.exists({'url': origin_url}): self.friends += [('L-function', lfun_url)] else: self.friends += [('L-function not available', "")] if not self.cm: if N <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=N, isogeny=iso))] if N <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=N, isogeny=iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.lmfdb_label)), ('Code to Magma', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')), ('Code to SageMath', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')), ('Code to GP', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='gp'))] try: self.plot = encode_plot(self.E.plot()) except AttributeError: self.plot = encode_plot(EllipticCurve(data['ainvs']).plot()) self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format( self.plot) self.properties = [ ('Label', self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label), (None, self.plot_link), ('Conductor', prop_int_pretty(data['conductor'])), ('Discriminant', prop_int_pretty(data['disc'])), ('j-invariant', '%s' % data['j_inv_latex']), ('CM', '%s' % data['CM']), ('Rank', 'unknown' if self.mwbsd['rank'] == '?' else prop_int_pretty(self.mwbsd['rank'])), ('Torsion structure', (r'\(%s\)' % self.mwbsd['tor_struct']) if self.mwbsd['tor_struct'] else 'trivial'), ] if self.label_type == 'Cremona': self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format( self.Clabel, self.lmfdb_label) elif N < CREMONA_BOUND: self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format( self.lmfdb_label, self.Clabel) else: self.title = "Elliptic curve with LMFDB label {}".format( self.lmfdb_label) self.bread = [('Elliptic curves', url_for("ecnf.index")), (r'$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)), ('%s' % num, ' ')]
def display_poly(coeffs): return web_latex(coeff_to_poly(string2list(coeffs)))
def make_class(self): self.CM = self.cm N, iso, number = split_lmfdb_label(self.lmfdb_iso) # Extract the size of the isogeny class from the database ncurves = self.class_size # Create a list of the curves in the class from the database self.curves = [db.ec_curves.lucky({'iso':self.iso, 'lmfdb_number': i+1}) for i in range(ncurves)] # Set optimality flags. The optimal curve is number 1 except # in one case which is labeled differently in the Cremona tables for c in self.curves: c['optimal'] = (c['number']==(3 if self.label == '990h' else 1)) c['ai'] = c['ainvs'] c['url'] = url_for(".by_triple_label", conductor=N, iso_label=iso, number=c['lmfdb_number']) from sage.matrix.all import Matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.newform = web_latex(PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True)) self.newform_label = db.mf_newforms.lucky({'level':N, 'weight':2, 'related_objects':{'$contains':'EllipticCurve/Q/%s/%s' % (N, iso)}},'label') self.newform_exists_in_db = self.newform_label is not None if self.newform_label is not None: char_orbit, hecke_orbit = self.newform_label.split('.')[2:] self.newform_link = url_for("cmf.by_url_newform_label", level=N, weight=2, char_orbit_label=char_orbit, hecke_orbit=hecke_orbit) self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label = N, isogeny_class_label = iso) self.friends = [('L-function', self.lfunction_link)] if not self.CM: self.CM = "no" if int(N)<=300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor = N, isogeny = iso))] if int(N)<=50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor = N, isogeny = iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.properties = [('Label', self.lmfdb_iso), ('Number of curves', str(ncurves)), ('Conductor', '\(%s\)' % N), ('CM', '%s' % self.CM), ('Rank', '\(%s\)' % self.rank), ('Graph', ''),(None, self.graph_link) ] self.downloads = [('Download q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)), ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))] if self.lmfdb_iso == self.iso: self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso else: self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')] self.code = {} self.code['show'] = {'sage':''} # use default show names self.code['class'] = {'sage':'E = EllipticCurve("%s1")\n'%(self.lmfdb_iso) + 'E.isogeny_class()\n'} self.code['curves'] = {'sage':'E.isogeny_class().curves'} self.code['rank'] = {'sage':'E.rank()'} self.code['q_eigenform'] = {'sage':'E.q_eigenform(10)'} self.code['matrix'] = {'sage':'E.isogeny_class().matrix()'} self.code['plot'] = {'sage':'E.isogeny_graph().plot(edge_labels=True)'}
def make_curve(self): # To start with the data fields of self are just those from # the database. We need to reformat these, construct the # and compute some further (easy) data about it. # # Weierstrass equation data = self.data = {} disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) # to deal with disc_key, uncomment line above and remove line below #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc) data['disc'] = disc data['cond'] = ZZ(self.cond) data['min_eqn'] = list_to_min_eqn(self.min_eqn) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['cond_factor_latex'] = web_latex(factor(int(self.cond))) data['aut_grp'] = groupid_to_meaningful(self.aut_grp) data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp) data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch] if len(self.torsion) == 0: data['tor_struct'] = '\mathrm{trivial}' else: tor_struct = [ZZ(a) for a in self.torsion] data['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct]) isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(self.label)}) for endalgtype in ['end_ring', 'rat_end_alg', 'real_end_alg', 'geom_end_ring', 'rat_geom_end_alg', 'real_geom_end_alg']: if endalgtype in isogeny_class: data[endalgtype + '_name'] = end_alg_name(isogeny_class[endalgtype]) else: data[endalgtype + '_name'] = '' data['geom_end_field'] = isogeny_class['geom_end_field'] if data['geom_end_field'] <> '': data['geom_end_field_name'] = field_pretty(data['geom_end_field']) else: data['geom_end_field_name'] = '' data['st_group_name'] = st_group_name(isogeny_class['st_group']) if isogeny_class['is_gl2_type']: data['is_gl2_type_name'] = 'yes' else: data['is_gl2_type_name'] = 'no' if 'is_simple' in isogeny_class: if isogeny_class['is_simple']: data['is_simple_name'] = 'yes' else: data['is_simple_name'] = 'no' else: data['is_simple_name'] = '?' if 'is_geom_simple' in isogeny_class: if isogeny_class['is_geom_simple']: data['is_geom_simple_name'] = 'yes' else: data['is_geom_simple_name'] = 'no' else: data['is_geom_simple_name'] = '?' x = self.label.split('.')[1] self.friends = [ ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)), ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)), ('Siegel modular form someday', '.')] self.downloads = [ ('Download Euler factors', '.')] iso = self.label.split('.')[1] num = '.'.join(self.label.split('.')[2:4]) self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn)) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = [('Label', self.label), (None, self.plot_link), ('Conductor','%s' % self.cond), ('Discriminant', '%s' % data['disc']), ('Invariants', '%s </br> %s </br> %s </br> %s'% tuple(data['igusa_clebsch'])), ('Sato-Tate group', '\(%s\)' % data['st_group_name']), ('\(\mathrm{End}(J_{\overline{\Q}}) \otimes \R\)','\(%s\)' % data['real_geom_end_alg_name']), ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])] self.title = "Genus 2 Curve %s" % (self.label) self.bread = [ ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)), ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)), ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))]