Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/schemes/projective/projective_point.py
8820 views
1
r"""
2
Points on projective varieties
3
4
Scheme morphism for points on projective varieties
5
6
7
8
AUTHORS:
9
10
- David Kohel, William Stein
11
12
- William Stein (2006-02-11): fixed bug where P(0,0,0) was allowed as
13
a projective point.
14
15
- Volker Braun (2011-08-08): Renamed classes, more documentation, misc
16
cleanups.
17
18
- Ben Hutz (June 2012) added support for projective ring;
19
(March 2013) iteration functionality and new directory structure
20
for affine/projective, height functionality
21
"""
22
23
# Historical note: in trac #11599, V.B. renamed
24
# * _point_morphism_class -> _morphism
25
# * _homset_class -> _point_homset
26
27
#*****************************************************************************
28
# Copyright (C) 2011 Volker Braun <[email protected]>
29
# Copyright (C) 2006 David Kohel <[email protected]>
30
# Copyright (C) 2006 William Stein <[email protected]>
31
#
32
# Distributed under the terms of the GNU General Public License (GPL)
33
# as published by the Free Software Foundation; either version 2 of
34
# the License, or (at your option) any later version.
35
# http://www.gnu.org/licenses/
36
#*****************************************************************************
37
38
from sage.categories.number_fields import NumberFields
39
_NumberFields = NumberFields()
40
from sage.rings.infinity import infinity
41
from sage.rings.arith import gcd, lcm, is_prime
42
from sage.rings.integer_ring import ZZ
43
from sage.rings.number_field.order import is_NumberFieldOrder
44
from sage.rings.padics.all import Qp
45
from sage.rings.quotient_ring import QuotientRing_generic
46
from sage.rings.rational_field import QQ
47
from sage.rings.real_mpfr import RealField, RR
48
from copy import copy
49
from sage.schemes.generic.morphism import (SchemeMorphism,
50
is_SchemeMorphism,
51
SchemeMorphism_point)
52
from sage.structure.element import AdditiveGroupElement
53
from sage.structure.sequence import Sequence
54
55
56
57
#*******************************************************************
58
# Projective varieties
59
#*******************************************************************
60
class SchemeMorphism_point_projective_ring(SchemeMorphism_point):
61
"""
62
A rational point of projective space over a ring.
63
64
INPUT:
65
66
- ``X`` -- a homset of a subscheme of an ambient projective space over a field `K`
67
68
- ``v`` -- a list or tuple of coordinates in `K`
69
70
- ``check`` -- boolean (optional, default:``True``). Whether to check the input for consistency.
71
72
EXAMPLES::
73
74
sage: P = ProjectiveSpace(2, ZZ)
75
sage: P(2,3,4)
76
(2 : 3 : 4)
77
78
"""
79
80
def __init__(self, X, v, check=True):
81
"""
82
The Python constructor.
83
84
EXAMPLES::
85
86
sage: P = ProjectiveSpace(2, QQ)
87
sage: P(2, 3/5, 4)
88
(1/2 : 3/20 : 1)
89
90
::
91
92
sage: P = ProjectiveSpace(1, ZZ)
93
sage: P([0, 1])
94
(0 : 1)
95
96
::
97
98
sage: P = ProjectiveSpace(1, ZZ)
99
sage: P([0, 0, 1])
100
Traceback (most recent call last):
101
...
102
TypeError: v (=[0, 0, 1]) must have 2 components
103
104
::
105
106
sage: P = ProjectiveSpace(3, QQ)
107
sage: P(0,0,0,0)
108
Traceback (most recent call last):
109
...
110
ValueError: [0, 0, 0, 0] does not define a valid point since all entries are 0
111
112
::
113
114
It is possible to avoid the possibly time consuming checks, but be careful!!
115
116
sage: P = ProjectiveSpace(3, QQ)
117
sage: P.point([0,0,0,0],check=False)
118
(0 : 0 : 0 : 0)
119
120
::
121
122
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
123
sage: X=P.subscheme([x^2-y*z])
124
sage: X([2,2,2])
125
(2 : 2 : 2)
126
"""
127
SchemeMorphism.__init__(self, X)
128
if check:
129
from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
130
d = X.codomain().ambient_space().ngens()
131
if is_SchemeMorphism(v) or isinstance(v, EllipticCurvePoint_field):
132
v = list(v)
133
elif v is infinity:
134
v = [0] * (d)
135
v[1] = 1
136
if not isinstance(v,(list,tuple)):
137
raise TypeError("Argument v (= %s) must be a scheme point, list, or tuple."%str(v))
138
if len(v) != d and len(v) != d-1:
139
raise TypeError("v (=%s) must have %s components"%(v, d))
140
141
R = X.value_ring()
142
v = Sequence(v, R)
143
if len(v) == d-1: # very common special case
144
v.append(1)
145
146
n = len(v)
147
all_zero = True
148
for i in range(n):
149
last = n-1-i
150
if v[last]:
151
all_zero = False
152
break
153
if all_zero:
154
raise ValueError("%s does not define a valid point since all entries are 0"%repr(v))
155
156
X.extended_codomain()._check_satisfies_equations(v)
157
158
if isinstance(X.codomain().base_ring(), QuotientRing_generic):
159
lift_coords = [P.lift() for P in v]
160
else:
161
lift_coords = v
162
v = Sequence(lift_coords)
163
164
self._coords = v
165
166
def __eq__(self,right):
167
"""
168
Tests the proejctive equality of two points.
169
170
INPUT:
171
172
- ``right`` - a point on projective space
173
174
OUTPUT:
175
176
- Boolean - True if ``self`` and ``right`` define the same point. False otherwise.
177
178
Examples::
179
180
sage: PS=ProjectiveSpace(ZZ,1,'x')
181
sage: P=PS([1,2])
182
sage: Q=PS([2,4])
183
sage: P==Q
184
True
185
186
::
187
188
sage: PS=ProjectiveSpace(ZZ,1,'x')
189
sage: P=PS([1,2])
190
sage: Q=PS([1,0])
191
sage: P==Q
192
False
193
194
::
195
196
sage: PS=ProjectiveSpace(Zp(5),1,'x')
197
sage: P=PS([0,1])
198
sage: P==0
199
True
200
201
::
202
203
sage: R.<t>=PolynomialRing(QQ)
204
sage: PS=ProjectiveSpace(R,1,'x')
205
sage: P=PS([t,1+t^2])
206
sage: Q=PS([t^2, t+t^3])
207
sage: P==Q
208
True
209
210
::
211
212
sage: PS=ProjectiveSpace(ZZ,2,'x')
213
sage: P=PS([0,1,2])
214
sage: P==0
215
False
216
217
::
218
219
sage: PS=ProjectiveSpace(ZZ,1,'x')
220
sage: P=PS([2,1])
221
sage: PS2=ProjectiveSpace(Zp(7),1,'x')
222
sage: Q=PS2([2,1])
223
sage: P==Q
224
False
225
226
::
227
228
sage: PS=ProjectiveSpace(ZZ.quo(6),2,'x')
229
sage: P=PS([2,4,1])
230
sage: Q=PS([0,1,3])
231
sage: P==Q
232
False
233
234
::
235
236
sage: R.<z>=PolynomialRing(QQ)
237
sage: K.<t>=NumberField(z^2+5)
238
sage: OK=K.ring_of_integers()
239
sage: t=OK.gen(1)
240
sage: PS.<x,y>=ProjectiveSpace(OK,1)
241
sage: P=PS(2,1+t)
242
sage: Q=PS(1-t,3)
243
sage: P==Q
244
True
245
246
"""
247
if not isinstance(right, SchemeMorphism_point):
248
try:
249
right = self.codomain()(right)
250
except TypeError:
251
return False
252
if self.codomain()!=right.codomain():
253
return False
254
n=len(self._coords)
255
for i in range(0,n):
256
for j in range(i+1,n):
257
if self._coords[i]*right._coords[j] != self._coords[j]*right._coords[i]:
258
return False
259
return True
260
261
def __ne__(self,right):
262
"""
263
Tests the proejctive equality of two points.
264
265
INPUT:
266
267
- ``right`` - a point on projective space
268
269
OUTPUT:
270
271
- Boolean - True if ``self`` and ``right`` define different points. False otherwise.
272
273
Examples::
274
275
sage: PS=ProjectiveSpace(ZZ,1,'x')
276
sage: P=PS([1,2])
277
sage: Q=PS([2,4])
278
sage: P!=Q
279
False
280
281
::
282
283
sage: PS=ProjectiveSpace(ZZ,1,'x')
284
sage: P=PS([1,2])
285
sage: Q=PS([1,0])
286
sage: P!=Q
287
True
288
289
::
290
291
sage: PS=ProjectiveSpace(Zp(5),1,'x')
292
sage: P=PS([0,1])
293
sage: P!=0
294
False
295
296
::
297
298
sage: R.<t>=PolynomialRing(QQ)
299
sage: PS=ProjectiveSpace(R,1,'x')
300
sage: P=PS([t,1+t^2])
301
sage: Q=PS([t^2, t+t^3])
302
sage: P!=Q
303
False
304
305
::
306
307
sage: PS=ProjectiveSpace(ZZ,2,'x')
308
sage: P=PS([0,1,2])
309
sage: P!=0
310
True
311
312
::
313
314
sage: PS=ProjectiveSpace(ZZ,1,'x')
315
sage: P=PS([2,1])
316
sage: PS2=ProjectiveSpace(Zp(7),1,'x')
317
sage: Q=PS2([2,1])
318
sage: P!=Q
319
True
320
321
::
322
323
sage: PS=ProjectiveSpace(ZZ.quo(6),2,'x')
324
sage: P=PS([2,4,1])
325
sage: Q=PS([0,1,3])
326
sage: P!=Q
327
True
328
"""
329
if not isinstance(right, SchemeMorphism_point):
330
try:
331
right = self.codomain()(right)
332
except TypeError:
333
return True
334
if self.codomain()!=right.codomain():
335
return True
336
n=len(self._coords)
337
for i in range(0,n):
338
for j in range(i+1,n):
339
if self._coords[i]*right._coords[j] != self._coords[j]*right._coords[i]:
340
return True
341
return False
342
343
def scale_by(self,t):
344
"""
345
Scale the coordinates of the point ``self`` by `t`. A ``TypeError`` occurs if
346
the point is not in the base_ring of the codomain after scaling.
347
348
INPUT:
349
350
- ``t`` -- a ring element
351
352
OUTPUT:
353
354
- None.
355
356
EXAMPLES::
357
358
sage: R.<t>=PolynomialRing(QQ)
359
sage: P=ProjectiveSpace(R,2,'x')
360
sage: p=P([3/5*t^3,6*t, t])
361
sage: p.scale_by(1/t); p
362
(3/5*t^2 : 6 : 1)
363
364
::
365
366
sage: R.<t>=PolynomialRing(QQ)
367
sage: S=R.quo(R.ideal(t^3))
368
sage: P.<x,y,z>=ProjectiveSpace(S,2)
369
sage: Q=P(t,1,1)
370
sage: Q.scale_by(t);Q
371
(tbar^2 : tbar : tbar)
372
373
::
374
375
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
376
sage: Q=P(2,2,2)
377
sage: Q.scale_by(1/2);Q
378
(1 : 1 : 1)
379
"""
380
if t==0: #what if R(t) == 0 ?
381
raise ValueError("Cannot scale by 0")
382
R=self.codomain().base_ring()
383
if isinstance(R, QuotientRing_generic):
384
phi=R.coerce_map_from(self.codomain().ambient_space().base_ring())
385
for i in range(self.codomain().ambient_space().dimension_relative()+1):
386
self._coords[i]=phi(self._coords[i]*t).lift()
387
else:
388
for i in range(self.codomain().ambient_space().dimension_relative()+1):
389
self._coords[i]=R(self._coords[i]*t)
390
391
def normalize_coordinates(self):
392
"""
393
Removes the gcd from the coordinates of ``self`` (including `-1`).
394
395
.. WARNING:: The gcd will depend on the base ring.
396
397
OUTPUT:
398
399
- None.
400
401
EXAMPLES::
402
403
sage: P = ProjectiveSpace(ZZ,2,'x')
404
sage: p = P([-5,-15,-20])
405
sage: p.normalize_coordinates(); p
406
(1 : 3 : 4)
407
408
::
409
410
sage: P = ProjectiveSpace(Zp(7),2,'x')
411
sage: p = P([-5,-15,-2])
412
sage: p.normalize_coordinates(); p
413
(5 + O(7^20) : 1 + 2*7 + O(7^20) : 2 + O(7^20))
414
415
::
416
417
sage: R.<t> = PolynomialRing(QQ)
418
sage: P = ProjectiveSpace(R,2,'x')
419
sage: p = P([3/5*t^3,6*t, t])
420
sage: p.normalize_coordinates(); p
421
(3/5*t^2 : 6 : 1)
422
423
::
424
425
sage: P.<x,y> = ProjectiveSpace(Zmod(20),1)
426
sage: Q = P(4,8)
427
sage: Q.normalize_coordinates()
428
sage: Q
429
(1 : 2)
430
431
::
432
433
sage: R.<t> = PolynomialRing(QQ,1)
434
sage: S = R.quotient_ring(R.ideal(t^3))
435
sage: P.<x,y> = ProjectiveSpace(S,1)
436
sage: Q = P(t,t^2)
437
sage: Q.normalize_coordinates()
438
sage: Q
439
(1 : t)
440
441
Since the base ring is a polynomial ring over a field, only the
442
gcd `c` is removed. ::
443
444
sage: R.<c> = PolynomialRing(QQ)
445
sage: P = ProjectiveSpace(R,1)
446
sage: Q = P(2*c,4*c)
447
sage: Q.normalize_coordinates();Q
448
(2 : 4)
449
450
A polynomial ring over a ring gives the more intuitive result. ::
451
452
sage: R.<c> = PolynomialRing(ZZ)
453
sage: P = ProjectiveSpace(R,1)
454
sage: Q = P(2*c,4*c)
455
sage: Q.normalize_coordinates();Q
456
(1 : 2)
457
"""
458
R=self.codomain().base_ring()
459
GCD = R(gcd(self[0],self[1]))
460
index=2
461
if self[0]>0 or self[1] >0:
462
neg=0
463
else:
464
neg=1
465
while GCD!=1 and index < len(self._coords):
466
if self[index]>0:
467
neg=0
468
GCD=R(gcd(GCD,self[index]))
469
index+=1
470
if isinstance(R,(QuotientRing_generic)):
471
R=R.cover_ring()
472
GCD=GCD.lift()
473
if GCD != 1:
474
if neg==1:
475
self.scale_by(R(-1)/GCD)
476
else:
477
self.scale_by(R(1)/GCD)
478
else:
479
if neg==1:
480
self.scale_by(R(-1))
481
482
def dehomogenize(self,n):
483
r"""
484
Dehomogenizes at the nth coordinate
485
486
INPUT:
487
488
- ``n`` -- non-negative integer
489
490
OUTPUT:
491
492
- :class:`SchemeMorphism_point_affine`
493
494
EXAMPLES::
495
496
sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
497
sage: X=P.subscheme(x^2-y^2);
498
sage: Q=X(23,23,46)
499
sage: Q.dehomogenize(2)
500
(1/2, 1/2)
501
502
::
503
504
sage: R.<t>=PolynomialRing(QQ)
505
sage: S=R.quo(R.ideal(t^3))
506
sage: P.<x,y,z>=ProjectiveSpace(S,2)
507
sage: Q=P(t,1,1)
508
sage: Q.dehomogenize(1)
509
(tbar, 1)
510
511
::
512
513
sage: P.<x,y,z>=ProjectiveSpace(GF(5),2)
514
sage: Q=P(1,3,1)
515
sage: Q.dehomogenize(0)
516
(3, 1)
517
518
::
519
520
sage: P.<x,y,z>=ProjectiveSpace(GF(5),2)
521
sage: Q=P(1,3,0)
522
sage: Q.dehomogenize(2)
523
Traceback (most recent call last):
524
...
525
ValueError: Can't dehomogenize at 0 coordinate.
526
"""
527
if self[n]==0:
528
raise ValueError("Can't dehomogenize at 0 coordinate.")
529
PS=self.codomain()
530
A=PS.affine_patch(n)
531
Q=[]
532
for i in range(0,PS.ambient_space().dimension_relative()+1):
533
if i !=n:
534
Q.append(self[i]/self[n])
535
return(A.point(Q))
536
537
def nth_iterate(self,f,n,normalize=False):
538
r"""
539
For a map ``self`` and a point `P` in ``self.domain()``
540
this function returns the nth iterate of `P` by ``self``. If ``normalize==True``,
541
then the coordinates are automatically normalized.
542
543
INPUT:
544
545
- ``f`` -- a SchmemMorphism_polynomial with ``self`` in ``f.domain()``
546
547
- ``n`` -- a positive integer.
548
549
- ``normalize`` -- Boolean (optional Default: ``False``)
550
551
OUTPUT:
552
553
- A point in ``self.codomain()``
554
555
EXAMPLES::
556
557
sage: P.<x,y>=ProjectiveSpace(ZZ,1)
558
sage: H=Hom(P,P)
559
sage: f=H([x^2+y^2,2*y^2])
560
sage: P(1,1).nth_iterate(f,4)
561
(32768 : 32768)
562
563
::
564
565
sage: P.<x,y>=ProjectiveSpace(ZZ,1)
566
sage: H=Hom(P,P)
567
sage: f=H([x^2+y^2,2*y^2])
568
sage: P(1,1).nth_iterate(f,4,1)
569
(1 : 1)
570
571
::
572
573
sage: R.<t>=PolynomialRing(QQ)
574
sage: P.<x,y,z>=ProjectiveSpace(R,2)
575
sage: H=Hom(P,P)
576
sage: f=H([x^2+t*y^2,(2-t)*y^2,z^2])
577
sage: P(2+t,7,t).nth_iterate(f,2)
578
(t^4 + 2507*t^3 - 6787*t^2 + 10028*t + 16 : -2401*t^3 + 14406*t^2 -
579
28812*t + 19208 : t^4)
580
581
::
582
583
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
584
sage: X=P.subscheme(x^2-y^2)
585
sage: H=Hom(X,X)
586
sage: f=H([x^2,y^2,z^2])
587
sage: X(2,2,3).nth_iterate(f,3)
588
(256 : 256 : 6561)
589
590
.. TODO:: Is there a more efficient way to do this?
591
"""
592
if self.codomain()!=f.domain():
593
raise TypeError("Point is not defined over domain of function")
594
if f.domain() != f.codomain():
595
raise TypeError("Domain and Codomain of function not equal")
596
try:
597
n=ZZ(n)
598
except TypeError:
599
raise TypeError("Iterate number must be an integer")
600
if n <0:
601
raise TypeError("Must be a forward orbit")
602
if n==0:
603
return(self)
604
else:
605
Q=f(self)
606
if normalize==True:
607
Q.normalize_coordinates()
608
for i in range(2,n+1):
609
Q=f(Q)
610
if normalize==True:
611
Q.normalize_coordinates()
612
return(Q)
613
614
def orbit(self,f,N,**kwds):
615
r"""
616
Returns the orbit of `P` by ``self``. If `n` is an integer it returns `[P,self(P),\ldots,self^n(P)]`.
617
If `n` is a list or tuple `n=[m,k]` it returns `[self^m(P),\ldots,self^k(P)`].
618
Automatically normalize the points if ``normalize=True``. Perform the checks on point initialization if
619
``check=True``
620
621
INPUT:
622
623
- ``f`` -- a :class:`SchemeMorphism_polynomial` with ``self`` in ``f.domain()``
624
625
- ``N`` -- a non-negative integer or list or tuple of two non-negative integers
626
627
kwds:
628
629
- ``check`` -- boolean (optional - default: ``True``)
630
631
- ``normalize`` -- boolean (optional - default: ``False``)
632
633
634
OUTPUT:
635
636
- a list of points in ``self.codomain()``
637
638
EXAMPLES::
639
640
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
641
sage: H=Hom(P,P)
642
sage: f=H([x^2+y^2,y^2-z^2,2*z^2])
643
sage: P(1,2,1).orbit(f,3)
644
[(1 : 2 : 1), (5 : 3 : 2), (34 : 5 : 8), (1181 : -39 : 128)]
645
646
::
647
648
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
649
sage: H=Hom(P,P)
650
sage: f=H([x^2+y^2,y^2-z^2,2*z^2])
651
sage: P(1,2,1).orbit(f,[2,4])
652
[(34 : 5 : 8), (1181 : -39 : 128), (1396282 : -14863 : 32768)]
653
654
::
655
656
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
657
sage: X=P.subscheme(x^2-y^2)
658
sage: H=Hom(X,X)
659
sage: f=H([x^2,y^2,x*z])
660
sage: X(2,2,3).orbit(f,3,normalize=True)
661
[(2 : 2 : 3), (2 : 2 : 3), (2 : 2 : 3), (2 : 2 : 3)]
662
663
::
664
665
sage: P.<x,y>=ProjectiveSpace(QQ,1)
666
sage: H=Hom(P,P)
667
sage: f=H([x^2+y^2,y^2])
668
sage: P.point([1,2],False).orbit(f,4,check=False)
669
[(1 : 2), (5 : 4), (41 : 16), (1937 : 256), (3817505 : 65536)]
670
"""
671
if (isinstance(N,(list,tuple))==False):
672
N=[0,N]
673
try:
674
N[0]=ZZ(N[0])
675
N[1]=ZZ(N[1])
676
except TypeError:
677
raise TypeError("Orbit bounds must be integers")
678
if N[0]<0 or N[1] <0:
679
raise TypeError("Orbit bounds must be non-negative")
680
if N[0] > N[1]:
681
return([])
682
683
Q=copy(self)
684
check = kwds.pop("check",True)
685
normalize = kwds.pop("normalize",False)
686
687
if normalize==True:
688
Q.normalize_coordinates()
689
for i in range(1,N[0]+1):
690
Q=f(Q,check)
691
if normalize==True:
692
Q.normalize_coordinates()
693
Orb=[Q]
694
for i in range(N[0]+1,N[1]+1):
695
Q=f(Q,check)
696
if normalize==True:
697
Q.normalize_coordinates()
698
Orb.append(Q)
699
return(Orb)
700
701
def green_function(self, G,v, **kwds):
702
r"""
703
Evaluates the local Green's function at the place ``v`` for ``self`` with ``N`` terms of the series
704
or, in dimension 1, to within the specified error bound. Defaults to ``N=10`` if no kwds provided
705
706
Use ``v=0`` for the archimedean place. Must be over `\ZZ` or `\QQ`.
707
708
ALGORITHM:
709
710
See Exercise 5.29 and Figure 5.6 of ``The Arithmetic of Dynamics Systems``, Joseph H. Silverman, Springer, GTM 241, 2007.
711
712
INPUT:
713
714
- ``G`` - an endomorphism of self.codomain()
715
716
- ``v`` - non-negative integer. a place, use v=0 for the archimedean place
717
718
kwds:
719
720
- ``N`` - positive integer. number of terms of the series to use
721
722
- ``prec`` - positive integer, float point or p-adic precision, default: 100
723
724
- ``error_bound`` - a positive real number
725
726
OUTPUT:
727
728
- a real number
729
730
Examples::
731
732
sage: P.<x,y>=ProjectiveSpace(QQ,1)
733
sage: H=Hom(P,P)
734
sage: f=H([x^2+y^2,x*y]);
735
sage: Q=P(5,1)
736
sage: f.green_function(Q,0,N=30)
737
1.6460930159932946233759277576
738
739
::
740
741
sage: P.<x,y>=ProjectiveSpace(QQ,1)
742
sage: H=Hom(P,P)
743
sage: f=H([x^2+y^2,x*y]);
744
sage: Q=P(5,1)
745
sage: Q.green_function(f,0,N=200,prec=200)
746
1.6460930160038721802875250367738355497198064992657997569827
747
748
.. TODO::
749
750
error bounds for dimension > 1
751
"""
752
N = kwds.get('N', None) #Get number of iterates (if entered)
753
err = kwds.get('error_bound', None) #Get error bound (if entered)
754
prec = kwds.get('prec', 100) #Get precision (if entered)
755
R=RealField(prec)
756
757
if not (v == 0 or is_prime(v)):
758
raise ValueError("Invalid valuation (=%s) entered."%v)
759
if v == 0:
760
K = R
761
else:
762
K = Qp(v, prec)
763
764
#Coerce all polynomials in F into polynomials with coefficients in K
765
F=G.change_ring(K,False)
766
d = F.degree()
767
D=F.codomain().ambient_space().dimension_relative()
768
769
if err is not None:
770
if D!=1:
771
raise NotImplementedError("error bounds only for dimension 1")
772
err = R(err)
773
if not err>0:
774
raise ValueError, "Error bound (=%s) must be positive."%err
775
776
#if doing error estimates, compute needed number of iterates
777
res = F.resultant()
778
779
#compute maximum coefficient of polynomials of F
780
C = R(G.global_height(prec))
781
782
if v == 0:
783
log_fact = R(0)
784
for i in range(2*d+1):
785
log_fact += R(i+1).log()
786
B = max((R(res.abs()) - R(2*d).log() - (2*d-1)*C - log_fact).log().abs(), (C + R(d+1).log()).abs())
787
else:
788
B = max(R(res.abs()).log() - ((2*d-1)*C).abs(), C.abs())
789
N = R(B/(err*(d-1))).log(d).abs().ceil()
790
791
elif N is None:
792
N=10 #default is to do 10 iterations
793
794
#Coerce the coordinates into Q_v
795
self.normalize_coordinates()
796
if self.codomain().base_ring()==QQ:
797
self.clear_denominators()
798
P=self.change_ring(K,False)
799
800
#START GREEN FUNCTION CALCULATION
801
802
g = R(0)
803
804
for i in range(N+1):
805
m = -1
806
807
#compute the maximum absolute value of entries of a, and where it occurs
808
for n in range(D+1):
809
a_v = R(P[n].abs())
810
if a_v > m:
811
j = n
812
m = a_v
813
814
#add to Greens function
815
g += (1/R(d))**(i)*R(m).log()
816
817
#normalize coordinates and evaluate
818
P.scale_by(1/P[j])
819
P = F(P,False)
820
821
return g
822
823
def canonical_height(self,F, **kwds):
824
r"""
825
Evaluates the canonical height of ``self`` with respect to ``F``. Must be over `\ZZ` or `\QQ`.
826
Specify either the number of terms of the series to evaluate or, in dimension 1, the error bound
827
required.
828
829
ALGORITHM:
830
831
The sum of the Green's function at the archimedean place and the places of bad reduction.
832
833
INPUT:
834
835
- ``P`` - a projective point
836
837
kwds:
838
839
- ``badprimes`` - a list of primes of bad reduction
840
841
- ``N`` - positive integer. number of terms of the series to use in the local green functions
842
843
- ``prec`` - positive integer, float point or p-adic precision
844
845
- ``error_bound`` - a positive real number
846
847
OUTPUT:
848
849
- a real number
850
851
EXAMPLES::
852
853
sage: P.<x,y>=ProjectiveSpace(ZZ,1)
854
sage: H=Hom(P,P)
855
sage: f=H([x^2+y^2,2*x*y]);
856
sage: Q=P(2,1)
857
sage: f.canonical_height(f(Q))
858
2.1965476757927038111992627081
859
sage: f.canonical_height(Q)
860
1.0979353871245941198040174712
861
862
Notice that preperiodic points may not be exactly 0. ::
863
864
sage: P.<x,y>=ProjectiveSpace(QQ,1)
865
sage: H=Hom(P,P)
866
sage: f=H([x^2-29/16*y^2,y^2]);
867
sage: Q=P(5,4)
868
sage: f.canonical_height(Q,N=30)
869
1.4989058602918874235863427216e-9
870
871
::
872
873
sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
874
sage: X=P.subscheme(x^2-y^2);
875
sage: H=Hom(X,X)
876
sage: f=H([x^2,y^2,30*z^2]);
877
sage: Q=X([4,4,1])
878
sage: f.canonical_height(Q,badprimes=[2,3,5],prec=200)
879
2.7054056208276961889784303469356774912979228770208655455481
880
"""
881
882
badprimes = kwds.pop("badprimes",None)
883
884
if badprimes is None:
885
badprimes=F.primes_of_bad_reduction(0)
886
887
h=self.green_function(F,0,**kwds) #arch Green function
888
for v in badprimes:
889
h+=self.green_function(F,v,**kwds) #non-arch Green functions
890
891
return h
892
893
def global_height(self, prec=None):
894
r"""
895
Returns the logarithmic height of the points. Must be over `\ZZ` or `\QQ`.
896
897
INPUT:
898
899
- ``prec`` -- desired floating point precision (default:
900
default RealField precision).
901
902
OUTPUT:
903
904
- a real number
905
906
EXAMPLES::
907
908
sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
909
sage: Q=P.point([4,4,1/30])
910
sage: Q.global_height()
911
4.78749174278205
912
913
::
914
915
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
916
sage: Q=P([4,1,30])
917
sage: Q.global_height()
918
3.40119738166216
919
920
::
921
922
sage: R.<x>=PolynomialRing(QQ)
923
sage: k.<w>=NumberField(x^2+5)
924
sage: A=ProjectiveSpace(k,2,'z')
925
sage: A([3,5*w+1,1]).global_height(prec=100)
926
2.4181409534757389986565376694
927
928
.. TODO::
929
930
p-adic heights
931
932
"""
933
if self.domain().base_ring() in _NumberFields or is_NumberFieldOrder(self.domain().base_ring()):
934
return(max([self[i].global_height(prec) for i in range(self.codomain().ambient_space().dimension_relative()+1)]))
935
else:
936
raise NotImplementedError("Must be over a Numberfield or a Numberfield Order")
937
938
939
def multiplier(self,f,n,check=True):
940
r"""
941
Returns the multiplier of the projective point ``self`` of period `n` by the function `f`.
942
`f` must be an endomorphism of projective space
943
944
INPUT:
945
946
- ``f`` - a endomorphism of ``self.codomain()``
947
948
- ``n`` - a positive integer, the period of ``self``
949
950
- ``check`` -- check if ``P`` is periodic of period ``n``, Default:True
951
952
OUTPUT:
953
954
- a square matrix of size ``self.codomain().dimension_relative()`` in the ``base_ring`` of ``self``
955
956
EXAMPLES::
957
958
sage: P.<x,y,z,w>=ProjectiveSpace(QQ,3)
959
sage: H=Hom(P,P)
960
sage: f=H([x^2,y^2,4*w^2,4*z^2]);
961
sage: Q=P.point([4,4,1,1],False);
962
sage: Q.multiplier(f,1)
963
[ 2 0 -8]
964
[ 0 2 -8]
965
[ 0 0 -2]
966
"""
967
return(f.multiplier(self,n,check))
968
969
class SchemeMorphism_point_projective_field(SchemeMorphism_point_projective_ring):
970
"""
971
A rational point of projective space over a field.
972
973
INPUT:
974
975
- ``X`` -- a homset of a subscheme of an ambient projective space
976
over a field `K`
977
978
- ``v`` -- a list or tuple of coordinates in `K`
979
980
- ``check`` -- boolean (optional, default:``True``). Whether to
981
check the input for consistency.
982
983
EXAMPLES::
984
985
sage: P = ProjectiveSpace(3, RR)
986
sage: P(2,3,4,5)
987
(0.400000000000000 : 0.600000000000000 : 0.800000000000000 : 1.00000000000000)
988
"""
989
990
def __init__(self, X, v, check=True):
991
"""
992
The Python constructor.
993
994
See :class:`SchemeMorphism_point_projective_ring` for details.
995
996
This function still normalized points so that the rightmost non-zero coordinate is 1. The is to maintain current functionality with current
997
implementations of curves in projectives space (plane, connic, elliptic, etc). The class:`SchemeMorphism_point_projective_ring` is for general use.
998
999
EXAMPLES::
1000
1001
sage: P = ProjectiveSpace(2, QQ)
1002
sage: P(2, 3/5, 4)
1003
(1/2 : 3/20 : 1)
1004
1005
::
1006
1007
sage: P = ProjectiveSpace(3, QQ)
1008
sage: P(0,0,0,0)
1009
Traceback (most recent call last):
1010
...
1011
ValueError: [0, 0, 0, 0] does not define a valid point since all entries are 0
1012
1013
::
1014
1015
sage: P.<x, y, z> = ProjectiveSpace(2, QQ)
1016
sage: X=P.subscheme([x^2-y*z])
1017
sage: X([2,2,2])
1018
(1 : 1 : 1)
1019
"""
1020
SchemeMorphism.__init__(self, X)
1021
if check:
1022
from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
1023
d = X.codomain().ambient_space().ngens()
1024
if is_SchemeMorphism(v) or isinstance(v, EllipticCurvePoint_field):
1025
v = list(v)
1026
elif v is infinity:
1027
v = [0] * (d)
1028
v[1] = 1
1029
if not isinstance(v,(list,tuple)):
1030
raise TypeError("Argument v (= %s) must be a scheme point, list, or tuple."%str(v))
1031
if len(v) != d and len(v) != d-1:
1032
raise TypeError("v (=%s) must have %s components"%(v, d))
1033
1034
R = X.value_ring()
1035
v = Sequence(v, R)
1036
if len(v) == d-1: # very common special case
1037
v.append(1)
1038
1039
n = len(v)
1040
all_zero = True
1041
for i in range(n):
1042
last = n-1-i
1043
if v[last]:
1044
all_zero = False
1045
c = v[last]
1046
if c == R.one():
1047
break
1048
for j in range(last):
1049
v[j] /= c
1050
v[last] = R.one()
1051
break
1052
if all_zero:
1053
raise ValueError("%s does not define a valid point since all entries are 0"%repr(v))
1054
1055
X.extended_codomain()._check_satisfies_equations(v)
1056
1057
self._coords = v
1058
1059
def normalize_coordinates(self):
1060
r"""
1061
Normalizes ``self`` so that the last non-zero coordinate is `1`.
1062
1063
OUTPUT: None.
1064
1065
EXAMPLES::
1066
1067
sage: P.<x,y,z>=ProjectiveSpace(GF(5),2)
1068
sage: Q=P.point([1,3,0],false);Q
1069
(1 : 3 : 0)
1070
sage: Q.normalize_coordinates();Q
1071
(2 : 1 : 0)
1072
1073
::
1074
1075
sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
1076
sage: X=P.subscheme(x^2-y^2);
1077
sage: Q=X.point([23,23,46], false);Q
1078
(23 : 23 : 46)
1079
sage: Q.normalize_coordinates();Q
1080
(1/2 : 1/2 : 1)
1081
"""
1082
index=self.codomain().ambient_space().dimension_relative()
1083
while self[index]==0:
1084
index-=1
1085
self.scale_by(1/self[index])
1086
1087
1088
def clear_denominators(self):
1089
r"""
1090
scales by the least common multiple of the denominators.
1091
1092
OUTPUT: None.
1093
1094
EXAMPLES::
1095
1096
sage: R.<t>=PolynomialRing(QQ)
1097
sage: P.<x,y,z>=ProjectiveSpace(FractionField(R),2)
1098
sage: Q=P([t,3/t^2,1])
1099
sage: Q.clear_denominators(); Q
1100
(t^3 : 3 : t^2)
1101
1102
::
1103
1104
sage: R.<x>=PolynomialRing(QQ)
1105
sage: K.<w>=NumberField(x^2-3)
1106
sage: P.<x,y,z>=ProjectiveSpace(K,2)
1107
sage: Q=P([1/w,3,0])
1108
sage: Q.clear_denominators(); Q
1109
(w : 9 : 0)
1110
1111
::
1112
1113
sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
1114
sage: X=P.subscheme(x^2-y^2);
1115
sage: Q=X([1/2,1/2,1]);
1116
sage: Q.clear_denominators(); Q
1117
(1 : 1 : 2)
1118
"""
1119
self.scale_by(lcm([self[i].denominator() for i in range(self.codomain().ambient_space().dimension_relative())]))
1120
1121
class SchemeMorphism_point_projective_finite_field(SchemeMorphism_point_projective_field):
1122
1123
def __hash__(self):
1124
r"""
1125
Returns the integer hash of ``self``
1126
1127
1128
OUTPUT:
1129
1130
- integer
1131
1132
EXAMPLES::
1133
1134
sage: P.<x,y,z>=ProjectiveSpace(GF(5),2)
1135
sage: hash(P(2,1,2))
1136
41
1137
1138
::
1139
1140
sage: P.<x,y,z>=ProjectiveSpace(GF(7),2)
1141
sage: X=P.subscheme(x^2-y^2)
1142
sage: hash(X(1,1,2))
1143
81
1144
1145
::
1146
1147
sage: P.<x,y>=ProjectiveSpace(GF(13),1)
1148
sage: hash(P(3,4))
1149
17
1150
1151
::
1152
1153
sage: P.<x,y>=ProjectiveSpace(GF(13^3,'t'),1)
1154
sage: hash(P(3,4))
1155
2201
1156
"""
1157
p=self.codomain().base_ring().order()
1158
N=self.codomain().ambient_space().dimension_relative()
1159
return sum(hash(self[i])*p**i for i in range(N+1))
1160
1161
def orbit_structure(self,f):
1162
r"""
1163
Every points is preperiodic over a finite field. This funtion returns the pair `[m,n]` where `m` is the
1164
preperiod and `n` the period of the point `P` by ``self``.
1165
1166
INPUT:
1167
1168
- ``f`` -- a :class:`ScemeMorphism_polynomial` with ``self`` in ``f.domain()``
1169
1170
OUTPUT:
1171
1172
- a list `[m,n]` of integers
1173
1174
EXAMPLES::
1175
1176
sage: P.<x,y,z>=ProjectiveSpace(GF(5),2)
1177
sage: H=Hom(P,P)
1178
sage: f=H([x^2+y^2,y^2,z^2 + y*z])
1179
sage: P(1,0,1).orbit_structure(f)
1180
[0, 1]
1181
1182
::
1183
1184
sage: P.<x,y,z>=ProjectiveSpace(GF(17),2)
1185
sage: X=P.subscheme(x^2-y^2)
1186
sage: H=Hom(X,X)
1187
sage: f=H([x^2,y^2,z^2])
1188
sage: X(1,1,2).orbit_structure(f)
1189
[3, 1]
1190
1191
::
1192
1193
sage: R.<t> = GF(13^3)
1194
sage: P.<x,y>=ProjectiveSpace(R,1)
1195
sage: H=Hom(P,P)
1196
sage: f=H([x^2-y^2,y^2])
1197
sage: P(t,4).orbit_structure(f)
1198
[11, 6]
1199
"""
1200
Orbit=[]
1201
index=1
1202
P=copy(self)
1203
P.normalize_coordinates()
1204
F=copy(f)
1205
F.normalize_coordinates()
1206
while not P in Orbit:
1207
Orbit.append(P)
1208
P=F(P)
1209
P.normalize_coordinates()
1210
index+=1
1211
I=Orbit.index(P)
1212
return([I,index-I-1])
1213
1214
#*******************************************************************
1215
# Abelian varieties
1216
#*******************************************************************
1217
class SchemeMorphism_point_abelian_variety_field(AdditiveGroupElement, SchemeMorphism_point_projective_field):
1218
"""
1219
A rational point of an abelian variety over a field.
1220
1221
EXAMPLES::
1222
1223
sage: E = EllipticCurve([0,0,1,-1,0])
1224
sage: origin = E(0)
1225
sage: origin.domain()
1226
Spectrum of Rational Field
1227
sage: origin.codomain()
1228
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
1229
"""
1230
pass
1231
1232
1233