Path: blob/master/sage/schemes/generic/projective_space.py
4069 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()50051"""5253#*****************************************************************************54# Copyright (C) 2006 William Stein <[email protected]>55#56# Distributed under the terms of the GNU General Public License (GPL)57#58# http://www.gnu.org/licenses/59#*****************************************************************************6061from sage.rings.all import (PolynomialRing,62is_Field,63is_FiniteField,64is_RationalField,65is_Ring,66is_CommutativeRing,67is_MPolynomialRing,68Integer,69ZZ)7071from sage.misc.all import latex72from sage.structure.parent_gens import normalize_names73from sage.rings.arith import gcd74from sage.combinat.tuple import Tuples7576from ambient_space import AmbientSpace77import homset78import morphism798081def is_ProjectiveSpace(x):82r"""83Return True if `x` is a projective space, i.e., an ambient space84`\mathbb{P}^n_R`, where `R` is a ring and `n\geq 0` is an85integer.8687EXAMPLES::8889sage: from sage.schemes.generic.projective_space import is_ProjectiveSpace90sage: is_ProjectiveSpace(ProjectiveSpace(5, names='x'))91True92sage: is_ProjectiveSpace(ProjectiveSpace(5, GF(9,'alpha'), names='x'))93True94sage: is_ProjectiveSpace(Spec(ZZ))95False96"""97return isinstance(x, ProjectiveSpace_ring)9899def ProjectiveSpace(n, R=None, names='x'):100r"""101Return projective space of dimension `n` over the ring `R`.102103EXAMPLES: The dimension and ring can be given in either order.104105::106107sage: ProjectiveSpace(3, QQ)108Projective Space of dimension 3 over Rational Field109sage: ProjectiveSpace(5, QQ)110Projective Space of dimension 5 over Rational Field111sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P112Projective Space of dimension 2 over Rational Field113sage: P.coordinate_ring()114Multivariate Polynomial Ring in X, Y, Z over Rational Field115116The divide operator does base extension.117118::119120sage: ProjectiveSpace(5)/GF(17)121Projective Space of dimension 5 over Finite Field of size 17122123The default base ring is `\ZZ`.124125::126127sage: ProjectiveSpace(5)128Projective Space of dimension 5 over Integer Ring129130There is also an projective space associated each polynomial ring.131132::133134sage: R = GF(7)['x,y,z']135sage: P = ProjectiveSpace(R); P136Projective Space of dimension 2 over Finite Field of size 7137sage: P.coordinate_ring()138Multivariate Polynomial Ring in x, y, z over Finite Field of size 7139sage: P.coordinate_ring() is R140True141142Projective spaces are not cached, i.e., there can be several with143the same base ring and dimension (to facilitate gluing144constructions).145"""146if is_MPolynomialRing(n) and R is None:147A = ProjectiveSpace(n.ngens()-1, n.base_ring())148A._coordinate_ring = n149return A150if isinstance(R, (int, long, Integer)):151n, R = R, n152if R is None:153R = ZZ # default is the integers154if is_Field(R):155if is_FiniteField(R):156return ProjectiveSpace_finite_field(n, R, names)157if is_RationalField(R):158return ProjectiveSpace_rational_field(n, R, names)159else:160return ProjectiveSpace_field(n, R, names)161elif is_CommutativeRing(R):162return ProjectiveSpace_ring(n, R, names)163else:164raise TypeError, "R (=%s) must be a commutative ring"%R165166class ProjectiveSpace_ring(AmbientSpace):167"""168Projective space of dimension `n` over the ring169`R`.170171EXAMPLES::172173sage: X.<x,y,z,w> = ProjectiveSpace(3, QQ)174sage: X.base_scheme()175Spectrum of Rational Field176sage: X.base_ring()177Rational Field178sage: X.structure_morphism()179Scheme morphism:180From: Projective Space of dimension 3 over Rational Field181To: Spectrum of Rational Field182Defn: Structure map183sage: X.coordinate_ring()184Multivariate Polynomial Ring in x, y, z, w over Rational Field185186Loading and saving::187188sage: loads(X.dumps()) == X189True190"""191def __init__(self, n, R=ZZ, names=None):192"""193EXAMPLES::194195sage: ProjectiveSpace(3, Zp(5), 'y')196Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20197"""198names = normalize_names(n+1, names)199AmbientSpace.__init__(self, n, R)200self._assign_names(names)201202def ngens(self):203"""204Return the number of generators of self, i.e. the number of205variables in the coordinate ring of self.206207EXAMPLES::208209sage: ProjectiveSpace(3, QQ).ngens()2104211sage: ProjectiveSpace(7, ZZ).ngens()2128213"""214return self.dimension_relative() + 1215216def _check_satisfies_equations(self, v):217"""218Return True if `v` defines a point on the scheme self; raise a219TypeError otherwise.220221EXAMPLES::222223sage: P = ProjectiveSpace(2, ZZ)224sage: P._check_satisfies_equations([1, 1, 0])225True226sage: P._check_satisfies_equations((0, 1, 0))227True228sage: P._check_satisfies_equations([0, 0, 0])229Traceback (most recent call last):230...231TypeError: The zero vector is not a point in projective space232sage: P._check_satisfies_equations([1, 2, 3, 4, 5])233Traceback (most recent call last):234...235TypeError: The list v=[1, 2, 3, 4, 5] must have 3 components236sage: P._check_satisfies_equations([1/2, 1, 1])237Traceback (most recent call last):238...239TypeError: The components of v=[1/2, 1, 1] must be elements of Integer Ring240sage: P._check_satisfies_equations(5)241Traceback (most recent call last):242...243TypeError: The argument v=5 must be a list or tuple244"""245if not isinstance(v, (list, tuple)):246raise TypeError, 'The argument v=%s must be a list or tuple'%v247n = self.ngens()248if not len(v) == n:249raise TypeError, 'The list v=%s must have %s components'%(v, n)250R = self.base_ring()251for coord in v:252if not coord in R:253raise TypeError, 'The components of v=%s must be elements of %s'%(v, R)254zero = [R(0)]*n255if v == zero:256raise TypeError, 'The zero vector is not a point in projective space'257return True258259def coordinate_ring(self):260"""261Return the coordinate ring of this scheme.262263EXAMPLES::264265sage: ProjectiveSpace(3, GF(19^2,'alpha'), 'abcd').coordinate_ring()266Multivariate Polynomial Ring in a, b, c, d over Finite Field in alpha of size 19^2267268::269270sage: ProjectiveSpace(3).coordinate_ring()271Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring272273::274275sage: ProjectiveSpace(2, QQ, ['alpha', 'beta', 'gamma']).coordinate_ring()276Multivariate Polynomial Ring in alpha, beta, gamma over Rational Field277"""278try:279return self._coordinate_ring280except AttributeError:281self._coordinate_ring = PolynomialRing(self.base_ring(),282self.variable_names(), self.dimension_relative()+1)283return self._coordinate_ring284285def _validate(self, polynomials):286"""287If ``polynomials`` is a tuple of valid polynomial functions on self,288return ``polynomials``, otherwise raise TypeError.289290Since this is a projective space, polynomials must be homogeneous.291292INPUT:293294- ``polynomials`` -- tuple of polynomials in the coordinate ring of295self296297OUTPUT:298299- tuple of polynomials in the coordinate ring of self300301EXAMPLES::302303sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)304sage: P._validate((x*y - z^2, x))305(x*y - z^2, x)306sage: P._validate((x*y - z, x))307Traceback (most recent call last):308...309TypeError: x*y - z is not a homogeneous polynomial!310"""311for f in polynomials:312if not f.is_homogeneous():313raise TypeError("%s is not a homogeneous polynomial!" % f)314return polynomials315316def __cmp__(self, right):317"""318EXAMPLES::319320sage: ProjectiveSpace(QQ, 3, 'a') == ProjectiveSpace(ZZ, 3, 'a')321False322sage: ProjectiveSpace(ZZ, 1, 'a') == ProjectiveSpace(ZZ, 0, 'a')323False324sage: ProjectiveSpace(ZZ, 2, 'a') == AffineSpace(ZZ, 2, 'a')325False326sage: loads(AffineSpace(ZZ, 1, 'x').dumps()) == AffineSpace(ZZ, 1, 'x')327True328"""329if not isinstance(right, ProjectiveSpace_ring):330return -1331return cmp([self.dimension_relative(), self.coordinate_ring()],332[right.dimension_relative(), right.coordinate_ring()])333334def _latex_(self):335r"""336Return a LaTeX representation of this projective space.337338EXAMPLES::339340sage: print latex(ProjectiveSpace(1, ZZ, 'x'))341{\mathbf P}_{\Bold{Z}}^1342343TESTS::344345sage: ProjectiveSpace(3, Zp(5), 'y')._latex_()346'{\\mathbf P}_{\\ZZ_{5}}^3'347"""348return "{\\mathbf P}_{%s}^%s"%(latex(self.base_ring()), self.dimension_relative())349350def _morphism(self, *args, **kwds):351"""352Construct a morphism.353354For internal use only. See :mod:`morphism` for details.355356TESTS::357358sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))359sage: P2._morphism(P2.Hom(P2), [x,y,z])360Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3361Defn: Defined on coordinates by sending (x : y : z) to362(x : y : z)363"""364return morphism.SchemeMorphism_polynomial_projective_space(*args, **kwds)365366def _point_homset(self, *args, **kwds):367"""368Construct a point Hom-set.369370For internal use only. See :mod:`morphism` for details.371372TESTS::373374sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))375sage: P2._point_homset(Spec(GF(3)), P2)376Set of rational points of Projective Space of dimension 2 over Finite Field of size 3377"""378return homset.SchemeHomset_points_projective_ring(*args, **kwds)379380def _point(self, *args, **kwds):381"""382Construct a point.383384For internal use only. See :mod:`morphism` for details.385386TESTS::387388sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))389sage: point_homset = P2._point_homset(Spec(GF(3)), P2)390sage: P2._point(point_homset, [1,2,3])391(2 : 1 : 0)392"""393return morphism.SchemeMorphism_point_projective_ring(*args, **kwds)394395def _repr_(self):396"""397Return a string representation of this projective space.398399EXAMPLES::400401sage: ProjectiveSpace(1, ZZ, 'x')402Projective Space of dimension 1 over Integer Ring403404TESTS::405406sage: ProjectiveSpace(3, Zp(5), 'y')._repr_()407'Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20'408"""409return "Projective Space of dimension %s over %s"%(self.dimension_relative(), self.base_ring())410411def _repr_generic_point(self, v=None):412"""413Return a string representation of the generic point414corresponding to the list of polys on this projective space.415416If polys is None, the representation of the generic point of417the projective space is returned.418419EXAMPLES::420421sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)422sage: P._repr_generic_point([z*y-x^2])423'(-x^2 + y*z)'424sage: P._repr_generic_point()425'(x : y : z)'426"""427if v is None:428v = self.gens()429return '(%s)'%(" : ".join([repr(f) for f in v]))430431def _latex_generic_point(self, v=None):432"""433Return a LaTeX representation of the generic point434corresponding to the list of polys on this projective space.435436If polys is None, the representation of the generic point of437the projective space is returned.438439EXAMPLES::440441sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)442sage: P._latex_generic_point([z*y-x^2])443'\\left(- x^{2} + y z\\right)'444sage: P._latex_generic_point()445'\\left(x : y : z\\right)'446"""447if v is None:448v = self.gens()449return '\\left(%s\\right)'%(" : ".join([str(latex(f)) for f in v]))450451def change_ring(self, R):452r"""453Return a projective space over ring `R` and otherwise the same as self.454455INPUT:456457- ``R`` -- commutative ring458459OUTPUT:460461- projective space over ``R``462463.. NOTE::464465There is no need to have any relation between `R` and the base ring466of self, if you want to have such a relation, use467``self.base_extend(R)`` instead.468469EXAMPLES::470471sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)472sage: PQ = P.change_ring(QQ); PQ473Projective Space of dimension 2 over Rational Field474sage: PQ.change_ring(GF(5))475Projective Space of dimension 2 over Finite Field of size 5476"""477return ProjectiveSpace(self.dimension_relative(), R,478self.variable_names())479480def is_projective(self):481"""482Return that this ambient space is projective n-space.483484EXAMPLES::485486sage: ProjectiveSpace(3,QQ).is_projective()487True488"""489return True490491def subscheme(self, X):492"""493Return the closed subscheme defined by X.494495INPUT:496497- ``X`` - a list or tuple of equations498499EXAMPLES::500501sage: A.<x,y,z> = ProjectiveSpace(2, QQ)502sage: X = A.subscheme([x*z^2, y^2*z, x*y^2]); X503Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:504x*z^2,505y^2*z,506x*y^2507sage: X.defining_polynomials ()508(x*z^2, y^2*z, x*y^2)509sage: I = X.defining_ideal(); I510Ideal (x*z^2, y^2*z, x*y^2) of Multivariate Polynomial Ring in x, y, z over Rational Field511sage: I.groebner_basis()512[x*y^2, y^2*z, x*z^2]513sage: X.dimension()5140515sage: X.base_ring()516Rational Field517sage: X.base_scheme()518Spectrum of Rational Field519sage: X.structure_morphism()520Scheme morphism:521From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:522x*z^2,523y^2*z,524x*y^2525To: Spectrum of Rational Field526Defn: Structure map527528sage: TestSuite(X).run(skip=["_test_an_element", "_test_elements", "_test_elements_eq", "_test_some_elements"])529"""530from algebraic_scheme import AlgebraicScheme_subscheme_projective531return AlgebraicScheme_subscheme_projective(self, X)532533def affine_patch(self, i):534r"""535Return the `i^{th}` affine patch of this projective space.536This is an ambient affine space `\mathbb{A}^n_R,` where537`R` is the base ring of self, whose "projective embedding"538map is `1` in the `i^{th}` factor.539540INPUT:541542- ``i`` -- integer between 0 and dimension of self, inclusive.543544OUTPUT:545546An ambient affine space with fixed projective_embedding map.547548EXAMPLES::549550sage: PP = ProjectiveSpace(5) / QQ551sage: AA = PP.affine_patch(2)552sage: AA553Affine Space of dimension 5 over Rational Field554sage: AA.projective_embedding()555Scheme morphism:556From: Affine Space of dimension 5 over Rational Field557To: Projective Space of dimension 5 over Rational Field558Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to559(x0 : x1 : 1 : x2 : x3 : x4)560sage: AA.projective_embedding(0)561Scheme morphism:562From: Affine Space of dimension 5 over Rational Field563To: Projective Space of dimension 5 over Rational Field564Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to565(1 : x0 : x1 : x2 : x3 : x4)566"""567i = int(i) # implicit type checking568n = self.dimension_relative()569if i < 0 or i > n:570raise ValueError, "Argument i (= %s) must be between 0 and %s."%(i, n)571try:572return self.__affine_patches[i]573except AttributeError:574self.__affine_patches = {}575except KeyError:576pass577from sage.schemes.generic.affine_space import AffineSpace578AA = AffineSpace(n, self.base_ring(), names='x')579AA._default_embedding_index = i580phi = AA.projective_embedding(i, self)581self.__affine_patches[i] = AA582return AA583584585class ProjectiveSpace_field(ProjectiveSpace_ring):586def _point_homset(self, *args, **kwds):587"""588Construct a point Hom-set.589590For internal use only. See :mod:`morphism` for details.591592TESTS::593594sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))595sage: P2._point_homset(Spec(GF(3)), P2)596Set of rational points of Projective Space of dimension 2 over Finite Field of size 3597"""598return homset.SchemeHomset_points_projective_field(*args, **kwds)599600def _point(self, *args, **kwds):601"""602Construct a point.603604For internal use only. See :mod:`morphism` for details.605606TESTS::607608sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3))609sage: point_homset = P2._point_homset(Spec(GF(3)), P2)610sage: P2._point(point_homset, [1,2,3])611(2 : 1 : 0)612"""613return morphism.SchemeMorphism_point_projective_field(*args, **kwds)614615616class ProjectiveSpace_finite_field(ProjectiveSpace_field):617def __iter__(self):618r"""619Return iterator over the elements of this projective space.620621Note that iteration is over the decomposition622`\PP^n = \mathbb{A}A^n \cup \PP^n-1`, where623`\mathbb{A}A^n` is the `n`-th affine patch and624`\PP^n-1` is the hyperplane at infinity625`x_n = 0`.626627EXAMPLES::628629sage: FF = FiniteField(3)630sage: PP = ProjectiveSpace(0,FF)631sage: [ x for x in PP ]632[(1)]633sage: PP = ProjectiveSpace(1,FF)634sage: [ x for x in PP ]635[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]636sage: PP = ProjectiveSpace(2,FF)637sage: [ x for x in PP ]638[(0 : 0 : 1),639(1 : 0 : 1),640(2 : 0 : 1),641(0 : 1 : 1),642(1 : 1 : 1),643(2 : 1 : 1),644(0 : 2 : 1),645(1 : 2 : 1),646(2 : 2 : 1),647(0 : 1 : 0),648(1 : 1 : 0),649(2 : 1 : 0),650(1 : 0 : 0)]651652AUTHORS:653654- David Kohel655656TODO: Iteration for point sets over finite fields, and return of657iter of point set over base field. Note that the point set does not658know whether this is a projective space or subscheme.659"""660n = self.dimension_relative()661R = self.base_ring()662zero = R(0)663i = n664while not i < 0:665P = [ zero for _ in range(i) ] + [ R(1) ] + [ zero for _ in range(n-i) ]666yield self(P)667iters = [ iter(R) for _ in range(i) ]668for x in iters: x.next() # put at zero669j = 0670while j < i:671try:672P[j] = iters[j].next()673yield self(P)674j = 0675except StopIteration:676iters[j] = iter(R) # reset677iters[j].next() # put at zero678P[j] = zero679j += 1680i -= 1681682def rational_points(self, F=None):683"""684Return the list of `F`-rational points on the affine space self,685where `F` is a given finite field, or the base ring of self.686687EXAMPLES::688689sage: P = ProjectiveSpace(1, GF(3))690sage: P.rational_points()691[(0 : 1), (1 : 1), (2 : 1), (1 : 0)]692sage: P.rational_points(GF(3^2, 'b'))693[(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)]694"""695if F == None:696return [ P for P in self ]697elif not is_FiniteField(F):698raise TypeError, "Second argument (= %s) must be a finite field."%F699return [ P for P in self.base_extend(F) ]700701class ProjectiveSpace_rational_field(ProjectiveSpace_field):702def rational_points(self,bound=0):703r"""704Returns the projective points `(x_0:\cdots:x_n)` over705`\QQ` with `|x_i| \leq` bound.706707INPUT:708709710- ``bound`` - integer711712713EXAMPLES::714715sage: PP = ProjectiveSpace(0,QQ)716sage: PP.rational_points(1)717[(1)]718sage: PP = ProjectiveSpace(1,QQ)719sage: PP.rational_points(2)720[(-2 : 1), (-1 : 1), (0 : 1), (1 : 1), (2 : 1), (-1/2 : 1), (1/2 : 1), (1 : 0)]721sage: PP = ProjectiveSpace(2,QQ)722sage: PP.rational_points(2)723[(-2 : -2 : 1), (-1 : -2 : 1), (0 : -2 : 1), (1 : -2 : 1), (2 : -2 : 1),724(-2 : -1 : 1), (-1 : -1 : 1), (0 : -1 : 1), (1 : -1 : 1), (2 : -1 : 1),725(-2 : 0 : 1), (-1 : 0 : 1), (0 : 0 : 1), (1 : 0 : 1), (2 : 0 : 1), (-2 :7261 : 1), (-1 : 1 : 1), (0 : 1 : 1), (1 : 1 : 1), (2 : 1 : 1), (-2 : 2 :7271), (-1 : 2 : 1), (0 : 2 : 1), (1 : 2 : 1), (2 : 2 : 1), (-1/2 : -1 :7281), (1/2 : -1 : 1), (-1 : -1/2 : 1), (-1/2 : -1/2 : 1), (0 : -1/2 : 1),729(1/2 : -1/2 : 1), (1 : -1/2 : 1), (-1/2 : 0 : 1), (1/2 : 0 : 1), (-1 :7301/2 : 1), (-1/2 : 1/2 : 1), (0 : 1/2 : 1), (1/2 : 1/2 : 1), (1 : 1/2 :7311), (-1/2 : 1 : 1), (1/2 : 1 : 1), (-2 : 1 : 0), (-1 : 1 : 0), (0 : 1 :7320), (1 : 1 : 0), (2 : 1 : 0), (-1/2 : 1 : 0), (1/2 : 1 : 0), (1 : 0 :7330)]734735.. note::736737The very simple algorithm works as follows: every point738`(x_0:\cdots:x_n)` in projective space has a unique739largest index `i` for which `x_i` is not740zero. The algorithm then iterates downward on this741index. We normalize by choosing `x_i` positive. Then,742the points `x_0,\ldots,x_{i-1}` are the points of743affine `i`-space that are relatively prime to744`x_i`. We access these by using the Tuples method.745746AUTHORS:747748- Benjamin Antieau (2008-01-12)749"""750if not bound > 0:751raise ValueError, \752"Argument bound (= %s) must be a positive integer."753754n = self.dimension_relative()755756757Q = [ k-bound for k in range(2*bound+1) ] # the affine coordinates758R = [ (k+1) for k in range(bound) ] # the projective coordinate759S = [ Tuples(Q,(k+1)) for k in range(n) ]760pts = []761762i=n763764while i > 0:765P = [ 0 for _ in range(n+1) ]766for ai in R:767P[i]=ai768for tup in S[i-1]:769if gcd([ai]+tup)==1:770for j in range(i):771P[j]=tup[j]772pts.append(self(P))773i-=1774775# now do i=0; this is treated as a special case so that776# we don't have all points (1:0),(2,0),(3,0),etc.777P = [ 0 for _ in range(n+1) ]; P[0]=1778pts.append(self(P))779return pts780781782