CoCalc Public Fileswww / cgi-bin / mfd / mfd_old.pyOpen with one click!
Author: William A. Stein
Compute Environment: Ubuntu 18.04 (Deprecated)
1
import misc
2
import constants
3
import magma, pari
4
import pg # postgresql access
5
import mfd_opendb
6
import os, string
7
import heegner
8
import mfe_source
9
import sys
10
11
db = mfd_opendb.opendb()
12
13
DATA = constants.home + '/data'
14
15
UNKNOWN = constants.not_computed
16
17
def sql_format(s):
18
s=s.replace("'","\\'")
19
return s
20
21
22
SEPARATOR = ";";
23
class Software:
24
def __init__(self, init_string):
25
d = init_string.split(SEPARATOR)
26
self.name = ""
27
self.version = ""
28
self.packages = ""
29
if len(d) > 0:
30
self.name = d[0]
31
if len(d) > 1:
32
self.version = d[1]
33
if len(d) > 2:
34
self.packages = d[2]
35
def __repr__(self):
36
return "%s%s%s%s%s"%(self.name, SEPARATOR, self.version, SEPARATOR, self.packages)
37
def get_name(self):
38
return self.name
39
def get_version(self):
40
return self.version
41
def get_packages(self):
42
return self.packages
43
44
45
##################################################################################
46
#
47
# Where a piece of data in the database came from.
48
#
49
# Represents the following postgresql table:
50
#
51
# Column | Type | Modifiers
52
#----------+-----------+---------------------------------------------------
53
# id | integer | not null default nextval('"source_id_seq"'::text)
54
# author | text |
55
# date | date |
56
# software | text |
57
# notes | text |
58
# Unique keys: source_id_key
59
class Source:
60
def init_from_id(self, id):
61
query = "SELECT * FROM source WHERE id=%s;"%id
62
out = db.query(query).dictresult()
63
if len(out) == 0:
64
raise "Error: Couldn't find Source with given id."
65
self.author = out[0]["author"]
66
self.date = out[0]["date"]
67
self.software = Software(out[0]["software"])
68
self.notes = out[0]["notes"]
69
self.id = id
70
71
def __init__(self, author, date="", software="::", notes=""):
72
if type(author) == type(1):
73
self.init_from_id(author)
74
return
75
self.id = -1
76
self.author = author
77
self.date = date
78
if type(software) == type(""):
79
self.software = Software(software)
80
else:
81
self.software = software
82
self.notes = notes
83
self.save_to_database()
84
85
def __repr__(self):
86
return "%s, %s, %s, %s"%self.get()
87
88
def HTML(self):
89
#td = '<td bgcolor="%s">'%constants.TABLE_BGCOLOR
90
td = '<td bgcolor="%s">'%"white"
91
s = "<table border=3><tr><td><table border=0 cellspacing=2 cellpadding=10 bgcolor=black>"
92
if self.get_author()!="":
93
author = self.get_author()
94
if author=="William Stein":
95
author='<a href="/">William Stein</a>'
96
s=s+"<tr>%s<b>Author</b></td>%s %s&nbsp</td></tr>"%(td,td,author)
97
if str(self.get_date()) != "None":
98
s=s+"<tr>%s<b>Date</b></td>%s%s&nbsp</td></tr>"%(td,td,self.get_date())
99
if self.get_software().get_name()!="":
100
sw = self.get_software()
101
if sw.get_packages() != "":
102
packages = "(Extra packages: %s)"%sw.get_packages()
103
else:
104
packages = ""
105
s=s+"<tr>%s<b>Software</b></td>%s%s, Version %s %s&nbsp</td></tr>"%(td,td,sw.get_name(), sw.get_version(), packages)
106
if str(self.get_notes())!="None" and str(self.get_notes())!="":
107
s=s+"<tr>%s<b>Notes</b></td>%s%s&nbsp</td></tr>"%(td,td,self.get_notes())
108
s=s+"</table></td></tr></table>"
109
return s
110
111
def __del__(self):
112
self.save_to_database()
113
114
def save_to_database(self):
115
id = self.get_id()
116
q1 = "UPDATE source SET author='%s' WHERE id=%s;"%(sql_format(self.author), id)
117
if self.date == "" or self.date == None:
118
q2 = "UPDATE source SET date=NULL WHERE id=%s;"%id
119
else:
120
q2 = "UPDATE source SET date='%s' WHERE id=%s;"%(self.date, id)
121
q3 = "UPDATE source SET software='%s' WHERE id=%s;"%(sql_format(str(self.software)), id)
122
q4 = "UPDATE source SET notes='%s' WHERE id=%s;"%(sql_format(self.notes), id)
123
query = q1+q2+q3+q4
124
db.query(query)
125
126
def set_author(self, author):
127
self.author = author
128
def set_date(self, date):
129
self.date = date
130
def set_software(self, software):
131
self.software = software
132
def set_notes(self, notes):
133
self.notes = notes
134
135
def get(self):
136
return (self.author, self.date, self.software, self.notes)
137
138
def get_id(self):
139
if self.id > -1:
140
return self.id
141
v = self.get()
142
values = (sql_format(v[0]),v[1],sql_format(str(v[2])),sql_format(v[3]))
143
query = "SELECT id FROM source WHERE author='%s' AND date='%s' \
144
AND software='%s' AND notes='%s'"%values
145
out = db.query(query).dictresult()
146
if len(out) == 0: # create new record in database
147
insert_query = "INSERT INTO source(author, date, software, notes) "+\
148
"VALUES('%s','%s','%s','%s')"%values
149
db.query(insert_query)
150
out = db.query(query).dictresult()
151
self.id=out[0]['id']
152
return self.id
153
154
def get_author(self):
155
return self.author
156
def get_date(self):
157
return self.date
158
def get_software(self):
159
return self.software
160
def get_notes(self):
161
return self.notes
162
163
164
165
166
167
##################################################################################
168
169
170
def delete(modsym, table):
171
query = "DELETE FROM %s WHERE mod_id = %s"%(table,modsym.id)
172
if table == 'mod':
173
query = query.replace('mod_id', 'id')
174
db.query(query)
175
176
def remove(modsym):
177
tables = ['a_invariants', 'anomalous_j_invariants', 'atkin_lehner',\
178
'charpoly', 'congruence_modulus', 'cuspidal_subgroup',\
179
'cusps', 'dimension', 'dimension_new', 'discriminant', 'equation',\
180
'hecke_field', 'j_invariant', 'leading_coefficient',\
181
'leading_ratio', 'lratio', 'lratio_odd', 'minus_volume',\
182
'modular_degree', 'modular_degree_odd',\
183
'mw_generators', 'mwrank', 'real_volume', 'regulator',\
184
'sha_an', 'sha_an_odd', 'slopes', 'torsion_subgroup', \
185
'traces', 'weierstrass_discriminant', 'inner_twists', \
186
'aplist', 'notes', 'heegner_heights'];
187
188
for i in range(0,len(tables)):
189
delete(modsym,tables[i])
190
191
query = "DELETE FROM mod WHERE id = %s"%modsym.id
192
db.query(query)
193
194
def insert(modsym, table, field, data):
195
# insert array of data into table for modular forms object modsym.
196
# use 'NULL' for NULL data...
197
if type(data) == type([1]):
198
data = misc.list_to_sqlstring(data)
199
if table_exists(modsym,table):
200
if data == 'NULL':
201
query = "UPDATE %s SET %s = NULL WHERE mod_id = %s"%(table,field,modsym.id)
202
else:
203
query = "UPDATE %s SET %s = '%s' WHERE mod_id = %s"%(table,field,data,modsym.id)
204
if table == 'mod':
205
query = query.replace('mod_id', 'id')
206
else:
207
if data != 'NULL':
208
query = "INSERT INTO %s(mod_id, %s) VALUES(%s, %s) " % \
209
(table, field, modsym.id, "'" + str(data) + "'")
210
db.query(query)
211
212
def lo_insert(modsym, table, field, fname, field2='', value2=''):
213
if table_exists(modsym,table,field2,value2):
214
if field2 != '':
215
extra2 = "AND %s = %s"%(field2,value2)
216
else:
217
extra2 = ""
218
query = "UPDATE %s SET %s = lo_import('%s') WHERE "\
219
"mod_id = %s %s"%(table,field,fname,modsym.id,extra2)
220
else:
221
if field2 != '':
222
extra2a = ", %s"%field2
223
extra2b = ", %s "%value2
224
else:
225
extra2a = ""
226
extra2b = ""
227
query = "INSERT INTO %s(mod_id, %s %s) VALUES(%s, lo_import('%s') %s) " % \
228
(table, field, extra2a, modsym.id, fname, extra2b)
229
db.query(query)
230
231
def table_exists(modsym, table, field2='', value2=''):
232
if field2 != '':
233
extra2 = " AND %s = %s"%(field2,value2)
234
else:
235
extra2 = ""
236
query = "SELECT * FROM %s WHERE mod_id = %s %s"%(table,modsym.id,extra2)
237
if table == 'mod':
238
query = query.replace('mod_id', 'id')
239
r = db.query(query).dictresult()
240
return len(r) != 0
241
242
def select(modsym, table, field, extra=""):
243
query = "SELECT %s FROM %s WHERE mod_id = %s %s"%(field,table,modsym.id,extra)
244
r = db.query(query).dictresult()
245
if len(r) == 0 or '%s'%r[0][field] == 'None':
246
return constants.not_computed
247
return r[0][field]
248
249
250
251
def lo_select(modsym, table, field, fname, field2='', value2=''):
252
if field2 != '':
253
extra2 = "AND %s = %s"%(field2,value2)
254
else:
255
extra2 = ""
256
query = "SELECT lo_export(%s,'%s') FROM %s "\
257
"WHERE mod_id = %s %s"%(field,fname,table,modsym.id, extra2)
258
db.query(query)
259
260
def get_data(fileid):
261
fname=DATA+'/'+str(fileid)
262
fnamebz2=fname+'.bz2'
263
if not os.path.exists(fnamebz2):
264
return constants.not_computed
265
os.system('/usr/bin/bunzip2 -fk '+fnamebz2);
266
file=open(fname,'r')
267
d=file.read()
268
file.close()
269
os.system('/bin/rm '+fname)
270
return d
271
272
def set_data(fileid, data):
273
fname=DATA+'/'+str(fileid)
274
file=open(fname,'w')
275
file.write(data)
276
file.close()
277
os.system('/usr/bin/bzip2 -f '+fname);
278
279
280
class ModSym:
281
def __init__(self, _level=1, _weight=2, _iso_class=0, \
282
_dirchar='1', _base_field='Q', number=1):
283
284
self.number_one_modsym=0 # unknown
285
286
if type(_level)== type("11A"):
287
t = ModSym_From_Code(_level)
288
self.level = t.level
289
self.weight = t.weight
290
self.iso_class = t.iso_class
291
self.dirchar = t.dirchar
292
self.base_field = t.base_field
293
self.number = t.number
294
self.id = t.id
295
return
296
297
self.level = int(_level)
298
self.weight = int(_weight)
299
self.iso_class = int(_iso_class)
300
self.dirchar = string.replace(_dirchar,' ','')
301
self.base_field = _base_field
302
self.number = number
303
t = self.tuple()
304
query = ("SELECT id FROM mod WHERE level=%s AND weight=%s " +\
305
" AND iso_class=%s AND dirchar='%s' AND base_field='%s' AND number=%s") % t
306
i = db.query(query).dictresult()
307
if len(i) == 0: # insert new mod entry
308
query = ("INSERT INTO mod(level, weight, iso_class, dirchar, base_field, number) " +\
309
"VALUES(%s,%s,%s,'%s','%s','%s')") % t
310
db.query(query)
311
i = db.query(("SELECT id FROM MOD WHERE level=%s AND weight=%s " + \
312
" AND iso_class=%s AND dirchar='%s' AND base_field='%s' " + \
313
" AND number='%s'") % t\
314
).dictresult()
315
self.id=i[0]['id']
316
317
def __repr__(self):
318
if self.iso_class != 0:
319
num = self.number
320
else:
321
num = ""
322
return "ModSym_%s(%s%s%s;%s)(%s)" % \
323
(self.weight, self.level, misc.ToIsogenyCode(self.iso_class),\
324
num, self.base_field, self.dirchar)
325
326
def code(self):
327
c = "%s"%self.level
328
if self.weight != 2:
329
c = c + "k%s"%self.weight
330
if self.iso_class != 0:
331
c = c + misc.ToIsogenyCode(self.iso_class)
332
if self.dirchar != '1':
333
c = c + self.dirchar
334
if self.base_field != 'Q':
335
c = c + self.base_field
336
if self.iso_class != 0:
337
c = c + str(self.number)
338
return c
339
340
def tuple(self):
341
return (self.level, self.weight, self.iso_class,\
342
self.dirchar, self.base_field, self.number)
343
344
def number_one(self):
345
if self.number == 1:
346
return self
347
if type(self.number_one_modsym) == type(0):
348
self.number_one_modsym = ModSym(self.level, self.weight, self.iso_class, \
349
self.dirchar, self.base_field, 1)
350
return self.number_one_modsym
351
def set_source(self, table, source):
352
if type(source) == type(1):
353
insert(self, table, 'source', source)
354
else:
355
insert(self, table, 'source', source.get_id())
356
357
def source(self, table):
358
if type(table) == type(1): # also call with a source id
359
return Source(table)
360
id = select(self, table, 'source')
361
if id == constants.not_computed:
362
return constants.not_computed
363
else:
364
return Source(int(id))
365
366
367
def change_iso_class(self, new_isoclass): # use with caution.
368
# print "changing iso_class",self.iso_class," to",new_isoclass
369
db.query('UPDATE mod SET iso_class = %s WHERE id=%s'%(new_isoclass, self.id))
370
371
def dimension(self):
372
if self.number > 1:
373
return self.number_one().dimension()
374
dim = select(self, 'dimension', 'dimension')
375
if dim != constants.not_computed:
376
return int(dim)
377
if dim == constants.not_computed:
378
if self.iso_class == 0:
379
if self.base_field=='Q':
380
d = magma.dimension_cuspforms(self.level,self.weight,self.dirchar)
381
self.set_dimension(d)
382
return d
383
return constants.not_computed
384
return int(dim)
385
386
def set_dimension(self, d):
387
insert(self, 'dimension', 'dimension', d)
388
389
def dimension_new(self):
390
if self.number > 1:
391
return self.number_one().dimension_new()
392
dim = select(self, 'dimension_new', 'dimension_new')
393
if dim == constants.not_computed:
394
if self.iso_class == 0:
395
if self.base_field=='Q':
396
d = magma.dimension_new_cuspforms(self.level,self.weight,self.dirchar)
397
self.set_dimension_new(d)
398
return d
399
return constants.not_computed
400
return int(dim)
401
402
def set_dimension_new(self, d):
403
insert(self, 'dimension_new', 'dimension_new', d)
404
405
406
def is_known(self, table, field, extra=""):
407
query = "SELECT %s FROM %s WHERE mod_id=%s %s"%(field,table,self.id,extra)
408
return len(db.query(query).dictresult())>0
409
410
######### charpolys are in the process of being migrated from being large objects (which suck)
411
def charpoly_is_known(self, n):
412
return self.is_known('charpoly','charpoly',' and n=%s'%n) or\
413
self.is_known('charpoly_2','charpoly',' and n=%s'%n)
414
415
def charpoly_no_lo(self, n):
416
return select(self, "charpoly_2", "charpoly", "AND n = %s"%n)
417
418
def charpoly(self, n, fname=""):
419
if self.number > 1:
420
return self.number_one().charpoly(n, fname)
421
if not table_exists(self, 'charpoly', 'n', n):
422
return self.charpoly_no_lo(n)
423
if fname != "":
424
lo_select(self, 'charpoly', 'charpoly', fname, 'n', n)
425
else:
426
fname = misc.newtempfilename()
427
self.charpoly(n, fname)
428
file = open(fname)
429
ans = file.read()
430
file.close()
431
os.system("rm "+fname)
432
return ans
433
434
435
def known_charpolys(self):
436
query = "SELECT n FROM charpoly WHERE mod_id=%s"%self.id
437
out = db.query(query).dictresult()
438
query = "SELECT n FROM charpoly_2 WHERE mod_id=%s"%self.id
439
out2 = db.query(query).dictresult()
440
return [int(o['n']) for o in out] + [int(o['n']) for o in out2]
441
442
def charpoly_source(self, n):
443
query = "SELECT source FROM charpoly_2 WHERE mod_id=%s AND n=%s"%(self.id,n)
444
out = db.query(query).dictresult()
445
if len(out) == 0 or str(out[0]['source']) == 'None':
446
return constants.not_computed
447
return out[0]['source']
448
449
def set_charpoly(self,n,f,source=0):
450
if source == 0:
451
query = "INSERT INTO charpoly_2(mod_id, n, charpoly) VALUES(%s,%s,'%s') "%\
452
(self.id, n, f)
453
else:
454
query = "INSERT INTO charpoly_2(mod_id, n, charpoly, source) VALUES(%s,%s,'%s',%s) "%\
455
(self.id, n, f, source)
456
db.query(query)
457
#fname = misc.newtempfilename()
458
#file = open(fname, "w")
459
#file.write(f)
460
#file.close()
461
#os.system("cp %s /home/was/a"%fname)
462
#lo_insert(self,'charpoly','charpoly',fname,'n',n)
463
######### charpolys are in the process of being migrated from being large objects (which suck)
464
465
466
def discriminant(self):
467
if self.number > 1:
468
return self.number_one().discriminant()
469
return select(self, 'discriminant', 'discriminant')
470
471
def discriminant_factored(self):
472
if self.number > 1:
473
return self.number_one().discriminant()
474
return select(self, 'discriminant', 'factorization')
475
476
def weierstrass_discriminant(self):
477
return select(self, 'weierstrass_discriminant', 'discriminant')
478
479
def set_weierstrass_discriminant(self, discriminant):
480
insert(self, 'weierstrass_discriminant', 'discriminant', discriminant)
481
482
def set_dirchar(self, dirchar):
483
insert(self, 'mod', 'dirchar', dirchar)
484
self.dirchar = dirchar
485
486
def cuspidal_subgroup(self):
487
return misc.parse_sqlarray(select(self, 'cuspidal_subgroup', 'invariants'))
488
489
def fileid(self, description):
490
query = "SELECT id FROM fileid WHERE mod_id = %s AND description = '%s'"%\
491
(self.id,description);
492
q = db.query(query).dictresult()
493
if len(q) == 0:
494
db.query("INSERT INTO fileid(mod_id, description) VALUES(%s,'%s')"%\
495
(self.id, description))
496
query = "SELECT id FROM fileid WHERE mod_id = %s AND description = '%s'"%\
497
(self.id,description);
498
q = db.query(query).dictresult()
499
return q[0]['id']
500
501
def notes(self):
502
return select(self, 'notes', 'notes')
503
504
def set_notes(self, notes):
505
insert(self, 'notes', 'notes', notes)
506
507
def equation(self):
508
return select(self, 'equation', 'equation')
509
510
def set_equation(self, eqn):
511
insert(self, 'equation', 'equation', eqn)
512
513
def cusps(self):
514
return select(self, 'cusps', 'cusps')
515
516
def set_cusps(self, eqn):
517
insert(self, 'cusps', 'cusps', eqn)
518
519
def hecke_field(self):
520
if self.number > 1:
521
return self.number_one().hecke_field()
522
ans = select(self, 'hecke_field', 'hecke_field')
523
if ans == constants.not_computed and self.dimension() == 1:
524
return "x-1" # for elliptic curves, where I forgot to set the field.
525
return ans
526
527
def set_hecke_field(self, eqn):
528
insert(self, 'hecke_field', 'hecke_field', eqn)
529
530
def hecke_field_discriminant(self):
531
if self.number > 1:
532
return self.number_one().hecke_field_discriminant()
533
return select(self, 'hecke_field', 'discriminant')
534
535
def set_hecke_field_discriminant(self, eqn):
536
insert(self, 'hecke_field', 'discriminant', eqn)
537
538
def a_invariants(self):
539
s=select(self, 'a_invariants', 'a_invariants')
540
s=s.replace("(","[")
541
s=s.replace(")","]")
542
return s
543
544
def set_a_invariants(self, a_invs):
545
insert(self, 'a_invariants', 'a_invariants', a_invs)
546
547
def mwrank(self):
548
if self.number > 1:
549
return self.number_one().mwrank()
550
return select(self, 'mwrank', 'mwrank')
551
def set_mwrank(self, r):
552
insert(self, 'mwrank', 'mwrank', r)
553
554
def regulator(self):
555
return select(self, 'regulator', 'regulator')
556
def set_regulator(self, r):
557
insert(self, 'regulator', 'regulator', r)
558
559
def leading_coefficient(self):
560
return select(self, 'leading_coefficient', 'leading_coefficient')
561
def set_leading_coefficient(self, r):
562
insert(self, 'leading_coefficient', 'leading_coefficient', r)
563
564
def real_volume(self):
565
return select(self, 'real_volume', 'real_volume')
566
567
def set_real_volume(self, r):
568
insert(self, 'real_volume', 'real_volume', r)
569
570
def torsion_subgroup(self):
571
return misc.parse_sqlarray(select(self, 'torsion_subgroup', 'invariants'))
572
def set_torsion_subgroup(self, invs):
573
insert(self, 'torsion_subgroup', 'invariants', invs)
574
575
def torsion_size(self):
576
return select(self, 'torsion_subgroup', 'size')
577
def set_torsion_size(self, size):
578
insert(self, 'torsion_subgroup', 'size', size)
579
def torsion_lower_bound(self):
580
return select(self, 'torsion_subgroup', 'lower_bound')
581
def set_torsion_lower_bound(self, bound, prec=0):
582
insert(self, 'torsion_subgroup', 'lower_bound', bound)
583
if prec>0:
584
insert(self, 'torsion_subgroup', 'lower_bound_prec', prec)
585
586
def torsion_upper_bound(self, prec=0):
587
if prec==0:
588
return select(self, 'torsion_subgroup', 'upper_bound')
589
my_prec = select(self, 'torsion_subgroup', 'upper_bound_prec')
590
if my_prec != constants.not_computed and int(my_prec) >= prec:
591
return select(self, 'torsion_subgroup', 'upper_bound')
592
if self.iso_class == 0:
593
if self.dirchar != '1':
594
return constants.not_computed
595
charpols = []
596
for p in pari.primes(3,prec):
597
cp = self.charpoly(p)
598
if cp==constants.not_computed:
599
return constants.not_computed
600
charpols.append([p,cp])
601
bound = pari.torsion_bound(self.level, prec, charpols)
602
if bound == 0:
603
return constants.not_computed
604
self.set_torsion_upper_bound(bound,prec)
605
return bound
606
else:
607
maxp = self.aplist_maxp()
608
if maxp == constants.not_computed:
609
print "Can't compute torsion upper bound, since aplist not known."
610
return
611
if maxp < prec:
612
print "aplist is only known to precision %s, which is less than needed."%maxp
613
return
614
bound = magma.torsion_upper_bound(self.aplist(), self.level, prec)
615
self.set_torsion_upper_bound(bound,prec)
616
return bound
617
618
def set_torsion_upper_bound(self, bound, prec=0):
619
insert(self, 'torsion_subgroup', 'upper_bound', bound)
620
if prec>0:
621
insert(self, 'torsion_subgroup', 'upper_bound_prec', prec)
622
623
def torsion_odd_upper_bound(self):
624
return select(self, 'torsion_odd_upper_bound', 'torsion_odd_upper_bound')
625
def set_torsion_odd_upper_bound(self, bound):
626
insert(self, 'torsion_odd_upper_bound', 'torsion_odd_upper_bound', bound)
627
628
def torsion_size(self):
629
return select(self, 'torsion_subgroup', 'size')
630
def set_torsion_size(self, bound):
631
insert(self, 'torsion_subgroup', 'size', bound)
632
633
def j_invariant(self):
634
return select(self, 'j_invariant', 'j_invariant')
635
def set_j_invariant(self, j):
636
insert(self, 'j_invariant', 'j_invariant', j)
637
638
def anomalous_j_invariants(self):
639
w = select(self, 'anomalous_j_invariants', 'j_invariants')
640
w = string.replace(w,"{","[")
641
w = string.replace(w,"}","]")
642
return w
643
644
def set_anomalous_j_invariants(self, js):
645
js = string.replace(js,"[","{")
646
js = string.replace(js,"]","}")
647
insert(self, 'anomalous_j_invariants', 'j_invariants', js)
648
649
def atkin_lehner(self):
650
if self.number > 1:
651
return self.number_one().atkin_lehner()
652
w = select(self, 'atkin_lehner', 'atkin_lehner')
653
w = string.replace(w,"{","[")
654
w = string.replace(w,"}","]")
655
return w
656
657
def set_atkin_lehner(self, signs):
658
signs = string.replace(signs,"[","{")
659
signs = string.replace(signs,"]","}")
660
insert(self, 'atkin_lehner', 'atkin_lehner', signs)
661
662
def tamagawa_numbers(self):
663
w = select(self, 'tamagawa_numbers', 'tamagawa_numbers')
664
w = string.replace(w,"{","[")
665
w = string.replace(w,"}","]")
666
w = string.replace(w,'"','')
667
return w
668
669
def set_tamagawa_numbers(self, signs):
670
signs = string.replace(signs,"[","{")
671
signs = string.replace(signs,"]","}")
672
insert(self, 'tamagawa_numbers', 'tamagawa_numbers', signs)
673
674
def tamagawa_numbers_odd(self):
675
w = select(self, 'tamagawa_numbers_odd', 'tamagawa_numbers_odd')
676
w = string.replace(w,"{","[")
677
w = string.replace(w,"}","]")
678
w = string.replace(w,'"','')
679
return w
680
681
def set_tamagawa_numbers_odd(self, signs):
682
signs = string.replace(signs,"[","{")
683
signs = string.replace(signs,"]","}")
684
insert(self, 'tamagawa_numbers_odd', 'tamagawa_numbers_odd', signs)
685
686
def traces(self):
687
if self.number > 1:
688
return self.number_one().traces()
689
return misc.parse_sqlarray(select(self, 'traces', 'traces'))
690
691
def set_traces(self, t):
692
insert(self, 'traces', 'traces', t)
693
694
def mw_generators(self):
695
gens = select(self, 'mw_generators', 'mw_generators')
696
gens = string.replace(gens,'"','')
697
gens = string.replace(gens,'{','(')
698
gens = string.replace(gens,'}',')')
699
gens = gens[1:-1]
700
gens = string.replace(gens,"),(","), (")
701
return gens
702
703
704
def set_mw_generators(self, gens):
705
insert(self, 'mw_generators', 'mw_generators', gens)
706
707
def congruence_modulus(self):
708
if self.number > 1:
709
return self.number_one().congruence_modulus()
710
return select(self, 'congruence_modulus', 'congruence_modulus')
711
712
def set_congruence_modulus(self, r):
713
insert(self, 'congruence_modulus', 'congruence_modulus', r)
714
715
def congruence_modulus_primes(self):
716
if self.number > 1:
717
return self.number_one().congruence_modulus_primes()
718
return select(self, 'congruence_modulus', 'primes')
719
720
def set_congruence_modulus_primes(self, r):
721
insert(self, 'congruence_modulus', 'primes', r)
722
723
def modular_degree(self):
724
return select(self, 'modular_degree', 'modular_degree')
725
def set_modular_degree(self, r):
726
insert(self, 'modular_degree', 'modular_degree', r)
727
728
def modular_degree_primes(self):
729
return select(self, 'modular_degree', 'primes')
730
def set_modular_degree_primes(self, r):
731
insert(self, 'modular_degree', 'primes', r)
732
733
def modular_degree_odd(self):
734
return select(self, 'modular_degree_odd', 'modular_degree_odd')
735
def set_modular_degree_odd(self, r):
736
insert(self, 'modular_degree_odd', 'modular_degree_odd', r)
737
738
def modular_degree_odd_primes(self):
739
return select(self, 'modular_degree_odd', 'primes')
740
def set_modular_degree_odd_primes(self, r):
741
insert(self, 'modular_degree_odd', 'primes', r)
742
743
def lratio(self):
744
l = select(self, 'lratio', 'lratio')
745
if l == constants.not_computed:
746
return l
747
return eval(l)
748
749
def lratio_k2(self):
750
L = self.lratio()
751
if L == constants.not_computed:
752
return constants.not_computed
753
return L[0]
754
def set_lratio_k2(self, L1):
755
self.set_lratio("['%s']"%L1)
756
757
def set_lratio(self, ratios): # format: ['lrat1', 'lrat2', etc.]
758
insert(self, 'lratio', 'lratio', ratios)
759
760
def lratio_odd(self):
761
l = select(self, 'lratio_odd', 'lratio_odd')
762
if l == constants.not_computed:
763
return l
764
return eval(l)
765
766
def set_lratio_odd(self, ratios):
767
insert(self, 'lratio_odd', 'lratio_odd', ratios)
768
769
def set_lratio_odd_k2(self, L1):
770
self.set_lratio_odd("['%s']"%L1)
771
772
def lratio_odd_k2(self):
773
L = self.lratio_odd()
774
if L == constants.not_computed:
775
return constants.not_computed
776
return L[0]
777
778
def sha_an(self):
779
return select(self, 'sha_an', 'sha_an');
780
781
def set_sha_an(self, sha):
782
insert(self, 'sha_an', 'sha_an', sha);
783
784
def sha_an_odd(self):
785
return select(self, 'sha_an_odd', 'sha_an_odd');
786
def set_sha_an_odd(self, sha):
787
insert(self, 'sha_an_odd', 'sha_an_odd', sha);
788
def sha_an_odd_upper_bound(self):
789
return select(self, 'sha_an_odd', 'upper_bound');
790
def set_sha_an_odd_upper_bound(self, upper_bound):
791
insert(self, 'sha_an_odd', 'upper_bound', upper_bound);
792
def sha_an_odd_lower_bound(self):
793
return select(self, 'sha_an_odd', 'lower_bound');
794
def set_sha_an_odd_lower_bound(self, lower_bound):
795
insert(self, 'sha_an_odd', 'lower_bound', lower_bound);
796
def sha_an_odd_lower_bound2(self):
797
numerator = select(self, 'sha_an_odd_lower_bound', 'numerator');
798
denominator = select(self, 'sha_an_odd_lower_bound', 'denominator');
799
if denominator=='1':
800
return numerator
801
return "%s/%s"%(numerator,denominator)
802
def set_sha_an_odd_lower_bound2(self, bound):
803
i = string.find(bound,"/")
804
if i != -1:
805
numerator = bound[:i]
806
denominator = bound[i+1:]
807
else:
808
numerator = bound
809
denominator = '1'
810
insert(self, 'sha_an_odd_lower_bound', 'numerator', numerator);
811
insert(self, 'sha_an_odd_lower_bound', 'denominator', denominator);
812
813
def heegner_heights(self):
814
discriminants = select(self, 'heegner_heights', 'discriminants')
815
heights = select(self, 'heegner_heights', 'heights')
816
if discriminants == constants.not_computed or heights == constants.not_computed:
817
return constants.not_computed
818
return [eval(discriminants), eval(heights)]
819
820
def set_heegner_heights(self, discriminants, heights):
821
insert(self, 'heegner_heights', 'discriminants', '%s'%discriminants)
822
heights='%s'%heights
823
heights=heights.replace("'",'"')
824
insert(self, 'heegner_heights', 'heights', heights)
825
826
def compute_heegner_heights(self, n):
827
invs = self.a_invariants()
828
if invs == constants.not_computed:
829
return
830
cmd = 'read("/var/www/cgi-bin/mfd/heegner.gp"); '\
831
'heegner_heights(ellinit(%s),%s);'%(invs,n)
832
cmd = cmd.replace("'","")
833
h = pari.pari(cmd)
834
discriminants = h[1:h.find(']')+1]
835
heights = h[h.find('], ')+3:-1]
836
self.set_heegner_heights(discriminants, heights)
837
return self.heegner_heights()
838
839
def heegner_indexes_odd(self):
840
indexes = select(self, 'heegner_indexes_odd', 'indexes')
841
proofs = select(self, 'heegner_indexes_odd', 'proofs')
842
if indexes == constants.not_computed or \
843
proofs == constants.not_computed:
844
return constants.not_computed
845
return [indexes, proofs]
846
847
def set_heegner_indexes_odd(self, indexes, proofs):
848
insert(self, 'heegner_indexes_odd', 'indexes', indexes)
849
insert(self, 'heegner_indexes_odd', 'proofs', proofs)
850
851
def compute_heegner_indexes_odd(self):
852
if self.dimension() == 1:
853
heegner.compute_heegner_indexes_odd(self)
854
return self.heegner_indexes_odd()
855
856
def modp_gcd_upper_bound(self):
857
bound = select(self, 'modp_gcd_upper_bound', 'bound')
858
max_prime = select(self, 'modp_gcd_upper_bound', 'max_prime')
859
if bound == constants.not_computed or max_prime == constants.not_computed:
860
return constants.not_computed
861
max_prime = int(max_prime)
862
return [max_prime, bound]
863
864
def set_modp_gcd_upper_bound(self, max_prime, bound):
865
insert(self, 'modp_gcd_upper_bound', 'max_prime', max_prime)
866
insert(self, 'modp_gcd_upper_bound', 'bound', bound)
867
868
def compute_modp_gcd_upper_bound(self):
869
if self.dimension() == 1:
870
aplist = self.aplist()
871
if aplist == constants.not_computed:
872
return self.modp_gcd_upper_bound()
873
aplist = aplist[aplist.find(',')+1:]; aplist = aplist[:aplist.find(']]')]
874
aplist = aplist.replace('[',''); aplist = aplist.replace(']',''); aplist = '[' + aplist + ']'
875
N = self.level
876
cmd ="p=1; bnd=0; aplist=%s; N=%s;"%(aplist,N) + \
877
"for(i=1,length(aplist),"\
878
" p = nextprime(p+1);"\
879
" if((2*N) % p != 0, bnd=gcd(bnd,p+1-aplist[i]))"\
880
");"\
881
"[bnd,p];"
882
ans = pari.pari(cmd)
883
print "ans = ", ans
884
max_prime = ans[ans.find(',')+2:ans.find(']')]
885
bound = ans[1:ans.find(',')]
886
self.set_modp_gcd_upper_bound(max_prime, bound)
887
return self.modp_gcd_upper_bound()
888
889
def visibility(self):
890
return select(self, 'visibility', 'visibility');
891
892
def set_visibility(self, data):
893
insert(self, 'visibility', 'visibility', data);
894
895
def is_elliptic_curve(self):
896
return self.dimension() == 1 and self.weight == 2 \
897
and self.iso_class > 0 and self.dirchar == '1' \
898
and self.base_field == 'Q'
899
900
def miscellaneous(self):
901
query = "SELECT * FROM miscellaneous WHERE mod_id=%s"%self.id
902
return db.query(query).dictresult()
903
904
def known_slopes(self):
905
query = "SELECT prime FROM slopes WHERE mod_id=%s"%self.id
906
out = db.query(query).dictresult()
907
return [int(o['prime']) for o in out]
908
909
def slopes(self, prime):
910
query = "SELECT slopes FROM slopes WHERE mod_id=%s and prime=%s"%(self.id,prime)
911
out = db.query(query).dictresult()
912
if len(out) == 0:
913
return constants.not_computed
914
ans=out[0]['slopes']
915
ans=ans.replace("{","[")
916
ans=ans.replace("}","]")
917
return ans
918
919
########## START: ap table: ap, traces, charpolys #########################
920
def known_ap(self):
921
query = "SELECT p FROM ap WHERE mod_id=%s"%self.id
922
out=db.query(query).dictresult()
923
return [x['p'] for x in out]
924
925
def known_ap_value(self):
926
query = "SELECT p, value FROM ap WHERE mod_id=%s AND value IS NOT NULL "%self.id
927
out=db.query(query).dictresult()
928
return [x['p'] for x in out]
929
930
def ap(self, p):
931
query = "SELECT value FROM ap WHERE mod_id=%s and p=%s"%(self.id,p)
932
out=db.query(query).dictresult()
933
if len(out) == 0:
934
return UNKNOWN
935
return out[0]['value']
936
def trace_ap(self, p):
937
query = "SELECT trace FROM ap WHERE mod_id=%s and p=%s"%(self.id,p)
938
out=db.query(query).dictresult()
939
if len(out) == 0 or "%s"%out[0]['trace'] == 'None':
940
return UNKNOWN
941
return out[0]['trace']
942
def known_trace_ap(self):
943
query = "SELECT p, trace FROM ap WHERE mod_id=%s AND trace IS NOT NULL"%self.id
944
out=db.query(query).dictresult()
945
return [x['p'] for x in out]
946
def charpoly_ap(self, p):
947
query = "SELECT charpoly FROM ap WHERE mod_id=%s and p=%s"%(self.id,p)
948
out=db.query(query).dictresult()
949
if len(out) == 0 or "%s"%out[0]['charpoly'] == 'None':
950
return UNKNOWN
951
return out[0]['charpoly']
952
def known_charpoly_ap(self):
953
query = "SELECT p, charpoly FROM ap WHERE mod_id=%s AND charpoly IS NOT NULL"%self.id
954
out=db.query(query).dictresult()
955
return [x['p'] for x in out]
956
957
def set_ap(self, p, ap):
958
query = "SELECT * FROM ap where mod_id=%s and p=%s"%(self.id,p)
959
if len(db.query(query).dictresult()) == 0:
960
query = "INSERT INTO ap(mod_id, p, value) VALUES(%s,%s,'%s')"%(self.id,p,ap)
961
else:
962
query = "UPDATE ap SET value='%s' WHERE mod_id=%s AND p=%s"%(ap,self.id,p)
963
db.query(query)
964
965
def set_trace_ap(self, p, trace):
966
query = "SELECT * FROM ap where mod_id=%s and p=%s"%(self.id,p)
967
if len(db.query(query).dictresult()) == 0:
968
query = "INSERT INTO ap(mod_id, p, trace) VALUES(%s,%s,'%s')"%(self.id,p,trace)
969
else:
970
query = "UPDATE ap SET trace='%s' WHERE mod_id=%s AND p=%s"%(trace,self.id,p)
971
db.query(query)
972
973
def set_charpoly_ap(self, p, charpoly):
974
charpoly=charpoly.replace(" ","")
975
query = "SELECT * FROM ap where mod_id=%s and p=%s"%(self.id,p)
976
if len(db.query(query).dictresult()) == 0:
977
query = "INSERT INTO ap(mod_id, p, charpoly) VALUES(%s,%s,'%s')"%(self.id,p,charpoly)
978
else:
979
query = "UPDATE ap SET charpoly='%s' WHERE mod_id=%s AND p=%s"%(charpoly,self.id,p)
980
db.query(query)
981
982
def set_ap_data(self, field='x-1', embedding='[]', source=0):
983
query = "DELETE FROM ap_data WHERE mod_id=%s"%self.id
984
db.query(query)
985
if source:
986
query = "INSERT INTO ap_data(mod_id, field, embedding, source) VALUES(%s,'%s','%s',%s)"%\
987
(self.id, field, embedding, source)
988
else:
989
query = "INSERT INTO ap_data(mod_id, field, embedding) VALUES(%s,'%s','%s')"%\
990
(self.id, field, embedding)
991
db.query(query)
992
993
def ap_field(self):
994
return select(self, "ap_data", "field")
995
def ap_embedding(self):
996
return select(self, "ap_data", "embedding")
997
def ap_source(self):
998
return select(self, "ap_data", "source")
999
1000
# this is a temporary function, which we'll eliminate
1001
def ap_set_using_aplist(self):
1002
x = self.aplist()
1003
if x == constants.not_computed:
1004
return
1005
x = x.replace(" ","")
1006
i=x.find("<")+1
1007
j=x.find(",")
1008
field=x[i:j]
1009
i=x.find("]]")+3
1010
j=x.find(">")
1011
embedding=x[i:j]
1012
source=12 # ap that come from aplist
1013
self.set_ap_data(field, embedding, source)
1014
i=x.find("[[")+1
1015
j=x.find("]]")+1
1016
x=x[i:j]
1017
n=0
1018
while x.find("[") != -1:
1019
i=x.find("[")
1020
j=x.find("]")+1
1021
p=constants.PRIMES[n]
1022
ap = x[i:j]
1023
self.set_ap(p,ap)
1024
x=x[j+1:]
1025
n=n+1
1026
1027
def remove_aplist(self):
1028
query = "DELETE FROM aplist WHERE mod_id = %s"%self.id
1029
db.query(query)
1030
1031
def ap_trace_using_traces(self):
1032
t = self.traces()
1033
if t == UNKNOWN:
1034
return
1035
for n in range(len(t)):
1036
p = constants.PRIMES[n]
1037
self.set_trace_ap(p, t[n])
1038
1039
def remove_traces(self):
1040
query = "DELETE FROM traces WHERE mod_id = %s"%self.id
1041
db.query(query)
1042
1043
def move_aplist_and_trace_for_fullspace(self, logfile=""):
1044
if type(logfile) != type(""):
1045
logfile.write("%s (%s)\n"%(self.code(), self.id))
1046
logfile.flush()
1047
1048
if self.iso_class != 0:
1049
print "Moving %s"%self.code()
1050
self.ap_set_using_aplist()
1051
self.ap_trace_using_traces()
1052
self.aplist_delete()
1053
self.remove_traces()
1054
return
1055
1056
print "** FULLSPACE %s ** "%self.code()
1057
for f in self.get_iso_classes():
1058
if f.aplist_is_deleted():
1059
print "already done..."
1060
return
1061
print "Moving %s"%f.code()
1062
f.ap_set_using_aplist()
1063
f.ap_trace_using_traces()
1064
f.aplist_delete()
1065
f.remove_traces()
1066
1067
########## END: ap table: ap, traces, charpolys #########################
1068
1069
1070
1071
# The aplist is stored in a bzip2'd file. That file contains a MAGMA-readable
1072
# 3-tuple. The first entry defines the field generated by the a_p. The second
1073
# entry is a sequence of sequences that give each a_p on a basis for the field,
1074
# the third entry embeds that basis in the field defined by the first entry.
1075
def aplist_is_deleted(self):
1076
query = "SELECT deleted FROM aplist WHERE mod_id=%s AND deleted=1"%self.id
1077
return len(db.query(query).dictresult()) > 0
1078
def aplist_delete(self, val=1):
1079
query = "SELECT * FROM aplist WHERE mod_id=%s"%self.id
1080
if len(db.query(query).dictresult()) > 0:
1081
query = "UPDATE aplist SET deleted=%s WHERE mod_id=%s"%(val,self.id)
1082
db.query(query)
1083
1084
def aplist(self, fname=""):
1085
if self.number > 1:
1086
return self.number_one().aplist(fname)
1087
#if self.aplist_maxp() == constants.not_computed:
1088
# if self.is_elliptic_curve():
1089
# return self.aplist_compute(1000)
1090
# return constants.not_computed
1091
if fname != "":
1092
lo_select(self, 'aplist', 'aplist', fname)
1093
else:
1094
fname = misc.newtempfilename()
1095
self.aplist(fname+".bz2")
1096
os.system("bunzip2 --force "+fname+".bz2")
1097
file = open(fname)
1098
ans = file.read()
1099
file.close()
1100
os.system("rm "+fname)
1101
return ans
1102
1103
def aplist_maxp(self):
1104
if self.number > 1:
1105
return self.number_one().aplist_maxp()
1106
return select(self, 'aplist', 'maxp')
1107
1108
def set_aplist(self, maxp, fname):
1109
lo_insert(self, 'aplist', 'aplist', fname)
1110
insert(self, 'aplist', 'maxp', maxp)
1111
1112
def aplist_hecke_field(self): # extract the hecke_field from the aplist string.
1113
if self.number > 1:
1114
return self.number_one().aplist_hecke_field()
1115
if self.aplist_maxp() == constants.not_computed:
1116
return constants.not_computed
1117
s = self.aplist()
1118
# the hecke field is stored between the opening < and the first comma.
1119
return string.replace(s[string.find(s,"<")+1:string.find(s,",")]," ","")
1120
1121
def aplist_embedding(self): # extract the embedding into the powerbasis from the aplist string.
1122
if self.number > 1:
1123
return self.number_one().aplist_embedding()
1124
if self.aplist_maxp() == constants.not_computed:
1125
return constants.not_computed
1126
s = self.aplist()
1127
# the embedding is stored as a list of polys between the last set of brackets.
1128
return string.replace(s[string.rfind(s,"["):string.rfind(s,"]")+1]," ","")
1129
1130
def aplist_dimension(self): # extract dimension from the aplist string
1131
if self.number > 1:
1132
return self.number_one().aplist_dimension()
1133
if self.aplist_maxp() == constants.not_computed:
1134
return constants.not_computed
1135
s = self.aplist_hecke_field()
1136
i = string.find(s,"^")+1
1137
if i==0: # degree 1 (no exponent)
1138
return 1
1139
j = i+1
1140
while j < len(s) and s[j] in ['0','1','2','3','4','5','6','7','8','9']:
1141
j = j+1
1142
return eval(s[i:j])
1143
1144
def aplist_compute(self, prec=1000):
1145
if self.number > 1:
1146
return self.number_one().aplist_compute(prec)
1147
if not self.is_elliptic_curve():
1148
return constants.not_computed
1149
cmd = "E = ellinit(%s); "%self.a_invariants()
1150
cmd = cmd.replace("'","")
1151
cmd = cmd + "v=[]; forprime(p=2,%s,v=concat(v,[[ellap(E,p)]])); v;"%prec
1152
ap = pari.pari(cmd)
1153
fname = misc.newtempfilename()
1154
file = open(fname,"w")
1155
file.write("<x-1, "+ap+", [1]>")
1156
file.close()
1157
os.system("bzip2 "+fname)
1158
self.set_aplist(prec, fname+".bz2")
1159
os.system("rm "+fname+".bz2")
1160
return self.aplist()
1161
1162
def q_expansion(self, prec=8):
1163
if self.number > 1:
1164
return self.number_one().q_expansion(prec)
1165
if self.aplist_maxp() == constants.not_computed:
1166
return constants.not_computed
1167
return magma.aplist_to_qexpansion(self.aplist(),self.level, self.weight,\
1168
self.dirchar, prec)
1169
1170
def q_integral_basis(self, prec=8):
1171
if self.number > 1:
1172
return self.number_one().q_integral_basis(prec)
1173
if self.aplist_maxp() == constants.not_computed:
1174
return constants.not_computed
1175
return magma.aplist_to_q_integral_basis(\
1176
self.aplist(),self.level, self.weight, self.dirchar, prec)
1177
1178
def congruence_group(self, M, prec=8):
1179
if self.number > 1:
1180
return self.number_one().congruence_group(M,prec)
1181
if self == M:
1182
raise "Can't compare form to self."
1183
if self.aplist_maxp() == constants.not_computed or M.aplist_maxp() == constants.not_computed \
1184
or self.iso_class == 0 or M.iso_class == 0:
1185
return constants.not_computed
1186
return magma.congruence_group(self.level, M.level, \
1187
self.q_integral_basis(prec), M.q_integral_basis(prec))
1188
1189
def inner_twists(self, force_compute=0):
1190
order_of_root = select(self, 'inner_twists', 'order_of_root');
1191
if order_of_root == constants.not_computed or force_compute:
1192
if force_compute and self.aplist_maxp() != constants.not_computed and self.dirchar == '1':
1193
data = magma.inner_twists_data(self.level,self.aplist())
1194
order_of_root = data[0] # order of root of unity used to write twist characters
1195
num_twists = data[1] # size of group of twists
1196
generators = data[2] # generators of group of twists
1197
fixed_field = data[3] # field fixed by the inner twist automorphisms
1198
fixed_degree= data[4] # field fixed by the inner twist automorphisms
1199
hilbert_sym = data[5] # hilbert symbol description of endomorphism algebra
1200
endo_alg = data[6] # desc. of the endomorphism algebra (evaluation of hilbert_sym)
1201
has_cm = data[7] # true <==> form has CM
1202
insert(self,'inner_twists','order_of_root',order_of_root)
1203
insert(self,'inner_twists','num_twists', num_twists)
1204
insert(self,'inner_twists','generators', generators)
1205
insert(self,'inner_twists','fixed_field', fixed_field)
1206
insert(self,'inner_twists','fixed_degree', fixed_degree)
1207
insert(self,'inner_twists','hilbert_sym', hilbert_sym)
1208
insert(self,'inner_twists','endo_alg', endo_alg)
1209
insert(self,'inner_twists','has_cm', has_cm)
1210
1211
return [select(self,'inner_twists','order_of_root'), \
1212
select(self,'inner_twists','num_twists'), \
1213
select(self,'inner_twists','generators'), \
1214
select(self,'inner_twists','fixed_field'), \
1215
select(self,'inner_twists','fixed_degree'), \
1216
select(self,'inner_twists','hilbert_sym'), \
1217
select(self,'inner_twists','endo_alg'), \
1218
select(self,'inner_twists','has_cm')]
1219
1220
#####################################################################################
1221
#
1222
# These methods are special to FULL space (with iso_class=0).
1223
#
1224
#####################################################################################
1225
def howmany_iso_classes(self):
1226
if self.iso_class != 0:
1227
raise "number_of_iso_classes: self must be a full factor (i.e., self.iso_class=0)."
1228
query = "SELECT * from mod where level=%s"%self.level + \
1229
" AND weight=%s AND iso_class>0 "%self.weight +\
1230
"AND dirchar='%s' AND base_field='%s' AND number=1"%(self.dirchar,self.base_field)
1231
return len(db.query(query).dictresult())
1232
1233
def get_iso_class(self, iso_class):
1234
if self.iso_class != 0:
1235
raise "get_newform: self must be a full factor (i.e., self.iso_class=0)."
1236
if iso_class <= 0:
1237
raise "get_newform: iso_class must be positive."
1238
if iso_class > self.howmany_iso_classes():
1239
raise "get_newform: iso_class too big; create it separately."
1240
return ModSym(self.level, self.weight, iso_class, self.dirchar, self.base_field, 1)
1241
1242
def get_iso_classes(self):
1243
if self.iso_class != 0:
1244
raise "get_iso_classes: self must be a full factor (i.e., self.iso_class=0)."
1245
classes = []
1246
for i in range(self.howmany_iso_classes()):
1247
classes.append(self.get_iso_class(i+1))
1248
return classes
1249
1250
def is_complete(self): # true if we're absolutely certain that all newforms are known
1251
if self.iso_class != 0:
1252
raise "get_newform: self must be a full factor (i.e., self.iso_class=0)."
1253
newdim = self.dimension_new()
1254
if newdim == constants.not_computed:
1255
return 0
1256
if newdim == 0:
1257
return 1
1258
d = 0
1259
c = self.get_iso_classes()
1260
for f in c:
1261
if f.dimension() == constants.not_computed:
1262
return 0
1263
d = d + f.dimension()
1264
return d == newdim
1265
1266
#############################################
1267
# #
1268
# A few useful functions #
1269
# #
1270
#############################################
1271
1272
def genusX0(N):
1273
m = ModSym(N,2)
1274
return m.dimension()
1275
1276
def charpoly(N,p):
1277
m = ModSym(N)
1278
f = m.charpoly(p)
1279
if N < 1000 and f == constants.not_computed:
1280
f = magma.charpolyGamma0(N,2,p)
1281
m.set_charpoly(p,f)
1282
return f
1283
1284
def discriminant(N,iso_class):
1285
m = ModSym(N,2,iso_class)
1286
return m.discriminant()
1287
1288
def cuspidal_subgroup(N,iso_class):
1289
m = ModSym(N,2,iso_class)
1290
return m.cuspidal_subgroup()
1291
1292
def iso_class_data(N, k, eps='1', base_field='Q'):
1293
query = "SELECT iso_class, number FROM mod WHERE "+\
1294
"level=%s AND weight=%s AND iso_class>0 "%(N,k)+\
1295
"AND dirchar='%s' AND base_field='%s' order by iso_class, number"%(eps,base_field)
1296
return db.query(query).dictresult()
1297
1298
def notes(N):
1299
m = ModSym(N,2)
1300
return m.notes()
1301
1302
def ModSymWeierstrass(invariants):
1303
query = "SELECT mod_id FROM a_invariants WHERE " + \
1304
" a_invariants[1] = CAST('%s' as numeric)"%invariants[0] + \
1305
"AND a_invariants[2] = CAST('%s' as numeric)"%invariants[1] + \
1306
"AND a_invariants[3] = CAST('%s' as numeric)"%invariants[2] + \
1307
"AND a_invariants[4] = CAST('%s' as numeric)"%invariants[3] + \
1308
"AND a_invariants[5] = CAST('%s' as numeric)"%invariants[4]
1309
1310
id = db.query(query).dictresult()
1311
if len(id) == 0:
1312
return constants.not_computed;
1313
1314
query = "SELECT level, iso_class FROM mod WHERE id=%s"%id[0]['mod_id']
1315
x = db.query(query).dictresult()
1316
if len(x) == 0:
1317
return constants.not_computed;
1318
return ModSym(x[0]['level'], 2, x[0]['iso_class'])
1319
1320
1321
def is_number(x):
1322
return x >= '0' and x <= '9'
1323
1324
def ModSym_From_ID(id):
1325
query = "SELECT * FROM mod WHERE id=%s"%id
1326
out = db.query(query).dictresult()
1327
if len(out) == 0:
1328
print "No such space"
1329
sys.exit(0)
1330
x=out[0]
1331
return ModSym(x['level'], x['weight'], x['iso_class'], x['dirchar'], \
1332
x['base_field'], x['number'])
1333
1334
def ModSym_From_Code(code):
1335
level = "";
1336
i = 0;
1337
while i<len(code) and code[i] >= '0' and code[i] <= '9':
1338
level = level + code[i]
1339
i = i + 1
1340
level = int(level)
1341
if i<len(code) and code[i] == 'k':
1342
i = i + 1
1343
weight = ""
1344
while i < len(code) and code[i] >= '0' and code[i] <= '9':
1345
weight = weight + code[i]
1346
i = i + 1
1347
weight = int(weight)
1348
else:
1349
weight = 2
1350
if i>=len(code) or code[i] == '[': # the '[' is for characters
1351
iso_class = 0
1352
else:
1353
iso = "";
1354
while i < len(code) and code[i] != '[' and not is_number(code[i]):
1355
iso = iso + code[i]
1356
i = i+1
1357
iso_class = misc.IsogenyCodeToInteger(iso)
1358
if i < len(code) and code[i] == '[':
1359
j = code.find(']')
1360
dirchar=code[i:j+1]
1361
i = j+1
1362
else:
1363
dirchar='1'
1364
if i < len(code):
1365
number = int(code[i:])
1366
else:
1367
number = 1
1368
base_field='Q'
1369
return ModSym(level, weight, iso_class, dirchar, base_field, number)
1370
1371
def characters_are_known(N):
1372
query = "SELECT * FROM characters WHERE modulus = %s"%N
1373
x = db.query(query).dictresult()
1374
return len(x) > 0
1375
1376
def characters(N):
1377
query = "SELECT * FROM characters WHERE modulus = %s"%N
1378
x = db.query(query).dictresult()
1379
if len(x) == 0:
1380
chardata = magma.character_data(N)
1381
for eps in chardata:
1382
query = "insert into characters values(%s,'%s',%s,%s,%s)"%(eps[0],eps[1],eps[2],eps[3],eps[4])
1383
db.query(query)
1384
query = "SELECT * FROM characters WHERE modulus = %s ORDER BY degree"%N
1385
x = db.query(query).dictresult()
1386
if len(x) == 0:
1387
raise "Error inserting characters into database."
1388
return x
1389
1390
1391
1392
1393
1394
##############################################
1395
# #
1396
# Elliptic Curves #
1397
# #
1398
##############################################
1399
1400
class EllipticCurve(ModSym) :
1401
def __init__(self, _level, _iso_class, _number=1):
1402
self.level = _level
1403
self.iso_class = _iso_class
1404
self.weight = 2
1405
self.dirchar='1'
1406
self.base_field='Q'
1407
self.number = _number
1408
1409
f = self.ModularForm()
1410
i = db.query(("SELECT id FROM elliptic WHERE mod_id=%s AND number=%s")%\
1411
(f.id, self.number)).dictresult()
1412
if len(i) == 0: # insert new elliptic table entry
1413
db.query(("INSERT INTO elliptic(mod_id, number) " +\
1414
"VALUES(%s,%s)") % (f.id,self.number))
1415
i = db.query(("SELECT id FROM elliptic WHERE mod_id=%s AND number=%s")%\
1416
(f.id, self.number)).dictresult()
1417
self.id=i[0]['id']
1418
1419
def __repr__(self):
1420
return "The elliptic curve %s"%(self.code())
1421
1422
def ModularForm(self): # the corresponding modular form
1423
return ModSym(self.level, 2, self.iso_class)
1424
1425
def code(self):
1426
return "%s%s%s"%(self.level,misc.ToIsogenyCode(self.iso_class),self.number)
1427
1428
def change_iso_class(self, new_isoclass):
1429
raise "Don't call this."
1430
1431
def dimension(self):
1432
return 1
1433
def set_dimension(self, d):
1434
raise "Don't call this."
1435
1436
def dimension_new(self):
1437
return 1
1438
def set_dimension_new(self, d):
1439
raise "Don't call this."
1440
1441
def charpoly(self, n):
1442
raise "Don't call this yet."
1443
1444
def discriminant(self):
1445
return self.weierstrass_discriminant()
1446
1447
def set_discriminant(self):
1448
return self.set_weierstrass_discriminant()
1449
1450
def cusps(self):
1451
raise "Don't call this yet."
1452
def set_cusps(self, eqn):
1453
raise "Don't call this yet."
1454
1455
def hecke_field():
1456
return "x-1"
1457
def set_hecke_field(self, eqn):
1458
raise "Don't call this yet."
1459
1460
def hecke_field_discriminant(self):
1461
return 1
1462
def set_hecke_field_discriminant(self, eqn):
1463
raise "Don't call this yet."
1464
1465
def lratio(self):
1466
return [misc.parse_sqlarray(select(self, 'lratio', 'numerator'))[0], \
1467
misc.parse_sqlarray(select(self, 'lratio', 'denominator'))[0]];
1468
def set_lratio(self, numerator, denominator):
1469
insert(self, 'lratio', 'numerator', [numerator])
1470
insert(self, 'lratio', 'denominator', [denominator])
1471
1472
def lratio_odd(self):
1473
return [misc.parse_sqlarray(select(self, 'lratio_odd', 'numerator'))[0], \
1474
misc.parse_sqlarray(select(self, 'lratio_odd', 'denominator'))[0]];
1475
def set_lratio_odd(self, numerator, denominator):
1476
insert(self, 'lratio_odd', 'numerator', [numerator])
1477
insert(self, 'lratio_odd', 'denominator', [denominator])
1478
1479
1480
1481
def atkin_lehner(self):
1482
return self.ModularForm().atkin_lehner()
1483
def set_atkin_lehner(self, signs):
1484
raise "Don't call this."
1485
def traces(self):
1486
return self.ModularForm().traces()
1487
def set_traces(self, t):
1488
raise "Don't call this."
1489
def aplist(self, fname=""):
1490
return self.ModularForm().aplist(fname)
1491
def aplist_maxp(self):
1492
return self.ModularForm().aplist_maxp()
1493
def set_aplist(self, maxp, fname):
1494
return self.ModularForm().set_aplist(self,maxp,fname)
1495
def aplist_hecke_field(self):
1496
return 'x-1'
1497
def aplist_embedding(self):
1498
return '[1]'
1499
def aplist_dimension(self):
1500
return 1
1501
def q_expansion(self,prec=8):
1502
return self.ModularForm().q_expansion(prec)
1503
def q_integral_basis(self, prec=8):
1504
return self.ModularForm().q_integral_basis(8)
1505
def congruence_group(self, M, prec=8):
1506
return self.ModularForm().congruence_group(M,prec)
1507
def inner_twists(self, force_compute=0):
1508
return self.ModularForms().inner_twists(force_compute)
1509
1510
############################################
1511
1512
1513
def Get_Definition_From_Database(phrase):
1514
query = "SELECT definition FROM glossary WHERE phrase='%s'"%phrase
1515
out = db.query(query).dictresult()
1516
if len(out) == 0:
1517
return "Definition not yet written."
1518
s = out[0]["definition"]
1519
query = "SELECT source FROM glossary WHERE phrase='%s'"%phrase
1520
out = db.query(query).dictresult()
1521
if len(out) > 0:
1522
s = s + "<hr>Source of Definition: " + mfe_source.Link(out[0]["source"])
1523
return s
1524
1525
def List_Of_Words_Defined_In_Glossary():
1526
query = "SELECT phrase FROM glossary"
1527
out = db.query(query).dictresult()
1528
return [out[i]["phrase"] for i in range(len(out))]
1529