Path: blob/main/scripts/hmf/convert_hecke_eigenvalues/hecke_eigenvals.py
1475 views
# If Hecke eigenfield is in the LMFDB, expresses eigenvalues in terms of listed integral basis1# TODO: Integrate with LLL-reduced basis? (see NotImplementedError below)23import pymongo, hashlib4from sage.all import PolynomialRing, QQ, preparse, gp, NumberField, matrix, vector5#from sage.all import *67#P = subprocess.Popen(["ssh","mongo","-N"])8_C = None91011def makeDBconnection():12global _C13_C = pymongo.MongoClient("localhost:37010")14# _C = pymongo.MongoClient("m0.lmfdb.xyz:27017")15# _C = pymongo.MongoClient("readonly.lmfdb.xyz:27017")16_C.admin.authenticate("lmfdb", "lmfdb")171819def getDBconnection():20if _C is None:21makeDBconnection()22return _C232425def get_hmfs_hecke_field_and_eigenvals(label):26"""Get the Hecke field and eigenvalues for the Hilbert modular form with given label.2728INPUT:29label -- string, the label of the Hilbert modular form3031OUTPUT:32K_old -- number field, the field containing the Hecke eigenvalues33e -- number field element, a generator for K_old over QQ34eigenvals -- list, a list of the Hecke eigenvalues35"""36C = getDBconnection()37# Should I use find_one, or something else?38R = PolynomialRing(QQ,names=('x'))39form = C.hmfs.forms.find_one({'label':label})40poly = R(str(form['hecke_polynomial']))41K_old = NumberField(poly, names=('e',))42(e,) = K_old._first_ngens(1)43eigenvals_str = form['hecke_eigenvalues']44eigenvals = [K_old(eval(preparse(el))) for el in eigenvals_str]45return K_old, e, eigenvals4647def polredabs_coeffs(poly):48"""Apply gp.polredabs to the given polynomial and return the coefficients as a comma-separated string.4950INPUT:51poly -- polynomial, a polynomial with coefficients in QQ5253OUTPUT:54cs_string -- string, the coefficients of the normalized polynomial (the output of gp.polredabs(poly)), given as a comma-separated string with no spaces55"""56R = poly.parent()57(x,) = R._first_ngens(1)58poly_new = R(str(gp.polredabs(poly)))59cs = poly_new.coefficients(sparse=False)60cs_string = ",".join([str(el) for el in cs])61return cs_string6263def coeffs_to_poly(c_string):64"""Given a string of coefficients, returns the polynomial with those coefficients6566INPUT:67c_string -- string, a a comma-separated string (with no spaces) of rational numbers6869OUTPUT:70The polynomial with these coefficients71"""72R = PolynomialRing(QQ, names=('x',))73(x,) = R._first_ngens(1)74tup = eval(c_string)75return sum([tup[i]*x**i for i in range(0,len(tup))])7677def field_coeffs_string_to_hash(c_string):78"""Given a string of coefficients, returns their hash7980INPUT:81c_string -- string, a comma-separated string (with no spaces) of rational numbers8283OUTPUT:84c_hash -- string, the hash of the string of coefficients85"""86c_hash = hashlib.md5(c_string).hexdigest()87return c_hash8889def get_number_field_integral_basis(c_string):90r"""Get the integral basis for the field specified by the string.9192INPUT:93c_string -- string, a string of comma-separated coefficients with no spaces: the coefficients of the normalized (using gp.polredabs) defining polynomial9495OUTPUT:96fld_bool -- bool, True if the number field has a page in the LMFDB, False otherwise97K_new -- number field, the number field with defining polynomial that is the normalized version (given by gp.polredabs) of the one with coefficients specified by c_string98a -- number field element, generator for K_new99the integral basis for K_new recorded on its LMFDB page100"""101C = getDBconnection()102c_hash = field_coeffs_string_to_hash(c_string)103field = C.numberfields.fields.find_one({'coeffhash':c_hash})104fld_bool = True105try:106field['degree']107except TypeError:108fld_bool = False109if fld_bool:110field_str = field['coeffs']111int_basis_str = field['zk']112poly = coeffs_to_poly(field_str)113K_new = NumberField(poly, names=('a',))114(a,) = K_new._first_ngens(1)115return fld_bool, K_new, a, [K_new(eval(preparse(el))) for el in int_basis_str]116else:117# could add polynomial to list of number fields missing from LMFDB here118return fld_bool, None, None, None119120def vector_to_string(vec):121"""Convert vector of integers to string122123INPUT:124vec -- vector, a vector of integers125126OUTPUT:127A comma-separated string with no spaces containing the integers in vec128"""129vec_string = ""130for i in range(0,len(vec)-1):131vec_string += str(vec[i]) + ","132vec_string += str(vec[len(vec)-1]) # don't forget to append last entry!133return vec_string134135def convert_hecke_eigenvalues(K_old, eigenvals, K_new, int_basis):136"""Re-express the Hecke eigenvalues in terms of the integral basis given in the LMFDB137138INPUT:139K_old -- the field containing the Hecke eigenvalues140eigenvals -- the Hecke eigenvalues, in terms of a field generator (usually the eigenvalue for T_2) for the field K_old141K_new -- a "nicer" field isomorphic to K_old (often one whose polynomial has been polredabs'd)142int_basis -- an integral basis for the ring of integers of K_new143144OUTPUT:145eigenvals_new -- list, a list of strings of the coefficients of the Hecke eigenvalues with respect to the integral basis recorded in the LMFDB146K_new -- number field, the (normalized) number field containing the Hecke eigenvalues, as given in the LMFDB147a -- number field element, the generator for the field K_new148int_basis -- list, a list containing the integral basis for K_new149"""150if not K_old.is_isomorphic(K_new):151raise RuntimeError("Fields not isomorphic!")152iota = K_old.embeddings(K_new)[0]153(a,) = K_new._first_ngens(1)154155# make change of basis matrix156chg_basis_entries = []157for el in int_basis:158chg_basis_entries.append(el.list())159chg_basis_mat = matrix(chg_basis_entries) # changes from int_basis to 1, a, a^2, ..., a^(n-1)160chg_basis_mat = chg_basis_mat.inverse() # changes from 1, a, a^2, ..., a^(n-1) to int_basis161162# convert entries163eigenvals_new = []164for el in eigenvals:165v = vector(iota(el).list())166eigenvals_new.append(v*chg_basis_mat)167168# verify correctness of new expression for eigenvalues169eigenvals_old = [iota(el) for el in eigenvals]170for j in range(0,len(eigenvals)):171new_val = 0172for i in range(0,len(int_basis)):173new_val += eigenvals_new[j][i]*int_basis[i]174assert new_val == eigenvals_old[j]175176eigen_strings = []177for c in eigenvals_new:178eigen_strings.append(vector_to_string(c))179return eigen_strings, K_new, a, int_basis180181# Wrapper for above functions182def convert_hmfs_hecke_eigenvalues_from_label(label):183"""Given the label of a Hilbert modular form, look for the entry of its Hecke eigenfield in the LMFDB and re-express the Hecke eigenvalues in terms of the integral basis given there184185INPUT:186label -- string, the label of a Hilbert modular form187188OUTPUT:189eigenvals_new -- list, a list of strings of the coefficients of the Hecke eigenvalues with respect to the integral basis recorded in the LMFDB190K_new -- number field, the (normalized) number field containing the Hecke eigenvalues, as given in the LMFDB191a -- number field element, the generator for the field K_new192int_basis -- list, a list containing the integral basis for K_new193"""194K_old, e, eigenvals = get_hmfs_hecke_field_and_eigenvals(label)195old_poly = K_old.defining_polynomial()196c_string = polredabs_coeffs(old_poly)197fld_bool, K_new, a, int_basis = get_number_field_integral_basis(c_string)198if not fld_bool:199raise NotImplementedError("No number field entry found in the LMFDB.")200else:201return convert_hecke_eigenvalues(K_old, eigenvals, K_new, int_basis)202203204205