Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
"""
2
3
(c) Copyright 2009-2010 Salman Baig and Chris Hall
4
5
This file is part of ELLFF
6
7
ELLFF is free software: you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation, either version 3 of the License, or
10
(at your option) any later version.
11
12
ELLFF is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""
21
22
#######################
23
# ELLFF DATABASE CODE #
24
#######################
25
import sage.databases.db
26
from sage.rings.all import PolynomialRing, GF
27
28
class jCurveDatabase(sage.databases.db.Database):
29
def __init__(self, read_only=True):
30
"""
31
Initialize the database.
32
33
INPUT:
34
35
36
- ``read_only`` - bool (default: True), if True, then
37
the database is read_only and changes cannot be committed to
38
disk.
39
"""
40
sage.databases.db.Database.__init__(self, name='jcurve_euler_tables', read_only=read_only)
41
42
# may not need __getitem__
43
"""
44
def __getitem__(self, key):
45
If key=q is an integer, return all data about FF_q(t) in the database.
46
If key=(q,n) is a pair of integers, return corresponding euler table,
47
if it is in the database.
48
49
INPUT:
50
51
52
- ``key`` - int or list of two ints
53
54
55
OUTPUT: dict (if key is an int) or list (if key is a list)
56
57
if isinstance(key, list) and len(key) > 1:
58
return sage.databases.db.Database.__getitem__(self, key[0])[key[1]]
59
60
return sage.databases.db.Database.__getitem__(self, key)
61
"""
62
63
def __repr__(self):
64
"""
65
String representation of this database. OUTPUT: str
66
"""
67
return 'Database of euler tables for the versal j-curve'
68
69
# TODO: which q are in db, which n are in db given q
70
71
def _update_(self, q, n, table, force=False, verbose=False):
72
r"""
73
Upate the database for self over $\mathbb{F}_{q^n}$, forcing
74
overwrite if so desired. If the table already exists and is
75
forced to be overwritten, the two tables are compared for
76
equality. If they are not equal, the old table is replaced
77
with the new one.
78
79
INPUT:
80
81
- q -- an integer the size of F_q
82
- n -- the degree of the extension of F_q
83
- force -- boolean that forces overwrite
84
85
"""
86
if self.read_only:
87
raise RuntimeError, 'The database must not be read_only.'
88
if self.has_key(q):
89
if self[q].has_key(n) and force:
90
if verbose:
91
print 'Already have this table; forcing overwrite'
92
if not self[q][n] == table:
93
print 'Tables mismatch; replacing preexisting table with new given one'
94
self[q][n] = table
95
self.changed(q)
96
# self[q][n] = self[q][n] # so database knows that self[q][n] changed
97
else:
98
self[q][n] = table
99
self.changed(q)
100
# self[q][n] = self[q][n] # so database knows that self[q][n] changed
101
else:
102
self[q] = {}
103
self[q][n] = table
104
self.changed(q)
105
# self[q][n] = self[q][n] # so database knows that self[q][n] changed
106
self.commit()
107
108
_jdb = None
109
def jCurveEulerTables(read_only=False):
110
r"""
111
Create the database of euler factors for the versal j curve.
112
"""
113
114
global _jdb
115
if _jdb != None:
116
return _jdb
117
if _jdb == None:
118
_jdb = jCurveDatabase(read_only)
119
return _jdb
120
121
class LocalEulerDatabase(sage.databases.db.Database):
122
def __init__(self, read_only=True):
123
"""
124
Initialize the database.
125
126
INPUT:
127
128
129
- ``read_only`` - bool (default: True), if True, then
130
the database is read_only and changes cannot be committed to
131
disk.
132
"""
133
sage.databases.db.Database.__init__(self, name='local_euler_tables', read_only=read_only)
134
135
def __repr__(self):
136
"""
137
String representation of this database. OUTPUT: str
138
"""
139
return 'Database of euler tables for user curves'
140
141
# TODO: which q are in db, which n are in db given q, which ainvs are in db
142
143
def _update_(self, ainvs, q, n, table, force=False, verbose=False):
144
r"""
145
Upate the database for self over $\mathbb{F}_{q^n}$, forcing
146
overwrite if so desired. If the table already exists and is
147
forced to be overwritten, the two tables are compared for
148
equality. If they are not equal, the old table is replaced
149
with the new one.
150
151
INPUT:
152
153
- q -- an integer the size of F_q
154
- n -- the degree of the extension of F_q
155
- force -- boolean that forces overwrite
156
157
"""
158
if self.read_only:
159
raise RuntimeError, 'The database must not be read_only.'
160
if self.has_key(ainvs):
161
if self[ainvs].has_key(q):
162
if self[ainvs][q].has_key(n):
163
if verbose:
164
print 'Already have this table;',
165
if force:
166
if verbose:
167
print 'forcing overwrite'
168
if not self[ainvs][q][n] == table:
169
print 'Tables mismath; replacing preexisting table with new given one'
170
self[ainvs][q][n] = table
171
self.changed(ainvs)
172
else:
173
self[ainvs][q][n] = table
174
self.changed(ainvs)
175
else:
176
self[ainvs][q] = {}
177
self[ainvs][q][n] = table
178
self.changed(ainvs)
179
else:
180
self[ainvs] = {}
181
self[ainvs][q] = {}
182
self[ainvs][q][n] = table
183
self.changed(ainvs)
184
self.commit()
185
186
_ldb = None
187
def LocalEulerTables(read_only=False):
188
r"""
189
Create the database of euler factors for the `user` curve
190
"""
191
192
global _ldb
193
if _ldb != None:
194
return _ldb
195
if _ldb == None:
196
_ldb = LocalEulerDatabase(read_only)
197
return _ldb
198
199
def _save_euler_table(self, n, verbose=False):
200
r"""
201
Save the euler table for self over the degree n extension of
202
$\mathbb{F}_q$ to disk. This is currently implemented with
203
sage.database.db, which uses ZODB. If self is the versal j-curve,
204
it stores the table in the database
205
206
SAGE_ROOT/data/jcurve_euler_tables .
207
208
Otherwise, the tables are stored in the `user` table
209
210
SAGE_ROOT/data/local_euler_tables .
211
212
It currently doesn't check if the table already is stored; it
213
merely writes over it in that case. This should eventually be
214
implemented using MongoDB.
215
216
INPUT:
217
218
- n -- the degree of the extension of F_q
219
220
EXAMPLES::
221
222
sage: import psage
223
sage: K.<t> = psage.FunctionField(GF(11))
224
sage: E = psage.ellff_EllipticCurve(K,[0,0,0,-27*t/(t-1728),54*t/(t-1728)])
225
sage: E._build_euler_table(1)
226
sage: E._euler_table(1)
227
[0, 0, 4, -6, 3, 5, 1, -2, 4, -2, 3, 1]
228
sage: E._build_euler_table(2)
229
sage: E._build_euler_table(3)
230
sage: E._euler_table(1)
231
[0, 0, 4, -6, 3, 5, 1, -2, 4, -2, 3, 1]
232
sage: E._save_euler_table(1)
233
sage: E._save_euler_table(2)
234
sage: E._save_euler_table(3)
235
236
"""
237
238
import os
239
SAGE_ROOT = os.environ['SAGE_ROOT']
240
241
K = self.K
242
R = self.R
243
t = K.gens()[0]
244
p = self.p
245
d = self.d
246
q = self.q
247
R2 = PolynomialRing(GF(q), 's')
248
a1n = R2(0)
249
a1d = R2(1)
250
a2n = R2(0)
251
a2d = R2(1)
252
a3n = R2(0)
253
a3d = R2(1)
254
a4n = R2(self.a4.numerator().coeffs())
255
a4d = R2(self.a4.denominator().coeffs())
256
a6n = R2(self.a6.numerator().coeffs())
257
a6d = R2(self.a6.denominator().coeffs())
258
259
ainvs = [0, 0, 0, self.a4, self.a6]
260
ainvs_pairs = ((a1n, a1d), (a2n, a2d), (a3n, a3d), (a4n, a4d), (a6n, a6d))
261
262
# recognize if self is j-curve and use special repository
263
if ainvs == [0,0,0,-27*t*(t-1728)**3,54*t*(t-1728)**5]:
264
if verbose:
265
print 'j-curve recognized; saving euler table to database'
266
if not os.path.exists(SAGE_ROOT + '/data/jcurve_euler_tables/jcurve_euler_tables'):
267
print 'Database does not exist; starting a new one'
268
if not os.path.exists(SAGE_ROOT + '/data/jcurve_euler_tables'):
269
os.makedirs(SAGE_ROOT + '/data/jcurve_euler_tables/')
270
filedb = open(SAGE_ROOT + '/data/jcurve_euler_tables/jcurve_euler_tables', "wb")
271
filedb.close()
272
273
euler_db = jCurveEulerTables(read_only = False)
274
euler_db._update_(q, n, self._euler_table(n))
275
if verbose:
276
print euler_db.as_dict()
277
euler_db.commit()
278
279
280
# work with user's repository of euler tables
281
else:
282
if not os.path.exists(SAGE_ROOT + '/data/local_euler_tables/local_euler_tables'):
283
print 'Database does not exist; creating a new one'
284
if not os.path.exists(SAGE_ROOT + '/data/local_euler_tables'):
285
os.makedirs(SAGE_ROOT + '/data/jcurve_euler_tables/')
286
filedb = open(SAGE_ROOT + '/data/local_euler_tables/local_euler_tables', "wb")
287
filedb.close()
288
289
local_euler_db = LocalEulerTables(read_only = False)
290
local_euler_db._update_(ainvs_pairs, q, n, self._euler_table(n))
291
if verbose:
292
print local_euler_db.as_dict()
293
local_euler_db.commit()
294
295
def _load_euler_table(self, n, force=False, verbose=False):
296
r"""
297
Load the euler table for self over the degree n extension of
298
$\mathbb{F}_q$ to disk. If self is the versal j-curve, the table
299
is pulled from
300
301
SAGE_ROOT/data/jcurve_euler_tables .
302
303
Otherwise, the table is pulled from the `user` table
304
305
SAGE_ROOT/data/local_euler_tables .
306
307
This should eventually be implemented using MongoDB.
308
309
It currently doesn't check if the key exist. If the key doesn't
310
exist, a RuntimeError is raised by sage.database.db. This
311
RuntimeError should be sufficient, so key checking may not be
312
necessary.
313
314
INPUT:
315
316
- n -- the degree of the extension of F_q
317
- force -- boolean that overwrites self's euler table with
318
one from database
319
320
EXAMPLES::
321
322
sage: import psage
323
sage: K.<t> = psage.FunctionField(GF(11))
324
sage: E = psage.ellff_EllipticCurve(K,[0,0,0,-27*t/(t-1728),54*t/(t-1728)])
325
sage: E._euler_table(1)
326
Traceback (most recent call last):
327
...
328
RuntimeError: table is empty
329
sage: E._load_euler_table(1)
330
sage: E._euler_table(1)
331
[0, 0, 4, -6, 3, 5, 1, -2, 4, -2, 3, 1]
332
333
"""
334
335
import os
336
SAGE_ROOT = os.environ['SAGE_ROOT']
337
338
K = self.K
339
R = self.R
340
t = K.gens()[0]
341
p = self.p
342
d = self.d
343
q = self.q
344
R2 = PolynomialRing(GF(q), 's')
345
s = R2.gens()[0]
346
a1n = R2(0)
347
a1d = R2(1)
348
a2n = R2(0)
349
a2d = R2(1)
350
a3n = R2(0)
351
a3d = R2(1)
352
a4n = R2(self.a4.numerator().coeffs())
353
a4d = R2(self.a4.denominator().coeffs())
354
a6n = R2(self.a6.numerator().coeffs())
355
a6d = R2(self.a6.denominator().coeffs())
356
357
ainvs = [0, 0, 0, self.a4, self.a6]
358
ainvs_pairs = ((a1n, a1d), (a2n, a2d), (a3n, a3d), (a4n, a4d), (a6n, a6d))
359
360
# recognize if self is j-curve and use special repository
361
if ainvs == [0,0,0,-27*t*(t-1728)**3,54*t*(t-1728)**5]:
362
if verbose:
363
print 'j-curve recognized; saving euler table to database'
364
if not os.path.exists(SAGE_ROOT + '/data/jcurve_euler_tables/jcurve_euler_tables'):
365
print 'Database does not exist; cannot load from it'
366
else:
367
euler_db = jCurveEulerTables()
368
# check that keys exist?
369
self._set_euler_table(n, euler_db[q][n], force)
370
371
# work with user's repository of euler tables
372
else:
373
if not os.path.exists(SAGE_ROOT + '/data/local_euler_tables/local_euler_tables'):
374
print 'Database does not exist; cannot load from it'
375
else:
376
local_euler_db = LocalEulerTables()
377
# check that keys exist?
378
self._set_euler_table(n, local_euler_db[ainvs_pairs][q][n], force)
379
380