Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/schemes/projective/projective_space.py
8820 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
AUTHORS:
54
55
- Ben Hutz: (June 2012): support for rings
56
"""
57
58
#*****************************************************************************
59
# Copyright (C) 2006 William Stein <[email protected]>
60
#
61
# Distributed under the terms of the GNU General Public License (GPL)
62
#
63
# http://www.gnu.org/licenses/
64
#*****************************************************************************
65
66
from sage.rings.all import (PolynomialRing,
67
Integer,
68
ZZ)
69
70
from sage.rings.ring import is_Ring
71
from sage.rings.rational_field import is_RationalField
72
from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing
73
from sage.rings.finite_rings.constructor import is_FiniteField
74
from sage.rings.commutative_ring import is_CommutativeRing
75
76
from sage.categories.fields import Fields
77
_Fields = Fields()
78
79
from sage.misc.all import (latex,
80
prod)
81
from sage.structure.parent_gens import normalize_names
82
from sage.rings.arith import (gcd,
83
binomial)
84
from sage.combinat.integer_vector import IntegerVectors
85
from sage.combinat.tuple import Tuples
86
from sage.matrix.constructor import matrix
87
from sage.modules.free_module_element import prepare
88
89
from sage.schemes.generic.ambient_space import AmbientSpace
90
from sage.schemes.projective.projective_homset import (SchemeHomset_points_projective_ring,
91
SchemeHomset_points_projective_field)
92
from sage.schemes.projective.projective_point import (SchemeMorphism_point_projective_ring,
93
SchemeMorphism_point_projective_field,
94
SchemeMorphism_point_projective_finite_field)
95
from sage.schemes.projective.projective_morphism import (SchemeMorphism_polynomial_projective_space,
96
SchemeMorphism_polynomial_projective_space_field,
97
SchemeMorphism_polynomial_projective_space_finite_field)
98
99
100
def is_ProjectiveSpace(x):
101
r"""
102
Return True if `x` is a projective space, i.e., an ambient space
103
`\mathbb{P}^n_R`, where `R` is a ring and `n\geq 0` is an
104
integer.
105
106
EXAMPLES::
107
108
sage: from sage.schemes.projective.projective_space import is_ProjectiveSpace
109
sage: is_ProjectiveSpace(ProjectiveSpace(5, names='x'))
110
True
111
sage: is_ProjectiveSpace(ProjectiveSpace(5, GF(9,'alpha'), names='x'))
112
True
113
sage: is_ProjectiveSpace(Spec(ZZ))
114
False
115
"""
116
return isinstance(x, ProjectiveSpace_ring)
117
118
def ProjectiveSpace(n, R=None, names='x'):
119
r"""
120
Return projective space of dimension `n` over the ring `R`.
121
122
EXAMPLES: The dimension and ring can be given in either order.
123
124
::
125
126
sage: ProjectiveSpace(3, QQ)
127
Projective Space of dimension 3 over Rational Field
128
sage: ProjectiveSpace(5, QQ)
129
Projective Space of dimension 5 over Rational Field
130
sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P
131
Projective Space of dimension 2 over Rational Field
132
sage: P.coordinate_ring()
133
Multivariate Polynomial Ring in X, Y, Z over Rational Field
134
135
The divide operator does base extension.
136
137
::
138
139
sage: ProjectiveSpace(5)/GF(17)
140
Projective Space of dimension 5 over Finite Field of size 17
141
142
The default base ring is `\ZZ`.
143
144
::
145
146
sage: ProjectiveSpace(5)
147
Projective Space of dimension 5 over Integer Ring
148
149
There is also an projective space associated each polynomial ring.
150
151
::
152
153
sage: R = GF(7)['x,y,z']
154
sage: P = ProjectiveSpace(R); P
155
Projective Space of dimension 2 over Finite Field of size 7
156
sage: P.coordinate_ring()
157
Multivariate Polynomial Ring in x, y, z over Finite Field of size 7
158
sage: P.coordinate_ring() is R
159
True
160
161
::
162
163
sage: ProjectiveSpace(3, Zp(5), 'y')
164
Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20
165
166
::
167
168
sage: ProjectiveSpace(2,QQ,'x,y,z')
169
Projective Space of dimension 2 over Rational Field
170
171
::
172
173
sage: PS.<x,y>=ProjectiveSpace(1,CC)
174
sage: PS
175
Projective Space of dimension 1 over Complex Field with 53 bits of precision
176
177
Projective spaces are not cached, i.e., there can be several with
178
the same base ring and dimension (to facilitate gluing
179
constructions).
180
"""
181
if is_MPolynomialRing(n) and R is None:
182
A = ProjectiveSpace(n.ngens()-1, n.base_ring())
183
A._coordinate_ring = n
184
return A
185
if isinstance(R, (int, long, Integer)):
186
n, R = R, n
187
if R is None:
188
R = ZZ # default is the integers
189
if R in _Fields:
190
if is_FiniteField(R):
191
return ProjectiveSpace_finite_field(n, R, names)
192
if is_RationalField(R):
193
return ProjectiveSpace_rational_field(n, R, names)
194
else:
195
return ProjectiveSpace_field(n, R, names)
196
elif is_CommutativeRing(R):
197
return ProjectiveSpace_ring(n, R, names)
198
else:
199
raise TypeError("R (=%s) must be a commutative ring"%R)
200
201
class ProjectiveSpace_ring(AmbientSpace):
202
"""
203
Projective space of dimension `n` over the ring
204
`R`.
205
206
EXAMPLES::
207
208
sage: X.<x,y,z,w> = ProjectiveSpace(3, QQ)
209
sage: X.base_scheme()
210
Spectrum of Rational Field
211
sage: X.base_ring()
212
Rational Field
213
sage: X.structure_morphism()
214
Scheme morphism:
215
From: Projective Space of dimension 3 over Rational Field
216
To: Spectrum of Rational Field
217
Defn: Structure map
218
sage: X.coordinate_ring()
219
Multivariate Polynomial Ring in x, y, z, w over Rational Field
220
221
Loading and saving::
222
223
sage: loads(X.dumps()) == X
224
True
225
"""
226
def __init__(self, n, R=ZZ, names=None):
227
"""
228
EXAMPLES::
229
230
sage: ProjectiveSpace(3, Zp(5), 'y')
231
Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20
232
"""
233
names = normalize_names(n+1, names)
234
AmbientSpace.__init__(self, n, R)
235
self._assign_names(names)
236
237
def ngens(self):
238
"""
239
Return the number of generators of self, i.e. the number of
240
variables in the coordinate ring of self.
241
242
EXAMPLES::
243
244
sage: ProjectiveSpace(3, QQ).ngens()
245
4
246
sage: ProjectiveSpace(7, ZZ).ngens()
247
8
248
"""
249
return self.dimension_relative() + 1
250
251
def _check_satisfies_equations(self, v):
252
"""
253
Return True if `v` defines a point on the scheme self; raise a
254
TypeError otherwise.
255
256
EXAMPLES::
257
258
sage: P = ProjectiveSpace(2, ZZ)
259
sage: P._check_satisfies_equations([1, 1, 0])
260
True
261
262
::
263
264
sage: P = ProjectiveSpace(1, QQ)
265
sage: P._check_satisfies_equations((1/2, 0))
266
True
267
268
::
269
270
sage: P = ProjectiveSpace(2, ZZ)
271
sage: P._check_satisfies_equations([0, 0, 0])
272
Traceback (most recent call last):
273
...
274
TypeError: The zero vector is not a point in projective space
275
276
::
277
278
sage: P = ProjectiveSpace(2, ZZ)
279
sage: P._check_satisfies_equations((1, 0))
280
Traceback (most recent call last):
281
...
282
TypeError: The list v=(1, 0) must have 3 components
283
284
::
285
286
sage: P = ProjectiveSpace(2, ZZ)
287
sage: P._check_satisfies_equations([1/2, 0, 1])
288
Traceback (most recent call last):
289
...
290
TypeError: The components of v=[1/2, 0, 1] must be elements of Integer Ring
291
"""
292
if not isinstance(v, (list, tuple)):
293
raise TypeError('The argument v=%s must be a list or tuple'%v)
294
n = self.ngens()
295
if not len(v) == n:
296
raise TypeError('The list v=%s must have %s components'%(v, n))
297
R = self.base_ring()
298
for coord in v:
299
if not coord in R:
300
raise TypeError('The components of v=%s must be elements of %s'%(v, R))
301
zero = [R(0)]*n
302
if v == zero:
303
raise TypeError('The zero vector is not a point in projective space')
304
return True
305
306
def coordinate_ring(self):
307
"""
308
Return the coordinate ring of this scheme.
309
310
EXAMPLES::
311
312
sage: ProjectiveSpace(3, GF(19^2,'alpha'), 'abcd').coordinate_ring()
313
Multivariate Polynomial Ring in a, b, c, d over Finite Field in alpha of size 19^2
314
315
::
316
317
sage: ProjectiveSpace(3).coordinate_ring()
318
Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring
319
320
::
321
322
sage: ProjectiveSpace(2, QQ, ['alpha', 'beta', 'gamma']).coordinate_ring()
323
Multivariate Polynomial Ring in alpha, beta, gamma over Rational Field
324
"""
325
try:
326
return self._coordinate_ring
327
except AttributeError:
328
self._coordinate_ring = PolynomialRing(self.base_ring(),
329
self.variable_names(), self.dimension_relative()+1)
330
return self._coordinate_ring
331
332
def _validate(self, polynomials):
333
"""
334
If ``polynomials`` is a tuple of valid polynomial functions on self,
335
return ``polynomials``, otherwise raise TypeError.
336
337
Since this is a projective space, polynomials must be homogeneous.
338
339
INPUT:
340
341
- ``polynomials`` -- tuple of polynomials in the coordinate ring of
342
self
343
344
OUTPUT:
345
346
- tuple of polynomials in the coordinate ring of self
347
348
EXAMPLES::
349
350
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
351
sage: P._validate([x*y - z^2, x])
352
[x*y - z^2, x]
353
354
::
355
356
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
357
sage: P._validate((x*y - z, x))
358
Traceback (most recent call last):
359
...
360
TypeError: x*y - z is not a homogeneous polynomial!
361
362
::
363
364
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
365
sage: P._validate(x*y - z)
366
Traceback (most recent call last):
367
...
368
TypeError: The argument polynomials=x*y - z must be a list or tuple
369
"""
370
if not isinstance(polynomials, (list, tuple)):
371
raise TypeError('The argument polynomials=%s must be a list or tuple'%polynomials)
372
for f in polynomials:
373
if not f.is_homogeneous():
374
raise TypeError("%s is not a homogeneous polynomial!" % f)
375
return polynomials
376
377
def __cmp__(self, right):
378
"""
379
EXAMPLES::
380
381
sage: ProjectiveSpace(QQ, 3, 'a') == ProjectiveSpace(ZZ, 3, 'a')
382
False
383
sage: ProjectiveSpace(ZZ, 1, 'a') == ProjectiveSpace(ZZ, 0, 'a')
384
False
385
sage: ProjectiveSpace(ZZ, 2, 'a') == AffineSpace(ZZ, 2, 'a')
386
False
387
sage: loads(AffineSpace(ZZ, 1, 'x').dumps()) == AffineSpace(ZZ, 1, 'x')
388
True
389
"""
390
if not isinstance(right, ProjectiveSpace_ring):
391
return -1
392
return cmp([self.dimension_relative(), self.coordinate_ring()],
393
[right.dimension_relative(), right.coordinate_ring()])
394
395
def _latex_(self):
396
r"""
397
Return a LaTeX representation of this projective space.
398
399
EXAMPLES::
400
401
sage: print latex(ProjectiveSpace(1, ZZ, 'x'))
402
{\mathbf P}_{\Bold{Z}}^1
403
404
TESTS::
405
406
sage: ProjectiveSpace(3, Zp(5), 'y')._latex_()
407
'{\\mathbf P}_{\\ZZ_{5}}^3'
408
"""
409
return "{\\mathbf P}_{%s}^%s"%(latex(self.base_ring()), self.dimension_relative())
410
411
def _linear_system_as_kernel(self, d, pt, m):
412
"""
413
Return a matrix whose kernel consists of the coefficient vectors
414
of the degree d hypersurfaces (wrt lexicographic ordering of its
415
monomials) with multiplicity at least m at pt.
416
417
INPUT:
418
419
- ``d`` -- a nonnegative integer
420
421
- ``pt`` -- a point of self (possibly represented by a list with at \
422
least one component equal to 1)
423
424
- ``m`` -- a nonnegative integer
425
426
OUTPUT:
427
428
A matrix of size `{m-1+n \choose n}` x `{d+n \choose n}` where n is the
429
relative dimension of self. The base ring of the matrix is a ring that
430
contains the base ring of self and the coefficients of the given point.
431
432
EXAMPLES:
433
434
If the degree `d` is 0, then a matrix consisting of the first unit vector
435
is returned::
436
437
sage: P = ProjectiveSpace(GF(5), 2, names='x')
438
sage: pt = P([1, 1, 1])
439
sage: P._linear_system_as_kernel(0, pt, 3)
440
[1]
441
[0]
442
[0]
443
[0]
444
[0]
445
[0]
446
447
If the multiplcity `m` is 0, then the a matrix with zero rows is returned::
448
449
sage: P = ProjectiveSpace(GF(5), 2, names='x')
450
sage: pt = P([1, 1, 1])
451
sage: M = P._linear_system_as_kernel(2, pt, 0)
452
sage: [M.nrows(), M.ncols()]
453
[0, 6]
454
455
The base ring does not need to be a field or even an integral domain.
456
In this case, the point can be given by a list::
457
458
sage: R = Zmod(4)
459
sage: P = ProjectiveSpace(R, 2, names='x')
460
sage: pt = [R(1), R(3), R(0)]
461
sage: P._linear_system_as_kernel(3, pt, 2)
462
[1 3 0 1 0 0 3 0 0 0]
463
[0 1 0 2 0 0 3 0 0 0]
464
[0 0 1 0 3 0 0 1 0 0]
465
466
When representing a point by a list at least one component must be 1
467
(even when the base ring is a field and the list gives a well-defined
468
point in projective space)::
469
470
sage: R = GF(5)
471
sage: P = ProjectiveSpace(R, 2, names='x')
472
sage: pt = [R(3), R(3), R(0)]
473
sage: P._linear_system_as_kernel(3, pt, 2)
474
Traceback (most recent call last):
475
...
476
TypeError: At least one component of pt=[3, 3, 0] must be equal
477
to 1
478
479
The components of the list do not have to be elements of the base ring
480
of the projective space. It suffices if there exists a common parent.
481
For example, the kernel of the following matrix corresponds to
482
hypersurfaces of degree 2 in 3-space with multiplicity at least 2 at a
483
general point in the third affine patch::
484
485
sage: P = ProjectiveSpace(QQ,3,names='x')
486
sage: RPol.<t0,t1,t2,t3> = PolynomialRing(QQ,4)
487
sage: pt = [t0,t1,1,t3]
488
sage: P._linear_system_as_kernel(2,pt,2)
489
[ 2*t0 t1 1 t3 0 0 0 0 0 0]
490
[ 0 t0 0 0 2*t1 1 t3 0 0 0]
491
[ t0^2 t0*t1 t0 t0*t3 t1^2 t1 t1*t3 1 t3 t3^2]
492
[ 0 0 0 t0 0 0 t1 0 1 2*t3]
493
494
.. TODO::
495
496
Use this method as starting point to implement a class
497
LinearSystem for linear systems of hypersurfaces.
498
499
"""
500
if not isinstance(d, (int, Integer)):
501
raise TypeError('The argument d=%s must be an integer'%d)
502
if d < 0:
503
raise ValueError('The integer d=%s must be nonnegative'%d)
504
if not isinstance(pt, (list, tuple, \
505
SchemeMorphism_point_projective_ring)):
506
raise TypeError('The argument pt=%s must be a list, tuple, or '
507
'point on a projective space'%pt)
508
pt, R = prepare(pt, None)
509
n = self.dimension_relative()
510
if not len(pt) == n+1:
511
raise TypeError('The sequence pt=%s must have %s '
512
'components'%(pt, n + 1))
513
if not R.has_coerce_map_from(self.base_ring()):
514
raise TypeError('Unable to find a common ring for all elements')
515
try:
516
i = pt.index(1)
517
except Exception:
518
raise TypeError('At least one component of pt=%s must be equal '
519
'to 1'%pt)
520
pt = pt[:i] + pt[i+1:]
521
if not isinstance(m, (int, Integer)):
522
raise TypeError('The argument m=%s must be an integer'%m)
523
if m < 0:
524
raise ValueError('The integer m=%s must be nonnegative'%m)
525
# the components of partials correspond to partial derivatives
526
# of order at most m-1 with respect to n variables
527
partials = IntegerVectors(m-1,n+1).list()
528
# the components of monoms correspond to monomials of degree
529
# at most d in n variables
530
monoms = IntegerVectors(d,n+1).list()
531
M = matrix(R,len(partials),len(monoms))
532
for row in range(M.nrows()):
533
e = partials[row][:i] + partials[row][i+1:]
534
for col in range(M.ncols()):
535
f = monoms[col][:i] + monoms[col][i+1:]
536
if min([f[j]-e[j] for j in range(n)]) >= 0:
537
M[row,col] = prod([binomial(f[j],e[j])*pt[j]**(f[j]-e[j]) \
538
for j in filter(lambda k: f[k]>e[k], range(n))])
539
return M
540
541
def _morphism(self, *args, **kwds):
542
"""
543
Construct a morphism.
544
545
For internal use only. See :mod:`morphism` for details.
546
547
TESTS::
548
549
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
550
sage: P2._morphism(P2.Hom(P2), [x,y,z])
551
Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3
552
Defn: Defined on coordinates by sending (x : y : z) to
553
(x : y : z)
554
"""
555
return SchemeMorphism_polynomial_projective_space(*args, **kwds)
556
557
def _point_homset(self, *args, **kwds):
558
"""
559
Construct a point Hom-set.
560
561
For internal use only. See :mod:`morphism` for details.
562
563
TESTS::
564
565
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
566
sage: P2._point_homset(Spec(GF(3)), P2)
567
Set of rational points of Projective Space of dimension 2 over Finite Field of size 3
568
"""
569
return SchemeHomset_points_projective_ring(*args, **kwds)
570
571
def _point(self, *args, **kwds):
572
"""
573
Construct a point.
574
575
For internal use only. See :mod:`morphism` for details.
576
577
TESTS::
578
579
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
580
sage: point_homset = P2._point_homset(Spec(GF(3)), P2)
581
sage: P2._point(point_homset, [1,2,3])
582
(2 : 1 : 0)
583
"""
584
return SchemeMorphism_point_projective_ring(*args, **kwds)
585
586
def _repr_(self):
587
"""
588
Return a string representation of this projective space.
589
590
EXAMPLES::
591
592
sage: ProjectiveSpace(1, ZZ, 'x')
593
Projective Space of dimension 1 over Integer Ring
594
595
TESTS::
596
597
sage: ProjectiveSpace(3, Zp(5), 'y')._repr_()
598
'Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20'
599
"""
600
return "Projective Space of dimension %s over %s"%(self.dimension_relative(), self.base_ring())
601
602
def _repr_generic_point(self, v=None):
603
"""
604
Return a string representation of the generic point
605
corresponding to the list of polys on this projective space.
606
607
If polys is None, the representation of the generic point of
608
the projective space is returned.
609
610
EXAMPLES::
611
612
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
613
sage: P._repr_generic_point([z*y-x^2])
614
'(-x^2 + y*z)'
615
sage: P._repr_generic_point()
616
'(x : y : z)'
617
"""
618
if v is None:
619
v = self.gens()
620
return '(%s)'%(" : ".join([repr(f) for f in v]))
621
622
def _latex_generic_point(self, v=None):
623
"""
624
Return a LaTeX representation of the generic point
625
corresponding to the list of polys on this projective space.
626
627
If polys is None, the representation of the generic point of
628
the projective space is returned.
629
630
EXAMPLES::
631
632
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
633
sage: P._latex_generic_point([z*y-x^2])
634
'\\left(- x^{2} + y z\\right)'
635
sage: P._latex_generic_point()
636
'\\left(x : y : z\\right)'
637
"""
638
if v is None:
639
v = self.gens()
640
return '\\left(%s\\right)'%(" : ".join([str(latex(f)) for f in v]))
641
642
def change_ring(self, R):
643
r"""
644
Return a projective space over ring `R` and otherwise the same as self.
645
646
INPUT:
647
648
- ``R`` -- commutative ring
649
650
OUTPUT:
651
652
- projective space over ``R``
653
654
.. NOTE::
655
656
There is no need to have any relation between `R` and the base ring
657
of self, if you want to have such a relation, use
658
``self.base_extend(R)`` instead.
659
660
EXAMPLES::
661
662
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)
663
sage: PQ = P.change_ring(QQ); PQ
664
Projective Space of dimension 2 over Rational Field
665
sage: PQ.change_ring(GF(5))
666
Projective Space of dimension 2 over Finite Field of size 5
667
"""
668
return ProjectiveSpace(self.dimension_relative(), R,
669
self.variable_names())
670
671
def is_projective(self):
672
"""
673
Return that this ambient space is projective n-space.
674
675
EXAMPLES::
676
677
sage: ProjectiveSpace(3,QQ).is_projective()
678
True
679
"""
680
return True
681
682
def subscheme(self, X):
683
"""
684
Return the closed subscheme defined by X.
685
686
INPUT:
687
688
- ``X`` - a list or tuple of equations
689
690
EXAMPLES::
691
692
sage: A.<x,y,z> = ProjectiveSpace(2, QQ)
693
sage: X = A.subscheme([x*z^2, y^2*z, x*y^2]); X
694
Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
695
x*z^2,
696
y^2*z,
697
x*y^2
698
sage: X.defining_polynomials ()
699
(x*z^2, y^2*z, x*y^2)
700
sage: I = X.defining_ideal(); I
701
Ideal (x*z^2, y^2*z, x*y^2) of Multivariate Polynomial Ring in x, y, z over Rational Field
702
sage: I.groebner_basis()
703
[x*y^2, y^2*z, x*z^2]
704
sage: X.dimension()
705
0
706
sage: X.base_ring()
707
Rational Field
708
sage: X.base_scheme()
709
Spectrum of Rational Field
710
sage: X.structure_morphism()
711
Scheme morphism:
712
From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
713
x*z^2,
714
y^2*z,
715
x*y^2
716
To: Spectrum of Rational Field
717
Defn: Structure map
718
719
sage: TestSuite(X).run(skip=["_test_an_element", "_test_elements", "_test_elements_eq", "_test_some_elements", "_test_elements_eq_reflexive", "_test_elements_eq_symmetric", "_test_elements_eq_transitive", "_test_elements_neq"])
720
"""
721
from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_projective
722
return AlgebraicScheme_subscheme_projective(self, X)
723
724
def affine_patch(self, i):
725
r"""
726
Return the `i^{th}` affine patch of this projective space.
727
This is an ambient affine space `\mathbb{A}^n_R,` where
728
`R` is the base ring of self, whose "projective embedding"
729
map is `1` in the `i^{th}` factor.
730
731
INPUT:
732
733
- ``i`` -- integer between 0 and dimension of self, inclusive.
734
735
OUTPUT:
736
737
- An ambient affine space with fixed projective_embedding map.
738
739
EXAMPLES::
740
741
sage: PP = ProjectiveSpace(5) / QQ
742
sage: AA = PP.affine_patch(2)
743
sage: AA
744
Affine Space of dimension 5 over Rational Field
745
sage: AA.projective_embedding()
746
Scheme morphism:
747
From: Affine Space of dimension 5 over Rational Field
748
To: Projective Space of dimension 5 over Rational Field
749
Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
750
(x0 : x1 : 1 : x2 : x3 : x4)
751
sage: AA.projective_embedding(0)
752
Scheme morphism:
753
From: Affine Space of dimension 5 over Rational Field
754
To: Projective Space of dimension 5 over Rational Field
755
Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to
756
(1 : x0 : x1 : x2 : x3 : x4)
757
"""
758
i = int(i) # implicit type checking
759
n = self.dimension_relative()
760
if i < 0 or i > n:
761
raise ValueError("Argument i (= %s) must be between 0 and %s."%(i, n))
762
try:
763
return self.__affine_patches[i]
764
except AttributeError:
765
self.__affine_patches = {}
766
except KeyError:
767
pass
768
from sage.schemes.affine.affine_space import AffineSpace
769
AA = AffineSpace(n, self.base_ring(), names='x')
770
AA._default_embedding_index = i
771
phi = AA.projective_embedding(i, self)
772
self.__affine_patches[i] = AA
773
return AA
774
775
def _an_element_(self):
776
r"""
777
Returns a (preferably typical) element of ``self``.
778
779
This is used both for illustration and testing purposes.
780
781
OUTPUT: a point in the projective space ``self``.
782
783
EXAMPLES::
784
785
sage: ProjectiveSpace(ZZ,3,'x').an_element()
786
(7 : 6 : 5 : 1)
787
788
sage: ProjectiveSpace(PolynomialRing(ZZ,'y'),3,'x').an_element()
789
(7*y : 6*y : 5*y : 1)
790
"""
791
n = self.dimension_relative()
792
R = self.base_ring()
793
return self([(7 - i) * R.an_element() for i in range(n)] + [R.one()])
794
795
796
class ProjectiveSpace_field(ProjectiveSpace_ring):
797
def _point_homset(self, *args, **kwds):
798
"""
799
Construct a point Hom-set.
800
801
For internal use only. See :mod:`morphism` for details.
802
803
TESTS::
804
805
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
806
sage: P2._point_homset(Spec(GF(3)), P2)
807
Set of rational points of Projective Space of dimension 2 over Finite Field of size 3
808
"""
809
return SchemeHomset_points_projective_field(*args, **kwds)
810
811
def _point(self, *args, **kwds):
812
"""
813
Construct a point.
814
815
For internal use only. See :mod:`morphism` for details.
816
817
TESTS::
818
819
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
820
sage: point_homset = P2._point_homset(Spec(GF(3)), P2)
821
sage: P2._point(point_homset, [1,2,3])
822
(2 : 1 : 0)
823
"""
824
return SchemeMorphism_point_projective_field(*args, **kwds)
825
826
def _morphism(self, *args, **kwds):
827
"""
828
Construct a morphism.
829
830
For internal use only. See :mod:`morphism` for details.
831
832
TESTS::
833
834
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
835
sage: P2._morphism(P2.Hom(P2), [x,y,z])
836
Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3
837
Defn: Defined on coordinates by sending (x : y : z) to
838
(x : y : z)
839
"""
840
return SchemeMorphism_polynomial_projective_space_field(*args, **kwds)
841
842
class ProjectiveSpace_finite_field(ProjectiveSpace_field):
843
def _point(self, *args, **kwds):
844
"""
845
Construct a point.
846
847
For internal use only. See :mod:`morphism` for details.
848
849
TESTS::
850
851
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
852
sage: point_homset = P2._point_homset(Spec(GF(3)), P2)
853
sage: P2._point(point_homset, [1,2,3])
854
(2 : 1 : 0)
855
"""
856
return SchemeMorphism_point_projective_finite_field(*args, **kwds)
857
858
def _morphism(self, *args, **kwds):
859
"""
860
Construct a morphism.
861
862
For internal use only. See :mod:`morphism` for details.
863
864
TESTS::
865
866
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))
867
sage: P2._morphism(P2.Hom(P2), [x,y,z])
868
Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3
869
Defn: Defined on coordinates by sending (x : y : z) to
870
(x : y : z)
871
"""
872
return SchemeMorphism_polynomial_projective_space_finite_field(*args, **kwds)
873
874
875
def __iter__(self):
876
r"""
877
Return iterator over the elements of this projective space.
878
879
Note that iteration is over the decomposition
880
`\mathbb{P}^n = \mathbb{A}A^n \cup \mathbb{P}^n-1`, where
881
`\mathbb{A}A^n` is the `n`-th affine patch and
882
`\mathbb{P}^n-1` is the hyperplane at infinity
883
`x_n = 0`.
884
885
EXAMPLES::
886
887
sage: FF = FiniteField(3)
888
sage: PP = ProjectiveSpace(0,FF)
889
sage: [ x for x in PP ]
890
[(1)]
891
sage: PP = ProjectiveSpace(1,FF)
892
sage: [ x for x in PP ]
893
[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]
894
sage: PP = ProjectiveSpace(2,FF)
895
sage: [ x for x in PP ]
896
[(0 : 0 : 1),
897
(1 : 0 : 1),
898
(2 : 0 : 1),
899
(0 : 1 : 1),
900
(1 : 1 : 1),
901
(2 : 1 : 1),
902
(0 : 2 : 1),
903
(1 : 2 : 1),
904
(2 : 2 : 1),
905
(0 : 1 : 0),
906
(1 : 1 : 0),
907
(2 : 1 : 0),
908
(1 : 0 : 0)]
909
910
AUTHORS:
911
912
- David Kohel
913
914
.. TODO::
915
916
Iteration for point sets over finite fields, and return of
917
iter of point set over base field. Note that the point set does not
918
know whether this is a projective space or subscheme.
919
"""
920
n = self.dimension_relative()
921
R = self.base_ring()
922
zero = R(0)
923
i = n
924
while not i < 0:
925
P = [ zero for _ in range(i) ] + [ R(1) ] + [ zero for _ in range(n-i) ]
926
yield self(P)
927
iters = [ iter(R) for _ in range(i) ]
928
for x in iters: x.next() # put at zero
929
j = 0
930
while j < i:
931
try:
932
P[j] = iters[j].next()
933
yield self(P)
934
j = 0
935
except StopIteration:
936
iters[j] = iter(R) # reset
937
iters[j].next() # put at zero
938
P[j] = zero
939
j += 1
940
i -= 1
941
942
def rational_points(self, F=None):
943
"""
944
Return the list of `F`-rational points on the affine space self,
945
where `F` is a given finite field, or the base ring of self.
946
947
EXAMPLES::
948
949
sage: P = ProjectiveSpace(1, GF(3))
950
sage: P.rational_points()
951
[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]
952
sage: P.rational_points(GF(3^2, 'b'))
953
[(0 : 1), (b : 1), (b + 1 : 1), (2*b + 1 : 1), (2 : 1), (2*b : 1), (2*b + 2 : 1), (b + 2 : 1), (1 : 1), (1 : 0)]
954
"""
955
if F == None:
956
return [ P for P in self ]
957
elif not is_FiniteField(F):
958
raise TypeError("Second argument (= %s) must be a finite field."%F)
959
return [ P for P in self.base_extend(F) ]
960
961
def rational_points_dictionary(self):
962
r"""
963
Return dictionary of points.
964
965
OUTPUT:
966
967
- dictionary
968
969
EXAMPLES::
970
971
sage: P1=ProjectiveSpace(GF(7),1,'x')
972
sage: P1.rational_points_dictionary()
973
{(1 : 0): 7, (0 : 1): 0, (1 : 1): 1, (2 : 1): 2, (3 : 1): 3, (4 : 1): 4,
974
(5 : 1): 5, (6 : 1): 6}
975
"""
976
n = self.dimension_relative()
977
R = self.base_ring()
978
D={}
979
zero = R(0)
980
i = n
981
index=0
982
while not i < 0:
983
P = [ zero for _ in range(i) ] + [ R(1) ] + [ zero for _ in range(n-i) ]
984
D.update({self(P):index})
985
index+=1
986
iters = [ iter(R) for _ in range(i) ]
987
for x in iters: x.next() # put at zero
988
j = 0
989
while j < i:
990
try:
991
P[j] = iters[j].next()
992
D.update({self(P):index})
993
index+=1
994
j = 0
995
except StopIteration:
996
iters[j] = iter(R) # reset
997
iters[j].next() # put at zero
998
P[j] = zero
999
j += 1
1000
i -= 1
1001
return(D)
1002
1003
class ProjectiveSpace_rational_field(ProjectiveSpace_field):
1004
def rational_points(self,bound=0):
1005
r"""
1006
Returns the projective points `(x_0:\cdots:x_n)` over
1007
`\QQ` with `|x_i| \leq` bound.
1008
1009
INPUT:
1010
1011
1012
- ``bound`` - integer
1013
1014
1015
EXAMPLES::
1016
1017
sage: PP = ProjectiveSpace(0,QQ)
1018
sage: PP.rational_points(1)
1019
[(1)]
1020
sage: PP = ProjectiveSpace(1,QQ)
1021
sage: PP.rational_points(2)
1022
[(-2 : 1), (-1 : 1), (0 : 1), (1 : 1), (2 : 1), (-1/2 : 1), (1/2 : 1), (1 : 0)]
1023
sage: PP = ProjectiveSpace(2,QQ)
1024
sage: PP.rational_points(2)
1025
[(-2 : -2 : 1), (-1 : -2 : 1), (0 : -2 : 1), (1 : -2 : 1), (2 : -2 : 1),
1026
(-2 : -1 : 1), (-1 : -1 : 1), (0 : -1 : 1), (1 : -1 : 1), (2 : -1 : 1),
1027
(-2 : 0 : 1), (-1 : 0 : 1), (0 : 0 : 1), (1 : 0 : 1), (2 : 0 : 1), (-2 :
1028
1 : 1), (-1 : 1 : 1), (0 : 1 : 1), (1 : 1 : 1), (2 : 1 : 1), (-2 : 2 :
1029
1), (-1 : 2 : 1), (0 : 2 : 1), (1 : 2 : 1), (2 : 2 : 1), (-1/2 : -1 :
1030
1), (1/2 : -1 : 1), (-1 : -1/2 : 1), (-1/2 : -1/2 : 1), (0 : -1/2 : 1),
1031
(1/2 : -1/2 : 1), (1 : -1/2 : 1), (-1/2 : 0 : 1), (1/2 : 0 : 1), (-1 :
1032
1/2 : 1), (-1/2 : 1/2 : 1), (0 : 1/2 : 1), (1/2 : 1/2 : 1), (1 : 1/2 :
1033
1), (-1/2 : 1 : 1), (1/2 : 1 : 1), (-2 : 1 : 0), (-1 : 1 : 0), (0 : 1 :
1034
0), (1 : 1 : 0), (2 : 1 : 0), (-1/2 : 1 : 0), (1/2 : 1 : 0), (1 : 0 :
1035
0)]
1036
1037
1038
.. note::
1039
1040
The very simple algorithm works as follows: every point
1041
`(x_0:\cdots:x_n)` in projective space has a unique
1042
largest index `i` for which `x_i` is not
1043
zero. The algorithm then iterates downward on this
1044
index. We normalize by choosing `x_i` positive. Then,
1045
the points `x_0,\ldots,x_{i-1}` are the points of
1046
affine `i`-space that are relatively prime to
1047
`x_i`. We access these by using the Tuples method.
1048
1049
AUTHORS:
1050
1051
- Benjamin Antieau (2008-01-12)
1052
"""
1053
if not bound > 0:
1054
raise ValueError("Argument bound (= %s) must be a positive integer.")
1055
1056
n = self.dimension_relative()
1057
1058
1059
Q = [ k-bound for k in range(2*bound+1) ] # the affine coordinates
1060
R = [ (k+1) for k in range(bound) ] # the projective coordinate
1061
S = [ Tuples(Q,(k+1)) for k in range(n) ]
1062
pts = []
1063
1064
i=n
1065
1066
while i > 0:
1067
P = [ 0 for _ in range(n+1) ]
1068
for ai in R:
1069
P[i]=ai
1070
for tup in S[i-1]:
1071
if gcd([ai]+tup)==1:
1072
for j in range(i):
1073
P[j]=tup[j]
1074
pts.append(self(P))
1075
i-=1
1076
1077
# now do i=0; this is treated as a special case so that
1078
# we don't have all points (1:0),(2,0),(3,0),etc.
1079
P = [ 0 for _ in range(n+1) ]; P[0]=1
1080
pts.append(self(P))
1081
return pts
1082
1083
1084
#fix the pickles from moving projective_space.py
1085
from sage.structure.sage_object import register_unpickle_override
1086
register_unpickle_override('sage.schemes.generic.projective_space',
1087
'ProjectiveSpace_field',
1088
ProjectiveSpace_field)
1089
1090
register_unpickle_override('sage.schemes.generic.projective_space',
1091
'ProjectiveSpace_rational_field',
1092
ProjectiveSpace_rational_field)
1093
1094
1095