Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py
4156 views
1
"""
2
Hyperelliptic curves over a padic field.
3
"""
4
5
#*****************************************************************************
6
# Copyright (C) 2007 Robert Bradshaw <[email protected]>
7
# Distributed under the terms of the GNU General Public License (GPL)
8
# http://www.gnu.org/licenses/
9
#*****************************************************************************
10
11
12
import hyperelliptic_generic
13
14
from sage.rings.all import PowerSeriesRing, PolynomialRing, ZZ, QQ, O, pAdicField, GF, RR, RationalField, Infinity
15
from sage.misc.functional import log
16
from sage.modules.free_module import VectorSpace
17
from sage.matrix.constructor import matrix
18
from sage.modules.all import vector
19
20
21
class HyperellipticCurve_padic_field(hyperelliptic_generic.HyperellipticCurve_generic):
22
23
# The functions below were prototyped at the 2007 Arizona Winter School by
24
# Robert Bradshaw and Ralf Gerkmann, working with Miljan Brakovevic and
25
# Kiran Kedlaya
26
# All of the below is with respect to the Monsky Washnitzer cohomology.
27
28
def local_analytic_interpolation(self, P, Q):
29
"""
30
For points $P$, $Q$ in the same residue disc,
31
this constructs an interpolation from $P$ to $Q$
32
(in homogeneous coordinates) in a power series in
33
the local parameter $t$, with precision equal to
34
the $p$-adic precision of the underlying ring.
35
36
INPUT:
37
38
- P and Q points on self in the same residue disc
39
40
OUTPUT:
41
42
Returns a point $X(t) = ( x(t) : y(t) : z(t) )$ such that
43
44
(1) $X(0) = P$ and $X(1) = Q$ if $P, Q$ are not in the infinite disc
45
(2) $X(P[0]^g}/P[1]) = P$ and $X(Q[0]^g/Q[1]) = Q$ if $P, Q$ are in the infinite disc
46
47
EXAMPLES::
48
49
sage: R.<x> = QQ['x']
50
sage: H = HyperellipticCurve(x^3-10*x+9)
51
sage: K = Qp(5,8)
52
sage: HK = H.change_ring(K)
53
54
A non-Weierstrass disc::
55
56
sage: P = HK(0,3)
57
sage: Q = HK(5, 3 + 3*5^2 + 2*5^3 + 3*5^4 + 2*5^5 + 2*5^6 + 3*5^7 + O(5^8))
58
sage: x,y,z, = HK.local_analytic_interpolation(P,Q)
59
sage: x(0) == P[0], x(1) == Q[0], y(0) == P[1], y(1) == Q[1]
60
(True, True, True, True)
61
62
A finite Weierstrass disc::
63
64
sage: P = HK.lift_x(1 + 2*5^2)
65
sage: Q = HK.lift_x(1 + 3*5^2)
66
sage: x,y,z = HK.local_analytic_interpolation(P,Q)
67
sage: x(0) == P[0], x(1) == Q[0], y(0) == P[1], y(1) == Q[1]
68
(True, True, True, True)
69
70
The infinite disc::
71
72
sage: P = HK.lift_x(5^-2)
73
sage: Q = HK.lift_x(4*5^-2)
74
sage: x,y,z = HK.local_analytic_interpolation(P,Q)
75
sage: x = x/z
76
sage: y = y/z
77
sage: x(P[0]/P[1]) == P[0]
78
True
79
sage: x(Q[0]/Q[1]) == Q[0]
80
True
81
sage: y(P[0]/P[1]) == P[1]
82
True
83
sage: y(Q[0]/Q[1]) == Q[1]
84
True
85
86
An error if points are not in the same disc::
87
88
sage: x,y,z = HK.local_analytic_interpolation(P,HK(1,0))
89
Traceback (most recent call last):
90
...
91
ValueError: (5^-2 + O(5^6) : 5^-3 + 4*5^2 + 5^3 + 3*5^4 + O(5^5) : 1 + O(5^8)) and (1 + O(5^8) : 0 : 1 + O(5^8)) are not in the same residue disc
92
93
AUTHORS:
94
95
- Robert Bradshaw (2007-03)
96
- Jennifer Balakrishnan (2010-02)
97
"""
98
prec = self.base_ring().precision_cap()
99
if self.is_same_disc(P,Q) == False:
100
raise ValueError, "%s and %s are not in the same residue disc"%(P,Q)
101
disc = self.residue_disc(P)
102
t = PowerSeriesRing(self.base_ring(), 't', prec).gen(0)
103
if disc == self.change_ring(self.base_ring().residue_field())(0,1,0):
104
x,y = self.local_coordinates_at_infinity(2*prec)
105
g = self.genus()
106
return (x*t**(2*g+1),y*t**(2*g+1),t**(2*g+1))
107
if disc[1] !=0:
108
x = P[0]+t*(Q[0]-P[0])
109
pts = self.lift_x(x, all=True)
110
if pts[0][1][0] == P[1]:
111
return pts[0]
112
else:
113
return pts[1]
114
else:
115
S = self.find_char_zero_weier_point(P)
116
x,y = self.local_coord(S)
117
a = P[1]
118
b = Q[1] - P[1]
119
y = a + b*t
120
x = x(y)
121
return (x, y, 1)
122
123
def weierstrass_points(self):
124
"""
125
Return the Weierstrass points of self defined over self.base_ring(),
126
that is, the point at infinity and those points in the support
127
of the divisor of $y$
128
129
EXAMPLES::
130
131
sage: K = pAdicField(11, 5)
132
sage: x = polygen(K)
133
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
134
sage: C.weierstrass_points()
135
[(0 : 1 + O(11^5) : 0), (7 + 10*11 + 4*11^3 + O(11^5) : 0 : 1 + O(11^5))]
136
"""
137
f, h = self.hyperelliptic_polynomials()
138
if h != 0:
139
raise NotImplementedError()
140
return [self((0,1,0))] + [self((x, 0, 1)) for x in f.roots()]
141
142
def is_in_weierstrass_disc(self,P):
143
"""
144
Checks if $P$ is in a Weierstrass disc
145
146
EXAMPLES::
147
148
sage: R.<x> = QQ['x']
149
sage: H = HyperellipticCurve(x^3-10*x+9)
150
sage: K = Qp(5,8)
151
sage: HK = H.change_ring(K)
152
sage: P = HK(0,3)
153
sage: HK.is_in_weierstrass_disc(P)
154
False
155
sage: Q = HK(0,1,0)
156
sage: HK.is_in_weierstrass_disc(Q)
157
True
158
sage: S = HK(1,0)
159
sage: HK.is_in_weierstrass_disc(S)
160
True
161
sage: T = HK.lift_x(1+3*5^2); T
162
(1 + 3*5^2 + O(5^8) : 2*5 + 4*5^3 + 3*5^4 + 5^5 + 3*5^6 + O(5^7) : 1 + O(5^8))
163
sage: HK.is_in_weierstrass_disc(T)
164
True
165
166
AUTHOR:
167
168
- Jennifer Balakrishnan (2010-02)
169
"""
170
if (P[1].valuation() == 0 and P != self(0,1,0)):
171
return False
172
else:
173
return True
174
175
def is_weierstrass(self,P):
176
"""
177
Checks if $P$ is a Weierstrass point (i.e., fixed by the hyperelliptic involution)
178
179
EXAMPLES::
180
181
sage: R.<x> = QQ['x']
182
sage: H = HyperellipticCurve(x^3-10*x+9)
183
sage: K = Qp(5,8)
184
sage: HK = H.change_ring(K)
185
sage: P = HK(0,3)
186
sage: HK.is_weierstrass(P)
187
False
188
sage: Q = HK(0,1,0)
189
sage: HK.is_weierstrass(Q)
190
True
191
sage: S = HK(1,0)
192
sage: HK.is_weierstrass(S)
193
True
194
sage: T = HK.lift_x(1+3*5^2); T
195
(1 + 3*5^2 + O(5^8) : 2*5 + 4*5^3 + 3*5^4 + 5^5 + 3*5^6 + O(5^7) : 1 + O(5^8))
196
sage: HK.is_weierstrass(T)
197
False
198
199
AUTHOR:
200
201
- Jennifer Balakrishnan (2010-02)
202
203
"""
204
if (P[1] == 0 or P[2] ==0):
205
return True
206
else:
207
return False
208
209
def find_char_zero_weier_point(self, Q):
210
"""
211
Given $Q$ a point on self in a Weierstrass disc, finds the
212
center of the Weierstrass disc (if defined over self.base_ring())
213
214
EXAMPLES::
215
216
sage: R.<x> = QQ['x']
217
sage: H = HyperellipticCurve(x^3-10*x+9)
218
sage: K = Qp(5,8)
219
sage: HK = H.change_ring(K)
220
sage: P = HK.lift_x(1 + 2*5^2)
221
sage: Q = HK.lift_x(5^-2)
222
sage: S = HK(1,0)
223
sage: T = HK(0,1,0)
224
sage: HK.find_char_zero_weier_point(P)
225
(1 + O(5^8) : 0 : 1 + O(5^8))
226
sage: HK.find_char_zero_weier_point(Q)
227
(0 : 1 + O(5^8) : 0)
228
sage: HK.find_char_zero_weier_point(S)
229
(1 + O(5^8) : 0 : 1 + O(5^8))
230
sage: HK.find_char_zero_weier_point(T)
231
(0 : 1 + O(5^8) : 0)
232
233
AUTHOR:
234
235
- Jennifer Balakrishnan
236
"""
237
if self.is_in_weierstrass_disc(Q) == False:
238
raise ValueError, "%s is not in a Weierstrass disc"%Q
239
points = self.weierstrass_points()
240
for P in points:
241
if self.is_same_disc(P,Q):
242
return P
243
244
def residue_disc(self,P):
245
"""
246
Gives the residue disc of $P$
247
248
EXAMPLES::
249
250
sage: R.<x> = QQ['x']
251
sage: H = HyperellipticCurve(x^3-10*x+9)
252
sage: K = Qp(5,8)
253
sage: HK = H.change_ring(K)
254
sage: P = HK.lift_x(1 + 2*5^2)
255
sage: HK.residue_disc(P)
256
(1 : 0 : 1)
257
sage: Q = HK(0,3)
258
sage: HK.residue_disc(Q)
259
(0 : 3 : 1)
260
sage: S = HK.lift_x(5^-2)
261
sage: HK.residue_disc(S)
262
(0 : 1 : 0)
263
sage: T = HK(0,1,0)
264
sage: HK.residue_disc(T)
265
(0 : 1 : 0)
266
267
AUTHOR:
268
269
- Jennifer Balakrishnan
270
"""
271
xPv = P[0].valuation()
272
yPv = P[1].valuation()
273
F = self.base_ring().residue_field()
274
HF = self.change_ring(F)
275
if P == self(0,1,0):
276
return HF(0,1,0)
277
elif yPv > 0:
278
if xPv > 0:
279
return HF(0,0,1)
280
if xPv == 0:
281
return HF(P[0].list()[0], 0,1)
282
elif yPv ==0:
283
if xPv > 0:
284
return HF(0, P[1].list()[0],1)
285
if xPv == 0:
286
return HF(P[0].list()[0], P[1].list()[0],1)
287
else:
288
return HF(0,1,0)
289
290
def is_same_disc(self,P,Q):
291
"""
292
Checks if $P,Q$ are in same residue disc
293
294
EXAMPLES::
295
296
sage: R.<x> = QQ['x']
297
sage: H = HyperellipticCurve(x^3-10*x+9)
298
sage: K = Qp(5,8)
299
sage: HK = H.change_ring(K)
300
sage: P = HK.lift_x(1 + 2*5^2)
301
sage: Q = HK.lift_x(5^-2)
302
sage: S = HK(1,0)
303
sage: HK.is_same_disc(P,Q)
304
False
305
sage: HK.is_same_disc(P,S)
306
True
307
sage: HK.is_same_disc(Q,S)
308
False
309
"""
310
if self.residue_disc(P) == self.residue_disc(Q):
311
return True
312
else:
313
return False
314
315
def tiny_integrals(self, F, P, Q):
316
r"""
317
Evaluate the integrals of $f_i dx/2y$ from $P$ to $Q$ for each $f_i$ in $F$
318
by formally integrating a power series in a local parameter $t$
319
320
$P$ and $Q$ MUST be in the same residue disc for this result to make sense.
321
322
INPUT:
323
324
- F a list of functions $f_i$
325
- P a point on self
326
- Q a point on self (in the same residue disc as P)
327
328
OUTPUT:
329
330
The integrals $\int_P^Q f_i dx/2y$
331
332
EXAMPLES::
333
334
sage: K = pAdicField(17, 5)
335
sage: E = EllipticCurve(K, [-31/3, -2501/108]) # 11a
336
sage: P = E(K(14/3), K(11/2))
337
sage: TP = E.teichmuller(P);
338
sage: x,y = E.monsky_washnitzer_gens()
339
sage: E.tiny_integrals([1,x],P, TP) == E.tiny_integrals_on_basis(P,TP)
340
True
341
342
::
343
344
sage: K = pAdicField(11, 5)
345
sage: x = polygen(K)
346
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
347
sage: P = C.lift_x(11^(-2))
348
sage: Q = C.lift_x(3*11^(-2))
349
sage: C.tiny_integrals([1],P,Q)
350
(3*11^3 + 7*11^4 + 4*11^5 + 7*11^6 + 5*11^7 + O(11^8))
351
352
Note that this fails if the points are not in the same residue disc::
353
354
sage: S = C(0,1/4)
355
sage: C.tiny_integrals([1,x,x^2,x^3],P,S)
356
Traceback (most recent call last):
357
...
358
ValueError: (11^-2 + O(11^3) : 11^-5 + 8*11^-2 + O(11^0) : 1 + O(11^5)) and (0 : 3 + 8*11 + 2*11^2 + 8*11^3 + 2*11^4 + O(11^5) : 1 + O(11^5)) are not in the same residue disc
359
360
"""
361
x, y, z = self.local_analytic_interpolation(P, Q) #homogeneous coordinates
362
x = x/z
363
y = y/z
364
dt = x.derivative() / (2*y)
365
integrals = []
366
g = self.genus()
367
for f in F:
368
try:
369
f_dt = f(x,y)*dt
370
except TypeError: #if f is a constant, not callable
371
f_dt = f*dt
372
if x.valuation() != -2:
373
I = sum([f_dt[n]/(n+1) for n in xrange(f_dt.degree()+1)]) # \int_0^1 f dt
374
else:
375
If_dt = f_dt.integral()
376
I = If_dt(Q[0]**g/Q[1]) - If_dt(P[0]**g/P[1])
377
integrals.append(I)
378
return vector(integrals)
379
380
def tiny_integrals_on_basis(self, P, Q):
381
r"""
382
Evaluate the integrals $\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}$
383
by formally integrating a power series in a local parameter $t$.
384
$P$ and $Q$ MUST be in the same residue disc for this result to make sense.
385
386
INPUT:
387
388
- P a point on self
389
- Q a point on self (in the same residue disc as P)
390
391
OUTPUT:
392
393
The integrals $\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}$
394
395
EXAMPLES::
396
397
sage: K = pAdicField(17, 5)
398
sage: E = EllipticCurve(K, [-31/3, -2501/108]) # 11a
399
sage: P = E(K(14/3), K(11/2))
400
sage: TP = E.teichmuller(P);
401
sage: E.tiny_integrals_on_basis(P, TP)
402
(17 + 14*17^2 + 17^3 + 8*17^4 + O(17^5), 16*17 + 5*17^2 + 8*17^3 + 14*17^4 + O(17^5))
403
404
::
405
406
sage: K = pAdicField(11, 5)
407
sage: x = polygen(K)
408
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
409
sage: P = C.lift_x(11^(-2))
410
sage: Q = C.lift_x(3*11^(-2))
411
sage: C.tiny_integrals_on_basis(P,Q)
412
(3*11^3 + 7*11^4 + 4*11^5 + 7*11^6 + 5*11^7 + O(11^8), 3*11 + 10*11^2 + 8*11^3 + 9*11^4 + 7*11^5 + O(11^6), 4*11^-1 + 2 + 6*11 + 6*11^2 + 7*11^3 + O(11^4), 11^-3 + 6*11^-2 + 2*11^-1 + 2 + O(11^2))
413
414
415
Note that this fails if the points are not in the same residue disc::
416
417
sage: S = C(0,1/4)
418
sage: C.tiny_integrals_on_basis(P,S)
419
Traceback (most recent call last):
420
...
421
ValueError: (11^-2 + O(11^3) : 11^-5 + 8*11^-2 + O(11^0) : 1 + O(11^5)) and (0 : 3 + 8*11 + 2*11^2 + 8*11^3 + 2*11^4 + O(11^5) : 1 + O(11^5)) are not in the same residue disc
422
423
"""
424
if P == Q:
425
V = VectorSpace(self.base_ring(), 2*self.genus())
426
return V(0)
427
R = PolynomialRing(self.base_ring(), ['x', 'y'])
428
x, y = R.gens()
429
return self.tiny_integrals([x**i for i in range(2*self.genus())], P, Q)
430
431
def teichmuller(self, P):
432
r"""
433
Find a Teichm\:uller point in the same residue class of $P$.
434
435
Because this lift of frobenius acts as $x \mapsto x^p$,
436
take the Teichmuller lift of $x$ and then find a matching $y$
437
from that.
438
439
EXAMPLES::
440
441
sage: K = pAdicField(7, 5)
442
sage: E = EllipticCurve(K, [-31/3, -2501/108]) # 11a
443
sage: P = E(K(14/3), K(11/2))
444
sage: E.frobenius(P) == P
445
False
446
sage: TP = E.teichmuller(P); TP
447
(0 : 2 + 3*7 + 3*7^2 + 3*7^4 + O(7^5) : 1 + O(7^5))
448
sage: E.frobenius(TP) == TP
449
True
450
sage: (TP[0] - P[0]).valuation() > 0, (TP[1] - P[1]).valuation() > 0
451
(True, True)
452
"""
453
K = P[0].parent()
454
x = K.teichmuller(P[0])
455
pts = self.lift_x(x, all=True)
456
p = K.prime()
457
if (pts[0][1] - P[1]).valuation() > 0:
458
return pts[0]
459
else:
460
return pts[1]
461
462
def coleman_integrals_on_basis(self, P, Q, algorithm=None):
463
r"""
464
Computes the Coleman integrals $\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}$
465
466
INPUT:
467
468
- P point on self
469
- Q point on self
470
- algorithm (optional) = None (uses Frobenius) or teichmuller (uses Teichmuller points)
471
472
OUTPUT:
473
474
the Coleman integrals $\{\int_P^Q x^i dx/2y \}_{i=0}^{2g-1}$
475
476
EXAMPLES::
477
478
sage: K = pAdicField(11, 5)
479
sage: x = polygen(K)
480
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
481
sage: P = C.lift_x(2)
482
sage: Q = C.lift_x(3)
483
sage: C.coleman_integrals_on_basis(P, Q)
484
(10*11 + 6*11^3 + 2*11^4 + O(11^5), 11 + 9*11^2 + 7*11^3 + 9*11^4 + O(11^5), 3 + 10*11 + 5*11^2 + 9*11^3 + 4*11^4 + O(11^5), 3 + 11 + 5*11^2 + 4*11^4 + O(11^5))
485
sage: C.coleman_integrals_on_basis(P, Q, algorithm='teichmuller')
486
(10*11 + 6*11^3 + 2*11^4 + O(11^5), 11 + 9*11^2 + 7*11^3 + 9*11^4 + O(11^5), 3 + 10*11 + 5*11^2 + 9*11^3 + 4*11^4 + O(11^5), 3 + 11 + 5*11^2 + 4*11^4 + O(11^5))
487
488
::
489
490
sage: K = pAdicField(11,5)
491
sage: x = polygen(K)
492
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
493
sage: P = C.lift_x(11^(-2))
494
sage: Q = C.lift_x(3*11^(-2))
495
sage: C.coleman_integrals_on_basis(P, Q)
496
(3*11^3 + 7*11^4 + 4*11^5 + 7*11^6 + 5*11^7 + O(11^8), 3*11 + 10*11^2 + 8*11^3 + 9*11^4 + 7*11^5 + O(11^6), 4*11^-1 + 2 + 6*11 + 6*11^2 + 7*11^3 + O(11^4), 11^-3 + 6*11^-2 + 2*11^-1 + 2 + O(11^2))
497
498
::
499
500
sage: R = C(0,1/4)
501
sage: a = C.coleman_integrals_on_basis(P,R) # long time (7s on sage.math, 2011)
502
sage: b = C.coleman_integrals_on_basis(R,Q) # long time (9s on sage.math, 2011)
503
sage: c = C.coleman_integrals_on_basis(P,Q) # long time
504
sage: a+b == c # long time
505
True
506
507
::
508
509
sage: R.<x> = QQ['x']
510
sage: H = HyperellipticCurve(x^3-10*x+9)
511
sage: K = Qp(5,8)
512
sage: HK = H.change_ring(K)
513
sage: S = HK(1,0)
514
sage: P = HK(0,3)
515
sage: T = HK(0,1,0)
516
sage: Q = HK.lift_x(5^-2)
517
sage: R = HK.lift_x(4*5^-2)
518
sage: HK.coleman_integrals_on_basis(S,P)
519
(2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 3*5^6 + 4*5^7 + 2*5^8 + O(5^9))
520
sage: HK.coleman_integrals_on_basis(T,P)
521
(2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 3*5^6 + 4*5^7 + 2*5^8 + O(5^9))
522
sage: HK.coleman_integrals_on_basis(P,S) == -HK.coleman_integrals_on_basis(S,P)
523
True
524
sage: HK.coleman_integrals_on_basis(S,Q)
525
(4*5 + 4*5^2 + 4*5^3 + O(5^4), 5^-1 + O(5^3))
526
sage: HK.coleman_integrals_on_basis(Q,R)
527
(4*5 + 2*5^2 + 2*5^3 + 2*5^4 + 5^5 + 5^6 + 5^7 + 3*5^8 + O(5^9), 2*5^-1 + 4 + 4*5 + 4*5^2 + 4*5^3 + 2*5^4 + 3*5^5 + 2*5^6 + O(5^7))
528
sage: HK.coleman_integrals_on_basis(S,R) == HK.coleman_integrals_on_basis(S,Q) + HK.coleman_integrals_on_basis(Q,R)
529
True
530
sage: HK.coleman_integrals_on_basis(T,T)
531
(0, 0)
532
sage: HK.coleman_integrals_on_basis(S,T)
533
(0, 0)
534
535
AUTHORS:
536
537
- Robert Bradshaw (2007-03): non-Weierstrass points
538
- Jennifer Balakrishnan and Robert Bradshaw (2010-02): Weierstrass points
539
"""
540
import sage.schemes.elliptic_curves.monsky_washnitzer as monsky_washnitzer
541
from sage.misc.profiler import Profiler
542
prof = Profiler()
543
prof("setup")
544
K = self.base_ring()
545
p = K.prime()
546
prec = K.precision_cap()
547
g = self.genus()
548
dim = 2*g
549
V = VectorSpace(K, dim)
550
#if P or Q is Weierstrass, use the Frobenius algorithm
551
if self.is_weierstrass(P):
552
if self.is_weierstrass(Q):
553
return V(0)
554
else:
555
PP = None
556
QQ = Q
557
TP = None
558
TQ = self.frobenius(Q)
559
elif self.is_weierstrass(Q):
560
PP = P
561
QQ = None
562
TQ = None
563
TP = self.frobenius(P)
564
elif self.is_same_disc(P,Q):
565
return self.tiny_integrals_on_basis(P,Q)
566
elif algorithm == 'teichmuller':
567
prof("teichmuller")
568
PP = TP = self.teichmuller(P)
569
QQ = TQ = self.teichmuller(Q)
570
evalP, evalQ = TP, TQ
571
else:
572
prof("frobPQ")
573
TP = self.frobenius(P)
574
TQ = self.frobenius(Q)
575
PP, QQ = P, Q
576
prof("tiny integrals")
577
if TP == None:
578
P_to_TP = V(0)
579
else:
580
if TP!=None:
581
TPv = (TP[0]**g/TP[1]).valuation()
582
xTPv = TP[0].valuation()
583
else:
584
xTPv = TPv = +Infinity
585
if TQ!=None:
586
TQv = (TQ[0]**g/TQ[1]).valuation()
587
xTQv = TQ[0].valuation()
588
else:
589
xTQv = TQv = +Infinity
590
offset = (2*g-1)*max(TPv, TQv)
591
if offset == +Infinity:
592
offset = (2*g-1)*min(TPv,TQv)
593
if (offset > prec and (xTPv <0 or xTQv <0) and (self.residue_disc(P) == self.change_ring(GF(p))(0,1,0) or self.residue_disc(Q) == self.change_ring(GF(p))(0,1,0))):
594
newprec = offset + prec
595
K = pAdicField(p,newprec)
596
A = PolynomialRing(RationalField(),'x')
597
f = A(self.hyperelliptic_polynomials()[0])
598
from sage.schemes.hyperelliptic_curves.constructor import HyperellipticCurve
599
self = HyperellipticCurve(f).change_ring(K)
600
xP = P[0]
601
xPv = xP.valuation()
602
xPnew = K(sum(xP.list()[i]*p**(xPv + i) for i in range(len(xP.list()))))
603
PP = P = self.lift_x(xPnew)
604
TP = self.frobenius(P)
605
xQ = Q[0]
606
xQv = xQ.valuation()
607
xQnew = K(sum(xQ.list()[i]*p**(xQv + i) for i in range(len(xQ.list()))))
608
QQ = Q = self.lift_x(xQnew)
609
TQ = self.frobenius(Q)
610
V = VectorSpace(K,dim)
611
P_to_TP = V(self.tiny_integrals_on_basis(P, TP))
612
if TQ == None:
613
TQ_to_Q = V(0)
614
else:
615
TQ_to_Q = V(self.tiny_integrals_on_basis(TQ, Q))
616
prof("mw calc")
617
try:
618
M_frob, forms = self._frob_calc
619
except AttributeError:
620
M_frob, forms = self._frob_calc = monsky_washnitzer.matrix_of_frobenius_hyperelliptic(self)
621
prof("eval f")
622
R = forms[0].base_ring()
623
try:
624
prof("eval f %s"%R)
625
if PP is None:
626
L = [-f(R(QQ[0]), R(QQ[1])) for f in forms] ##changed
627
elif QQ is None:
628
L = [f(R(PP[0]), R(PP[1])) for f in forms]
629
else:
630
L = [f(R(PP[0]), R(PP[1])) - f(R(QQ[0]), R(QQ[1])) for f in forms]
631
except ValueError:
632
prof("changing rings")
633
forms = [f.change_ring(self.base_ring()) for f in forms]
634
prof("eval f %s"%self.base_ring())
635
if PP is None:
636
L = [-f(QQ[0], QQ[1]) for f in forms] ##changed
637
elif QQ is None:
638
L = [f(PP[0], PP[1]) for f in forms]
639
else:
640
L = [f(PP[0], PP[1]) - f(QQ[0], QQ[1]) for f in forms]
641
b = V(L)
642
if PP is None:
643
b -= TQ_to_Q
644
elif QQ is None:
645
b -= P_to_TP
646
elif algorithm != 'teichmuller':
647
b -= P_to_TP + TQ_to_Q
648
prof("lin alg")
649
M_sys = matrix(K, M_frob).transpose() - 1
650
TP_to_TQ = M_sys**(-1) * b
651
prof("done")
652
# print prof
653
if algorithm == 'teichmuller':
654
return P_to_TP + TP_to_TQ + TQ_to_Q
655
else:
656
return TP_to_TQ
657
658
coleman_integrals_on_basis_hyperelliptic = coleman_integrals_on_basis
659
660
661
# def invariant_differential(self):
662
# """
663
# Returns the invariant differential $dx/2y$ on self
664
#
665
# EXAMPLES::
666
#
667
# sage: R.<x> = QQ['x']
668
# sage: H = HyperellipticCurve(x^3+1)
669
# sage: K = Qp(5,8)
670
# sage: HK = H.change_ring(K)
671
# sage: w = HK.invariant_differential(); w
672
# (((1+O(5^8)))*1) dx/2y
673
#
674
# ::
675
#
676
# sage: K = pAdicField(11, 6)
677
# sage: x = polygen(K)
678
# sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
679
# sage: C.invariant_differential()
680
# (((1+O(11^6)))*1) dx/2y
681
#
682
# """
683
# import sage.schemes.elliptic_curves.monsky_washnitzer as monsky_washnitzer
684
# S = monsky_washnitzer.SpecialHyperellipticQuotientRing(self)
685
# MW = monsky_washnitzer.MonskyWashnitzerDifferentialRing(S)
686
# return MW.invariant_differential()
687
688
def coleman_integral(self, w, P, Q, algorithm = 'None'):
689
r"""
690
Returns the Coleman integral $\int_P^Q w$
691
692
INPUT:
693
694
- w differential (if one of P,Q is Weierstrass, w must be odd)
695
- P point on self
696
- Q point on self
697
- algorithm (optional) = None (uses Frobenius) or teichmuller (uses Teichmuller points)
698
699
OUTPUT:
700
701
the Coleman integral $\int_P^Q w$
702
703
EXAMPLES::
704
705
Example of Leprevost from Kiran Kedlaya
706
The first two should be zero as $(P-Q) = 30(P-Q)$ in the Jacobian
707
and $dx/2y$ and $x dx/2y$ are holomorphic.
708
709
sage: K = pAdicField(11, 6)
710
sage: x = polygen(K)
711
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
712
sage: P = C(-1, 1); P1 = C(-1, -1)
713
sage: Q = C(0, 1/4); Q1 = C(0, -1/4)
714
sage: x, y = C.monsky_washnitzer_gens()
715
sage: w = C.invariant_differential()
716
sage: w.coleman_integral(P, Q)
717
O(11^6)
718
sage: C.coleman_integral(x*w, P, Q)
719
O(11^6)
720
sage: C.coleman_integral(x^2*w, P, Q)
721
7*11 + 6*11^2 + 3*11^3 + 11^4 + 5*11^5 + O(11^6)
722
723
::
724
725
sage: p = 71; m = 4
726
sage: K = pAdicField(p, m)
727
sage: x = polygen(K)
728
sage: C = HyperellipticCurve(x^5 + 33/16*x^4 + 3/4*x^3 + 3/8*x^2 - 1/4*x + 1/16)
729
sage: P = C(-1, 1); P1 = C(-1, -1)
730
sage: Q = C(0, 1/4); Q1 = C(0, -1/4)
731
sage: x, y = C.monsky_washnitzer_gens()
732
sage: w = C.invariant_differential()
733
sage: w.integrate(P, Q), (x*w).integrate(P, Q)
734
(O(71^4), O(71^4))
735
sage: R, R1 = C.lift_x(4, all=True)
736
sage: w.integrate(P, R)
737
21*71 + 67*71^2 + 27*71^3 + O(71^4)
738
sage: w.integrate(P, R) + w.integrate(P1, R1)
739
O(71^4)
740
741
A simple example, integrating dx::
742
743
sage: R.<x> = QQ['x']
744
sage: E= HyperellipticCurve(x^3-4*x+4)
745
sage: K = Qp(5,10)
746
sage: EK = E.change_ring(K)
747
sage: P = EK(2, 2)
748
sage: Q = EK.teichmuller(P)
749
sage: x, y = EK.monsky_washnitzer_gens()
750
sage: EK.coleman_integral(x.diff(), P, Q)
751
5 + 2*5^2 + 5^3 + 3*5^4 + 4*5^5 + 2*5^6 + 3*5^7 + 3*5^9 + O(5^10)
752
sage: Q[0] - P[0]
753
5 + 2*5^2 + 5^3 + 3*5^4 + 4*5^5 + 2*5^6 + 3*5^7 + 3*5^9 + O(5^10)
754
755
Yet another example::
756
757
sage: R.<x> = QQ['x']
758
sage: H = HyperellipticCurve(x*(x-1)*(x+9))
759
sage: K = Qp(7,10)
760
sage: HK = H.change_ring(K)
761
sage: import sage.schemes.elliptic_curves.monsky_washnitzer as mw
762
sage: M_frob, forms = mw.matrix_of_frobenius_hyperelliptic(HK)
763
sage: w = HK.invariant_differential()
764
sage: x,y = HK.monsky_washnitzer_gens()
765
sage: f = forms[0]
766
sage: S = HK(9,36)
767
sage: Q = HK.teichmuller(S)
768
sage: P = HK(-1,4)
769
sage: b = x*w*w._coeff.parent()(f)
770
sage: HK.coleman_integral(b,P,Q)
771
7 + 7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^6 + 5*7^7 + 3*7^8 + 4*7^9 + 4*7^10 + O(7^11)
772
773
::
774
775
sage: R.<x> = QQ['x']
776
sage: H = HyperellipticCurve(x^3+1)
777
sage: K = Qp(5,8)
778
sage: HK = H.change_ring(K)
779
sage: w = HK.invariant_differential()
780
sage: P = HK(0,1)
781
sage: Q = HK.lift_x(5)
782
sage: x,y = HK.monsky_washnitzer_gens()
783
sage: (2*y*w).coleman_integral(P,Q)
784
5 + O(5^9)
785
sage: xloc,yloc,zloc = HK.local_analytic_interpolation(P,Q)
786
sage: I2 = (xloc.derivative()/(2*yloc)).integral()
787
sage: I2(1)-I2(0)
788
3*5 + 2*5^2 + 2*5^3 + 5^4 + 4*5^6 + 5^7 + O(5^9)
789
sage: HK.coleman_integral(w,P,Q)
790
3*5 + 2*5^2 + 2*5^3 + 5^4 + 4*5^6 + 5^7 + O(5^9)
791
792
Integrals involving Weierstrass points::
793
794
sage: R.<x> = QQ['x']
795
sage: H = HyperellipticCurve(x^3-10*x+9)
796
sage: K = Qp(5,8)
797
sage: HK = H.change_ring(K)
798
sage: S = HK(1,0)
799
sage: P = HK(0,3)
800
sage: negP = HK(0,-3)
801
sage: T = HK(0,1,0)
802
sage: w = HK.invariant_differential()
803
sage: x,y = HK.monsky_washnitzer_gens()
804
sage: HK.coleman_integral(w*x^3,S,T)
805
0
806
sage: HK.coleman_integral(w*x^3,T,S)
807
0
808
sage: HK.coleman_integral(w,S,P)
809
2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9)
810
sage: HK.coleman_integral(w,T,P)
811
2*5^2 + 5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + O(5^9)
812
sage: HK.coleman_integral(w*x^3,T,P)
813
5^2 + 2*5^3 + 3*5^6 + 3*5^7 + O(5^8)
814
sage: HK.coleman_integral(w*x^3,S,P)
815
5^2 + 2*5^3 + 3*5^6 + 3*5^7 + O(5^8)
816
sage: HK.coleman_integral(w, P, negP, algorithm='teichmuller')
817
5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 3*5^6 + 2*5^7 + 4*5^8 + O(5^9)
818
sage: HK.coleman_integral(w, P, negP)
819
5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 3*5^6 + 2*5^7 + 4*5^8 + O(5^9)
820
821
AUTHORS:
822
823
- Robert Bradshaw (2007-03)
824
- Kiran Kedlaya (2008-05)
825
- Jennifer Balakrishnan (2010-02)
826
827
"""
828
# TODO: implement Jacobians and show the relationship directly
829
import sage.schemes.elliptic_curves.monsky_washnitzer as monsky_washnitzer
830
K = self.base_ring()
831
prec = K.precision_cap()
832
S = monsky_washnitzer.SpecialHyperellipticQuotientRing(self, K)
833
MW = monsky_washnitzer.MonskyWashnitzerDifferentialRing(S)
834
w = MW(w)
835
f, vec = w.reduce_fast()
836
basis_values = self.coleman_integrals_on_basis(P, Q, algorithm)
837
dim = len(basis_values)
838
x,y = self.local_coordinates_at_infinity(2*prec)
839
if self.is_weierstrass(P):
840
if self.is_weierstrass(Q):
841
return 0
842
elif f == 0:
843
return sum([vec[i] * basis_values[i] for i in range(dim)])
844
elif w._coeff(x,-y)*x.derivative()/(-2*y)+w._coeff(x,y)*x.derivative()/(2*y) == 0:
845
return self.coleman_integral(w,self(Q[0],-Q[1]), self(Q[0],Q[1]), algorithm)/2
846
else:
847
raise ValueError, "The differential is not odd: use coleman_integral_from_weierstrass_via_boundary"
848
849
elif self.is_weierstrass(Q):
850
if f == 0:
851
return sum([vec[i] * basis_values[i] for i in range(dim)])
852
elif w._coeff(x,-y)*x.derivative()/(-2*y)+w._coeff(x,y)*x.derivative()/(2*y) == 0:
853
return -self.coleman_integral(w,self(P[0],-P[1]), self(P[0],P[1]), algorithm)/2
854
else:
855
raise ValueError, "The differential is not odd: use coleman_integral_from_weierstrass_via_boundary"
856
else:
857
return f(Q[0], Q[1]) - f(P[0], P[1]) + sum([vec[i] * basis_values[i] for i in range(dim)]) # this is just a dot product...
858
859
def frobenius(self, P=None):
860
"""
861
Returns the $p$-th power lift of Frobenius of $P$
862
863
EXAMPLES::
864
865
sage: K = Qp(11, 5)
866
sage: R.<x> = K[]
867
sage: E = HyperellipticCurve(x^5 - 21*x - 20)
868
sage: P = E.lift_x(2)
869
sage: E.frobenius(P)
870
(2 + 10*11 + 5*11^2 + 11^3 + O(11^5) : 5 + 9*11 + 2*11^2 + 2*11^3 + O(11^5) : 1 + O(11^5))
871
sage: Q = E.teichmuller(P); Q
872
(2 + 10*11 + 4*11^2 + 9*11^3 + 11^4 + O(11^5) : 5 + 9*11 + 6*11^2 + 11^3 + 6*11^4 + O(11^5) : 1 + O(11^5))
873
sage: E.frobenius(Q)
874
(2 + 10*11 + 4*11^2 + 9*11^3 + 11^4 + O(11^5) : 5 + 9*11 + 6*11^2 + 11^3 + 6*11^4 + O(11^5) : 1 + O(11^5))
875
876
::
877
878
sage: R.<x> = QQ[]
879
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
880
sage: Q = H(0,0)
881
sage: u,v = H.local_coord(Q,prec=100)
882
sage: K = Qp(11,5)
883
sage: L.<a> = K.extension(x^20-11)
884
sage: HL = H.change_ring(L)
885
sage: S = HL(u(a),v(a))
886
sage: HL.frobenius(S)
887
(8*a^22 + 10*a^42 + 4*a^44 + 2*a^46 + 9*a^48 + 8*a^50 + a^52 + 7*a^54 +
888
7*a^56 + 5*a^58 + 9*a^62 + 5*a^64 + a^66 + 6*a^68 + a^70 + 6*a^74 +
889
2*a^76 + 2*a^78 + 4*a^82 + 5*a^84 + 2*a^86 + 7*a^88 + a^90 + 6*a^92 +
890
a^96 + 5*a^98 + 2*a^102 + 2*a^106 + 6*a^108 + 8*a^110 + 3*a^112 +
891
a^114 + 8*a^116 + 10*a^118 + 3*a^120 + O(a^122) :
892
a^11 + 7*a^33 + 7*a^35 + 4*a^37 + 6*a^39 + 9*a^41 + 8*a^43 + 8*a^45 +
893
a^47 + 7*a^51 + 4*a^53 + 5*a^55 + a^57 + 7*a^59 + 5*a^61 + 9*a^63 +
894
4*a^65 + 10*a^69 + 3*a^71 + 2*a^73 + 9*a^75 + 10*a^77 + 6*a^79 +
895
10*a^81 + 7*a^85 + a^87 + 4*a^89 + 8*a^91 + a^93 + 8*a^95 + 2*a^97 +
896
7*a^99 + a^101 + 3*a^103 + 6*a^105 + 7*a^107 + 4*a^109 + O(a^111) :
897
1 + O(a^100))
898
899
AUTHORS:
900
901
- Robert Bradshaw and Jennifer Balakrishnan (2010-02)
902
"""
903
try:
904
_frob = self._frob
905
except AttributeError:
906
K = self.base_ring()
907
p = K.prime()
908
x = K['x'].gen(0)
909
910
f, f2 = self.hyperelliptic_polynomials()
911
if f2 != 0:
912
raise NotImplementedError, "Curve must be in weierstrass normal form."
913
h = (f(x**p) - f**p)
914
915
def _frob(P):
916
if P == self(0,1,0):
917
return P
918
x0 = P[0]
919
y0 = P[1]
920
try:
921
uN = (1 + h(x0)/y0**(2*p)).sqrt()
922
yres=y0**p * uN
923
xres=x0**p
924
if (yres-y0).valuation() == 0:
925
yres=-yres
926
return self.point([xres,yres, K(1)])
927
except (TypeError, NotImplementedError):
928
uN2 = 1 + h(x0)/y0**(2*p)
929
#yfrob2 = f(x)
930
c = uN2.list()[0]
931
v = uN2.valuation()
932
a = uN2.parent().gen()
933
uN = self.newton_sqrt(uN2,c.sqrt()*a**(v//2),K.precision_cap())
934
yres = y0**p *uN
935
xres = x0**p
936
if (yres - y0).valuation() == 0:
937
yres = -yres
938
try:
939
return self(xres,yres)
940
except ValueError:
941
return self._curve_over_ram_extn(xres,yres)
942
943
self._frob = _frob
944
945
if P is None:
946
return _frob
947
else:
948
return _frob(P)
949
950
def newton_sqrt(self,f,x0, prec):
951
r"""
952
Takes the square root of the power series $f$ by Newton's method
953
954
NOTE:
955
956
this function should eventually be moved to $p$-adic power series ring
957
958
INPUT:
959
960
- f power series wtih coefficients in $\Q_p$ or an extension
961
- x0 seeds the Newton iteration
962
- prec precision
963
964
OUTPUT:
965
966
the square root of $f$
967
968
EXAMPLES::
969
970
sage: R.<x> = QQ['x']
971
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
972
sage: Q = H(0,0)
973
sage: u,v = H.local_coord(Q,prec=100)
974
sage: K = Qp(11,5)
975
sage: HK = H.change_ring(K)
976
sage: L.<a> = K.extension(x^20-11)
977
sage: HL = H.change_ring(L)
978
sage: S = HL(u(a),v(a))
979
sage: f = H.hyperelliptic_polynomials()[0]
980
sage: y = HK.newton_sqrt( f(u(a)^11), a^11,5)
981
sage: y^2 - f(u(a)^11)
982
O(a^122)
983
984
AUTHOR:
985
986
- Jennifer Balakrishnan
987
988
"""
989
z = x0
990
try:
991
x = f.parent().variable_name()
992
if x!='a' : #this is to distinguish between extensions of Qp that are finite vs. not
993
S = f.base_ring()[[x]]
994
x = S.gen()
995
except ValueError:
996
pass
997
z = x0
998
loop_prec = (log(RR(prec))/log(RR(2))).ceil()
999
for i in range(loop_prec):
1000
z = (z+f/z)/2
1001
try:
1002
return z + O(x**prec)
1003
except (NameError,ArithmeticError,TypeError):
1004
return z
1005
1006
def curve_over_ram_extn(self,deg):
1007
r"""
1008
Returns self over $\Q_p(p^(1/deg))$
1009
1010
INPUT:
1011
1012
- deg: the degree of the ramified extension
1013
1014
OUTPUT:
1015
1016
self over $\Q_p(p^(1/deg))$
1017
1018
EXAMPLES::
1019
1020
sage: R.<x> = QQ['x']
1021
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
1022
sage: K = Qp(11,5)
1023
sage: HK = H.change_ring(K)
1024
sage: HL = HK.curve_over_ram_extn(2)
1025
sage: HL
1026
Hyperelliptic Curve over Eisenstein Extension of 11-adic Field with capped relative precision 5 in a defined by (1 + O(11^5))*x^2 + (O(11^6))*x + (10*11 + 10*11^2 + 10*11^3 + 10*11^4 + 10*11^5 + O(11^6)) defined by (1 + O(a^10))*y^2 = (1 + O(a^10))*x^5 + (10 + 8*a^2 + 10*a^4 + 10*a^6 + 10*a^8 + O(a^10))*x^3 + (7 + a^2 + O(a^10))*x^2 + (7 + 3*a^2 + O(a^10))*x
1027
1028
AUTHOR:
1029
1030
- Jennifer Balakrishnan
1031
1032
"""
1033
from sage.schemes.hyperelliptic_curves.constructor import HyperellipticCurve
1034
K = self.base_ring()
1035
p = K.prime()
1036
A = PolynomialRing(QQ,'x')
1037
x = A.gen()
1038
J = K.extension(x**deg-p,names='a')
1039
pol = self.hyperelliptic_polynomials()[0]
1040
H = HyperellipticCurve(A(pol))
1041
HJ = H.change_ring(J)
1042
self._curve_over_ram_extn = HJ
1043
self._curve_over_ram_extn._curve_over_Qp = self
1044
return HJ
1045
1046
def get_boundary_point(self, curve_over_extn, P):
1047
"""
1048
Given self over an extension field, find a point in the disc of $P$ near the boundary
1049
1050
INPUT:
1051
1052
- curve_over_extn: self over a totally ramified extension
1053
- P: Weierstrass point
1054
1055
OUTPUT:
1056
1057
a point in the disc of $P$ near the boundary
1058
1059
EXAMPLES::
1060
1061
sage: R.<x> = QQ['x']
1062
sage: H = HyperellipticCurve(x^3-10*x+9)
1063
sage: K = Qp(3,6)
1064
sage: HK = H.change_ring(K)
1065
sage: P = HK(1,0)
1066
sage: J.<a> = K.extension(x^30-3)
1067
sage: HJ = H.change_ring(J)
1068
sage: S = HK.get_boundary_point(HJ,P)
1069
sage: S
1070
(1 + 2*a^2 + 2*a^6 + 2*a^18 + a^32 + a^34 + a^36 + 2*a^38 + 2*a^40 + a^42 + 2*a^44 + a^48 + 2*a^50 + 2*a^52 + a^54 + a^56 + 2*a^60 + 2*a^62 + a^70 + 2*a^72 + a^76 + 2*a^78 + a^82 + a^88 + a^96 + 2*a^98 + 2*a^102 + a^104 + 2*a^106 + a^108 + 2*a^110 + a^112 + 2*a^116 + a^126 + 2*a^130 + 2*a^132 + a^144 + 2*a^148 + 2*a^150 + a^152 + 2*a^154 + a^162 + a^164 + a^166 + a^168 + a^170 + a^176 + a^178 + O(a^180) : a + O(a^181) : 1 + O(a^180))
1071
1072
AUTHOR:
1073
1074
- Jennifer Balakrishnan
1075
1076
"""
1077
J = curve_over_extn.base_ring()
1078
a = J.gen()
1079
prec2 = J.precision_cap()
1080
x,y = self.local_coord(P,prec2)
1081
return curve_over_extn(x(a),y(a))
1082
1083
def P_to_S(self, P, S):
1084
r"""
1085
Given a finite Weierstrass point $P$ and a point $S$
1086
in the same disc, computes the Coleman integrals $\{\int_P^S x^i dx/2y \}_{i=0}^{2g-1}$
1087
1088
INPUT:
1089
1090
- P: finite Weierstrass point
1091
- S: point in disc of P
1092
1093
OUTPUT:
1094
1095
Coleman integrals $\{\int_P^S x^i dx/2y \}_{i=0}^{2g-1}$
1096
1097
EXAMPLES::
1098
1099
sage: R.<x> = QQ['x']
1100
sage: H = HyperellipticCurve(x^3-10*x+9)
1101
sage: K = Qp(5,4)
1102
sage: HK = H.change_ring(K)
1103
sage: P = HK(1,0)
1104
sage: HJ = HK.curve_over_ram_extn(10)
1105
sage: S = HK.get_boundary_point(HJ,P)
1106
sage: HK.P_to_S(P, S)
1107
(2*a + 4*a^3 + 2*a^11 + 4*a^13 + 2*a^17 + 2*a^19 + a^21 + 4*a^23 + a^25 + 2*a^27 + 2*a^29 + 3*a^31 + 4*a^33 + O(a^35), a^-5 + 2*a + 2*a^3 + a^7 + 3*a^11 + a^13 + 3*a^15 + 3*a^17 + 2*a^19 + 4*a^21 + 4*a^23 + 4*a^25 + 2*a^27 + a^29 + a^31 + 3*a^33 + O(a^35))
1108
1109
AUTHOR:
1110
1111
- Jennifer Balakrishnan
1112
1113
"""
1114
prec = self.base_ring().precision_cap()
1115
deg = (S[0]).parent().defining_polynomial().degree()
1116
prec2= prec*deg
1117
x,y = self.local_coord(P,prec2)
1118
g = self.genus()
1119
integrals = [((x**k*x.derivative()/(2*y)).integral()) for k in range(2*g)]
1120
val = [I(S[1]) for I in integrals]
1121
return vector(val)
1122
1123
def coleman_integral_P_to_S(self,w,P,S):
1124
r"""
1125
Given a finite Weierstrass point $P$ and a point $S$
1126
in the same disc, computes the Coleman integral $\int_P^S w$
1127
1128
INPUT:
1129
1130
- w: differential
1131
- P: Weierstrass point
1132
- S: point in the same disc of P (S is defined over an extension of $\Q_p$; coordinates
1133
of S are given in terms of uniformizer $a$)
1134
1135
OUTPUT:
1136
1137
Coleman integral $\int_P^S w$ in terms of $a$
1138
1139
EXAMPLES::
1140
1141
sage: R.<x> = QQ['x']
1142
sage: H = HyperellipticCurve(x^3-10*x+9)
1143
sage: K = Qp(5,4)
1144
sage: HK = H.change_ring(K)
1145
sage: P = HK(1,0)
1146
sage: J.<a> = K.extension(x^10-5)
1147
sage: HJ = H.change_ring(J)
1148
sage: S = HK.get_boundary_point(HJ,P)
1149
sage: x,y = HK.monsky_washnitzer_gens()
1150
sage: S[0]-P[0] == HK.coleman_integral_P_to_S(x.diff(),P,S)
1151
True
1152
sage: HK.coleman_integral_P_to_S(HK.invariant_differential(),P,S) == HK.P_to_S(P,S)[0]
1153
True
1154
1155
AUTHOR:
1156
1157
- Jennifer Balakrishnan
1158
1159
"""
1160
prec = self.base_ring().precision_cap()
1161
deg = S[0].parent().defining_polynomial().degree()
1162
prec2= prec*deg
1163
x,y = self.local_coord(P,prec2)
1164
g = self.genus()
1165
int_sing = (w.coeff()(x,y)*x.derivative()/(2*y)).integral()
1166
int_sing_a = int_sing(S[1])
1167
return int_sing_a
1168
1169
def S_to_Q(self,S,Q):
1170
r"""
1171
Given $S$ a point on self over an extension field, computes the
1172
Coleman integrals $\{\int_S^Q x^i dx/2y \}_{i=0}^{2g-1}$
1173
1174
**one should be able to feed $S,Q$ into coleman_integral,
1175
but currently that segfaults**
1176
1177
INPUT:
1178
1179
- S: a point with coordinates in an extension of $\Q_p$ (with unif. a)
1180
- Q: a non-Weierstrass point defined over $\Q_p$
1181
1182
OUTPUT:
1183
1184
the Coleman integrals $\{\int_S^Q x^i dx/2y \}_{i=0}^{2g-1}$ in terms of $a$
1185
1186
EXAMPLES::
1187
1188
sage: R.<x> = QQ['x']
1189
sage: H = HyperellipticCurve(x^3-10*x+9)
1190
sage: K = Qp(5,6)
1191
sage: HK = H.change_ring(K)
1192
sage: J.<a> = K.extension(x^20-5)
1193
sage: HJ = H.change_ring(J)
1194
sage: w = HK.invariant_differential()
1195
sage: x,y = HK.monsky_washnitzer_gens()
1196
sage: P = HK(1,0)
1197
sage: Q = HK(0,3)
1198
sage: S = HK.get_boundary_point(HJ,P)
1199
sage: P_to_S = HK.P_to_S(P,S)
1200
sage: S_to_Q = HJ.S_to_Q(S,Q)
1201
sage: P_to_S + S_to_Q
1202
(2*a^40 + a^80 + a^100 + O(a^105), a^20 + 2*a^40 + 4*a^60 + 2*a^80 + O(a^105))
1203
sage: HK.coleman_integrals_on_basis(P,Q)
1204
(2*5^2 + 5^4 + 5^5 + 3*5^6 + O(5^7), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 5^6 + O(5^7))
1205
1206
AUTHOR:
1207
1208
- Jennifer Balakrishnan
1209
1210
"""
1211
FS = self.frobenius(S)
1212
FS = (FS[0],FS[1])
1213
FQ = self.frobenius(Q)
1214
import sage.schemes.elliptic_curves.monsky_washnitzer as monsky_washnitzer
1215
try:
1216
M_frob, forms = self._frob_calc
1217
except AttributeError:
1218
M_frob, forms = self._frob_calc = monsky_washnitzer.matrix_of_frobenius_hyperelliptic(self)
1219
try:
1220
HJ = self._curve_over_ram_extn
1221
K = HJ.base_ring()
1222
except AttributeError:
1223
HJ = S.scheme()
1224
K = self.base_ring()
1225
g = self.genus()
1226
prec2 = K.precision_cap()
1227
p = K.prime()
1228
dim = 2*g
1229
V = VectorSpace(K,dim)
1230
if S == FS:
1231
S_to_FS = V(dim*[0])
1232
else:
1233
P = self(ZZ(FS[0][0]),ZZ(FS[1][0]))
1234
x,y = self.local_coord(P,prec2)
1235
integrals = [(x**i*x.derivative()/(2*y)).integral() for i in range(dim)]
1236
S_to_FS = vector([I(FS[1])-I(S[1]) for I in integrals])
1237
if HJ(Q[0],Q[1]) == HJ(FQ):
1238
FQ_to_Q = V(dim*[0])
1239
else:
1240
FQ_to_Q = V(self.tiny_integrals_on_basis(FQ, Q))
1241
try:
1242
L = [f(K(S[0]), K(S[1])) - f(K(Q[0]), K(Q[1])) for f in forms]
1243
except ValueError:
1244
forms = [f.change_ring(K) for f in forms]
1245
L = [f(S[0], S[1]) - f(Q[0], Q[1]) for f in forms]
1246
b = V(L)
1247
M_sys = matrix(K, M_frob).transpose() - 1
1248
B = (~M_sys)
1249
v = [B.list()[i].valuation() for i in range(len(B.list()))]
1250
vv= min(v)
1251
B = (p**(-vv)*B).change_ring(K)
1252
B = p**(vv)*B
1253
return B*(b-S_to_FS-FQ_to_Q)
1254
1255
def coleman_integral_S_to_Q(self,w,S,Q):
1256
r"""
1257
Computes the Coleman integral $\int_S^Q w$
1258
1259
**one should be able to feed $S,Q$ into coleman_integral,
1260
but currently that segfaults**
1261
1262
INPUT:
1263
1264
- w: a differential
1265
- S: a point with coordinates in an extension of $\Q_p$
1266
- Q: a non-Weierstrass point defined over $\Q_p$
1267
1268
OUTPUT:
1269
1270
the Coleman integral $\int_S^Q w$
1271
1272
EXAMPLES::
1273
1274
sage: R.<x> = QQ['x']
1275
sage: H = HyperellipticCurve(x^3-10*x+9)
1276
sage: K = Qp(5,6)
1277
sage: HK = H.change_ring(K)
1278
sage: J.<a> = K.extension(x^20-5)
1279
sage: HJ = H.change_ring(J)
1280
sage: x,y = HK.monsky_washnitzer_gens()
1281
sage: P = HK(1,0)
1282
sage: Q = HK(0,3)
1283
sage: S = HK.get_boundary_point(HJ,P)
1284
sage: P_to_S = HK.coleman_integral_P_to_S(y.diff(),P,S)
1285
sage: S_to_Q = HJ.coleman_integral_S_to_Q(y.diff(),S,Q)
1286
sage: P_to_S + S_to_Q
1287
3 + O(a^120)
1288
sage: HK.coleman_integral(y.diff(),P,Q)
1289
3 + O(5^6)
1290
1291
AUTHOR:
1292
1293
- Jennifer Balakrishnan
1294
1295
"""
1296
import sage.schemes.elliptic_curves.monsky_washnitzer as monsky_washnitzer
1297
K = self.base_ring()
1298
R = monsky_washnitzer.SpecialHyperellipticQuotientRing(self, K)
1299
MW = monsky_washnitzer.MonskyWashnitzerDifferentialRing(R)
1300
w = MW(w)
1301
f, vec = w.reduce_fast()
1302
g = self.genus()
1303
const = f(Q[0],Q[1])-f(S[0],S[1])
1304
if vec == vector(2*g*[0]):
1305
return const
1306
else:
1307
basis_values = self.S_to_Q(S, Q)
1308
dim = len(basis_values)
1309
dot = sum([vec[i] * basis_values[i] for i in range(dim)])
1310
return const + dot
1311
1312
def coleman_integral_from_weierstrass_via_boundary(self, w, P, Q, d):
1313
r"""
1314
Computes the Coleman integral $\int_P^Q w$ via a boundary point
1315
in the disc of $P$, defined over a degree $d$ extension
1316
1317
INPUT:
1318
1319
- w: a differential
1320
- P: a Weierstrass point
1321
- Q: a non-Weierstrass point
1322
- d: degree of extension where coordinates of boundary point lie
1323
1324
OUTPUT:
1325
1326
the Coleman integral $\int_P^Q w$, written in terms of the uniformizer
1327
$a$ of the degree $d$ extension
1328
1329
EXAMPLES::
1330
1331
sage: R.<x> = QQ['x']
1332
sage: H = HyperellipticCurve(x^3-10*x+9)
1333
sage: K = Qp(5,6)
1334
sage: HK = H.change_ring(K)
1335
sage: P = HK(1,0)
1336
sage: Q = HK(0,3)
1337
sage: x,y = HK.monsky_washnitzer_gens()
1338
sage: HK.coleman_integral_from_weierstrass_via_boundary(y.diff(),P,Q,20)
1339
3 + O(a^120)
1340
sage: HK.coleman_integral(y.diff(),P,Q)
1341
3 + O(5^6)
1342
sage: w = HK.invariant_differential()
1343
sage: HK.coleman_integral_from_weierstrass_via_boundary(w,P,Q,20)
1344
2*a^40 + a^80 + a^100 + O(a^105)
1345
sage: HK.coleman_integral(w,P,Q)
1346
2*5^2 + 5^4 + 5^5 + 3*5^6 + O(5^7)
1347
1348
AUTHOR:
1349
1350
- Jennifer Balakrishnan
1351
1352
"""
1353
HJ = self.curve_over_ram_extn(d)
1354
S = self.get_boundary_point(HJ,P)
1355
P_to_S = self.coleman_integral_P_to_S(w,P,S)
1356
S_to_Q = HJ.coleman_integral_S_to_Q(w,S,Q)
1357
return P_to_S + S_to_Q
1358
1359