def galois_rep_from_path(p): C = getDBConnection() if p[0] == 'EllipticCurve': # create the sage elliptic curve then create Galois rep object data = C.elliptic_curves.curves.find_one( {'lmfdb_label': p[2] + "." + p[3] + p[4]}) ainvs = [int(a) for a in data['ainvs']] E = EllipticCurve(ainvs) return GaloisRepresentation(E) elif (p[0] == 'Character' and p[1] == 'Dirichlet'): dirichletArgs = { 'type': 'Dirichlet', 'modulus': int(p[2]), 'number': int(p[3]) } chi = WebDirichletCharacter(**dirichletArgs) return GaloisRepresentation(chi) elif (p[0] == 'ModularForm'): N = int(p[4]) k = int(p[5]) chi = p[6] # this should be zero; TODO check this is the case label = p[7] # this is a, b, c, etc.; chooses the galois orbit embedding = p[8] # this is the embedding of that galois orbit form = WebNewForm(N, k, chi=chi, label=label) return GaloisRepresentation([form, ZZ(embedding)]) elif (p[0] == 'ArtinRepresentation'): dim = p[1] conductor = p[2] index = p[3] rho = ArtinRepresentation(dim, conductor, index) return GaloisRepresentation(rho) else: return
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()), 'kod':web_latex(ld.kodaira_symbol()).replace('$',''), 'cp':int(ld.tamagawa_number())} for ld in E.local_data()] Etw, Dtw = E.minimal_quadratic_twist() if Etw.conductor()==E.conductor(): data['min_quad_twist'] = {'label':label, 'disc':int(1)} else: # Later this should be changed to look for xainvs but now all curves have ainvs minq_ainvs = [str(c) for c in Etw.ainvs()] r = curves.find_one({'jinv':str(E.j_invariant()), 'ainvs':minq_ainvs}) minq_label = "" if r is None else r['label'] data['min_quad_twist'] = {'label':minq_label, 'disc':int(Dtw)} from lmfdb.elliptic_curves.web_ec import parse_points gens = [E(g) for g in parse_points(gens)] data['heights'] = [float(P.height()) for P in gens] if number==1: data['aplist'] = E.aplist(100,python_ints=True) data['anlist'] = E.anlist(20,python_ints=True) return data
def make_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 render_curve_webpage_by_label(label): C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({'lmfdb_label': label}) if data is None: return elliptic_curve_jump_error(label, {}) info = {} ainvs = [int(a) for a in data['ainvs']] E = EllipticCurve(ainvs) cremona_label = data['label'] lmfdb_label = data['lmfdb_label'] N = ZZ(data['conductor']) cremona_iso_class = data['iso'] # eg '37a' lmfdb_iso_class = data['lmfdb_iso'] # eg '37.a' rank = data['rank'] try: j_invariant = QQ(str(data['jinv'])) except KeyError: j_invariant = E.j_invariant() if j_invariant == 0: j_inv_factored = latex(0) else: j_inv_factored = latex(j_invariant.factor()) jinv = unicode(str(j_invariant)) CMD = 0 CM = "no" EndE = "\(\Z\)" if E.has_cm(): CMD = E.cm_discriminant() CM = "yes (\(%s\))" % CMD if CMD % 4 == 0: d4 = ZZ(CMD) // 4 # r = d4.squarefree_part() # f = (d4//r).isqrt() # f="" if f==1 else str(f) # EndE = "\(\Z[%s\sqrt{%s}]\)"%(f,r) EndE = "\(\Z[\sqrt{%s}]\)" % (d4) else: EndE = "\(\Z[(1+\sqrt{%s})/2]\)" % CMD # plot=E.plot() discriminant = E.discriminant() xintpoints_projective = [ E.lift_x(x) for x in xintegral_point(data['x-coordinates_of_integral_points']) ] xintpoints = proj_to_aff(xintpoints_projective) if 'degree' in data: modular_degree = data['degree'] else: try: modular_degree = E.modular_degree() except RuntimeError: modular_degree = 0 # invalid, will be displayed nicely G = E.torsion_subgroup().gens() E_pari = E.pari_curve(prec=200) from sage.libs.pari.all import PariError try: minq = E.minimal_quadratic_twist()[0] except PariError: # this does occur with 164411a1 print "PariError computing minimal quadratic twist of elliptic curve %s" % lmfdb_label minq = E if E == minq: minq_label = lmfdb_label else: minq_ainvs = [str(c) for c in minq.ainvs()] minq_label = C.elliptic_curves.curves.find_one({'ainvs': minq_ainvs })['lmfdb_label'] # We do not just do the following, as Sage's installed database # might not have all the curves in the LMFDB database. # minq_label = E.minimal_quadratic_twist()[0].label() if 'gens' in data: generator = parse_gens(data['gens']) if len(G) == 0: tor_struct = '\mathrm{Trivial}' tor_group = '\mathrm{Trivial}' else: tor_group = ' \\times '.join(['\Z/{%s}\Z' % a.order() for a in G]) if 'torsion_structure' in data: info['tor_structure'] = ' \\times '.join( ['\Z/{%s}\Z' % int(a) for a in data['torsion_structure']]) else: info['tor_structure'] = tor_group def trim_galois_image_code(s): return s[2:] if s[1].isdigit() else s[1:] if 'galois_images' in data: galois_images = data['galois_images'] galois_images = [trim_galois_image_code(s) for s in galois_images] non_surjective_primes = data['non-surjective_primes'] galois_data = [{ 'p': p, 'image': im } for p, im in zip(non_surjective_primes, galois_images)] info.update(data) if rank >= 2: lder_tex = "L%s(E,1)" % ("^{(" + str(rank) + ")}") elif rank == 1: lder_tex = "L%s(E,1)" % ("'" * rank) else: assert rank == 0 lder_tex = "L(E,1)" info['Gamma0optimal'] = (cremona_label[-1] == '1' if cremona_iso_class != '990h' else cremona_label[-1] == '3') info['modular_degree'] = modular_degree p_adic_data_exists = (C.elliptic_curves.padic_db.find({ 'lmfdb_iso': lmfdb_iso_class }).count()) > 0 and info['Gamma0optimal'] # Local data local_data = [] for p in N.prime_factors(): local_info = E.local_data(p, algorithm="generic") local_data.append({ 'p': p, 'tamagawa_number': local_info.tamagawa_number(), 'kodaira_symbol': web_latex(local_info.kodaira_symbol()).replace('$', ''), 'reduction_type': local_info.bad_reduction_type() }) mod_form_iso = lmfdb_label_regex.match(lmfdb_iso_class).groups()[1] tamagawa_numbers = [ E.local_data(p, algorithm="generic").tamagawa_number() for p in N.prime_factors() ] # if we use E.tamagawa_numbers() it calls E.local_data(p) which # crashes on some curves e.g. 164411a1 info.update({ 'conductor': N, 'disc_factor': latex(discriminant.factor()), 'j_invar_factor': j_inv_factored, 'label': lmfdb_label, 'cremona_label': cremona_label, 'iso_class': lmfdb_iso_class, 'cremona_iso_class': cremona_iso_class, 'equation': web_latex(E), #'f': ajax_more(E.q_eigenform, 10, 20, 50, 100, 250), 'f': web_latex(E.q_eigenform(10)), 'generators': ', '.join(web_latex(g) for g in generator) if 'gens' in data else ' ', 'lder': lder_tex, 'p_adic_primes': [ p for p in sage.all.prime_range(5, 100) if E.is_ordinary(p) and not p.divides(N) ], 'p_adic_data_exists': p_adic_data_exists, 'ainvs': format_ainvs(data['ainvs']), 'CM': CM, 'CMD': CMD, 'EndE': EndE, 'tamagawa_numbers': r' \cdot '.join(str(sage.all.factor(c)) for c in tamagawa_numbers), 'local_data': local_data, 'cond_factor': latex(N.factor()), 'galois_data': galois_data, 'xintegral_points': ', '.join(web_latex(P) for P in xintpoints), 'tor_gens': ', '.join(web_latex(eval(g)) for g in data['torsion_generators']) if False else ', '.join( web_latex(P.element().xy()) for P in list(G)) }) info['friends'] = [('Isogeny class ' + lmfdb_iso_class, url_for(".by_ec_label", label=lmfdb_iso_class)), ('Minimal quadratic twist ' + minq_label, url_for(".by_ec_label", label=minq_label)), ('All twists ', url_for(".rational_elliptic_curves", jinv=jinv)), ('L-function', url_for("l_functions.l_function_ec_page", label=lmfdb_label)), ('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=lmfdb_iso_class)), ('Symmetric 4th power L-function', url_for("l_functions.l_function_ec_sym_page", power='4', label=lmfdb_iso_class))] info['friends'].append( ('Modular form ' + lmfdb_iso_class.replace('.', '.2'), url_for("emf.render_elliptic_modular_forms", level=int(N), weight=2, character=0, label=mod_form_iso))) info['downloads'] = [('Download coeffients of q-expansion', url_for(".download_EC_qexp", label=lmfdb_label, limit=100)), ('Download all stored data', url_for(".download_EC_all", label=lmfdb_label))] # info['learnmore'] = [('Elliptic Curves', url_for(".not_yet_implemented"))] # info['plot'] = image_src(plot) info['plot'] = url_for('.plot_ec', label=lmfdb_label) properties2 = [('Label', '%s' % lmfdb_label), (None, '<img src="%s" width="200" height="150"/>' % url_for('.plot_ec', label=lmfdb_label)), ('Conductor', '\(%s\)' % N), ('Discriminant', '\(%s\)' % discriminant), ('j-invariant', '%s' % web_latex(j_invariant)), ('CM', '%s' % CM), ('Rank', '\(%s\)' % rank), ('Torsion Structure', '\(%s\)' % tor_group)] # properties.extend([ "prop %s = %s<br/>" % (_,_*1923) for _ in range(12) ]) credit = 'John Cremona and Andrew Sutherland' if info['label'] == info['cremona_label']: t = "Elliptic Curve %s" % info['label'] else: t = "Elliptic Curve %s (Cremona label %s)" % (info['label'], info['cremona_label']) bread = [('Elliptic Curves ', url_for(".rational_elliptic_curves")), ('Elliptic curves %s' % lmfdb_label, ' ')] return render_template("curve.html", properties2=properties2, credit=credit, bread=bread, title=t, info=info, friends=info['friends'], downloads=info['downloads'])
def elliptic_curve_search(**args): info = to_dict(args) query = {} bread = [('Elliptic Curves', url_for(".rational_elliptic_curves")), ('Search Results', '.')] if 'jump' in args: label = info.get('label', '').replace(" ", "") m = lmfdb_label_regex.match(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = cremona_label_regex.match(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif cremona_label_regex.match(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] lab = re.sub(r'\s', '', label) lab = re.sub(r'^\[', '', lab) lab = re.sub(r']$', '', lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) ainvs = [str(c) for c in E.minimal_model().ainvs()] C = lmfdb.base.getDBConnection() data = C.elliptic_curves.curves.find_one({'ainvs': ainvs}) if data is None: return elliptic_curve_jump_error(label, info) return by_ec_label(data['lmfdb_label']) except (ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' if info.get('jinv'): j = clean_input(info['jinv']) j = j.replace('+', '') if not QQ_RE.match(j): info[ 'err'] = 'Error parsing input for the j-invariant. It needs to be a rational number.' return search_input_error(info, bread) query['jinv'] = j for field in ['conductor', 'torsion', 'rank', 'sha_an']: if info.get(field): info[field] = clean_input(info[field]) ran = info[field] ran = ran.replace('..', '-').replace(' ', '') if not LIST_RE.match(ran): names = { 'conductor': 'conductor', 'torsion': 'torsion order', 'rank': 'rank', 'sha_an': 'analytic order of Ш' } info[ 'err'] = 'Error parsing input for the %s. It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[ field] return search_input_error(info, bread) # Past input check tmp = parse_range2(ran, field) # work around syntax for $or # we have to foil out multiple or conditions if tmp[0] == '$or' and '$or' in query: newors = [] for y in tmp[1]: oldors = [dict.copy(x) for x in query['$or']] for x in oldors: x.update(y) newors.extend(oldors) tmp[1] = newors if field == 'sha_an': # database sha_an values are not all exact! query[tmp[0]] = {'$gt': tmp[1] - 0.1, '$lt': tmp[1] + 0.1} else: query[tmp[0]] = tmp[1] if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 if 'torsion_structure' in info and info['torsion_structure']: info['torsion_structure'] = clean_input(info['torsion_structure']) if not TORS_RE.match(info['torsion_structure']): info[ 'err'] = 'Error parsing input for the torsion structure. It needs to be one or more integers in square brackets, such as [6], [2,2], or [2,4]. Moreover, each integer should be bigger than 1, and each divides the next.' return search_input_error(info, bread) query['torsion_structure'] = [ str(a) for a in parse_list(info['torsion_structure']) ] if info.get('surj_primes'): info['surj_primes'] = clean_input(info['surj_primes']) format_ok = LIST_POSINT_RE.match(info['surj_primes']) if format_ok: surj_primes = [int(p) for p in info['surj_primes'].split(',')] format_ok = all([ZZ(p).is_prime(proof=False) for p in surj_primes]) if format_ok: query['non-surjective_primes'] = {"$nin": surj_primes} else: info[ 'err'] = 'Error parsing input for surjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) if info.get('nonsurj_primes'): info['nonsurj_primes'] = clean_input(info['nonsurj_primes']) format_ok = LIST_POSINT_RE.match(info['nonsurj_primes']) if format_ok: nonsurj_primes = [ int(p) for p in info['nonsurj_primes'].split(',') ] format_ok = all( [ZZ(p).is_prime(proof=False) for p in nonsurj_primes]) if format_ok: if info['surj_quantifier'] == 'exactly': nonsurj_primes.sort() query['non-surjective_primes'] = nonsurj_primes else: if 'non-surjective_primes' in query: query['non-surjective_primes'] = { "$nin": surj_primes, "$all": nonsurj_primes } else: query['non-surjective_primes'] = {"$all": nonsurj_primes} else: info[ 'err'] = 'Error parsing input for nonsurjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) info['query'] = query count_default = 100 if info.get('count'): try: count = int(info['count']) except: count = count_default else: count = count_default info['count'] = count start_default = 0 if info.get('start'): try: start = int(info['start']) if (start < 0): start += (1 - (start + 1) / count) * count except: start = start_default else: start = start_default cursor = lmfdb.base.getDBConnection().elliptic_curves.curves.find(query) nres = cursor.count() if (start >= nres): start -= (1 + (start - nres) / count) * count if (start < 0): start = 0 res = cursor.sort([('conductor', ASCENDING), ('lmfdb_iso', ASCENDING), ('lmfdb_number', ASCENDING)]).skip(start).limit(count) info['curves'] = res info['format_ainvs'] = format_ainvs info['number'] = nres info['start'] = start if nres == 1: info['report'] = 'unique match' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % ( start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres credit = 'John Cremona' if 'non-surjective_primes' in query: credit += 'and Andrew Sutherland' t = 'Elliptic Curves' return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
def check_Q_curves(field_label='2.2.5.1', min_norm=0, max_norm=None, fix=False, verbose=False): """Given a (quadratic) field label test all curves E over that field for being Q-curves. """ query = {} query['field_label'] = field_label query['conductor_norm'] = {'$gte': int(min_norm)} if max_norm: query['conductor_norm']['$lte'] = int(max_norm) else: max_norm = 'infinity' cursor = nfcurves.find(query) # keep the curves and re-find them, else the cursor times out. curves = [ec['label'] for ec in cursor] ncurves = len(curves) print("Checking {} curves over field {}".format(ncurves, field_label)) K = FIELD(field_label) sigma = K.K().galois_group()[1] bad1 = [] bad2 = [] count = 0 for label in curves: count += 1 if count % 1000 == 0: print("checked {} curves ({}%)".format(count, 100.0 * count / ncurves)) ec = nfcurves.find_one({'label': label}) assert label == ec['label'] method = None # first check that j(E) is rational (no computation needed) jinv = ec['jinv'] if all(c == '0' for c in jinv.split(",")[1:]): if verbose: print("{}: j in QQ".format(label)) qc = True method = "j in Q" elif ec['cm']: if verbose: print("{}: CM".format(label)) qc = True method = "CM" else: # construct and check the conductor if verbose: print("{}: checking conductor".format(label)) N = ideal_from_string(K.K(), ec['conductor_ideal']) if sigma(N) != N: qc = False method = "conductor" else: # construct and check the curve if verbose: print("{}: checking isogenies".format(label)) ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) qc = is_Q_curve(E) method = "isogenies" db_qc = ec['q_curve'] if qc and not db_qc: print("Curve {} is a Q-curve (using {}) but database thinks not". format(label, method)) bad1 += [label] elif db_qc and not qc: print( "Curve {} is not a Q-curve (using {}) but database thinks it is" .format(label, method)) bad2 += [label] else: if verbose: print("Curve {} OK (using {})".format(label, method)) print( "{} curves in the database are incorrectly labelled as being Q-curves". format(len(bad2))) print( "{} curves in the database are incorrectly labelled as NOT being Q-curves" .format(len(bad1))) return bad1, bad2
def elliptic_curve_search(info): if info.get('download') == '1' and info.get('Submit') and info.get('query'): return download_search(info) if 'SearchAgain' in info: return rational_elliptic_curves() query = {} bread = info.get('bread',[('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')]) if 'jump' in info: label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) # Now we do have a valid curve over Q, but it might # not be in the database. ainvs = [str(c) for c in E.minimal_model().ainvs()] xainvs = ''.join(['[',','.join(ainvs),']']) data = db_ec().find_one({'xainvs': xainvs}) if data is None: data = db_ec().find_one({'ainvs': ainvs}) if data is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data['lmfdb_label']) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' try: parse_rational(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion if 'torsion_structure' in query and not 'torsion' in query: query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='surjective primes', qfield='non-maximal_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes', qfield='non-maximal_primes',mode=mode) except ValueError as err: info['err'] = str(err) return search_input_error(info, bread) count = parse_count(info,100) start = parse_start(info) if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 info['query'] = query cursor = db_ec().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING)]).skip(start).limit(count) info['curves'] = res info['format_ainvs'] = format_ainvs info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number']) info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres #credit = 'John Cremona' #if 'non-surjective_primes' in query or 'non-maximal_primes' in query: # credit += ' and Andrew Sutherland' t = info.get('title','Elliptic Curves search results') return render_template("ec-search-results.html", info=info, credit=ec_credit(), bread=bread, title=t)
def read_line_old(line): r""" Parses one line from input file. Returns the hash and a dict containing fields with keys as above. This original version expects 6 fields on each line, separated by a colon: 0. hash 1. label 2. root number 3. (not used) 4. zeros 5. plot data """ fields = line.split(":") assert len(fields)==6 label = fields[1] # use this isogeny class label to get info about the curve E = curves.find_one({'iso': label}) data = constant_data() instances = {} # Set the fields in the Instances collection: cond = data['conductor'] = int(E['conductor']) iso = E['lmfdb_iso'].split('.')[1] instances['url'] = 'EllipticCurve/Q/%s/%s' % (cond,iso) instances['Lhash'] = Lhash = fields[0] instances['type'] = 'ECQ' # Set the fields in the Lfunctions collection: data['Lhash'] = Lhash data['root_number'] = int(fields[2]) data['order_of_vanishing'] = int(E['rank']) data['central_character'] = '%s.1' % cond data['st_group'] = 'N(U(1))' if E['cm'] else 'SU(2)' data['leading_term'] = float(E['special_value']) # Zeros zeros = fields[4][1:-1].split(",") # omit negative ones and 0, using only string tests: data['positive_zeros'] = [y for y in zeros if y!='0' and y[0]!='-'] data['z1'] = data['positive_zeros'][0] data['z2'] = data['positive_zeros'][1] data['z3'] = data['positive_zeros'][2] # plot data plot_xy = [[float(v) for v in vv.split(",")] for vv in fields[5][2:-3].split("],[")] # constant difference in x-coordinate sequence: data['plot_delta'] = plot_xy[1][0]-plot_xy[0][0] # list of y coordinates for x>0: data['plot_values'] = [y for x,y in plot_xy if x>=0] # Euler factors: we need the ap which are currently not in the # database so we call Sage. It might be a good idea to store in # the ec database (1) all ap for p<100; (2) all ap for bad p. Esage = EllipticCurve([ZZ(a) for a in E['ainvs']]) data['bad_lfactors'] = make_bad_lfactors(Esage) data['euler_factors'] = make_euler_factors(Esage) # Dirichlet coefficients an = Esage.anlist(10) for n in range(2,11): data['A%s' % n] = str(an[n]) data['a%s' % n] = [an[n]/sqrt(float(n)),0] return Lhash, data, instances
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'] = 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]) 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'] minq_label = self.min_quad_twist['label'] data['minq_label'] = db.ec_curves.lucky({'label': minq_label}, 'lmfdb_label') data['minq_info'] = '(itself)' if minqD == 1 else '(by %s)' % minqD if self.degree is None: data['degree'] = 0 # invalid, but will be displayed nicely else: data['degree'] = self.degree if self.number == 1: data['an'] = self.anlist data['ap'] = self.aplist else: r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1}) data['an'] = r['anlist'] data['ap'] = r['aplist'] minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label']) 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.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso) self.one_deg = ZZ(self.class_deg).is_prime() self.ncurves = db.ec_curves.count({'lmfdb_iso': self.lmfdb_iso}) 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) 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'] = 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 = newform_label( cond, 2, 1, iso) self.newform_link = url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso) self.newform_exists_in_db = is_newform_in_db(self.newform_label) self._code = None self.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso) self.friends = [('Isogeny class ' + self.lmfdb_iso, self.class_url), ('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", conductor_label=N, isogeny_class_label=iso))] 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 = [('Download coefficients of q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)), ('Download all stored data', url_for(".download_EC_all", label=self.lmfdb_label)), ('Download Magma code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')), ('Download SageMath code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')), ('Download GP code', 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.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'])] 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 make_curve(q, t, r, k, D, debug=False): """ Description: Finds the curve equation for the elliptic curve (q,t,r,k,D) using the Complex Multiplication method Input: q - size of prime field t - trace of Frobenius r - size of prime order subgroup k - embedding degree D - (negative) fundamental discriminant Output: E - elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D """ assert is_valid_curve(q, t, r, k, D), 'Invalid input. No curve exists.' # check inputs if debug: print('Tested input') poly = hilbert_class_polynomial(D) # compute hilbert class polynomial if debug: print('Computed Hilbert class polynomial') check = False j_inv = poly.any_root(GF(q)) # find j-invariant orig_curve = EllipticCurve(GF(q), j=j_inv) # make a curve E = orig_curve check = test_curve(q, t, r, k, D, E) # see if this is the right curve twist = False if not check: # not the right curve, use quadratic twist E = E.quadratic_twist() check = test_curve(q, t, r, k, D, E) if check: twist = True else: # twist didnt work => j = 0 or 1728 if j_inv == 0: # for j = 0, use sextic twists prim = primitive_root(q) i = 1 while t != E.trace_of_frobenius() and i < 6: E = orig_curve.sextic_twist(power_mod(prim, i, q)) i += 1 elif j_inv == 1728: # for j = 1728, use quartic twists prim = primitive_root(q) i = 1 while t != E.trace_of_frobenius() and i < 4: E = orig_curve.quartic_twist(power_mod(prim, i, q)) i += 1 else: # twist didnt work and j != 0, 1728. this should never happen, so write input to a file for debugging print( 'Error. Quadratic twist failed to find the correct curve with j != 0, 1728. Logging output to debug.txt' ) # this line should never be reached' f = open('debug.txt', 'w') f.write('Twist: ' + str(twist) + '\n') f.write('q: ' + str(q) + '\n') f.write('t: ' + str(t) + '\n') f.write('r: ' + str(r) + '\n') f.write('k: ' + str(k) + '\n') f.write('D: ' + str(D) + '\n') f.write('E: ' + str(E) + '\n') f.write('orig_curve: ' + str(orig_curve)) f.close() return False check = test_curve(q, t, r, k, D, E) twist = True if not check: # didnt find a curve. this should never happen, so write input to a file for debugging print('Error. Failed to find curve. Logging output to debug.txt') f = open('debug.txt', 'w') f.write('Twist: ' + str(twist) + '\n') f.write('q: ' + str(q) + '\n') f.write('t: ' + str(t) + '\n') f.write('r: ' + str(r) + '\n') f.write('k: ' + str(k) + '\n') f.write('D: ' + str(D) + '\n') f.write('E: ' + str(E) + '\n') f.write('orig_curve: ' + str(orig_curve)) f.close() return False return E
def mod_p_iso_red_set(ss, p=7, Detail=0): """Given a list of labels of non-isogenous curves whose mod-p representations are reducible and isomorphic up to semisimplification, return a list of disjoint lists of labels whose union is the list of all curves isogenous to the input curves, such that the curves have isomorphic mod-p representations if and only if they are in the same sublist. """ if Detail > 1: print("testing {}".format(ss)) nss = len(ss) base_curves = [EllipticCurve(lab) for lab in ss] isogenies = [E.isogenies_prime_degree(p)[0] for E in base_curves] isog_curves = [phi.codomain() for phi in isogenies] kernel_field = isogeny_kernel_field(isogenies[0], optimize=True) dual_kernel_field = isogeny_kernel_field(isogenies[0].dual(), optimize=True) if Detail > 1: print("Kernel field: {}".format(kernel_field)) print("Dual kernel field: {}".format(dual_kernel_field)) # Swap the two parts in each class after the first, if necessary, # so that the isogeny characters of the curves in all the first # parts agree. for i, E, phi, Edash in zip(range(nss), base_curves, isogenies, isog_curves): this_kernel_field = isogeny_kernel_field(phi, optimize=True) if not this_kernel_field.is_isomorphic(kernel_field): if this_kernel_field.is_isomorphic(dual_kernel_field): if Detail > 1: print("swapping {}!".format(i)) base_curves[i] = Edash isog_curves[i] = E phi = isogenies[i] = phi.dual() else: print( "problem at i={}: this kernel field = {}, different from both the kernel field and dual kernel field!" .format(i, this_kernel_field)) if Detail > 1: print("After sorting, base curves are {}".format( [Elabel(E) for E in base_curves])) print(" and {}-isogenous curves are {}".format( p, [Elabel(E) for E in isog_curves])) # Now the curves in base_curves have the same isogeny characters # in the same order, and we sort them according to their *-fields: star_fields = [isogeny_star_field(psi) for psi in isogenies] maps = dict([(F, [ Elabel(E) for E, F1 in zip(base_curves, star_fields) if F1.is_isomorphic(F) ]) for F in star_fields]) if Detail: print("star field subsets: {}".format(maps.values())) isog_star_fields = [isogeny_star_field(psi.dual()) for psi in isogenies] isog_maps = dict([(F, [ Elabel(E) for E, F1 in zip(isog_curves, isog_star_fields) if F1.is_isomorphic(F) ]) for F in isog_star_fields]) if Detail: print("star-star field subsets: {}".format(isog_maps.values())) return maps.values(), isog_maps.values()
def test_irred(s, p=7): return len(isog_pol(EllipticCurve(s[0]), p).roots()) == 0
def EC_from_SW_label(lab): N, ainvs = lab.split(".") N = ZZ(N) E = EllipticCurve([ZZ(a) for a in ainvs[1:-1].split(",")]) assert E.conductor() == N return N, E
def read_cong(fname): for L in open(fname).readlines(): p, lab1, lab2 = L.split() yield ZZ(p), EllipticCurve(lab1), EllipticCurve(lab2)
def find_curves(field_label='2.2.5.1', min_norm=0, max_norm=None, label=None, outfilename=None, verbose=False, effort=500): r""" Go through all Hilbert Modular Forms with the given field label, assumed totally real, for level norms in the given range, test whether an elliptic curve exists with the same label; if not, find the curves using Magma; output these to a file. """ print("Checking forms over {}, norms from {} to {}".format( field_label, min_norm, max_norm)) if outfilename: print("Output of curves found to {}".format(outfilename)) else: print("No curve search or output, just checking") query = {} query['field_label'] = field_label if fields.find({'label': field_label}).count() == 0: if verbose: print("No HMF data for field %s" % field_label) return None query['dimension'] = 1 # only look at rational newforms if label: print("looking for {} only".format(label)) query['short_label'] = label # e.g. '91.1-a' else: query['level_norm'] = {'$gte': int(min_norm)} if max_norm: query['level_norm']['$lte'] = int(max_norm) cursor = forms.find(query) cursor.sort([('level_norm', pymongo.ASCENDING)]) labels = [f['label'] for f in cursor] nfound = 0 nnotfound = 0 nok = 0 missing_curves = [] K = HilbertNumberField(field_label) primes = [P['ideal'] for P in K.primes_iter(1000)] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Step 1: look at all newforms, check that there is an elliptic # curve of the same label, and if so compare ap-lists. The # dicts curve_ap and form_ap store these when there is # disagreement: e.g. curve_ap[conductor_label][iso_label] = # aplist. for curve_label in labels: # We find the forms again since otherwise the cursor might timeout during the loop. f = forms.find_one({'label': curve_label}) ec = nfcurves.find_one({ 'field_label': field_label, 'class_label': curve_label, 'number': 1 }) if ec: if verbose: print("curve with label %s found in the database" % curve_label) nfound += 1 ainvsK = parse_ainvs(K.K(), ec['ainvs']) E = EllipticCurve(ainvsK) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] aplist = [E.reduction(P).trace_of_frobenius() for P in good_primes] f_aplist = [int(a) for a in f['hecke_eigenvalues']] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag] nap = min(len(aplist), len(f_aplist)) if aplist[:nap] == f_aplist[:nap]: nok += 1 if verbose: print("Curve {} and newform agree! (checked {} ap)".format( ec['short_label'], nap)) else: print("Curve {} does NOT agree with newform".format( ec['short_label'])) if verbose: for P, aPf, aPc in zip(good_primes[:nap], f_aplist[:nap], aplist[:nap]): if aPf != aPc: print("P = {} with norm {}".format( P, P.norm().factor())) print("ap from curve: %s" % aPc) print("ap from form: %s" % aPf) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No curve with label %s found in the database!" % curve_label) missing_curves.append(f['short_label']) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print( "Out of %s newforms, %s curves were found in the database and %s were not found" % (n, nfound, nnotfound)) else: print( "Out of %s newforms, all %s had curves with the same label and ap" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) if nnotfound: print("%s missing curves" % len(missing_curves)) else: return # Step 2: for each newform for which there was no curve, call interface to Magma's EllipticCurveSearch() # (unless outfilename is None in which case just dump the missing labels to a file) if outfilename: outfile = file(outfilename, mode="w") else: t = file("curves_missing.{}".format(field_label), mode="w") for c in missing_curves: t.write(c) t.write("\n") t.close() return def output(L): if outfilename: outfile.write(L) if verbose: sys.stdout.write(L) bad_p = [] #if field_label=='4.4.1600.1': bad_p = [7**2,13**2,29**2] if field_label == '4.4.2304.1': bad_p = [19**2, 29**2] if field_label == '4.4.4225.1': bad_p = [17**2, 23**2] if field_label == '4.4.7056.1': bad_p = [29**2, 31**2] if field_label == '4.4.7168.1': bad_p = [29**2] if field_label == '4.4.9248.1': bad_p = [23**2] if field_label == '4.4.11025.1': bad_p = [17**2, 37**2, 43**2] if field_label == '4.4.13824.1': bad_p = [19**2] if field_label == '4.4.12400.1': bad_p = [23**2] if field_label == '4.4.180769.1': bad_p = [23**2] if field_label == '6.6.905177.1': bad_p = [2**3] bad_p = [] effort0 = effort for nf_label in missing_curves: if verbose: print("Curve %s is missing from the database..." % nf_label) form = forms.find_one({ 'field_label': field_label, 'short_label': nf_label }) if not form: print("... form %s not found!" % nf_label) else: if verbose: print("... found form, calling Magma search") print("Conductor = %s" % form['level_ideal'].replace(" ", "")) N = K.ideal(form['level_label']) neigs = len(form['hecke_eigenvalues']) Plist = [P['ideal'] for P in K.primes_iter(neigs)] goodP = [(i, P) for i, P in enumerate(Plist) if not P.divides(N) and not P.norm() in bad_p and P.residue_class_degree() == 1] aplist = [int(form['hecke_eigenvalues'][i]) for i, P in goodP] Plist = [P for i, P in goodP] nap = len(Plist) neigs0 = min(nap, 100) effort = effort0 if verbose: print("Using %s ap from Hilbert newform and effort %s" % (neigs0, effort)) if bad_p: print("( excluding primes with norms {})".format(bad_p)) #inds = list(set([randint(0,nap-1) for _ in range(neigs0)])) inds = range(neigs0) Plist0 = [Plist[i] for i in inds] aplist0 = [aplist[i] for i in inds] curves = EllipticCurveSearch(K.K(), Plist0, N, aplist0, effort) # rep = 0 allrep = 0 while not curves and allrep < 10: allrep += 1 effort *= 2 # if rep<2: # rep += 1 # else: # rep = 1 # effort *=2 if verbose: print( "No curves found by Magma, trying again with effort %s..." % effort) curves = EllipticCurveSearch(K.K(), Plist0, N, aplist0, effort) if verbose: if curves: print("Success!") else: print("Still no success") E = None if curves: E = curves[0] print("%s curves for %s found, first is %s" % (len(curves), nf_label, E.ainvs())) else: print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") print("!!! No curves for %s found (using %s ap) !!!" % (nf_label, len(aplist))) print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") if E != None: ec = {} ec['field_label'] = field_label ec['conductor_label'] = form['level_label'] ec['iso_label'] = form['label_suffix'] ec['number'] = int(1) ec['conductor_ideal'] = form['level_ideal'].replace(" ", "") ec['conductor_norm'] = form['level_norm'] ai = E.ainvs() ec['ainvs'] = ";".join( [",".join([str(c) for c in list(a)]) for a in ai]) #print ec['ainvs'] ec['cm'] = '?' ec['base_change'] = [] output(make_curves_line(ec) + "\n") if outfilename: outfile.flush()
def render_curve_webpage_by_label(label): C = base.getDBConnection() data = C.ellcurves.curves.find_one({'label': label}) if data is None: return "No such curve" info = {} ainvs = [int(a) for a in data['ainvs']] E = EllipticCurve(ainvs) label = data['label'] N = ZZ(data['conductor']) iso_class = data['iso'] rank = data['rank'] j_invariant = E.j_invariant() #plot=E.plot() discriminant = E.discriminant() xintpoints_projective = [ E.lift_x(x) for x in xintegral_point(data['x-coordinates_of_integral_points']) ] xintpoints = proj_to_aff(xintpoints_projective) G = E.torsion_subgroup().gens() if 'gens' in data: generator = parse_gens(data['gens']) if len(G) == 0: tor_struct = 'Trivial' tor_group = 'Trivial' else: tor_group = ' \\times '.join( ['\mathbb{Z}/{%s}\mathbb{Z}' % a.order() for a in G]) if 'torsion_structure' in data: info['tor_structure'] = ' \\times '.join([ '\mathbb{Z}/{%s}\mathbb{Z}' % int(a) for a in data['torsion_structure'] ]) else: info['tor_structure'] = tor_group info.update(data) if rank >= 2: lder_tex = "L%s(E,1)" % ("^{(" + str(rank) + ")}") elif rank == 1: lder_tex = "L%s(E,1)" % ("'" * rank) else: assert rank == 0 lder_tex = "L(E,1)" info.update({ 'conductor': N, 'disc_factor': latex(discriminant.factor()), 'j_invar_factor': latex(j_invariant.factor()), 'label': label, 'isogeny': iso_class, 'equation': web_latex(E), #'f': ajax_more(E.q_eigenform, 10, 20, 50, 100, 250), 'f': web_latex(E.q_eigenform(10)), 'generators': ','.join(web_latex(g) for g in generator) if 'gens' in data else ' ', 'lder': lder_tex, 'p_adic_primes': [ p for p in sage.all.prime_range(5, 100) if E.is_ordinary(p) and not p.divides(N) ], 'ainvs': format_ainvs(data['ainvs']), 'tamagawa_numbers': r' \cdot '.join(str(sage.all.factor(c)) for c in E.tamagawa_numbers()), 'cond_factor': latex(N.factor()), 'xintegral_points': ','.join(web_latex(i_p) for i_p in xintpoints), 'tor_gens': ','.join(web_latex(eval(g)) for g in data['torsion_generators']) if 'torsion_generators' in data else list(G) }) info['downloads_visible'] = True info['downloads'] = [('worksheet', url_for("not_yet_implemented"))] info['friends'] = [('Isogeny class', "/EllipticCurve/Q/%s" % iso_class), ('Modular Form', url_for("emf.render_elliptic_modular_form_from_label", label="%s" % (iso_class))), ('L-function', "/L/EllipticCurve/Q/%s" % label)] info['learnmore'] = [('Elliptic Curves', url_for("not_yet_implemented"))] #info['plot'] = image_src(plot) info['plot'] = url_for('plot_ec', label=label) info['iso_class'] = data['iso'] info['download_qexp_url'] = url_for('download_qexp', limit=100, ainvs=','.join([str(a) for a in ainvs])) properties2 = [('Label', '%s' % label), (None, '<img src="%s" width="200" height="150"/>' % url_for('plot_ec', label=label)), ('Conductor', '\(%s\)' % N), ('Discriminant', '\(%s\)' % discriminant), ('j-invariant', '\(%s\)' % j_invariant), ('Rank', '\(%s\)' % rank), ('Torsion Structure', '\(%s\)' % tor_group)] #properties.extend([ "prop %s = %s<br/>" % (_,_*1923) for _ in range(12) ]) credit = 'John Cremona' t = "Elliptic Curve %s" % info['label'] bread = [('Elliptic Curves ', url_for("rational_elliptic_curves")), ('Elliptic curves %s' % info['label'], ' ')] return render_template("elliptic_curve/elliptic_curve.html", info=info, properties2=properties2, credit=credit, bread=bread, title=t)
def make_class(self): self.ainvs_str = self.ainvs self.ainvs = [int(a) for a in self.ainvs_str] self.E = EllipticCurve(self.ainvs) self.CM = self.E.has_cm() try: # Extract the isogeny degree matrix from the database size = len(self.isogeny_matrix) from sage.matrix.all import Matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) except AttributeError: # Failsafe: construct it from scratch self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix() size = self.isogeny_matrix.nrows() self.ncurves = size # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img # Create a list of the curves in the class from the database self.db_curves = [self.E] self.optimal_flags = [False] * size self.degrees = [0] * size if self.degree: self.degrees[0] = self.degree else: try: self.degrees[0] = self.E.modular_degree() except RuntimeError: pass # Fill in the curves in the class by looking each one up in the db: self.cremona_labels = [self.label] + [0] * (size - 1) if self.number == 1: self.optimal_flags[0] = True for i in range(2, size + 1): Edata = db_ec().find_one({'lmfdb_label': self.lmfdb_iso + str(i)}) Ei = EllipticCurve([int(a) for a in Edata['ainvs']]) self.cremona_labels[i - 1] = Edata['label'] if Edata['number'] == 1: self.optimal_flags[i - 1] = True if 'degree' in Edata: self.degrees[i - 1] = Edata['degree'] else: try: self.degrees[i - 1] = Ei.modular_degree() except RuntimeError: pass self.db_curves.append(Ei) if self.iso == '990h': # this isogeny class is labeled wrong in Cremona's tables self.optimal_flags = [False, False, True, False] self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) N, iso, number = split_lmfdb_label(self.lmfdb_iso) self.newform = web_latex(self.E.q_eigenform(10)) self.newform_label = newform_label(N, 2, 1, iso) self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso) newform_exists_in_db = is_newform_in_db(self.newform_label) self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso) self.curves = [ dict([('label', self.lmfdb_iso + str(i + 1)), ('url', url_for(".by_triple_label", conductor=N, iso_label=iso, number=i + 1)), ('cremona_label', self.cremona_labels[i]), ('ainvs', str(list(c.ainvs()))), ('torsion', c.torsion_order()), ('degree', self.degrees[i]), ('optimal', self.optimal_flags[i])]) for i, c in enumerate(self.db_curves) ] self.friends = [('L-function', self.lfunction_link)] if not self.CM: if int(N) <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso))] if int(N) <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', label=self.lmfdb_iso))] if newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.properties = [('Label', self.lmfdb_iso), ('Number of curves', str(self.ncurves)), ('Conductor', '\(%s\)' % N), ('CM', '%s' % self.CM), ('Rank', '\(%s\)' % self.rank), ('Graph', ''), (None, self.graph_link)] self.downloads = [('Download coefficients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=100)), ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))] if self.lmfdb_iso == self.iso: self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso else: self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % ( self.lmfdb_iso, self.iso) self.bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')]
def elliptic_curve_search(**args): info = to_dict(args) query = {} bread = [('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')] if 'SearchAgain' in args: return rational_elliptic_curves() if 'jump' in args: label = info.get('label', '').replace(" ", "") m = match_lmfdb_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif label.startswith("Cremona:"): label = label[8:] m = match_cremona_label(label) if m: try: return by_ec_label(label) except ValueError: return elliptic_curve_jump_error(label, info, wellformed_label=True) elif match_cremona_label(label): return elliptic_curve_jump_error(label, info, cremona_label=True) elif label: # Try to parse a string like [1,0,3,2,4] as valid # Weistrass coefficients: lab = re.sub(r'\s','',label) lab = re.sub(r'^\[','',lab) lab = re.sub(r']$','',lab) try: labvec = lab.split(',') labvec = [QQ(str(z)) for z in labvec] # Rationals allowed E = EllipticCurve(labvec) # Now we do have a valid curve over Q, but it might # not be in the database. ainvs = [str(c) for c in E.minimal_model().ainvs()] data = db_ec().find_one({'ainvs': ainvs}) if data is None: info['conductor'] = E.conductor() return elliptic_curve_jump_error(label, info, missing_curve=True) return by_ec_label(data['lmfdb_label']) except (TypeError, ValueError, ArithmeticError): return elliptic_curve_jump_error(label, info) else: query['label'] = '' if info.get('jinv'): j = clean_input(info['jinv']) j = j.replace('+', '') if not QQ_RE.match(j): info['err'] = 'Error parsing input for the j-invariant. It needs to be a rational number.' return search_input_error(info, bread) query['jinv'] = str(QQ(j)) # to simplify e.g. 1728/1 for field in ['conductor', 'torsion', 'rank', 'sha']: if info.get(field): info[field] = clean_input(info[field]) ran = info[field] ran = ran.replace('..', '-').replace(' ', '') if not LIST_RE.match(ran): names = {'conductor': 'conductor', 'torsion': 'torsion order', 'rank': 'rank', 'sha': 'analytic order of Ш'} info['err'] = 'Error parsing input for the %s. It needs to be an integer (such as 25), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 4,9,16 or 4-25, 81-121).' % names[field] return search_input_error(info, bread) # Past input check tmp = parse_range2(ran, field) # work around syntax for $or # we have to foil out multiple or conditions if tmp[0] == '$or' and '$or' in query: newors = [] for y in tmp[1]: oldors = [dict.copy(x) for x in query['$or']] for x in oldors: x.update(y) newors.extend(oldors) tmp[1] = newors query[tmp[0]] = tmp[1] if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 if 'torsion_structure' in info and info['torsion_structure']: res = parse_torsion_structure(info['torsion_structure'],2) if 'Error' in res: info['err'] = res return search_input_error(info, bread) #update info for repeat searches info['torsion_structure'] = str(res).replace(' ','') query['torsion_structure'] = [str(r) for r in res] if info.get('surj_primes'): info['surj_primes'] = clean_input(info['surj_primes']) format_ok = LIST_POSINT_RE.match(info['surj_primes']) if format_ok: surj_primes = [int(p) for p in info['surj_primes'].split(',')] format_ok = all([ZZ(p).is_prime(proof=False) for p in surj_primes]) if format_ok: query['non-surjective_primes'] = {"$nin": surj_primes} else: info['err'] = 'Error parsing input for surjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) if info.get('nonsurj_primes'): info['nonsurj_primes'] = clean_input(info['nonsurj_primes']) format_ok = LIST_POSINT_RE.match(info['nonsurj_primes']) if format_ok: nonsurj_primes = [int(p) for p in info['nonsurj_primes'].split(',')] format_ok = all([ZZ(p).is_prime(proof=False) for p in nonsurj_primes]) if format_ok: if info['surj_quantifier'] == 'exactly': nonsurj_primes.sort() query['non-surjective_primes'] = nonsurj_primes else: if 'non-surjective_primes' in query: query['non-surjective_primes'] = { "$nin": surj_primes, "$all": nonsurj_primes } else: query['non-surjective_primes'] = { "$all": nonsurj_primes } else: info['err'] = 'Error parsing input for nonsurjective primes. It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).' return search_input_error(info, bread) if 'download' in info and info['download'] != '0': res = db_ec().find(query).sort([ ('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING) ]) return download_search(info, res) count_default = 100 if info.get('count'): try: count = int(info['count']) except: count = count_default else: count = count_default info['count'] = count start_default = 0 if info.get('start'): try: start = int(info['start']) if(start < 0): start += (1 - (start + 1) / count) * count except: start = start_default else: start = start_default cursor = db_ec().find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING) ]).skip(start).limit(count) info['curves'] = res info['format_ainvs'] = format_ainvs info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number']) info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['number'] = nres info['start'] = start info['count'] = count info['more'] = int(start + count < nres) if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres credit = 'John Cremona' if 'non-surjective_primes' in query: credit += 'and Andrew Sutherland' t = 'Elliptic Curves search results' return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
def r_alg(a_invs): return EllipticCurve(F, a_invs).rank()
def KH0(T): return EllipticCurve([0,7,0,0,28*T])
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 = {} try: data['ainvs'] = [int(c) for c in self.xainvs[1:-1].split(',')] except AttributeError: data['ainvs'] = [int(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']) mw = self.mw = {} mw['rank'] = self.rank mw['int_points'] = '' if self.xintcoords: a1, a2, a3, a4, a6 = [ZZ(a) for a in data['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(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['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)) # try to get all the data we need from the database entry (now in self) try: data['equation'] = self.equation local_data = self.local_data D = self.signD * prod( [ld['p']**ld['ord_disc'] for ld in local_data]) 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'] minq_label = self.min_quad_twist['label'] data['minq_label'] = db_ec().find_one( {'label': minq_label}, ['lmfdb_label'])['lmfdb_label'] data['minq_info'] = '(itself)' if minqD == 1 else '(by %s)' % minqD try: data['degree'] = self.degree except AttributeError: data['degree'] = 0 # invalid, but will be displayed nicely mw['heights'] = self.heights if self.number == 1: data['an'] = self.anlist data['ap'] = self.aplist else: r = db_ec().find_one({ 'lmfdb_iso': self.lmfdb_iso, 'number': 1 }, ['anlist', 'aplist']) data['an'] = r['anlist'] data['ap'] = r['aplist'] # otherwise fall back to computing it from the curve except AttributeError: print("Falling back to constructing E") self.E = EllipticCurve(data['ainvs']) data['equation'] = web_latex(self.E) data['disc'] = D = self.E.discriminant() Nfac = N.factor() Dfac = D.factor() bad_primes = [p for p, e in Nfac] try: data['degree'] = self.degree except AttributeError: try: data['degree'] = self.E.modular_degree() except RuntimeError: data['degree'] = 0 # invalid, but will be displayed nicely minq, minqD = self.E.minimal_quadratic_twist() data['minq_D'] = minqD if minqD == 1: data['minq_label'] = self.lmfdb_label data['minq_info'] = '(itself)' else: # This relies on the minimal twist being in the # database, which is true when the database only # contains the Cremona database. It would be a good # idea if, when the database is extended, we ensured # that for any curve included, all twists of smaller # conductor are also included. minq_ainvs = [str(c) for c in minq.ainvs()] data['minq_label'] = db_ec().find_one( { 'jinv': str(self.E.j_invariant()), 'ainvs': minq_ainvs }, ['lmfdb_label'])['lmfdb_label'] data['minq_info'] = '(by %s)' % minqD if self.gens: self.generators = [self.E(g) for g in parse_points(self.gens)] mw['heights'] = [P.height() for P in self.generators] data['an'] = self.E.anlist(20, python_ints=True) data['ap'] = self.E.aplist(100, python_ints=True) self.local_data = local_data = [] for p in bad_primes: ld = self.E.local_data(p, algorithm="generic") local_data_p = {} local_data_p['p'] = p local_data_p['cp'] = ld.tamagawa_number() local_data_p['kod'] = web_latex(ld.kodaira_symbol()).replace( '$', '') local_data_p['red'] = ld.bad_reduction_type() rootno = -ld.bad_reduction_type() if rootno == 0: rootno = self.E.root_number(p) local_data_p['rootno'] = rootno local_data_p['ord_cond'] = ld.conductor_valuation() local_data_p['ord_disc'] = ld.discriminant_valuation() local_data_p['ord_den_j'] = max( 0, -self.E.j_invariant().valuation(p)) local_data.append(local_data_p) # If we got the data from the database, the root numbers may # not have been stored there, so we have to compute them. If # there are additive primes this means constructing the curve. for ld in self.local_data: if not 'rootno' in ld: rootno = -ld['red'] if rootno == 0: try: E = self.E except AttributeError: self.E = E = EllipticCurve(data['ainvs']) rootno = E.root_number(ld['p']) ld['rootno'] = rootno minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label']) data['disc_factor'] = latex(Dfac) data['cond_factor'] = latex(Nfac) data['disc_latex'] = web_latex(D) data['cond_latex'] = web_latex(N) 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'] 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 ] 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'])] cond, iso, num = split_lmfdb_label(self.lmfdb_label) self.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso) self.ncurves = db_ec().count({'lmfdb_iso': self.lmfdb_iso}) 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 & 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 tamagawa_numbers = [ZZ(ld['cp']) for ld in local_data] cp_fac = [cp.factor() for cp in tamagawa_numbers] cp_fac = [ latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')' for cp in cp_fac ] bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac) bsd['tamagawa_product'] = prod(tamagawa_numbers) data['newform'] = web_latex( PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)) data['newform_label'] = self.newform_label = newform_label( cond, 2, 1, iso) self.newform_link = url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso) self.newform_exists_in_db = is_newform_in_db(self.newform_label) self._code = None self.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso) self.friends = [('Isogeny class ' + self.lmfdb_iso, self.class_url), ('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))] if not self.cm: if N <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso))] if N <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', label=self.lmfdb_iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.downloads = [('Download coefficients of q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)), ('Download all stored data', url_for(".download_EC_all", label=self.lmfdb_label)), ('Download Magma code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')), ('Download Sage code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')), ('Download GP code', 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 = '<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 KH1(T): a4 = 7*T**3+7*T**2-19*T-16 a6 = -T**5+14*T**4+63*T**3+77*T**2+38*T+20 return EllipticCurve([0,1,0,a4,a6])
def curves(line, verbose=False): r""" Parses one line from a curves file. Returns the label and a dict containing fields with keys 'field_label', 'degree', 'signature', 'abs_disc', 'label', 'short_label', conductor_label', 'conductor_ideal', 'conductor_norm', 'iso_label', 'iso_nlabel', 'number', 'ainvs', 'jinv', 'cm', 'q_curve', 'base_change', 'torsion_order', 'torsion_structure', 'torsion_gens'; and (added May 2016): 'equation', 'local_data', 'non_min_p', 'minD' Input line fields (13): field_label conductor_label iso_label number conductor_ideal conductor_norm a1 a2 a3 a4 a6 cm base_change Sample input line: 2.0.4.1 65.18.1 a 1 [65,18,1] 65 1,1 1,1 0,1 -1,1 -1,0 0 0 """ # Parse the line and form the full label: data = split(line) if len(data) != 13: print "line %s does not have 13 fields, skipping" % line field_label = data[0] # string IQF_flag = field_label.split(".")[:2] == ['2', '0'] K = nf_lookup(field_label) if IQF_flag else None conductor_label = data[1] # string # convert label (does nothing except for imaginary quadratic) conductor_label = convert_conductor_label(field_label, conductor_label) iso_label = data[2] # string iso_nlabel = numerify_iso_label(iso_label) # int number = int(data[3]) # int short_class_label = "%s-%s" % (conductor_label, iso_label) short_label = "%s%s" % (short_class_label, str(number)) class_label = "%s-%s" % (field_label, short_class_label) label = "%s-%s" % (field_label, short_label) conductor_ideal = data[4] # string conductor_norm = int(data[5]) # int ainvs = ";".join(data[6:11]) # one string joining 5 NFelt strings cm = data[11] # int or '?' if cm != '?': cm = int(cm) # Create the field and curve to compute the j-invariant: dummy, deg, sig, abs_disc = field_data(field_label) K = nf_lookup(field_label) #print("Field %s created, gen_name = %s" % (field_label,str(K.gen()))) ainvsK = parse_ainvs(K, ainvs) # list of K-elements E = EllipticCurve(ainvsK) #print("{} created with disc = {}, N(disc)={}".format(E,K.ideal(E.discriminant()).factor(),E.discriminant().norm().factor())) j = E.j_invariant() jinv = NFelt(j) if cm == '?': cm = get_cm(j) if cm: print "cm=%s for j=%s" % (cm, j) q_curve = data[12] # 0, 1 or ?. If unknown we'll determine this below. if q_curve in ['0', '1']: # already set -- easy q_curve = bool(int(q_curve)) else: try: q_curve = is_Q_curve(E) except NotImplementedError: q_curve = '?' # Here we should check that the conductor of the constructed curve # agrees with the input conductor. N = ideal_from_string(K, conductor_ideal) NE = E.conductor() if N == "wrong" or N != NE: print( "Wrong conductor ideal {} for label {}, using actual conductor {} instead" .format(conductor_ideal, label, NE)) conductor_ideal = ideal_to_string(NE) N = NE # get torsion order, structure and generators: torgroup = E.torsion_subgroup() ntors = int(torgroup.order()) torstruct = [int(n) for n in list(torgroup.invariants())] torgens = [point_string(P.element()) for P in torgroup.gens()] # get label of elliptic curve over Q for base_change cases (a # subset of Q-curves) if True: # q_curve: now we have not precomputed Q-curve status # but still want to test for base change! if verbose: print("testing {} for base-change...".format(label)) E1list = E.descend_to(QQ) if len(E1list): base_change = [cremona_to_lmfdb(E1.label()) for E1 in E1list] if verbose: print "%s is base change of %s" % (label, base_change) else: base_change = [] # print "%s is a Q-curve, but not base-change..." % label else: base_change = [] # NB if this is not a global minimal model then local_data may # include a prime at which we have good reduction. This causes no # problems except that the bad_reduction_type is then None which # cannot be converted to an integer. The bad reduction types are # coded as (Sage) integers in {-1,0,1}. local_data = [{ 'p': ideal_to_string(ld.prime()), 'normp': str(ld.prime().norm()), 'ord_cond': int(ld.conductor_valuation()), 'ord_disc': int(ld.discriminant_valuation()), 'ord_den_j': int(max(0, -(E.j_invariant().valuation(ld.prime())))), 'red': None if ld.bad_reduction_type() == None else int(ld.bad_reduction_type()), 'kod': web_latex(ld.kodaira_symbol()).replace('$', ''), 'cp': int(ld.tamagawa_number()) } for ld in E.local_data()] non_minimal_primes = [ideal_to_string(P) for P in E.non_minimal_primes()] minD = ideal_to_string(E.minimal_discriminant_ideal()) edata = { 'field_label': field_label, 'degree': deg, 'signature': sig, 'abs_disc': abs_disc, 'class_label': class_label, 'short_class_label': short_class_label, 'label': label, 'short_label': short_label, 'conductor_label': conductor_label, 'conductor_ideal': conductor_ideal, 'conductor_norm': conductor_norm, 'iso_label': iso_label, 'iso_nlabel': iso_nlabel, 'number': number, 'ainvs': ainvs, 'jinv': jinv, 'cm': cm, 'q_curve': q_curve, 'base_change': base_change, 'torsion_order': ntors, 'torsion_structure': torstruct, 'torsion_gens': torgens, 'equation': web_latex(E), 'local_data': local_data, 'minD': minD, 'non_min_p': non_minimal_primes, } return label, edata
def KH2(T): a4 = -(45927*T**3+204120*T**2+162432*T+4181) a6 = -(531441*T**5 + 12262509*T**4 + 39287997*T**3 + 43008840*T**2 + 8670080*T - 102675) return EllipticCurve([0,1,0,a4,a6])
def render_isogeny_class(iso_class): info = {} credit = 'John Cremona' lmfdb_iso = iso_class # e.g. '11.a' N, iso, number = lmfdb_label_regex.match(lmfdb_iso).groups() CDB = lmfdb.base.getDBConnection().elliptic_curves.curves E1data = CDB.find_one({'lmfdb_label': lmfdb_iso + '1'}) if E1data is None: return elliptic_curve_jump_error(lmfdb_iso, {}) cremona_iso = E1data['iso'] ainvs = [int(a) for a in E1data['ainvs']] E1 = EllipticCurve(ainvs) ver = sage.version.version.split('.') # e.g. "6.1.beta2" ma = int(ver[0]) mi = int(ver[1]) if ma > 6 or ma == 6 and mi > 1: # Code for Sage 6.2 and later: isogeny_class = E1.isogeny_class() curves = isogeny_class.curves mat = isogeny_class.matrix() else: # Code for Sage 6.1 and before: curves, mat = E1.isogeny_class() size = len(curves) # Create a list of the curves in the class from the database, so # they are in the correct order! db_curves = [E1] optimal_flags = [False] * size degrees = [0] * size if 'degree' in E1data: degrees[0] = E1data['degree'] else: try: degrees[0] = E1.modular_degree() except RuntimeError: pass cremona_labels = [E1data['label']] + [0] * (size - 1) if E1data['number'] == 1: optimal_flags[0] = True for i in range(2, size + 1): Edata = CDB.find_one({'lmfdb_label': lmfdb_iso + str(i)}) E = EllipticCurve([int(a) for a in Edata['ainvs']]) cremona_labels[i - 1] = Edata['label'] if Edata['number'] == 1: optimal_flags[i - 1] = True if 'degree' in Edata: degrees[i - 1] = Edata['degree'] else: try: degrees[i - 1] = E.modular_degree() except RuntimeError: pass db_curves.append(E) if cremona_iso == '990h': # this isogeny class is labeled wrong in Cremona's tables optimal_flags = [False, False, True, False] # Now work out the permutation needed to match the two lists of curves: perm = [db_curves.index(E) for E in curves] # Apply the same permutation to the isogeny matrix: mat = [[mat[perm[i], perm[j]] for j in range(size)] for i in range(size)] info = {'label': lmfdb_iso} info['optimal_ainvs'] = ainvs info['rank'] = E1data['rank'] info['isogeny_matrix'] = latex(matrix(mat)) # info['f'] = ajax_more(E.q_eigenform, 10, 20, 50, 100, 250) info['f'] = web_latex(E.q_eigenform(10)) info['graph_img'] = url_for('.plot_iso_graph', label=lmfdb_iso) info['curves'] = [[ lmfdb_iso + str(i + 1), cremona_labels[i], str(list(c.ainvs())), c.torsion_order(), degrees[i], optimal_flags[i] ] for i, c in enumerate(db_curves)] friends = [] # friends.append(('Quadratic Twist', "/quadratic_twists/%s" % (lmfdb_iso))) friends.append(('L-function', url_for("l_functions.l_function_ec_page", label=lmfdb_iso))) friends.append(('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=lmfdb_iso))) friends.append(('Symmetric 4th power L-function', url_for("l_functions.l_function_ec_sym_page", power='4', label=lmfdb_iso))) # render_one_elliptic_modular_form(level,weight,character,label,**kwds) friends.append(('Modular form ' + lmfdb_iso.replace('.', '.2'), url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=0, label=iso))) info['friends'] = friends info['downloads'] = [('Download coeffients of q-expansion', url_for(".download_EC_qexp", label=lmfdb_iso, limit=100)), ('Download stored data for curves in this class', url_for(".download_EC_all", label=lmfdb_iso))] if lmfdb_iso == cremona_iso: t = "Elliptic Curve Isogeny Class %s" % lmfdb_iso else: t = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % ( lmfdb_iso, cremona_iso) bread = [('Elliptic Curves ', url_for(".rational_elliptic_curves")), ('isogeny class %s' % lmfdb_iso, ' ')] return render_template("iso_class.html", info=info, bread=bread, credit=credit, title=t, friends=info['friends'], downloads=info['downloads'])
def from_label(lab, symplectic=True): return XE7.from_elliptic_curve(EllipticCurve(lab),symplectic=symplectic)
def check_curves(field_label='2.0.4.1', min_norm=0, max_norm=None, label=None, check_ap=False, verbose=False): r"""Go through all Bianchi Modular Forms with the given field label, assumed imaginary quadratic (i.e. '2.0.d.1' with d in {4,8,3,7,11}), check whether an elliptic curve exists with the same label. If so, and if check_ap is True, check that the a_P agree. """ if field_label not in fields: print("No BMF data available for field {}".format(field_label)) return else: K = field_from_label(field_label) print("Checking forms over {}, norms from {} to {}".format( field_label, min_norm, max_norm)) query = {} query['field_label'] = field_label query['dimension'] = 1 # only look at rational newforms if label: print("looking for {} only".format(label)) query['short_label'] = label # e.g. '91.1-a' else: query['level_norm'] = {'$gte': int(min_norm)} if max_norm: query['level_norm']['$lte'] = int(max_norm) cursor = forms.search(query, sort=['level_norm']) labels = [f['short_label'] for f in cursor] nforms = len(labels) print("found {} newforms".format(nforms)) labels = [lab for lab in labels if lab not in false_curves[field_label]] nforms = len(labels) print( " of which {} should have associated curves (not false ones)".format( nforms)) nfound = 0 nnotfound = 0 nok = 0 missing_curves = [] mismatches = [] primes = list(primes_iter(K, maxnorm=1000)) if check_ap else [] curve_ap = {} # curve_ap[conductor_label] will be a dict iso -> ap form_ap = {} # form_ap[conductor_label] will be a dict iso -> ap # Now look at all newforms, check that there is an elliptic # curve of the same label, and if so compare ap-lists. The # dicts curve_ap and form_ap store these when there is # disagreement: e.g. curve_ap[conductor_label][iso_label] = # aplist. print("checking {} newforms".format(nforms)) n = 0 for curve_label in labels: n += 1 if n % 100 == 0: perc = 100.0 * n / nforms print("{} forms checked ({}%)".format(n, perc)) # We find the forms again since otherwise the cursor might timeout during the loop. label = "-".join([field_label, curve_label]) if verbose: print("newform and isogeny class label {}".format(label)) f = forms.lucky({'label': label}) if f: if verbose: print("found newform with label {}".format(label)) else: print("no newform in database has label {}!".format(label)) continue ec = nfcurves.lucky({'class_label': label, 'number': 1}) if ec: if verbose: print("curve with label %s found in the database" % curve_label) nfound += 1 if not check_ap: continue ainvsK = parse_ainvs(K, ec['ainvs']) if verbose: print("E = {}".format(ainvsK)) E = EllipticCurve(ainvsK) if verbose: print("constructed elliptic curve {}".format(E.ainvs())) good_flags = [E.has_good_reduction(P) for P in primes] good_primes = [P for (P, flag) in zip(primes, good_flags) if flag] if verbose: print("{} good primes".format(len(good_primes))) f_aplist = f['hecke_eigs'] f_aplist = [ap for ap, flag in zip(f_aplist, good_flags) if flag] nap = len(f_aplist) if verbose: print("recovered {} ap from BMF".format(nap)) aplist = [ E.reduction(P).trace_of_frobenius() for P in good_primes[:nap] ] if verbose: print("computed {} ap from elliptic curve".format(nap)) if aplist[:nap] == f_aplist[:nap]: nok += 1 if verbose: print("Curve {} and newform agree! (checked {} ap)".format( ec['short_label'], nap)) else: print("Curve {} does NOT agree with newform".format( ec['short_label'])) mismatches.append(label) if verbose: for P, aPf, aPc in zip(good_primes[:nap], f_aplist[:nap], aplist[:nap]): if aPf != aPc: print("P = {} with norm {}".format( P, P.norm().factor())) print("ap from curve: %s" % aPc) print("ap from form: %s" % aPf) if not ec['conductor_label'] in curve_ap: curve_ap[ec['conductor_label']] = {} form_ap[ec['conductor_label']] = {} curve_ap[ec['conductor_label']][ec['iso_label']] = aplist form_ap[ec['conductor_label']][f['label_suffix']] = f_aplist else: if verbose: print("No curve with label %s found in the database!" % curve_label) missing_curves.append(f['short_label']) nnotfound += 1 # Report progress: n = nfound + nnotfound if nnotfound: print( "Out of %s newforms, %s curves were found in the database and %s were not found" % (n, nfound, nnotfound)) else: print( "Out of %s newforms, all %s had curves with the same label and ap" % (n, nfound)) if nfound == nok: print("All curves agree with matching newforms") else: print("%s curves agree with matching newforms, %s do not" % (nok, nfound - nok)) if nnotfound: print("%s missing curves" % len(missing_curves)) else: pass if mismatches: print("{} form-curve pairs had inconsistent ap:".format( len(mismatches))) print(mismatches)
def test_isom_labels(lab1,lab2, symplectic=True, verbose=False): E1 = EllipticCurve(lab1) E2 = EllipticCurve(lab2) if verbose: print("Testing {} ={} and {} = {}".format(lab1,E1.ainvs(),lab2,E2.ainvs())) return test_isom(E1, E2, symplectic=symplectic, verbose=verbose)
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, ' ')]
from structures.fields.finite import FiniteField from time import time from point_counting.naive import naive_order def measure_time(func, *args): t = time() res = func(*args) print(f"Function took {time()-t} seconds to run") return res # print(time("challenge", "challenges.exceptional_curves", "")) # a,b,p = 46, 74, 97 a, b, p = (1333, 1129, 3571) E = EllipticCurve(GF(p), [a, b]) print(E.order()) F = FiniteField(p) E2 = EC(F, a, b) print(measure_time(naive_order, E2)) print(measure_time(schoof, E2)) """ E = EllipticCurve(GF(p), [a, b]) print(E.order()) F = FiniteField(p) E2 = EC(F, a, b) print(measure_time(schoof, E2)) """ """ ec_test_values = [ (13, 215, 229), (106, 166, 197), (31, 16, 137),