CoCalc Public Fileswww / cgi-bin / mfd / mfe_full.py
Author: William A. Stein
Compute Environment: Ubuntu 18.04 (Deprecated)
1# mfe_full.py
2# (c) William Stein, 2000
3
4import cgi  # cgi-bin
5import Documents, HTML
6
7import misc
8import constants
9import mfd  # modular forms database
10import mfe_misc, mfe_data_table, mfe_glossary
11
12import pari
13
14import os, string
15
16too_long = 6  # stuff longer than this is centered
17
18def is_valid(form):
19    if form.has_key("level_weight"):
20        x = mfe_misc.parse_level_weight(form["level_weight"].value)
21        if x[0] == 0:
22            return [0]
23        level = x[1]
24        weight = x[2]
25    elif form.has_key("level") and form.has_key("weight"):
26        level  = string.replace(form["level"].value," ","")
27        weight = string.replace(form["weight"].value, " ","")
28    else:
29        return [0]
30    if not (misc.is_nonnegative_number(level) and misc.is_nonnegative_number(weight)):
31        return [0]
32    if len(level) > 9 or int(level) < 1:
33        return [0]
34    if len(weight) > 9 or int(weight) < 2:
35        return [0]
36    return [1, level, weight]
37
38def factor_level(N):
39    f = pari.pari("factor(%s)"%N)
40    if f[0]=='M':
41        f=f[4:-1]
42    if f[0]=='m':
43        s="%s"%N
44    else:
45        f = string.replace(f,"[","")
46        f = string.replace(f,"]","")
47        f = string.replace(f," ","")
48        is_first = 1
49        s = ""
50        for a in string.split(f,";"):
51            b = string.split(a,",")
52            if not is_first:
53                s = s + "*"
54            s = s + "%s"%b[0]
55            if b[1]!="1":
56                s = s + "<sup>%s</sup>"%b[1]
57            is_first = 0
58    return s
59
60
61def character_selector(N,k,eps):
62    if not mfd.characters_are_known(N):
63        return ["Trivial Character", 1]
64    if k % 2 == 1:
65        parity = -1
66    else:
67        parity = +1
68    chars = mfd.characters(N)
69    s = '<SELECT name="character">';
70    selected = 0
71    our_order=1
72    for chi in chars:
73        if chi['parity'] == parity:
74            if chi['label'] == eps:
75                s = s+'<OPTION selected '
76                selected = 1
77                our_order = chi['degree']
78            else:
79                s = s+'<OPTION '
80            if chi['label'] == '1':
81                s = s+' value="1:1">Trivial character</option>'
82            else:
83                s = s + ' value="%s:%s"> Conductor %s and Order %s, &nbsp&nbsp %s </OPTION>'%(chi['label'],chi['modulus'],chi['conductor'],chi['degree'],chi['label']);
84    if not selected:
85        s = s + '<OPTION selected value="%s:%s">  %s </OPTION>'%(eps,N,eps)
86    s = s + '</SELECT>'
87    return [s,our_order]
88
90    known = M.known_charpolys()
91    if len(known) == 0:
92        return ""
93    ans = ""
94    for n in known:
95        url = '<a href="%s/mfe_charpoly.py?code=%s&n=%s">%s</a>'%(constants.CGIROOT,M.code(),n,n)
96        ans = ans + url + "&nbsp "
97    return ans
98
100    known = M.known_ap()
101    if len(known) == 0 or M.number > 1:
102        return ""
103    ans = ""
104    for n in known:
105        #if n < 100:
106        url = '<a href="%s/mfe_ap.py?code=%s&n=%s">%s</a>'%(constants.CGIROOT,M.code(),n,n)
107        ans = ans + url + "&nbsp "
108    ans = ans
109    return ans
110
111
113    known = M.known_trace_ap()
114    return "%s, %s, %s, %s"%(M.trace_ap(2),M.trace_ap(3),M.trace_ap(5),M.trace_ap(7))
115
117    primes = M.known_slopes()
118    if len(primes) == 0:
119        return ""
120    ans = "Click for slopes: "
121    for p in primes:
122        url = '<a href="%s/mfe_slopes.py?code=%s&prime=%s">%s</a>'%(constants.CGIROOT,M.code(),p,p)
123        ans = ans + url
124        if p != primes[len(primes)-1]:
125            ans = ans + ", "
126    return ans
127
129    if M.weight == 2:
130        return M.lratio_k2()
131    lratio = M.lratio()
132    ans=""
133    if lratio != constants.not_computed:
134        r = range(1,len(lratio)+1) + ['all']
135        for j in r:
136            url = '<a href="%s/mfe_lratio.py?code=%s&j=%s">L(%s)</a>'%(constants.CGIROOT,M.code(),j,j)
137            ans = ans + url + "&nbsp "
138    return ans
139
141    if M.weight == 2:
142        return M.lratio_odd_k2()
143    lratio_odd = M.lratio_odd()
144    ans=""
145    if lratio_odd != constants.not_computed:
146        r = range(1,len(lratio_odd)+1) + ['all']
147        for j in r:
148            url = '<a href="%s/mfe_lratio_odd.py?code=%s&j=%s">L(%s)</a>'%(constants.CGIROOT,M.code(),j,j)
149            ans = ans + url + "&nbsp "
150    return ans
151
152def level_weight_character_selector(N,k,eps):
153    s=  '<form action=%s/mfe_full_html.py method="get">'%constants.CGIROOT
154    s=s+'<input type="hidden" name="level_fallback" value="%s">\n'%N
155    s=s+'<input type="hidden" name="weight_fallback" value="%s">\n'%k
156    s=s+'<input type="hidden" name="level" value="%s">\n'%N
157    s=s+'<input type="hidden" name="weight" value="%s">\n'%k
158    s=s+'<input type="hidden" name="iso_class" value="0">\n'
159    s=s+'<input type="submit" value="Change space to ">\n'
160    s=s+'<input type="text" name="level_weight" value="%s,%s">\n'%(N,k)
161    x = character_selector(N,k,eps)
162    s=s + x[0]
163    s=s+ ' </form>'
164    return [s, x[1]]   # returns string and order of character, since character_select computes order of character.
165
166
167def browser(N,k):
168    s = '<a href="%s/mfe_known_html.py?level_weight=%s,%s&table=ap_data"> '%\
169        (constants.CGIROOT, N, k) + \
170        'Open Graphical Browser</a>'
171    return s
172
173def is_complete(M, order_of_eps):
174    phi_of_order_of_eps = int(pari.eulerphi(order_of_eps))
175    dim = M.dimension_new() * phi_of_order_of_eps
176    d = 0
177    for f in M.get_iso_classes():
178        if f.dimension() == constants.not_computed:
179            return 0
180        d = d + f.dimension()
181    return d == dim
182
183def table_newforms(N,k,eps, order_of_eps):
184    M = mfd.ModSym(N,k,0,eps)
185    iso = mfd.iso_class_data(N,k,eps)
186    ans = ""
187    if M.dimension_new() == constants.not_computed:
188        ans = "WARNING: Some newforms <b>might be</b> missing."
189    elif not is_complete(M, order_of_eps):
190        ans = "WARNING: Some newforms <b>are definitely missing</b>... (or?)"
191
192    if ans=="" and len(iso) == 0:
193        ans = "No newforms of this level, weight, and character"
194
195    if ans != "":
196        ans='<br><center><table bgcolor=white cellpadding=10 border=2><tr><td>' + ans + '</td></tr></table></center><br>'
197
198    if len(iso) != 0:
200        ans = ans + '<table border=0 cellpadding=4 cellspacing=2 bgcolor=%s><tr>'%constants.TABLE_BORDER_COLOR
201        ans = ans+'<td bgcolor="%s" align=center><b>Label (id)</b>&nbsp</td>'%color+\
202              '<td bgcolor="%s" align=center><b>Eigenvalue Field</b></td>'%color+\
203              '<td bgcolor="%s" align=center><b>q-Expansions</b></td>'%color+\
204              '<td bgcolor="%s" align=center><b>Traces of a<sub>p</sub> for p=2,3,5,7</b></td>'%color+\
205              '</tr>'
206
207        for i in range(0,len(iso)):
208            f = mfd.ModSym(N,k,iso[i]['iso_class'],eps,'Q',iso[i]['number'])
209            code = f.code()
210
211            ################
212            url = constants.CGIROOT + "/mfe_newfactor.py?code=%s"%code
213            label_button = '<a href="%s">%s</a><font size=1>(%s)</font>'%(url,code,f.id)
214            if k == 2 and eps == '1' and f.dimension() == 1:
215                cremona_label = misc.stein_to_cremona(N, f.iso_class)
216                if cremona_label[1] != f.iso_class:
217                    label_button = label_button + "<br>(%s%s in [Cremona])"%\
218                                   (N,misc.ToIsogenyCode(cremona_label[1]))
219
220
221            ################
222            #if f.aplist_maxp() != constants.not_computed or \
223            #   f.traces() != constants.not_computed:
224            #    if f.traces() != constants.not_computed:
225            #        s = "%s"%f.traces()
226            #        s = string.replace(s," ","")
227            #        s = string.replace(s,"'","")
228            #        s = string.replace(s,"[","")
229            #        s = string.replace(s,"]","")
230            #        s = s[:15+string.find(s[15:],",")] + ", ..."
231            #    else:
232            #        s = "q-Expansions"
233            #else:
234            #    s = "unknown"
235            s = "<center>Click</center>"
236            url = constants.CGIROOT + '/mfe_eigenvalues.py?code=%s'%code
237            aplist_button = '<a href="%s">%s</a>'%(url,s)
238
239            ################
240            if f.hecke_field() != constants.not_computed:
241                field = f.hecke_field()
242                field = string.replace(field, " ","")
243                field = string.replace(field, "+", "+")
244                field = string.replace(field, "-", "-")
245                n = 9
246                if len(field)>n:
247                    m = min(string.find(field[n-5:],"+"), string.find(field[n-5:],"-")) + 2
248                    field=field[:n-5+m] + "..."
249            else:
250                field = "unknown"
251            url = constants.CGIROOT + "/mfe_hecke_field.py?code=%s"%code
252            field_button = '<a href="%s">%s</a>'%(url,field)
253
256
257
258            td = '<td align=center bgcolor="%s">'%constants.TABLE_BGCOLOR
259            ans = ans + "<tr>%s%s</td>%s%s</td>%s%s</td>%s%s</td></tr>"%\
260                  (td,label_button, td,field_button, td,aplist_button, td, traces_button)
261        ans = ans + "</table>"
262    ans = "<table border=1><tr><td>" + ans + "</td></tr></table>"
263    return ans
264
265
266def miscellaneous_rows(M):
267    ans = []
268    for m in M.miscellaneous():
269        field = m['field']
270        data = m['data']
271        notes = m['notes']
272        if str(notes) == "None":
273            notes =""
274        source = m['source']
275        if str(source) == "None":
276            source ="NA"
277        ans.append([M, field, "", data, notes, source])
278    return ans
279
280def order_with_character(M,order_of_eps):
281    if order_of_eps == 1:
282        return [M,"Dimension of space spanned by forms with character a conjugate of eps.", "dimension", \
283                M.dimension(), "","", 0]
284    phi_of_order_of_eps = int(pari.eulerphi(order_of_eps))
285    return [M,"Dimension of space spanned by forms with character a conjugate of eps.", "dimension", \
286            str(phi_of_order_of_eps*M.dimension()), "","", 1]
287
288def fullspace_with_char_table(N,k,eps, order_of_eps):
289    M = mfd.ModSym(N,k,0,eps,'Q')
290    table = [\
291        [M,"Dimension (over C)", "dimension", str(M.dimension()), "", ""]\
292        ,order_with_character(M,order_of_eps)\
293        #,[M,"Characteristic polynomials", "charpoly", charpoly_links(M),"<center>Get charpoly of T<sub>p</sub></center>","NA"]\
294        ,[M,"Dimension of new subspace", "dimension_new", str(M.dimension_new()), "", ""]\
295        ,[M,"Cuspidal subgroup", "cuspidal_subgroup", str(M.cuspidal_subgroup()),"", ""]\
296        ,[M,"Cusps on modular curve", "cusps", str(M.cusps()),"",""]\
297        ,[M,"Discriminant (of Hecke algebra)", "discriminant", str(M.discriminant()), "", ""]\
298        ,[M,"Discriminant (factored)", "discriminant", str(M.discriminant_factored()), "", ""]\
299        ,[M,"Equation for Modular Curve", "equation", str(M.equation()),"", ""]\
300        ,[M,"Rank of Mordell-Weil group", "mwrank", str(M.mwrank()), "", ""]\
301        ,[M,"Mordell-Weil group generators", "mw_generators",str(M.mw_generators()),"",""]\
302        ,[M,"Regulator of Mordell-Weil group", "regulator", str(M.regulator()),"", ""]\
304        ,[M,"Real volume", "real_volume", str(M.real_volume()), "Omega in the BSD conjecture, up to a Manin constant", ""]\
305        ,[M,"Anomalous j-invariants in characteristic %s"%N, "anomalous_j_invariants", str(M.anomalous_j_invariants()), "", ""]\
306        ,[M,"Torsion subgroup", "torsion_subgroup",str(M.torsion_subgroup()), "", ""]\
307        ,[M,"Torsion subgroup size", "torsion_size", str(M.torsion_size()), "", "torsion_subgroup"]\
308        ,[M,"Torsion subgroup size (upper bound)", "torsion_upper_bound", str(M.torsion_upper_bound()), "Multiple of order of torsion subgroup", "torsion_subgroup"]\
309        ,[M,"Torsion subgroup size (odd part of upper bound)", "torsion_odd_upper_bound",str(M.torsion_odd_upper_bound()), "", ""]\
310        ,[M,"Torsion subgroup size (lower bound)", "torsion_lower_bound", str(M.torsion_lower_bound()), "", "torsion_subgroup"]\
311        ,[M,"Tamagawa numbers", "tamagawa_numbers", str(M.tamagawa_numbers()), "the c<sub>p</sub> in BSD conjecture", ""]\
312        ,[M,"Tamagawa numbers (odd parts)", "tamagawa_numbers_odd",str(M.tamagawa_numbers_odd()), "(0 means not yet computed)", ""]\
313        ,[M,"Slopes of T<sub>p</sub>", "slopes", slope_links(M), "p-adic slopes of Newton polygon", ""]\
314        ,[M,"L-ratios L(A,i)/Omega_i for i=1,...,k-1", "lratio", lratio_links(M), "", "", M.weight > 2]\
315        ,[M,"L-ratio L(A,1)/Omega", "lratio_k2", str(M.lratio_k2()), "", "lratio", M.weight == 2]\
316        ,[M,"L-ratios L(A,i)/Omega_i for i=1,...,k-1 (odd parts)", "lratio_odd", lratio_odd_links(M), "", "", M.weight > 2]\
317        ,[M,"L-ratio L(A,1)/Omega (odd parts)", "lratio_odd_k2", str(M.lratio_odd_k2()), "", "lratio_odd", M.weight == 2]\
318        ,[M,"Shafarevich-Tate group (analytic order)", "sha_an", str(M.sha_an()), "", ""]\
319        ,[M,"Shafarevich-Tate group (odd part of analytic order)", "sha_an_odd", str(M.sha_an_odd()), "", ""]\
320        ,[M,"Shafarevich-Tate group (upper bound on odd part of analytic order)", "sha_an_odd_upper_bound", str(M.sha_an_odd_upper_bound()), "", "sha_an_odd"]\
321        ,[M,"Shafarevich-Tate group (lower bound on odd part of analytic order)", "sha_an_odd_lower_bound", str(M.sha_an_odd_lower_bound()), "", "sha_an_odd"]\
322        ,[M,"Notes", "notes",str(M.notes()),"", ""]\
323        ]
324    misc = miscellaneous_rows(M)
325    return table + misc
326
327def parity(x):
328    if x % 2 == 1:
329        return -1
330    return 1
331
332def fullspace_table(N,k,eps, order_of_eps):
333    s = "<h2>Newforms / Abelian Variety Table</h2>\n"
334    s = s+table_newforms(N,k,eps, order_of_eps)
335    s = s+"<hr><h2>Information About Full Space</h2>\n"
336    table = fullspace_with_char_table(N,k,eps,order_of_eps)
337    table = mfe_data_table.Generate_Data_Table(table)
338    table = mfe_glossary.Glossarize(table)
339    s = s + table
340    return s
341
342def contact_info():
343    return "<font size=2> If something is missing or incorrect, "+\
344           "send an email to William Stein at "+\
345           '<a href="mailto:[email protected]">[email protected]</a>.</font>'
346
347def html_space(N, k, eps, error_msg):
348    title="Level %s and Weight %s\n"%(N,k)
352    s=s+"<body class=top>\n"
353    s=s+'<center>\n'
354    s=s+'<h1><a href="/mfd/mfe/">The Modular Forms Explorer</a></h1>'
355    s=s+error_msg
356    s=s+'<h2>%s</h2>\n'%title
357    fac = factor_level(N)
358    if fac == str(N):
359        s = s + "Prime Level<br>"
360    else:
361        s=s+str(N)+" = "+factor_level(N)+"<br>\n"
362    s=s+'<hr>\n'
363    x = level_weight_character_selector(N,k,eps)
364    order_of_eps = x[1]
365    s=s+x[0] + '\n'
366    s=s+browser(N,k)+"\n<br>"
367    s=s+"<hr>\n"
368    s=s+fullspace_table(N,k,eps, order_of_eps)
369    s=s+"<hr></center>\n"
370    s=s+contact_info()
371
372    return s
373
374