Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/generic/projective_space.py
4069 views
1
r"""
2
Projective `n` space over a ring
3
4
EXAMPLES: We construct projective space over various rings of
5
various dimensions.
6
7
The simplest projective space::
8
9
sage: ProjectiveSpace(0)
10
Projective Space of dimension 0 over Integer Ring
11
12
A slightly bigger projective space over `\QQ`::
13
14
sage: X = ProjectiveSpace(1000, QQ); X
15
Projective Space of dimension 1000 over Rational Field
16
sage: X.dimension()
17
1000
18
19
We can use "over" notation to create projective spaces over various
20
base rings.
21
22
::
23
24
sage: X = ProjectiveSpace(5)/QQ; X
25
Projective Space of dimension 5 over Rational Field
26
sage: X/CC
27
Projective Space of dimension 5 over Complex Field with 53 bits of precision
28
29
The third argument specifies the printing names of the generators
30
of the homogenous coordinate ring. Using objgens() you can obtain
31
both the space and the generators as ready to use variables.
32
33
::
34
35
sage: P2, (x,y,z) = ProjectiveSpace(2, QQ, 'xyz').objgens()
36
sage: P2
37
Projective Space of dimension 2 over Rational Field
38
sage: x.parent()
39
Multivariate Polynomial Ring in x, y, z over Rational Field
40
41
For example, we use `x,y,z` to define the intersection of
42
two lines.
43
44
::
45
46
sage: V = P2.subscheme([x+y+z, x+y-z]); V
47
Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
48
x + y + z,
49
x + y - z
50
sage: V.dimension()
51
0
52
"""
53
54
#*****************************************************************************
55
# Copyright (C) 2006 William Stein <[email protected]>
56
#
57
# Distributed under the terms of the GNU General Public License (GPL)
58
#
59
# http://www.gnu.org/licenses/
60
#*****************************************************************************
61
62
from sage.rings.all import (PolynomialRing,
63
is_Field,
64
is_FiniteField,
65
is_RationalField,
66
is_Ring,
67
is_CommutativeRing,
68
is_MPolynomialRing,
69
Integer,
70
ZZ)
71
72
from sage.misc.all import latex
73
from sage.structure.parent_gens import normalize_names
74
from sage.rings.arith import gcd
75
from sage.combinat.tuple import Tuples
76
77
from ambient_space import AmbientSpace
78
import homset
79
import morphism
80
81
82
def is_ProjectiveSpace(x):
83
r"""
84
Return True if `x` is a projective space, i.e., an ambient space
85
`\mathbb{P}^n_R`, where `R` is a ring and `n\geq 0` is an
86
integer.
87
88
EXAMPLES::
89
90
sage: from sage.schemes.generic.projective_space import is_ProjectiveSpace
91
sage: is_ProjectiveSpace(ProjectiveSpace(5, names='x'))
92
True
93
sage: is_ProjectiveSpace(ProjectiveSpace(5, GF(9,'alpha'), names='x'))
94
True
95
sage: is_ProjectiveSpace(Spec(ZZ))
96
False
97
"""
98
return isinstance(x, ProjectiveSpace_ring)
99
100
def ProjectiveSpace(n, R=None, names='x'):
101
r"""
102
Return projective space of dimension `n` over the ring `R`.
103
104
EXAMPLES: The dimension and ring can be given in either order.
105
106
::
107
108
sage: ProjectiveSpace(3, QQ)
109
Projective Space of dimension 3 over Rational Field
110
sage: ProjectiveSpace(5, QQ)
111
Projective Space of dimension 5 over Rational Field
112
sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P
113
Projective Space of dimension 2 over Rational Field
114
sage: P.coordinate_ring()
115
Multivariate Polynomial Ring in X, Y, Z over Rational Field
116
117
The divide operator does base extension.
118
119
::
120
121
sage: ProjectiveSpace(5)/GF(17)
122
Projective Space of dimension 5 over Finite Field of size 17
123
124
The default base ring is `\ZZ`.
125
126
::
127
128
sage: ProjectiveSpace(5)
129
Projective Space of dimension 5 over Integer Ring
130
131
There is also an projective space associated each polynomial ring.
132
133
::
134
135
sage: R = GF(7)['x,y,z']
136
sage: P = ProjectiveSpace(R); P
137
Projective Space of dimension 2 over Finite Field of size 7
138
sage: P.coordinate_ring()
139
Multivariate Polynomial Ring in x, y, z over Finite Field of size 7
140
sage: P.coordinate_ring() is R
141
True
142
143
Projective spaces are not cached, i.e., there can be several with
144
the same base ring and dimension (to facilitate gluing
145
constructions).
146
"""
147
if is_MPolynomialRing(n) and R is None:
148
A = ProjectiveSpace(n.ngens()-1, n.base_ring())
149
A._coordinate_ring = n
150
return A
151
if isinstance(R, (int, long, Integer)):
152
n, R = R, n
153
if R is None:
154
R = ZZ # default is the integers
155
if is_Field(R):
156
if is_FiniteField(R):
157
return ProjectiveSpace_finite_field(n, R, names)
158
if is_RationalField(R):
159
return ProjectiveSpace_rational_field(n, R, names)
160
else:
161
return ProjectiveSpace_field(n, R, names)
162
elif is_CommutativeRing(R):
163
return ProjectiveSpace_ring(n, R, names)
164
else:
165
raise TypeError, "R (=%s) must be a commutative ring"%R
166
167
class ProjectiveSpace_ring(AmbientSpace):
168
"""
169
Projective space of dimension `n` over the ring
170
`R`.
171
172
EXAMPLES::
173
174
sage: X.<x,y,z,w> = ProjectiveSpace(3, QQ)
175
sage: X.base_scheme()
176
Spectrum of Rational Field
177
sage: X.base_ring()
178
Rational Field
179
sage: X.structure_morphism()
180
Scheme morphism:
181
From: Projective Space of dimension 3 over Rational Field
182
To: Spectrum of Rational Field
183
Defn: Structure map
184
sage: X.coordinate_ring()
185
Multivariate Polynomial Ring in x, y, z, w over Rational Field
186
187
Loading and saving::
188
189
sage: loads(X.dumps()) == X
190
True
191
"""
192
def __init__(self, n, R=ZZ, names=None):
193
"""
194
EXAMPLES::
195
196
sage: ProjectiveSpace(3, Zp(5), 'y')
197
Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20
198
"""
199
names = normalize_names(n+1, names)
200
AmbientSpace.__init__(self, n, R)
201
self._assign_names(names)
202
203
def ngens(self):
204
"""
205
Return the number of generators of self, i.e. the number of
206
variables in the coordinate ring of self.
207
208
EXAMPLES::
209
210
sage: ProjectiveSpace(3, QQ).ngens()
211
4
212
sage: ProjectiveSpace(7, ZZ).ngens()
213
8
214
"""
215
return self.dimension_relative() + 1
216
217
def _check_satisfies_equations(self, v):
218
"""
219
Return True if `v` defines a point on the scheme self; raise a
220
TypeError otherwise.
221
222
EXAMPLES::
223
224
sage: P = ProjectiveSpace(2, ZZ)
225
sage: P._check_satisfies_equations([1, 1, 0])
226
True
227
sage: P._check_satisfies_equations((0, 1, 0))
228
True
229
sage: P._check_satisfies_equations([0, 0, 0])
230
Traceback (most recent call last):
231
...
232
TypeError: The zero vector is not a point in projective space
233
sage: P._check_satisfies_equations([1, 2, 3, 4, 5])
234
Traceback (most recent call last):
235
...
236
TypeError: The list v=[1, 2, 3, 4, 5] must have 3 components
237
sage: P._check_satisfies_equations([1/2, 1, 1])
238
Traceback (most recent call last):
239
...
240
TypeError: The components of v=[1/2, 1, 1] must be elements of Integer Ring
241
sage: P._check_satisfies_equations(5)
242
Traceback (most recent call last):
243
...
244
TypeError: The argument v=5 must be a list or tuple
245
"""
246
if not isinstance(v, (list, tuple)):
247
raise TypeError, 'The argument v=%s must be a list or tuple'%v
248
n = self.ngens()
249
if not len(v) == n:
250
raise TypeError, 'The list v=%s must have %s components'%(v, n)
251
R = self.base_ring()
252
for coord in v:
253
if not coord in R:
254
raise TypeError, 'The components of v=%s must be elements of %s'%(v, R)
255
zero = [R(0)]*n
256
if v == zero:
257
raise TypeError, 'The zero vector is not a point in projective space'
258
return True
259
260
def coordinate_ring(self):
261
"""
262
Return the coordinate ring of this scheme.
263
264
EXAMPLES::
265
266
sage: ProjectiveSpace(3, GF(19^2,'alpha'), 'abcd').coordinate_ring()
267
Multivariate Polynomial Ring in a, b, c, d over Finite Field in alpha of size 19^2
268
269
::
270
271
sage: ProjectiveSpace(3).coordinate_ring()
272
Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring
273
274
::
275
276
sage: ProjectiveSpace(2, QQ, ['alpha', 'beta', 'gamma']).coordinate_ring()
277
Multivariate Polynomial Ring in alpha, beta, gamma over Rational Field
278
"""
279
try:
280
return self._coordinate_ring
281
except AttributeError:
282
self._coordinate_ring = PolynomialRing(self.base_ring(),
283
self.variable_names(), self.dimension_relative()+1)
284
return self._coordinate_ring
285
286
def _validate(self, polynomials):
287
"""
288
If ``polynomials`` is a tuple of valid polynomial functions on self,
289
return ``polynomials``, otherwise raise TypeError.
290
291
Since this is a projective space, polynomials must be homogeneous.
292
293
INPUT:
294
295
- ``polynomials`` -- tuple of polynomials in the coordinate ring of
296
self
297
298
OUTPUT:
299
300
- tuple of polynomials in the coordinate ring of self
301
302
EXAMPLES::
303
304
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
305
sage: P._validate((x*y - z^2, x))
306
(x*y - z^2, x)
307
sage: P._validate((x*y - z, x))
308
Traceback (most recent call last):
309
...
310
TypeError: x*y - z is not a homogeneous polynomial!
311
"""
312
for f in polynomials:
313
if not f.is_homogeneous():
314
raise TypeError("%s is not a homogeneous polynomial!" % f)
315
return polynomials
316
317
def __cmp__(self, right):
318
"""
319
EXAMPLES::
320
321
sage: ProjectiveSpace(QQ, 3, 'a') == ProjectiveSpace(ZZ, 3, 'a')
322
False
323
sage: ProjectiveSpace(ZZ, 1, 'a') == ProjectiveSpace(ZZ, 0, 'a')
324
False
325
sage: ProjectiveSpace(ZZ, 2, 'a') == AffineSpace(ZZ, 2, 'a')
326
False
327
sage: loads(AffineSpace(ZZ, 1, 'x').dumps()) == AffineSpace(ZZ, 1, 'x')
328
True
329
"""
330
if not isinstance(right, ProjectiveSpace_ring):
331
return -1
332
return cmp([self.dimension_relative(), self.coordinate_ring()],
333
[right.dimension_relative(), right.coordinate_ring()])
334
335
def _latex_(self):
336
r"""
337
Return a LaTeX representation of this projective space.
338
339
EXAMPLES::
340
341
sage: print latex(ProjectiveSpace(1, ZZ, 'x'))
342
{\mathbf P}_{\Bold{Z}}^1
343
344
TESTS::
345
346
sage: ProjectiveSpace(3, Zp(5), 'y')._latex_()
347
'{\\mathbf P}_{\\ZZ_{5}}^3'
348
"""
349
return "{\\mathbf P}_{%s}^%s"%(latex(self.base_ring()), self.dimension_relative())
350
351
def _morphism(self, *args, **kwds):
352
"""
353
Construct a morphism.
354
355
For internal use only. See :mod:`morphism` for details.
356
357
TESTS::
358
359
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
360
sage: P2._morphism(P2.Hom(P2), [x,y,z])
361
Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3
362
Defn: Defined on coordinates by sending (x : y : z) to
363
(x : y : z)
364
"""
365
return morphism.SchemeMorphism_polynomial_projective_space(*args, **kwds)
366
367
def _point_homset(self, *args, **kwds):
368
"""
369
Construct a point Hom-set.
370
371
For internal use only. See :mod:`morphism` for details.
372
373
TESTS::
374
375
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
376
sage: P2._point_homset(Spec(GF(3)), P2)
377
Set of rational points of Projective Space of dimension 2 over Finite Field of size 3
378
"""
379
return homset.SchemeHomset_points_projective_ring(*args, **kwds)
380
381
def _point(self, *args, **kwds):
382
"""
383
Construct a point.
384
385
For internal use only. See :mod:`morphism` for details.
386
387
TESTS::
388
389
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
390
sage: point_homset = P2._point_homset(Spec(GF(3)), P2)
391
sage: P2._point(point_homset, [1,2,3])
392
(2 : 1 : 0)
393
"""
394
return morphism.SchemeMorphism_point_projective_ring(*args, **kwds)
395
396
def _repr_(self):
397
"""
398
Return a string representation of this projective space.
399
400
EXAMPLES::
401
402
sage: ProjectiveSpace(1, ZZ, 'x')
403
Projective Space of dimension 1 over Integer Ring
404
405
TESTS::
406
407
sage: ProjectiveSpace(3, Zp(5), 'y')._repr_()
408
'Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20'
409
"""
410
return "Projective Space of dimension %s over %s"%(self.dimension_relative(), self.base_ring())
411
412
def _repr_generic_point(self, v=None):
413
"""
414
Return a string representation of the generic point
415
corresponding to the list of polys on this projective space.
416
417
If polys is None, the representation of the generic point of
418
the projective space is returned.
419
420
EXAMPLES::
421
422
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
423
sage: P._repr_generic_point([z*y-x^2])
424
'(-x^2 + y*z)'
425
sage: P._repr_generic_point()
426
'(x : y : z)'
427
"""
428
if v is None:
429
v = self.gens()
430
return '(%s)'%(" : ".join([repr(f) for f in v]))
431
432
def _latex_generic_point(self, v=None):
433
"""
434
Return a LaTeX representation of the generic point
435
corresponding to the list of polys on this projective space.
436
437
If polys is None, the representation of the generic point of
438
the projective space is returned.
439
440
EXAMPLES::
441
442
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
443
sage: P._latex_generic_point([z*y-x^2])
444
'\\left(- x^{2} + y z\\right)'
445
sage: P._latex_generic_point()
446
'\\left(x : y : z\\right)'
447
"""
448
if v is None:
449
v = self.gens()
450
return '\\left(%s\\right)'%(" : ".join([str(latex(f)) for f in v]))
451
452
def change_ring(self, R):
453
r"""
454
Return a projective space over ring `R` and otherwise the same as self.
455
456
INPUT:
457
458
- ``R`` -- commutative ring
459
460
OUTPUT:
461
462
- projective space over ``R``
463
464
.. NOTE::
465
466
There is no need to have any relation between `R` and the base ring
467
of self, if you want to have such a relation, use
468
``self.base_extend(R)`` instead.
469
470
EXAMPLES::
471
472
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
473
sage: PQ = P.change_ring(QQ); PQ
474
Projective Space of dimension 2 over Rational Field
475
sage: PQ.change_ring(GF(5))
476
Projective Space of dimension 2 over Finite Field of size 5
477
"""
478
return ProjectiveSpace(self.dimension_relative(), R,
479
self.variable_names())
480
481
def is_projective(self):
482
"""
483
Return that this ambient space is projective n-space.
484
485
EXAMPLES::
486
487
sage: ProjectiveSpace(3,QQ).is_projective()
488
True
489
"""
490
return True
491
492
def subscheme(self, X):
493
"""
494
Return the closed subscheme defined by X.
495
496
INPUT:
497
498
- ``X`` - a list or tuple of equations
499
500
EXAMPLES::
501
502
sage: A.<x,y,z> = ProjectiveSpace(2, QQ)
503
sage: X = A.subscheme([x*z^2, y^2*z, x*y^2]); X
504
Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
505
x*z^2,
506
y^2*z,
507
x*y^2
508
sage: X.defining_polynomials ()
509
(x*z^2, y^2*z, x*y^2)
510
sage: I = X.defining_ideal(); I
511
Ideal (x*z^2, y^2*z, x*y^2) of Multivariate Polynomial Ring in x, y, z over Rational Field
512
sage: I.groebner_basis()
513
[x*y^2, y^2*z, x*z^2]
514
sage: X.dimension()
515
0
516
sage: X.base_ring()
517
Rational Field
518
sage: X.base_scheme()
519
Spectrum of Rational Field
520
sage: X.structure_morphism()
521
Scheme morphism:
522
From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
523
x*z^2,
524
y^2*z,
525
x*y^2
526
To: Spectrum of Rational Field
527
Defn: Structure map
528
529
sage: TestSuite(X).run(skip=["_test_an_element", "_test_elements", "_test_elements_eq", "_test_some_elements"])
530
"""
531
from algebraic_scheme import AlgebraicScheme_subscheme_projective
532
return AlgebraicScheme_subscheme_projective(self, X)
533
534
def affine_patch(self, i):
535
r"""
536
Return the `i^{th}` affine patch of this projective space.
537
This is an ambient affine space `\mathbb{A}^n_R,` where
538
`R` is the base ring of self, whose "projective embedding"
539
map is `1` in the `i^{th}` factor.
540
541
INPUT:
542
543
- ``i`` -- integer between 0 and dimension of self, inclusive.
544
545
OUTPUT:
546
547
An ambient affine space with fixed projective_embedding map.
548
549
EXAMPLES::
550
551
sage: PP = ProjectiveSpace(5) / QQ
552
sage: AA = PP.affine_patch(2)
553
sage: AA
554
Affine Space of dimension 5 over Rational Field
555
sage: AA.projective_embedding()
556
Scheme morphism:
557
From: Affine Space of dimension 5 over Rational Field
558
To: Projective Space of dimension 5 over Rational Field
559
Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
560
(x0 : x1 : 1 : x2 : x3 : x4)
561
sage: AA.projective_embedding(0)
562
Scheme morphism:
563
From: Affine Space of dimension 5 over Rational Field
564
To: Projective Space of dimension 5 over Rational Field
565
Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
566
(1 : x0 : x1 : x2 : x3 : x4)
567
"""
568
i = int(i) # implicit type checking
569
n = self.dimension_relative()
570
if i < 0 or i > n:
571
raise ValueError, "Argument i (= %s) must be between 0 and %s."%(i, n)
572
try:
573
return self.__affine_patches[i]
574
except AttributeError:
575
self.__affine_patches = {}
576
except KeyError:
577
pass
578
from sage.schemes.generic.affine_space import AffineSpace
579
AA = AffineSpace(n, self.base_ring(), names='x')
580
AA._default_embedding_index = i
581
phi = AA.projective_embedding(i, self)
582
self.__affine_patches[i] = AA
583
return AA
584
585
586
class ProjectiveSpace_field(ProjectiveSpace_ring):
587
def _point_homset(self, *args, **kwds):
588
"""
589
Construct a point Hom-set.
590
591
For internal use only. See :mod:`morphism` for details.
592
593
TESTS::
594
595
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
596
sage: P2._point_homset(Spec(GF(3)), P2)
597
Set of rational points of Projective Space of dimension 2 over Finite Field of size 3
598
"""
599
return homset.SchemeHomset_points_projective_field(*args, **kwds)
600
601
def _point(self, *args, **kwds):
602
"""
603
Construct a point.
604
605
For internal use only. See :mod:`morphism` for details.
606
607
TESTS::
608
609
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
610
sage: point_homset = P2._point_homset(Spec(GF(3)), P2)
611
sage: P2._point(point_homset, [1,2,3])
612
(2 : 1 : 0)
613
"""
614
return morphism.SchemeMorphism_point_projective_field(*args, **kwds)
615
616
617
class ProjectiveSpace_finite_field(ProjectiveSpace_field):
618
def __iter__(self):
619
r"""
620
Return iterator over the elements of this projective space.
621
622
Note that iteration is over the decomposition
623
`\PP^n = \mathbb{A}A^n \cup \PP^n-1`, where
624
`\mathbb{A}A^n` is the `n`-th affine patch and
625
`\PP^n-1` is the hyperplane at infinity
626
`x_n = 0`.
627
628
EXAMPLES::
629
630
sage: FF = FiniteField(3)
631
sage: PP = ProjectiveSpace(0,FF)
632
sage: [ x for x in PP ]
633
[(1)]
634
sage: PP = ProjectiveSpace(1,FF)
635
sage: [ x for x in PP ]
636
[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]
637
sage: PP = ProjectiveSpace(2,FF)
638
sage: [ x for x in PP ]
639
[(0 : 0 : 1),
640
(1 : 0 : 1),
641
(2 : 0 : 1),
642
(0 : 1 : 1),
643
(1 : 1 : 1),
644
(2 : 1 : 1),
645
(0 : 2 : 1),
646
(1 : 2 : 1),
647
(2 : 2 : 1),
648
(0 : 1 : 0),
649
(1 : 1 : 0),
650
(2 : 1 : 0),
651
(1 : 0 : 0)]
652
653
AUTHORS:
654
655
- David Kohel
656
657
TODO: Iteration for point sets over finite fields, and return of
658
iter of point set over base field. Note that the point set does not
659
know whether this is a projective space or subscheme.
660
"""
661
n = self.dimension_relative()
662
R = self.base_ring()
663
zero = R(0)
664
i = n
665
while not i < 0:
666
P = [ zero for _ in range(i) ] + [ R(1) ] + [ zero for _ in range(n-i) ]
667
yield self(P)
668
iters = [ iter(R) for _ in range(i) ]
669
for x in iters: x.next() # put at zero
670
j = 0
671
while j < i:
672
try:
673
P[j] = iters[j].next()
674
yield self(P)
675
j = 0
676
except StopIteration:
677
iters[j] = iter(R) # reset
678
iters[j].next() # put at zero
679
P[j] = zero
680
j += 1
681
i -= 1
682
683
def rational_points(self, F=None):
684
"""
685
Return the list of `F`-rational points on the affine space self,
686
where `F` is a given finite field, or the base ring of self.
687
688
EXAMPLES::
689
690
sage: P = ProjectiveSpace(1, GF(3))
691
sage: P.rational_points()
692
[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]
693
sage: P.rational_points(GF(3^2, 'b'))
694
[(0 : 1), (2*b : 1), (b + 1 : 1), (b + 2 : 1), (2 : 1), (b : 1), (2*b + 2 : 1), (2*b + 1 : 1), (1 : 1), (1 : 0)]
695
"""
696
if F == None:
697
return [ P for P in self ]
698
elif not is_FiniteField(F):
699
raise TypeError, "Second argument (= %s) must be a finite field."%F
700
return [ P for P in self.base_extend(F) ]
701
702
class ProjectiveSpace_rational_field(ProjectiveSpace_field):
703
def rational_points(self,bound=0):
704
r"""
705
Returns the projective points `(x_0:\cdots:x_n)` over
706
`\QQ` with `|x_i| \leq` bound.
707
708
INPUT:
709
710
711
- ``bound`` - integer
712
713
714
EXAMPLES::
715
716
sage: PP = ProjectiveSpace(0,QQ)
717
sage: PP.rational_points(1)
718
[(1)]
719
sage: PP = ProjectiveSpace(1,QQ)
720
sage: PP.rational_points(2)
721
[(-2 : 1), (-1 : 1), (0 : 1), (1 : 1), (2 : 1), (-1/2 : 1), (1/2 : 1), (1 : 0)]
722
sage: PP = ProjectiveSpace(2,QQ)
723
sage: PP.rational_points(2)
724
[(-2 : -2 : 1), (-1 : -2 : 1), (0 : -2 : 1), (1 : -2 : 1), (2 : -2 : 1),
725
(-2 : -1 : 1), (-1 : -1 : 1), (0 : -1 : 1), (1 : -1 : 1), (2 : -1 : 1),
726
(-2 : 0 : 1), (-1 : 0 : 1), (0 : 0 : 1), (1 : 0 : 1), (2 : 0 : 1), (-2 :
727
1 : 1), (-1 : 1 : 1), (0 : 1 : 1), (1 : 1 : 1), (2 : 1 : 1), (-2 : 2 :
728
1), (-1 : 2 : 1), (0 : 2 : 1), (1 : 2 : 1), (2 : 2 : 1), (-1/2 : -1 :
729
1), (1/2 : -1 : 1), (-1 : -1/2 : 1), (-1/2 : -1/2 : 1), (0 : -1/2 : 1),
730
(1/2 : -1/2 : 1), (1 : -1/2 : 1), (-1/2 : 0 : 1), (1/2 : 0 : 1), (-1 :
731
1/2 : 1), (-1/2 : 1/2 : 1), (0 : 1/2 : 1), (1/2 : 1/2 : 1), (1 : 1/2 :
732
1), (-1/2 : 1 : 1), (1/2 : 1 : 1), (-2 : 1 : 0), (-1 : 1 : 0), (0 : 1 :
733
0), (1 : 1 : 0), (2 : 1 : 0), (-1/2 : 1 : 0), (1/2 : 1 : 0), (1 : 0 :
734
0)]
735
736
.. note::
737
738
The very simple algorithm works as follows: every point
739
`(x_0:\cdots:x_n)` in projective space has a unique
740
largest index `i` for which `x_i` is not
741
zero. The algorithm then iterates downward on this
742
index. We normalize by choosing `x_i` positive. Then,
743
the points `x_0,\ldots,x_{i-1}` are the points of
744
affine `i`-space that are relatively prime to
745
`x_i`. We access these by using the Tuples method.
746
747
AUTHORS:
748
749
- Benjamin Antieau (2008-01-12)
750
"""
751
if not bound > 0:
752
raise ValueError, \
753
"Argument bound (= %s) must be a positive integer."
754
755
n = self.dimension_relative()
756
757
758
Q = [ k-bound for k in range(2*bound+1) ] # the affine coordinates
759
R = [ (k+1) for k in range(bound) ] # the projective coordinate
760
S = [ Tuples(Q,(k+1)) for k in range(n) ]
761
pts = []
762
763
i=n
764
765
while i > 0:
766
P = [ 0 for _ in range(n+1) ]
767
for ai in R:
768
P[i]=ai
769
for tup in S[i-1]:
770
if gcd([ai]+tup)==1:
771
for j in range(i):
772
P[j]=tup[j]
773
pts.append(self(P))
774
i-=1
775
776
# now do i=0; this is treated as a special case so that
777
# we don't have all points (1:0),(2,0),(3,0),etc.
778
P = [ 0 for _ in range(n+1) ]; P[0]=1
779
pts.append(self(P))
780
return pts
781
782