Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AndrewVSutherland
GitHub Repository: AndrewVSutherland/lmfdb
Path: blob/main/scripts/hmf/convert_hecke_eigenvalues/hecke_eigenvals.py
1475 views
1
# If Hecke eigenfield is in the LMFDB, expresses eigenvalues in terms of listed integral basis
2
# TODO: Integrate with LLL-reduced basis? (see NotImplementedError below)
3
4
import pymongo, hashlib
5
from sage.all import PolynomialRing, QQ, preparse, gp, NumberField, matrix, vector
6
#from sage.all import *
7
8
#P = subprocess.Popen(["ssh","mongo","-N"])
9
_C = None
10
11
12
def makeDBconnection():
13
global _C
14
_C = pymongo.MongoClient("localhost:37010")
15
# _C = pymongo.MongoClient("m0.lmfdb.xyz:27017")
16
# _C = pymongo.MongoClient("readonly.lmfdb.xyz:27017")
17
_C.admin.authenticate("lmfdb", "lmfdb")
18
19
20
def getDBconnection():
21
if _C is None:
22
makeDBconnection()
23
return _C
24
25
26
def get_hmfs_hecke_field_and_eigenvals(label):
27
"""Get the Hecke field and eigenvalues for the Hilbert modular form with given label.
28
29
INPUT:
30
label -- string, the label of the Hilbert modular form
31
32
OUTPUT:
33
K_old -- number field, the field containing the Hecke eigenvalues
34
e -- number field element, a generator for K_old over QQ
35
eigenvals -- list, a list of the Hecke eigenvalues
36
"""
37
C = getDBconnection()
38
# Should I use find_one, or something else?
39
R = PolynomialRing(QQ,names=('x'))
40
form = C.hmfs.forms.find_one({'label':label})
41
poly = R(str(form['hecke_polynomial']))
42
K_old = NumberField(poly, names=('e',))
43
(e,) = K_old._first_ngens(1)
44
eigenvals_str = form['hecke_eigenvalues']
45
eigenvals = [K_old(eval(preparse(el))) for el in eigenvals_str]
46
return K_old, e, eigenvals
47
48
def polredabs_coeffs(poly):
49
"""Apply gp.polredabs to the given polynomial and return the coefficients as a comma-separated string.
50
51
INPUT:
52
poly -- polynomial, a polynomial with coefficients in QQ
53
54
OUTPUT:
55
cs_string -- string, the coefficients of the normalized polynomial (the output of gp.polredabs(poly)), given as a comma-separated string with no spaces
56
"""
57
R = poly.parent()
58
(x,) = R._first_ngens(1)
59
poly_new = R(str(gp.polredabs(poly)))
60
cs = poly_new.coefficients(sparse=False)
61
cs_string = ",".join([str(el) for el in cs])
62
return cs_string
63
64
def coeffs_to_poly(c_string):
65
"""Given a string of coefficients, returns the polynomial with those coefficients
66
67
INPUT:
68
c_string -- string, a a comma-separated string (with no spaces) of rational numbers
69
70
OUTPUT:
71
The polynomial with these coefficients
72
"""
73
R = PolynomialRing(QQ, names=('x',))
74
(x,) = R._first_ngens(1)
75
tup = eval(c_string)
76
return sum([tup[i]*x**i for i in range(0,len(tup))])
77
78
def field_coeffs_string_to_hash(c_string):
79
"""Given a string of coefficients, returns their hash
80
81
INPUT:
82
c_string -- string, a comma-separated string (with no spaces) of rational numbers
83
84
OUTPUT:
85
c_hash -- string, the hash of the string of coefficients
86
"""
87
c_hash = hashlib.md5(c_string).hexdigest()
88
return c_hash
89
90
def get_number_field_integral_basis(c_string):
91
r"""Get the integral basis for the field specified by the string.
92
93
INPUT:
94
c_string -- string, a string of comma-separated coefficients with no spaces: the coefficients of the normalized (using gp.polredabs) defining polynomial
95
96
OUTPUT:
97
fld_bool -- bool, True if the number field has a page in the LMFDB, False otherwise
98
K_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_string
99
a -- number field element, generator for K_new
100
the integral basis for K_new recorded on its LMFDB page
101
"""
102
C = getDBconnection()
103
c_hash = field_coeffs_string_to_hash(c_string)
104
field = C.numberfields.fields.find_one({'coeffhash':c_hash})
105
fld_bool = True
106
try:
107
field['degree']
108
except TypeError:
109
fld_bool = False
110
if fld_bool:
111
field_str = field['coeffs']
112
int_basis_str = field['zk']
113
poly = coeffs_to_poly(field_str)
114
K_new = NumberField(poly, names=('a',))
115
(a,) = K_new._first_ngens(1)
116
return fld_bool, K_new, a, [K_new(eval(preparse(el))) for el in int_basis_str]
117
else:
118
# could add polynomial to list of number fields missing from LMFDB here
119
return fld_bool, None, None, None
120
121
def vector_to_string(vec):
122
"""Convert vector of integers to string
123
124
INPUT:
125
vec -- vector, a vector of integers
126
127
OUTPUT:
128
A comma-separated string with no spaces containing the integers in vec
129
"""
130
vec_string = ""
131
for i in range(0,len(vec)-1):
132
vec_string += str(vec[i]) + ","
133
vec_string += str(vec[len(vec)-1]) # don't forget to append last entry!
134
return vec_string
135
136
def convert_hecke_eigenvalues(K_old, eigenvals, K_new, int_basis):
137
"""Re-express the Hecke eigenvalues in terms of the integral basis given in the LMFDB
138
139
INPUT:
140
K_old -- the field containing the Hecke eigenvalues
141
eigenvals -- the Hecke eigenvalues, in terms of a field generator (usually the eigenvalue for T_2) for the field K_old
142
K_new -- a "nicer" field isomorphic to K_old (often one whose polynomial has been polredabs'd)
143
int_basis -- an integral basis for the ring of integers of K_new
144
145
OUTPUT:
146
eigenvals_new -- list, a list of strings of the coefficients of the Hecke eigenvalues with respect to the integral basis recorded in the LMFDB
147
K_new -- number field, the (normalized) number field containing the Hecke eigenvalues, as given in the LMFDB
148
a -- number field element, the generator for the field K_new
149
int_basis -- list, a list containing the integral basis for K_new
150
"""
151
if not K_old.is_isomorphic(K_new):
152
raise RuntimeError("Fields not isomorphic!")
153
iota = K_old.embeddings(K_new)[0]
154
(a,) = K_new._first_ngens(1)
155
156
# make change of basis matrix
157
chg_basis_entries = []
158
for el in int_basis:
159
chg_basis_entries.append(el.list())
160
chg_basis_mat = matrix(chg_basis_entries) # changes from int_basis to 1, a, a^2, ..., a^(n-1)
161
chg_basis_mat = chg_basis_mat.inverse() # changes from 1, a, a^2, ..., a^(n-1) to int_basis
162
163
# convert entries
164
eigenvals_new = []
165
for el in eigenvals:
166
v = vector(iota(el).list())
167
eigenvals_new.append(v*chg_basis_mat)
168
169
# verify correctness of new expression for eigenvalues
170
eigenvals_old = [iota(el) for el in eigenvals]
171
for j in range(0,len(eigenvals)):
172
new_val = 0
173
for i in range(0,len(int_basis)):
174
new_val += eigenvals_new[j][i]*int_basis[i]
175
assert new_val == eigenvals_old[j]
176
177
eigen_strings = []
178
for c in eigenvals_new:
179
eigen_strings.append(vector_to_string(c))
180
return eigen_strings, K_new, a, int_basis
181
182
# Wrapper for above functions
183
def convert_hmfs_hecke_eigenvalues_from_label(label):
184
"""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 there
185
186
INPUT:
187
label -- string, the label of a Hilbert modular form
188
189
OUTPUT:
190
eigenvals_new -- list, a list of strings of the coefficients of the Hecke eigenvalues with respect to the integral basis recorded in the LMFDB
191
K_new -- number field, the (normalized) number field containing the Hecke eigenvalues, as given in the LMFDB
192
a -- number field element, the generator for the field K_new
193
int_basis -- list, a list containing the integral basis for K_new
194
"""
195
K_old, e, eigenvals = get_hmfs_hecke_field_and_eigenvals(label)
196
old_poly = K_old.defining_polynomial()
197
c_string = polredabs_coeffs(old_poly)
198
fld_bool, K_new, a, int_basis = get_number_field_integral_basis(c_string)
199
if not fld_bool:
200
raise NotImplementedError("No number field entry found in the LMFDB.")
201
else:
202
return convert_hecke_eigenvalues(K_old, eigenvals, K_new, int_basis)
203
204
205