Path: blob/master/src/sage/schemes/projective/projective_space.py
8820 views
r"""1Projective `n` space over a ring23EXAMPLES: We construct projective space over various rings of4various dimensions.56The simplest projective space::78sage: ProjectiveSpace(0)9Projective Space of dimension 0 over Integer Ring1011A slightly bigger projective space over `\QQ`::1213sage: X = ProjectiveSpace(1000, QQ); X14Projective Space of dimension 1000 over Rational Field15sage: X.dimension()1610001718We can use "over" notation to create projective spaces over various19base rings.2021::2223sage: X = ProjectiveSpace(5)/QQ; X24Projective Space of dimension 5 over Rational Field25sage: X/CC26Projective Space of dimension 5 over Complex Field with 53 bits of precision2728The third argument specifies the printing names of the generators29of the homogenous coordinate ring. Using objgens() you can obtain30both the space and the generators as ready to use variables.3132::3334sage: P2, (x,y,z) = ProjectiveSpace(2, QQ, 'xyz').objgens()35sage: P236Projective Space of dimension 2 over Rational Field37sage: x.parent()38Multivariate Polynomial Ring in x, y, z over Rational Field3940For example, we use `x,y,z` to define the intersection of41two lines.4243::4445sage: V = P2.subscheme([x+y+z, x+y-z]); V46Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:47x + y + z,48x + y - z49sage: V.dimension()5005152AUTHORS:5354- Ben Hutz: (June 2012): support for rings55"""5657#*****************************************************************************58# Copyright (C) 2006 William Stein <[email protected]>59#60# Distributed under the terms of the GNU General Public License (GPL)61#62# http://www.gnu.org/licenses/63#*****************************************************************************6465from sage.rings.all import (PolynomialRing,66Integer,67ZZ)6869from sage.rings.ring import is_Ring70from sage.rings.rational_field import is_RationalField71from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing72from sage.rings.finite_rings.constructor import is_FiniteField73from sage.rings.commutative_ring import is_CommutativeRing7475from sage.categories.fields import Fields76_Fields = Fields()7778from sage.misc.all import (latex,79prod)80from sage.structure.parent_gens import normalize_names81from sage.rings.arith import (gcd,82binomial)83from sage.combinat.integer_vector import IntegerVectors84from sage.combinat.tuple import Tuples85from sage.matrix.constructor import matrix86from sage.modules.free_module_element import prepare8788from sage.schemes.generic.ambient_space import AmbientSpace89from sage.schemes.projective.projective_homset import (SchemeHomset_points_projective_ring,90SchemeHomset_points_projective_field)91from sage.schemes.projective.projective_point import (SchemeMorphism_point_projective_ring,92SchemeMorphism_point_projective_field,93SchemeMorphism_point_projective_finite_field)94from sage.schemes.projective.projective_morphism import (SchemeMorphism_polynomial_projective_space,95SchemeMorphism_polynomial_projective_space_field,96SchemeMorphism_polynomial_projective_space_finite_field)979899def is_ProjectiveSpace(x):100r"""101Return True if `x` is a projective space, i.e., an ambient space102`\mathbb{P}^n_R`, where `R` is a ring and `n\geq 0` is an103integer.104105EXAMPLES::106107sage: from sage.schemes.projective.projective_space import is_ProjectiveSpace108sage: is_ProjectiveSpace(ProjectiveSpace(5, names='x'))109True110sage: is_ProjectiveSpace(ProjectiveSpace(5, GF(9,'alpha'), names='x'))111True112sage: is_ProjectiveSpace(Spec(ZZ))113False114"""115return isinstance(x, ProjectiveSpace_ring)116117def ProjectiveSpace(n, R=None, names='x'):118r"""119Return projective space of dimension `n` over the ring `R`.120121EXAMPLES: The dimension and ring can be given in either order.122123::124125sage: ProjectiveSpace(3, QQ)126Projective Space of dimension 3 over Rational Field127sage: ProjectiveSpace(5, QQ)128Projective Space of dimension 5 over Rational Field129sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P130Projective Space of dimension 2 over Rational Field131sage: P.coordinate_ring()132Multivariate Polynomial Ring in X, Y, Z over Rational Field133134The divide operator does base extension.135136::137138sage: ProjectiveSpace(5)/GF(17)139Projective Space of dimension 5 over Finite Field of size 17140141The default base ring is `\ZZ`.142143::144145sage: ProjectiveSpace(5)146Projective Space of dimension 5 over Integer Ring147148There is also an projective space associated each polynomial ring.149150::151152sage: R = GF(7)['x,y,z']153sage: P = ProjectiveSpace(R); P154Projective Space of dimension 2 over Finite Field of size 7155sage: P.coordinate_ring()156Multivariate Polynomial Ring in x, y, z over Finite Field of size 7157sage: P.coordinate_ring() is R158True159160::161162sage: ProjectiveSpace(3, Zp(5), 'y')163Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20164165::166167sage: ProjectiveSpace(2,QQ,'x,y,z')168Projective Space of dimension 2 over Rational Field169170::171172sage: PS.<x,y>=ProjectiveSpace(1,CC)173sage: PS174Projective Space of dimension 1 over Complex Field with 53 bits of precision175176Projective spaces are not cached, i.e., there can be several with177the same base ring and dimension (to facilitate gluing178constructions).179"""180if is_MPolynomialRing(n) and R is None:181A = ProjectiveSpace(n.ngens()-1, n.base_ring())182A._coordinate_ring = n183return A184if isinstance(R, (int, long, Integer)):185n, R = R, n186if R is None:187R = ZZ # default is the integers188if R in _Fields:189if is_FiniteField(R):190return ProjectiveSpace_finite_field(n, R, names)191if is_RationalField(R):192return ProjectiveSpace_rational_field(n, R, names)193else:194return ProjectiveSpace_field(n, R, names)195elif is_CommutativeRing(R):196return ProjectiveSpace_ring(n, R, names)197else:198raise TypeError("R (=%s) must be a commutative ring"%R)199200class ProjectiveSpace_ring(AmbientSpace):201"""202Projective space of dimension `n` over the ring203`R`.204205EXAMPLES::206207sage: X.<x,y,z,w> = ProjectiveSpace(3, QQ)208sage: X.base_scheme()209Spectrum of Rational Field210sage: X.base_ring()211Rational Field212sage: X.structure_morphism()213Scheme morphism:214From: Projective Space of dimension 3 over Rational Field215To: Spectrum of Rational Field216Defn: Structure map217sage: X.coordinate_ring()218Multivariate Polynomial Ring in x, y, z, w over Rational Field219220Loading and saving::221222sage: loads(X.dumps()) == X223True224"""225def __init__(self, n, R=ZZ, names=None):226"""227EXAMPLES::228229sage: ProjectiveSpace(3, Zp(5), 'y')230Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20231"""232names = normalize_names(n+1, names)233AmbientSpace.__init__(self, n, R)234self._assign_names(names)235236def ngens(self):237"""238Return the number of generators of self, i.e. the number of239variables in the coordinate ring of self.240241EXAMPLES::242243sage: ProjectiveSpace(3, QQ).ngens()2444245sage: ProjectiveSpace(7, ZZ).ngens()2468247"""248return self.dimension_relative() + 1249250def _check_satisfies_equations(self, v):251"""252Return True if `v` defines a point on the scheme self; raise a253TypeError otherwise.254255EXAMPLES::256257sage: P = ProjectiveSpace(2, ZZ)258sage: P._check_satisfies_equations([1, 1, 0])259True260261::262263sage: P = ProjectiveSpace(1, QQ)264sage: P._check_satisfies_equations((1/2, 0))265True266267::268269sage: P = ProjectiveSpace(2, ZZ)270sage: P._check_satisfies_equations([0, 0, 0])271Traceback (most recent call last):272...273TypeError: The zero vector is not a point in projective space274275::276277sage: P = ProjectiveSpace(2, ZZ)278sage: P._check_satisfies_equations((1, 0))279Traceback (most recent call last):280...281TypeError: The list v=(1, 0) must have 3 components282283::284285sage: P = ProjectiveSpace(2, ZZ)286sage: P._check_satisfies_equations([1/2, 0, 1])287Traceback (most recent call last):288...289TypeError: The components of v=[1/2, 0, 1] must be elements of Integer Ring290"""291if not isinstance(v, (list, tuple)):292raise TypeError('The argument v=%s must be a list or tuple'%v)293n = self.ngens()294if not len(v) == n:295raise TypeError('The list v=%s must have %s components'%(v, n))296R = self.base_ring()297for coord in v:298if not coord in R:299raise TypeError('The components of v=%s must be elements of %s'%(v, R))300zero = [R(0)]*n301if v == zero:302raise TypeError('The zero vector is not a point in projective space')303return True304305def coordinate_ring(self):306"""307Return the coordinate ring of this scheme.308309EXAMPLES::310311sage: ProjectiveSpace(3, GF(19^2,'alpha'), 'abcd').coordinate_ring()312Multivariate Polynomial Ring in a, b, c, d over Finite Field in alpha of size 19^2313314::315316sage: ProjectiveSpace(3).coordinate_ring()317Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring318319::320321sage: ProjectiveSpace(2, QQ, ['alpha', 'beta', 'gamma']).coordinate_ring()322Multivariate Polynomial Ring in alpha, beta, gamma over Rational Field323"""324try:325return self._coordinate_ring326except AttributeError:327self._coordinate_ring = PolynomialRing(self.base_ring(),328self.variable_names(), self.dimension_relative()+1)329return self._coordinate_ring330331def _validate(self, polynomials):332"""333If ``polynomials`` is a tuple of valid polynomial functions on self,334return ``polynomials``, otherwise raise TypeError.335336Since this is a projective space, polynomials must be homogeneous.337338INPUT:339340- ``polynomials`` -- tuple of polynomials in the coordinate ring of341self342343OUTPUT:344345- tuple of polynomials in the coordinate ring of self346347EXAMPLES::348349sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)350sage: P._validate([x*y - z^2, x])351[x*y - z^2, x]352353::354355sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)356sage: P._validate((x*y - z, x))357Traceback (most recent call last):358...359TypeError: x*y - z is not a homogeneous polynomial!360361::362363sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)364sage: P._validate(x*y - z)365Traceback (most recent call last):366...367TypeError: The argument polynomials=x*y - z must be a list or tuple368"""369if not isinstance(polynomials, (list, tuple)):370raise TypeError('The argument polynomials=%s must be a list or tuple'%polynomials)371for f in polynomials:372if not f.is_homogeneous():373raise TypeError("%s is not a homogeneous polynomial!" % f)374return polynomials375376def __cmp__(self, right):377"""378EXAMPLES::379380sage: ProjectiveSpace(QQ, 3, 'a') == ProjectiveSpace(ZZ, 3, 'a')381False382sage: ProjectiveSpace(ZZ, 1, 'a') == ProjectiveSpace(ZZ, 0, 'a')383False384sage: ProjectiveSpace(ZZ, 2, 'a') == AffineSpace(ZZ, 2, 'a')385False386sage: loads(AffineSpace(ZZ, 1, 'x').dumps()) == AffineSpace(ZZ, 1, 'x')387True388"""389if not isinstance(right, ProjectiveSpace_ring):390return -1391return cmp([self.dimension_relative(), self.coordinate_ring()],392[right.dimension_relative(), right.coordinate_ring()])393394def _latex_(self):395r"""396Return a LaTeX representation of this projective space.397398EXAMPLES::399400sage: print latex(ProjectiveSpace(1, ZZ, 'x'))401{\mathbf P}_{\Bold{Z}}^1402403TESTS::404405sage: ProjectiveSpace(3, Zp(5), 'y')._latex_()406'{\\mathbf P}_{\\ZZ_{5}}^3'407"""408return "{\\mathbf P}_{%s}^%s"%(latex(self.base_ring()), self.dimension_relative())409410def _linear_system_as_kernel(self, d, pt, m):411"""412Return a matrix whose kernel consists of the coefficient vectors413of the degree d hypersurfaces (wrt lexicographic ordering of its414monomials) with multiplicity at least m at pt.415416INPUT:417418- ``d`` -- a nonnegative integer419420- ``pt`` -- a point of self (possibly represented by a list with at \421least one component equal to 1)422423- ``m`` -- a nonnegative integer424425OUTPUT:426427A matrix of size `{m-1+n \choose n}` x `{d+n \choose n}` where n is the428relative dimension of self. The base ring of the matrix is a ring that429contains the base ring of self and the coefficients of the given point.430431EXAMPLES:432433If the degree `d` is 0, then a matrix consisting of the first unit vector434is returned::435436sage: P = ProjectiveSpace(GF(5), 2, names='x')437sage: pt = P([1, 1, 1])438sage: P._linear_system_as_kernel(0, pt, 3)439[1]440[0]441[0]442[0]443[0]444[0]445446If the multiplcity `m` is 0, then the a matrix with zero rows is returned::447448sage: P = ProjectiveSpace(GF(5), 2, names='x')449sage: pt = P([1, 1, 1])450sage: M = P._linear_system_as_kernel(2, pt, 0)451sage: [M.nrows(), M.ncols()]452[0, 6]453454The base ring does not need to be a field or even an integral domain.455In this case, the point can be given by a list::456457sage: R = Zmod(4)458sage: P = ProjectiveSpace(R, 2, names='x')459sage: pt = [R(1), R(3), R(0)]460sage: P._linear_system_as_kernel(3, pt, 2)461[1 3 0 1 0 0 3 0 0 0]462[0 1 0 2 0 0 3 0 0 0]463[0 0 1 0 3 0 0 1 0 0]464465When representing a point by a list at least one component must be 1466(even when the base ring is a field and the list gives a well-defined467point in projective space)::468469sage: R = GF(5)470sage: P = ProjectiveSpace(R, 2, names='x')471sage: pt = [R(3), R(3), R(0)]472sage: P._linear_system_as_kernel(3, pt, 2)473Traceback (most recent call last):474...475TypeError: At least one component of pt=[3, 3, 0] must be equal476to 1477478The components of the list do not have to be elements of the base ring479of the projective space. It suffices if there exists a common parent.480For example, the kernel of the following matrix corresponds to481hypersurfaces of degree 2 in 3-space with multiplicity at least 2 at a482general point in the third affine patch::483484sage: P = ProjectiveSpace(QQ,3,names='x')485sage: RPol.<t0,t1,t2,t3> = PolynomialRing(QQ,4)486sage: pt = [t0,t1,1,t3]487sage: P._linear_system_as_kernel(2,pt,2)488[ 2*t0 t1 1 t3 0 0 0 0 0 0]489[ 0 t0 0 0 2*t1 1 t3 0 0 0]490[ t0^2 t0*t1 t0 t0*t3 t1^2 t1 t1*t3 1 t3 t3^2]491[ 0 0 0 t0 0 0 t1 0 1 2*t3]492493.. TODO::494495Use this method as starting point to implement a class496LinearSystem for linear systems of hypersurfaces.497498"""499if not isinstance(d, (int, Integer)):500raise TypeError('The argument d=%s must be an integer'%d)501if d < 0:502raise ValueError('The integer d=%s must be nonnegative'%d)503if not isinstance(pt, (list, tuple, \504SchemeMorphism_point_projective_ring)):505raise TypeError('The argument pt=%s must be a list, tuple, or '506'point on a projective space'%pt)507pt, R = prepare(pt, None)508n = self.dimension_relative()509if not len(pt) == n+1:510raise TypeError('The sequence pt=%s must have %s '511'components'%(pt, n + 1))512if not R.has_coerce_map_from(self.base_ring()):513raise TypeError('Unable to find a common ring for all elements')514try:515i = pt.index(1)516except Exception:517raise TypeError('At least one component of pt=%s must be equal '518'to 1'%pt)519pt = pt[:i] + pt[i+1:]520if not isinstance(m, (int, Integer)):521raise TypeError('The argument m=%s must be an integer'%m)522if m < 0:523raise ValueError('The integer m=%s must be nonnegative'%m)524# the components of partials correspond to partial derivatives525# of order at most m-1 with respect to n variables526partials = IntegerVectors(m-1,n+1).list()527# the components of monoms correspond to monomials of degree528# at most d in n variables529monoms = IntegerVectors(d,n+1).list()530M = matrix(R,len(partials),len(monoms))531for row in range(M.nrows()):532e = partials[row][:i] + partials[row][i+1:]533for col in range(M.ncols()):534f = monoms[col][:i] + monoms[col][i+1:]535if min([f[j]-e[j] for j in range(n)]) >= 0:536M[row,col] = prod([binomial(f[j],e[j])*pt[j]**(f[j]-e[j]) \537for j in filter(lambda k: f[k]>e[k], range(n))])538return M539540def _morphism(self, *args, **kwds):541"""542Construct a morphism.543544For internal use only. See :mod:`morphism` for details.545546TESTS::547548sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))549sage: P2._morphism(P2.Hom(P2), [x,y,z])550Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3551Defn: Defined on coordinates by sending (x : y : z) to552(x : y : z)553"""554return SchemeMorphism_polynomial_projective_space(*args, **kwds)555556def _point_homset(self, *args, **kwds):557"""558Construct a point Hom-set.559560For internal use only. See :mod:`morphism` for details.561562TESTS::563564sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))565sage: P2._point_homset(Spec(GF(3)), P2)566Set of rational points of Projective Space of dimension 2 over Finite Field of size 3567"""568return SchemeHomset_points_projective_ring(*args, **kwds)569570def _point(self, *args, **kwds):571"""572Construct a point.573574For internal use only. See :mod:`morphism` for details.575576TESTS::577578sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))579sage: point_homset = P2._point_homset(Spec(GF(3)), P2)580sage: P2._point(point_homset, [1,2,3])581(2 : 1 : 0)582"""583return SchemeMorphism_point_projective_ring(*args, **kwds)584585def _repr_(self):586"""587Return a string representation of this projective space.588589EXAMPLES::590591sage: ProjectiveSpace(1, ZZ, 'x')592Projective Space of dimension 1 over Integer Ring593594TESTS::595596sage: ProjectiveSpace(3, Zp(5), 'y')._repr_()597'Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20'598"""599return "Projective Space of dimension %s over %s"%(self.dimension_relative(), self.base_ring())600601def _repr_generic_point(self, v=None):602"""603Return a string representation of the generic point604corresponding to the list of polys on this projective space.605606If polys is None, the representation of the generic point of607the projective space is returned.608609EXAMPLES::610611sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)612sage: P._repr_generic_point([z*y-x^2])613'(-x^2 + y*z)'614sage: P._repr_generic_point()615'(x : y : z)'616"""617if v is None:618v = self.gens()619return '(%s)'%(" : ".join([repr(f) for f in v]))620621def _latex_generic_point(self, v=None):622"""623Return a LaTeX representation of the generic point624corresponding to the list of polys on this projective space.625626If polys is None, the representation of the generic point of627the projective space is returned.628629EXAMPLES::630631sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)632sage: P._latex_generic_point([z*y-x^2])633'\\left(- x^{2} + y z\\right)'634sage: P._latex_generic_point()635'\\left(x : y : z\\right)'636"""637if v is None:638v = self.gens()639return '\\left(%s\\right)'%(" : ".join([str(latex(f)) for f in v]))640641def change_ring(self, R):642r"""643Return a projective space over ring `R` and otherwise the same as self.644645INPUT:646647- ``R`` -- commutative ring648649OUTPUT:650651- projective space over ``R``652653.. NOTE::654655There is no need to have any relation between `R` and the base ring656of self, if you want to have such a relation, use657``self.base_extend(R)`` instead.658659EXAMPLES::660661sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)662sage: PQ = P.change_ring(QQ); PQ663Projective Space of dimension 2 over Rational Field664sage: PQ.change_ring(GF(5))665Projective Space of dimension 2 over Finite Field of size 5666"""667return ProjectiveSpace(self.dimension_relative(), R,668self.variable_names())669670def is_projective(self):671"""672Return that this ambient space is projective n-space.673674EXAMPLES::675676sage: ProjectiveSpace(3,QQ).is_projective()677True678"""679return True680681def subscheme(self, X):682"""683Return the closed subscheme defined by X.684685INPUT:686687- ``X`` - a list or tuple of equations688689EXAMPLES::690691sage: A.<x,y,z> = ProjectiveSpace(2, QQ)692sage: X = A.subscheme([x*z^2, y^2*z, x*y^2]); X693Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:694x*z^2,695y^2*z,696x*y^2697sage: X.defining_polynomials ()698(x*z^2, y^2*z, x*y^2)699sage: I = X.defining_ideal(); I700Ideal (x*z^2, y^2*z, x*y^2) of Multivariate Polynomial Ring in x, y, z over Rational Field701sage: I.groebner_basis()702[x*y^2, y^2*z, x*z^2]703sage: X.dimension()7040705sage: X.base_ring()706Rational Field707sage: X.base_scheme()708Spectrum of Rational Field709sage: X.structure_morphism()710Scheme morphism:711From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:712x*z^2,713y^2*z,714x*y^2715To: Spectrum of Rational Field716Defn: Structure map717718sage: 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"])719"""720from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_projective721return AlgebraicScheme_subscheme_projective(self, X)722723def affine_patch(self, i):724r"""725Return the `i^{th}` affine patch of this projective space.726This is an ambient affine space `\mathbb{A}^n_R,` where727`R` is the base ring of self, whose "projective embedding"728map is `1` in the `i^{th}` factor.729730INPUT:731732- ``i`` -- integer between 0 and dimension of self, inclusive.733734OUTPUT:735736- An ambient affine space with fixed projective_embedding map.737738EXAMPLES::739740sage: PP = ProjectiveSpace(5) / QQ741sage: AA = PP.affine_patch(2)742sage: AA743Affine Space of dimension 5 over Rational Field744sage: AA.projective_embedding()745Scheme morphism:746From: Affine Space of dimension 5 over Rational Field747To: Projective Space of dimension 5 over Rational Field748Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to749(x0 : x1 : 1 : x2 : x3 : x4)750sage: AA.projective_embedding(0)751Scheme morphism:752From: Affine Space of dimension 5 over Rational Field753To: Projective Space of dimension 5 over Rational Field754Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to755(1 : x0 : x1 : x2 : x3 : x4)756"""757i = int(i) # implicit type checking758n = self.dimension_relative()759if i < 0 or i > n:760raise ValueError("Argument i (= %s) must be between 0 and %s."%(i, n))761try:762return self.__affine_patches[i]763except AttributeError:764self.__affine_patches = {}765except KeyError:766pass767from sage.schemes.affine.affine_space import AffineSpace768AA = AffineSpace(n, self.base_ring(), names='x')769AA._default_embedding_index = i770phi = AA.projective_embedding(i, self)771self.__affine_patches[i] = AA772return AA773774def _an_element_(self):775r"""776Returns a (preferably typical) element of ``self``.777778This is used both for illustration and testing purposes.779780OUTPUT: a point in the projective space ``self``.781782EXAMPLES::783784sage: ProjectiveSpace(ZZ,3,'x').an_element()785(7 : 6 : 5 : 1)786787sage: ProjectiveSpace(PolynomialRing(ZZ,'y'),3,'x').an_element()788(7*y : 6*y : 5*y : 1)789"""790n = self.dimension_relative()791R = self.base_ring()792return self([(7 - i) * R.an_element() for i in range(n)] + [R.one()])793794795class ProjectiveSpace_field(ProjectiveSpace_ring):796def _point_homset(self, *args, **kwds):797"""798Construct a point Hom-set.799800For internal use only. See :mod:`morphism` for details.801802TESTS::803804sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))805sage: P2._point_homset(Spec(GF(3)), P2)806Set of rational points of Projective Space of dimension 2 over Finite Field of size 3807"""808return SchemeHomset_points_projective_field(*args, **kwds)809810def _point(self, *args, **kwds):811"""812Construct a point.813814For internal use only. See :mod:`morphism` for details.815816TESTS::817818sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))819sage: point_homset = P2._point_homset(Spec(GF(3)), P2)820sage: P2._point(point_homset, [1,2,3])821(2 : 1 : 0)822"""823return SchemeMorphism_point_projective_field(*args, **kwds)824825def _morphism(self, *args, **kwds):826"""827Construct a morphism.828829For internal use only. See :mod:`morphism` for details.830831TESTS::832833sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))834sage: P2._morphism(P2.Hom(P2), [x,y,z])835Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3836Defn: Defined on coordinates by sending (x : y : z) to837(x : y : z)838"""839return SchemeMorphism_polynomial_projective_space_field(*args, **kwds)840841class ProjectiveSpace_finite_field(ProjectiveSpace_field):842def _point(self, *args, **kwds):843"""844Construct a point.845846For internal use only. See :mod:`morphism` for details.847848TESTS::849850sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))851sage: point_homset = P2._point_homset(Spec(GF(3)), P2)852sage: P2._point(point_homset, [1,2,3])853(2 : 1 : 0)854"""855return SchemeMorphism_point_projective_finite_field(*args, **kwds)856857def _morphism(self, *args, **kwds):858"""859Construct a morphism.860861For internal use only. See :mod:`morphism` for details.862863TESTS::864865sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))866sage: P2._morphism(P2.Hom(P2), [x,y,z])867Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3868Defn: Defined on coordinates by sending (x : y : z) to869(x : y : z)870"""871return SchemeMorphism_polynomial_projective_space_finite_field(*args, **kwds)872873874def __iter__(self):875r"""876Return iterator over the elements of this projective space.877878Note that iteration is over the decomposition879`\mathbb{P}^n = \mathbb{A}A^n \cup \mathbb{P}^n-1`, where880`\mathbb{A}A^n` is the `n`-th affine patch and881`\mathbb{P}^n-1` is the hyperplane at infinity882`x_n = 0`.883884EXAMPLES::885886sage: FF = FiniteField(3)887sage: PP = ProjectiveSpace(0,FF)888sage: [ x for x in PP ]889[(1)]890sage: PP = ProjectiveSpace(1,FF)891sage: [ x for x in PP ]892[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]893sage: PP = ProjectiveSpace(2,FF)894sage: [ x for x in PP ]895[(0 : 0 : 1),896(1 : 0 : 1),897(2 : 0 : 1),898(0 : 1 : 1),899(1 : 1 : 1),900(2 : 1 : 1),901(0 : 2 : 1),902(1 : 2 : 1),903(2 : 2 : 1),904(0 : 1 : 0),905(1 : 1 : 0),906(2 : 1 : 0),907(1 : 0 : 0)]908909AUTHORS:910911- David Kohel912913.. TODO::914915Iteration for point sets over finite fields, and return of916iter of point set over base field. Note that the point set does not917know whether this is a projective space or subscheme.918"""919n = self.dimension_relative()920R = self.base_ring()921zero = R(0)922i = n923while not i < 0:924P = [ zero for _ in range(i) ] + [ R(1) ] + [ zero for _ in range(n-i) ]925yield self(P)926iters = [ iter(R) for _ in range(i) ]927for x in iters: x.next() # put at zero928j = 0929while j < i:930try:931P[j] = iters[j].next()932yield self(P)933j = 0934except StopIteration:935iters[j] = iter(R) # reset936iters[j].next() # put at zero937P[j] = zero938j += 1939i -= 1940941def rational_points(self, F=None):942"""943Return the list of `F`-rational points on the affine space self,944where `F` is a given finite field, or the base ring of self.945946EXAMPLES::947948sage: P = ProjectiveSpace(1, GF(3))949sage: P.rational_points()950[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]951sage: P.rational_points(GF(3^2, 'b'))952[(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)]953"""954if F == None:955return [ P for P in self ]956elif not is_FiniteField(F):957raise TypeError("Second argument (= %s) must be a finite field."%F)958return [ P for P in self.base_extend(F) ]959960def rational_points_dictionary(self):961r"""962Return dictionary of points.963964OUTPUT:965966- dictionary967968EXAMPLES::969970sage: P1=ProjectiveSpace(GF(7),1,'x')971sage: P1.rational_points_dictionary()972{(1 : 0): 7, (0 : 1): 0, (1 : 1): 1, (2 : 1): 2, (3 : 1): 3, (4 : 1): 4,973(5 : 1): 5, (6 : 1): 6}974"""975n = self.dimension_relative()976R = self.base_ring()977D={}978zero = R(0)979i = n980index=0981while not i < 0:982P = [ zero for _ in range(i) ] + [ R(1) ] + [ zero for _ in range(n-i) ]983D.update({self(P):index})984index+=1985iters = [ iter(R) for _ in range(i) ]986for x in iters: x.next() # put at zero987j = 0988while j < i:989try:990P[j] = iters[j].next()991D.update({self(P):index})992index+=1993j = 0994except StopIteration:995iters[j] = iter(R) # reset996iters[j].next() # put at zero997P[j] = zero998j += 1999i -= 11000return(D)10011002class ProjectiveSpace_rational_field(ProjectiveSpace_field):1003def rational_points(self,bound=0):1004r"""1005Returns the projective points `(x_0:\cdots:x_n)` over1006`\QQ` with `|x_i| \leq` bound.10071008INPUT:100910101011- ``bound`` - integer101210131014EXAMPLES::10151016sage: PP = ProjectiveSpace(0,QQ)1017sage: PP.rational_points(1)1018[(1)]1019sage: PP = ProjectiveSpace(1,QQ)1020sage: PP.rational_points(2)1021[(-2 : 1), (-1 : 1), (0 : 1), (1 : 1), (2 : 1), (-1/2 : 1), (1/2 : 1), (1 : 0)]1022sage: PP = ProjectiveSpace(2,QQ)1023sage: PP.rational_points(2)1024[(-2 : -2 : 1), (-1 : -2 : 1), (0 : -2 : 1), (1 : -2 : 1), (2 : -2 : 1),1025(-2 : -1 : 1), (-1 : -1 : 1), (0 : -1 : 1), (1 : -1 : 1), (2 : -1 : 1),1026(-2 : 0 : 1), (-1 : 0 : 1), (0 : 0 : 1), (1 : 0 : 1), (2 : 0 : 1), (-2 :10271 : 1), (-1 : 1 : 1), (0 : 1 : 1), (1 : 1 : 1), (2 : 1 : 1), (-2 : 2 :10281), (-1 : 2 : 1), (0 : 2 : 1), (1 : 2 : 1), (2 : 2 : 1), (-1/2 : -1 :10291), (1/2 : -1 : 1), (-1 : -1/2 : 1), (-1/2 : -1/2 : 1), (0 : -1/2 : 1),1030(1/2 : -1/2 : 1), (1 : -1/2 : 1), (-1/2 : 0 : 1), (1/2 : 0 : 1), (-1 :10311/2 : 1), (-1/2 : 1/2 : 1), (0 : 1/2 : 1), (1/2 : 1/2 : 1), (1 : 1/2 :10321), (-1/2 : 1 : 1), (1/2 : 1 : 1), (-2 : 1 : 0), (-1 : 1 : 0), (0 : 1 :10330), (1 : 1 : 0), (2 : 1 : 0), (-1/2 : 1 : 0), (1/2 : 1 : 0), (1 : 0 :10340)]103510361037.. note::10381039The very simple algorithm works as follows: every point1040`(x_0:\cdots:x_n)` in projective space has a unique1041largest index `i` for which `x_i` is not1042zero. The algorithm then iterates downward on this1043index. We normalize by choosing `x_i` positive. Then,1044the points `x_0,\ldots,x_{i-1}` are the points of1045affine `i`-space that are relatively prime to1046`x_i`. We access these by using the Tuples method.10471048AUTHORS:10491050- Benjamin Antieau (2008-01-12)1051"""1052if not bound > 0:1053raise ValueError("Argument bound (= %s) must be a positive integer.")10541055n = self.dimension_relative()105610571058Q = [ k-bound for k in range(2*bound+1) ] # the affine coordinates1059R = [ (k+1) for k in range(bound) ] # the projective coordinate1060S = [ Tuples(Q,(k+1)) for k in range(n) ]1061pts = []10621063i=n10641065while i > 0:1066P = [ 0 for _ in range(n+1) ]1067for ai in R:1068P[i]=ai1069for tup in S[i-1]:1070if gcd([ai]+tup)==1:1071for j in range(i):1072P[j]=tup[j]1073pts.append(self(P))1074i-=110751076# now do i=0; this is treated as a special case so that1077# we don't have all points (1:0),(2,0),(3,0),etc.1078P = [ 0 for _ in range(n+1) ]; P[0]=11079pts.append(self(P))1080return pts108110821083#fix the pickles from moving projective_space.py1084from sage.structure.sage_object import register_unpickle_override1085register_unpickle_override('sage.schemes.generic.projective_space',1086'ProjectiveSpace_field',1087ProjectiveSpace_field)10881089register_unpickle_override('sage.schemes.generic.projective_space',1090'ProjectiveSpace_rational_field',1091ProjectiveSpace_rational_field)1092109310941095