Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Projective `n` space over a ring
EXAMPLES:
We construct projective space over various rings of various dimensions.
The simplest projective space::
sage: ProjectiveSpace(0) Projective Space of dimension 0 over Integer Ring
A slightly bigger projective space over `\QQ`::
sage: X = ProjectiveSpace(1000, QQ); X Projective Space of dimension 1000 over Rational Field sage: X.dimension() 1000
We can use "over" notation to create projective spaces over various base rings.
::
sage: X = ProjectiveSpace(5)/QQ; X Projective Space of dimension 5 over Rational Field sage: X/CC Projective Space of dimension 5 over Complex Field with 53 bits of precision
The third argument specifies the printing names of the generators of the homogenous coordinate ring. Using the method `.objgens()` you can obtain both the space and the generators as ready to use variables. ::
sage: P2, vars = ProjectiveSpace(10, QQ, 't').objgens() sage: vars (t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
You can alternatively use the special syntax with ``<`` and ``>``.
::
sage: P2.<x,y,z> = ProjectiveSpace(2, QQ) sage: P2 Projective Space of dimension 2 over Rational Field sage: P2.coordinate_ring() Multivariate Polynomial Ring in x, y, z over Rational Field
The first of the three lines above is just equivalent to the two lines::
sage: P2 = ProjectiveSpace(2, QQ, 'xyz') sage: x,y,z = P2.gens()
For example, we use `x,y,z` to define the intersection of two lines.
::
sage: V = P2.subscheme([x+y+z, x+y-z]); V Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x + y + z, x + y - z sage: V.dimension() 0
AUTHORS:
- Ben Hutz: (June 2012): support for rings
- Ben Hutz (9/2014): added support for Cartesian products
- Rebecca Lauren Miller (March 2016) : added point_transformation_matrix """
#***************************************************************************** # Copyright (C) 2006 William Stein <wstein@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function from six.moves import range from six import integer_types
from sage.arith.misc import binomial
from sage.rings.all import (PolynomialRing, Integer, ZZ)
from sage.rings.ring import CommutativeRing from sage.rings.rational_field import is_RationalField from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.finite_rings.finite_field_constructor import is_FiniteField
from sage.categories.fields import Fields _Fields = Fields()
from sage.categories.homset import Hom, End from sage.categories.number_fields import NumberFields from sage.categories.map import Map
from sage.misc.all import (latex, prod) from sage.structure.category_object import normalize_names from sage.arith.all import gcd, binomial from sage.combinat.integer_vector import IntegerVectors from sage.combinat.integer_vector_weighted import WeightedIntegerVectors from sage.combinat.permutation import Permutation from sage.combinat.tuple import Tuples from sage.combinat.tuple import UnorderedTuples from sage.matrix.constructor import matrix from sage.modules.free_module_element import prepare from sage.schemes.generic.ambient_space import AmbientSpace from sage.schemes.projective.projective_homset import (SchemeHomset_points_projective_ring, SchemeHomset_points_projective_field) from sage.schemes.projective.projective_point import (SchemeMorphism_point_projective_ring, SchemeMorphism_point_projective_field, SchemeMorphism_point_projective_finite_field) from sage.schemes.projective.projective_morphism import (SchemeMorphism_polynomial_projective_space, SchemeMorphism_polynomial_projective_space_field, SchemeMorphism_polynomial_projective_space_finite_field)
def is_ProjectiveSpace(x): r""" Return True if ``x`` is a projective space.
In other words, if ``x`` is an ambient space `\mathbb{P}^n_R`, where `R` is a ring and `n\geq 0` is an integer.
EXAMPLES::
sage: from sage.schemes.projective.projective_space import is_ProjectiveSpace sage: is_ProjectiveSpace(ProjectiveSpace(5, names='x')) True sage: is_ProjectiveSpace(ProjectiveSpace(5, GF(9,'alpha'), names='x')) True sage: is_ProjectiveSpace(Spec(ZZ)) False """
def ProjectiveSpace(n, R=None, names='x'): r""" Return projective space of dimension ``n`` over the ring ``R``.
EXAMPLES: The dimension and ring can be given in either order.
::
sage: ProjectiveSpace(3, QQ) Projective Space of dimension 3 over Rational Field sage: ProjectiveSpace(5, QQ) Projective Space of dimension 5 over Rational Field sage: P = ProjectiveSpace(2, QQ, names='XYZ'); P Projective Space of dimension 2 over Rational Field sage: P.coordinate_ring() Multivariate Polynomial Ring in X, Y, Z over Rational Field
The divide operator does base extension.
::
sage: ProjectiveSpace(5)/GF(17) Projective Space of dimension 5 over Finite Field of size 17
The default base ring is `\ZZ`.
::
sage: ProjectiveSpace(5) Projective Space of dimension 5 over Integer Ring
There is also an projective space associated each polynomial ring.
::
sage: R = GF(7)['x,y,z'] sage: P = ProjectiveSpace(R); P Projective Space of dimension 2 over Finite Field of size 7 sage: P.coordinate_ring() Multivariate Polynomial Ring in x, y, z over Finite Field of size 7 sage: P.coordinate_ring() is R True
::
sage: ProjectiveSpace(3, Zp(5), 'y') Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20
::
sage: ProjectiveSpace(2,QQ,'x,y,z') Projective Space of dimension 2 over Rational Field
::
sage: PS.<x,y>=ProjectiveSpace(1,CC) sage: PS Projective Space of dimension 1 over Complex Field with 53 bits of precision
::
sage: R.<x,y,z> = QQ[] sage: ProjectiveSpace(R).variable_names() ('x', 'y', 'z')
Projective spaces are not cached, i.e., there can be several with the same base ring and dimension (to facilitate gluing constructions). """ else: else: raise TypeError("R (=%s) must be a commutative ring"%R)
class ProjectiveSpace_ring(AmbientSpace): """ Projective space of dimension `n` over the ring `R`.
EXAMPLES::
sage: X.<x,y,z,w> = ProjectiveSpace(3, QQ) sage: X.base_scheme() Spectrum of Rational Field sage: X.base_ring() Rational Field sage: X.structure_morphism() Scheme morphism: From: Projective Space of dimension 3 over Rational Field To: Spectrum of Rational Field Defn: Structure map sage: X.coordinate_ring() Multivariate Polynomial Ring in x, y, z, w over Rational Field
Loading and saving::
sage: loads(X.dumps()) == X True """ def __init__(self, n, R=ZZ, names=None): """ Initialization function.
EXAMPLES::
sage: ProjectiveSpace(3, Zp(5), 'y') Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20 """
def ngens(self): """ Return the number of generators of this projective space.
This is the number of variables in the coordinate ring of self.
EXAMPLES::
sage: ProjectiveSpace(3, QQ).ngens() 4 sage: ProjectiveSpace(7, ZZ).ngens() 8 """
def _check_satisfies_equations(self, v): """ Return True if ``v`` defines a point on the scheme; raise a TypeError otherwise.
EXAMPLES::
sage: P = ProjectiveSpace(2, ZZ) sage: P._check_satisfies_equations([1, 1, 0]) True
::
sage: P = ProjectiveSpace(1, QQ) sage: P._check_satisfies_equations((1/2, 0)) True
::
sage: P = ProjectiveSpace(2, ZZ) sage: P._check_satisfies_equations([0, 0, 0]) Traceback (most recent call last): ... TypeError: the zero vector is not a point in projective space
::
sage: P = ProjectiveSpace(2, ZZ) sage: P._check_satisfies_equations((1, 0)) Traceback (most recent call last): ... TypeError: the list v=(1, 0) must have 3 components
::
sage: P = ProjectiveSpace(2, ZZ) sage: P._check_satisfies_equations([1/2, 0, 1]) Traceback (most recent call last): ... TypeError: the components of v=[1/2, 0, 1] must be elements of Integer Ring """ raise TypeError('the argument v=%s must be a list or tuple'%v)
def coordinate_ring(self): """ Return the coordinate ring of this scheme.
EXAMPLES::
sage: ProjectiveSpace(3, GF(19^2,'alpha'), 'abcd').coordinate_ring() Multivariate Polynomial Ring in a, b, c, d over Finite Field in alpha of size 19^2
::
sage: ProjectiveSpace(3).coordinate_ring() Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring
::
sage: ProjectiveSpace(2, QQ, ['alpha', 'beta', 'gamma']).coordinate_ring() Multivariate Polynomial Ring in alpha, beta, gamma over Rational Field """ self.variable_names(), self.dimension_relative()+1)
def _validate(self, polynomials): """ If ``polynomials`` is a tuple of valid polynomial functions on self, return ``polynomials``, otherwise raise TypeError.
Since this is a projective space, polynomials must be homogeneous.
INPUT:
- ``polynomials`` -- tuple of polynomials in the coordinate ring of this space.
OUTPUT:
- tuple of polynomials in the coordinate ring of this space.
EXAMPLES::
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ) sage: P._validate([x*y - z^2, x]) [x*y - z^2, x]
::
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ) sage: P._validate((x*y - z, x)) Traceback (most recent call last): ... TypeError: x*y - z is not a homogeneous polynomial
::
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ) sage: P._validate(x*y - z) Traceback (most recent call last): ... TypeError: the argument polynomials=x*y - z must be a list or tuple """
def __eq__(self, right): """ Check equality of two projective spaces.
EXAMPLES::
sage: ProjectiveSpace(QQ, 3, 'a') == ProjectiveSpace(ZZ, 3, 'a') False sage: ProjectiveSpace(ZZ, 1, 'a') == ProjectiveSpace(ZZ, 0, 'a') False sage: ProjectiveSpace(ZZ, 2, 'a') == AffineSpace(ZZ, 2, 'a') False sage: P = ProjectiveSpace(ZZ, 1, 'x') sage: loads(P.dumps()) == P True """ self.coordinate_ring() == right.coordinate_ring())
def __ne__(self, other): """ Check non-equality of two projective spaces.
EXAMPLES::
sage: ProjectiveSpace(QQ, 3, 'a') != ProjectiveSpace(ZZ, 3, 'a') True sage: ProjectiveSpace(ZZ, 1, 'a') != ProjectiveSpace(ZZ, 0, 'a') True sage: ProjectiveSpace(ZZ, 2, 'a') != AffineSpace(ZZ, 2, 'a') True """
def __pow__(self, m): """ Return the Cartesian power of this space.
INPUT: ``m`` -- integer.
OUTPUT: product of projective spaces.
EXAMPLES::
sage: P = ProjectiveSpace(1, QQ, 'x') sage: P3 = P^3; P3 Product of projective spaces P^1 x P^1 x P^1 over Rational Field sage: P3.variable_names() ('x0', 'x1', 'x2', 'x3', 'x4', 'x5')
As you see, custom variable names are not preserved by power operator, since there is no natural way to make new ones in general. """ raise ValueError("m must be an integer")
def __mul__(self, right): r""" Create the product of projective spaces.
INPUT:
- ``right`` - a projective space, product of projective spaces, or subscheme.
OUTPUT: a product of projective spaces or subscheme.
EXAMPLES::
sage: P1 = ProjectiveSpace(QQ, 1, 'x') sage: P2 = ProjectiveSpace(QQ, 2, 'y') sage: P1*P2 Product of projective spaces P^1 x P^2 over Rational Field
::
sage: S.<t,x,y,z,u,v,w> = ProductProjectiveSpaces([3, 2], QQ) sage: T.<a,b> = ProjectiveSpace(QQ, 1) sage: T*S Product of projective spaces P^1 x P^3 x P^2 over Rational Field
::
sage: S = ProjectiveSpace(ZZ, 2, 't') sage: T = ProjectiveSpace(ZZ, 3, 'x') sage: T.inject_variables() Defining x0, x1, x2, x3 sage: X = T.subscheme([x0*x2 - x1*x3]) sage: S*X Closed subscheme of Product of projective spaces P^2 x P^3 over Integer Ring defined by: x0*x2 - x1*x3
::
sage: S = ProjectiveSpace(QQ, 3, 'x') sage: T = AffineSpace(2, QQ, 'y') sage: S*T Traceback (most recent call last): ... TypeError: Affine Space of dimension 2 over Rational Field must be a projective space, product of projective spaces, or subscheme """ raise ValueError ('Must have the same base ring')
return self.__pow__(2)
else:
def _latex_(self): r""" Return a LaTeX representation of this projective space.
EXAMPLES::
sage: print(latex(ProjectiveSpace(1, ZZ, 'x'))) {\mathbf P}_{\Bold{Z}}^1
TESTS::
sage: ProjectiveSpace(3, Zp(5), 'y')._latex_() '{\\mathbf P}_{\\ZZ_{5}}^3' """
def _linear_system_as_kernel(self, d, pt, m): """ Return a matrix whose kernel consists of the coefficient vectors of the degree ``d`` hypersurfaces (wrt lexicographic ordering of its monomials) with multiplicity at least ``m`` at ``pt``.
INPUT:
- ``d`` -- a nonnegative integer.
- ``pt`` -- a point of self (possibly represented by a list with at \ least one component equal to 1).
- ``m`` -- a nonnegative integer.
OUTPUT:
A matrix of size `\binom{m-1+n}{n}` x `\binom{d+n}{n}` where n is the relative dimension of self. The base ring of the matrix is a ring that contains the base ring of self and the coefficients of the given point.
EXAMPLES:
If the degree `d` is 0, then a matrix consisting of the first unit vector is returned::
sage: P = ProjectiveSpace(GF(5), 2, names='x') sage: pt = P([1, 1, 1]) sage: P._linear_system_as_kernel(0, pt, 3) [1] [0] [0] [0] [0] [0]
If the multiplicity `m` is 0, then the a matrix with zero rows is returned::
sage: P = ProjectiveSpace(GF(5), 2, names='x') sage: pt = P([1, 1, 1]) sage: M = P._linear_system_as_kernel(2, pt, 0) sage: [M.nrows(), M.ncols()] [0, 6]
The base ring does not need to be a field or even an integral domain. In this case, the point can be given by a list::
sage: R = Zmod(4) sage: P = ProjectiveSpace(R, 2, names='x') sage: pt = [R(1), R(3), R(0)] sage: P._linear_system_as_kernel(3, pt, 2) [1 3 0 1 0 0 3 0 0 0] [0 1 0 2 0 0 3 0 0 0] [0 0 1 0 3 0 0 1 0 0]
When representing a point by a list at least one component must be 1 (even when the base ring is a field and the list gives a well-defined point in projective space)::
sage: R = GF(5) sage: P = ProjectiveSpace(R, 2, names='x') sage: pt = [R(3), R(3), R(0)] sage: P._linear_system_as_kernel(3, pt, 2) Traceback (most recent call last): ... TypeError: at least one component of pt=[3, 3, 0] must be equal to 1
The components of the list do not have to be elements of the base ring of the projective space. It suffices if there exists a common parent. For example, the kernel of the following matrix corresponds to hypersurfaces of degree 2 in 3-space with multiplicity at least 2 at a general point in the third affine patch::
sage: P = ProjectiveSpace(QQ,3,names='x') sage: RPol.<t0,t1,t2,t3> = PolynomialRing(QQ,4) sage: pt = [t0,t1,1,t3] sage: P._linear_system_as_kernel(2,pt,2) [ 2*t0 t1 1 t3 0 0 0 0 0 0] [ 0 t0 0 0 2*t1 1 t3 0 0 0] [ t0^2 t0*t1 t0 t0*t3 t1^2 t1 t1*t3 1 t3 t3^2] [ 0 0 0 t0 0 0 t1 0 1 2*t3]
.. TODO::
Use this method as starting point to implement a class LinearSystem for linear systems of hypersurfaces.
""" raise TypeError('the argument d=%s must be an integer'%d) raise ValueError('the integer d=%s must be nonnegative'%d) SchemeMorphism_point_projective_ring)): raise TypeError('the argument pt=%s must be a list, tuple, or ' 'point on a projective space'%pt) raise TypeError('the sequence pt=%s must have %s ' 'components'%(pt, n + 1)) raise TypeError('unable to find a common ring for all elements') 'to 1'%pt) raise TypeError('the argument m=%s must be an integer'%m) raise ValueError('the integer m=%s must be nonnegative'%m) # the components of partials correspond to partial derivatives # of order at most m-1 with respect to n variables # the components of monoms correspond to monomials of degree # at most d in n variables for j in (k for k in range(n) if f[k] > e[k]) ])
def _morphism(self, *args, **kwds): """ Construct a morphism.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: P2._morphism(P2.Hom(P2), [x,y,z]) Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3 Defn: Defined on coordinates by sending (x : y : z) to (x : y : z) """
def _point_homset(self, *args, **kwds): """ Construct a point Hom-set.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: P2._point_homset(Spec(GF(3)), P2) Set of rational points of Projective Space of dimension 2 over Finite Field of size 3 """
def point(self, v, check=True): """ Create a point on this projective space.
INPUT:
- ``v`` -- anything that defines a point
- ``check`` -- boolean (optional, default: ``True``); whether to check the defining data for consistency
OUTPUT: A point of this projective space.
EXAMPLES::
sage: P2 = ProjectiveSpace(QQ, 2) sage: P2.point([4,5]) (4 : 5 : 1)
::
sage: P = ProjectiveSpace(QQ, 1) sage: P.point(infinity) (1 : 0)
::
sage: P = ProjectiveSpace(QQ, 2) sage: P.point(infinity) Traceback (most recent call last): ... ValueError: +Infinity not well defined in dimension > 1
::
sage: P = ProjectiveSpace(ZZ, 2) sage: P.point([infinity]) Traceback (most recent call last): ... ValueError: [+Infinity] not well defined in dimension > 1 """ (isinstance(v, (list,tuple)) and len(v) == 1 and v[0] is infinity):
def _point(self, *args, **kwds): """ Construct a point.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: point_homset = P2._point_homset(Spec(GF(3)), P2) sage: P2._point(point_homset, [1,2,3]) (2 : 1 : 0) """
def _repr_(self): """ Return a string representation of this projective space.
EXAMPLES::
sage: ProjectiveSpace(1, ZZ, 'x') Projective Space of dimension 1 over Integer Ring
TESTS::
sage: ProjectiveSpace(3, Zp(5), 'y')._repr_() 'Projective Space of dimension 3 over 5-adic Ring with capped relative precision 20' """
def _repr_generic_point(self, v=None): """ Return a string representation of the generic point corresponding to the list of polys ``v`` on this projective space.
If ``v`` is None, the representation of the generic point of the projective space is returned.
EXAMPLES::
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ) sage: P._repr_generic_point([z*y-x^2]) '(-x^2 + y*z)' sage: P._repr_generic_point() '(x : y : z)' """
def _latex_generic_point(self, v=None): """ Return a LaTeX representation of the generic point corresponding to the list of polys ``v`` on this projective space.
If ``v`` is None, the representation of the generic point of the projective space is returned.
EXAMPLES::
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ) sage: P._latex_generic_point([z*y-x^2]) '\\left(- x^{2} + y z\\right)' sage: P._latex_generic_point() '\\left(x : y : z\\right)' """
def change_ring(self, R): r""" Return a projective space over ring ``R``.
INPUT:
- ``R`` -- commutative ring or morphism.
OUTPUT:
- projective space over ``R``.
.. NOTE::
There is no need to have any relation between ``R`` and the base ring of this space, if you want to have such a relation, use ``self.base_extend(R)`` instead.
EXAMPLES::
sage: P.<x, y, z> = ProjectiveSpace(2, ZZ) sage: PQ = P.change_ring(QQ); PQ Projective Space of dimension 2 over Rational Field sage: PQ.change_ring(GF(5)) Projective Space of dimension 2 over Finite Field of size 5
::
sage: K.<w> = QuadraticField(2) sage: P = ProjectiveSpace(K,2,'t') sage: P.change_ring(K.embeddings(QQbar)[0]) Projective Space of dimension 2 over Algebraic Field """ self.variable_names()) else: self.variable_names())
def is_projective(self): """ Return that this ambient space is projective `n`-space.
EXAMPLES::
sage: ProjectiveSpace(3,QQ).is_projective() True """
def subscheme(self, X): """ Return the closed subscheme defined by ``X``.
INPUT:
- ``X`` - a list or tuple of equations.
EXAMPLES::
sage: A.<x,y,z> = ProjectiveSpace(2, QQ) sage: X = A.subscheme([x*z^2, y^2*z, x*y^2]); X Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x*z^2, y^2*z, x*y^2 sage: X.defining_polynomials () (x*z^2, y^2*z, x*y^2) sage: I = X.defining_ideal(); I Ideal (x*z^2, y^2*z, x*y^2) of Multivariate Polynomial Ring in x, y, z over Rational Field sage: I.groebner_basis() [x*y^2, y^2*z, x*z^2] sage: X.dimension() 0 sage: X.base_ring() Rational Field sage: X.base_scheme() Spectrum of Rational Field sage: X.structure_morphism() Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x*z^2, y^2*z, x*y^2 To: Spectrum of Rational Field Defn: Structure map
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"]) """
def affine_patch(self, i, AA=None): r""" Return the `i^{th}` affine patch of this projective space.
This is an ambient affine space `\mathbb{A}^n_R,` where `R` is the base ring of self, whose "projective embedding" map is `1` in the `i^{th}` factor.
INPUT:
- ``i`` -- integer between 0 and dimension of self, inclusive.
- ``AA`` -- (default: None) ambient affine space, this is constructed if it is not given.
OUTPUT:
- An ambient affine space with fixed projective_embedding map.
EXAMPLES::
sage: PP = ProjectiveSpace(5) / QQ sage: AA = PP.affine_patch(2) sage: AA Affine Space of dimension 5 over Rational Field sage: AA.projective_embedding() Scheme morphism: From: Affine Space of dimension 5 over Rational Field To: Projective Space of dimension 5 over Rational Field Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to (x0 : x1 : 1 : x2 : x3 : x4) sage: AA.projective_embedding(0) Scheme morphism: From: Affine Space of dimension 5 over Rational Field To: Projective Space of dimension 5 over Rational Field Defn: Defined on coordinates by sending (x0, x1, x2, x3, x4) to (1 : x0 : x1 : x2 : x3 : x4)
::
sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: P.affine_patch(0).projective_embedding(0).codomain() == P True """ raise ValueError("argument i (= %s) must be between 0 and %s"%(i, n)) #assume that if you've passed in a new affine space you want to override #the existing patch #if no ith patch exists, we may still be here with AA==None raise ValueError("affine space must be of the dimension %s"%(n))
def _an_element_(self): r""" Returns a (preferably typical) element of this space.
This is used both for illustration and testing purposes.
OUTPUT: a point in this projective space.
EXAMPLES::
sage: ProjectiveSpace(ZZ, 3, 'x').an_element() (7 : 6 : 5 : 1)
sage: ProjectiveSpace(PolynomialRing(ZZ,'y'), 3, 'x').an_element() (7*y : 6*y : 5*y : 1) """
def Lattes_map(self, E, m): r""" Given an elliptic curve ``E`` and an integer ``m`` return the Lattes map associated to multiplication by `m`.
In other words, the rational map on the quotient `E/\{\pm 1\} \cong \mathbb{P}^1` associated to `[m]:E \to E`.
INPUT:
- ``E`` -- an elliptic curve.
- ``m`` -- an integer.
OUTPUT: an endomorphism of this projective space.
Examples::
sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: E = EllipticCurve(QQ,[-1, 0]) sage: P.Lattes_map(E, 2) Scheme endomorphism of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^4 + 2*x^2*y^2 + y^4 : 4*x^3*y - 4*x*y^3) """ raise TypeError("must be dimension 1")
def cartesian_product(self, other): r""" Return the Cartesian product of this projective space and ``other``.
INPUT:
- ``other`` - A projective space with the same base ring as this space.
OUTPUT:
- A Cartesian product of projective spaces.
EXAMPLES::
sage: P1 = ProjectiveSpace(QQ, 1, 'x') sage: P2 = ProjectiveSpace(QQ, 2, 'y') sage: PP = P1.cartesian_product(P2); PP Product of projective spaces P^1 x P^2 over Rational Field sage: PP.gens() (x0, x1, y0, y1, y2) """
def chebyshev_polynomial(self, n, kind='first'): """ Generates an endomorphism of this projective line by a Chebyshev polynomial.
Chebyshev polynomials are a sequence of recursively defined orthogonal polynomials. Chebyshev of the first kind are defined as `T_0(x) = 1`, `T_1(x) = x`, and `T_{n+1}(x) = 2xT_n(x) - T_{n-1}(x)`. Chebyshev of the second kind are defined as `U_0(x) = 1`, `U_1(x) = 2x`, and `U_{n+1}(x) = 2xU_n(x) - U_{n-1}(x)`.
INPUT:
- ``n`` -- a non-negative integer.
- ``kind`` -- ``first`` or ``second`` specifying which kind of chebyshev the user would like to generate. Defaults to ``first``.
OUTPUT: :class:`SchemeMorphism_polynomial_projective_space`
EXAMPLES::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: P.chebyshev_polynomial(5, 'first') Scheme endomorphism of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (16*x^5 - 20*x^3*y^2 + 5*x*y^4 : y^5)
::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: P.chebyshev_polynomial(3, 'second') Scheme endomorphism of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (8*x^3 - 4*x*y^2 : y^3)
::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: P.chebyshev_polynomial(3, 2) Traceback (most recent call last): ... ValueError: keyword 'kind' must have a value of either 'first' or 'second'
::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: P.chebyshev_polynomial(-4, 'second') Traceback (most recent call last): ... ValueError: first parameter 'n' must be a non-negative integer
::
sage: P = ProjectiveSpace(QQ, 2, 'x') sage: P.chebyshev_polynomial(2) Traceback (most recent call last): ... TypeError: projective space must be of dimension 1 """ #use the affine version and then homogenize.
def veronese_embedding(self, d, CS=None, order='lex'): r""" Return the degree ``d`` Veronese embedding from this projective space.
INPUT:
- ``d`` -- a positive integer.
- ``CS`` -- a projective ambient space to embed into. If this projective space has dimension `N`, the dimension of ``CS`` must be `\binom{N + d}{d} - 1`. This is constructed if not specified. Default: ``None``.
- ``order`` -- a monomial order to use to arrange the monomials defining the embedding. The monomials will be arranged from greatest to least with respect to this order. Default: ``'lex'``.
OUTPUT:
- a scheme morphism from this projective space to ``CS``.
EXAMPLES::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: vd = P.veronese_embedding(4, order='invlex') sage: vd Scheme morphism: From: Projective Space of dimension 1 over Rational Field To: Projective Space of dimension 4 over Rational Field Defn: Defined on coordinates by sending (x : y) to (y^4 : x*y^3 : x^2*y^2 : x^3*y : x^4)
Veronese surface::
sage: P.<x,y,z> = ProjectiveSpace(QQ, 2) sage: Q.<q,r,s,t,u,v> = ProjectiveSpace(QQ, 5) sage: vd = P.veronese_embedding(2, Q) sage: vd Scheme morphism: From: Projective Space of dimension 2 over Rational Field To: Projective Space of dimension 5 over Rational Field Defn: Defined on coordinates by sending (x : y : z) to (x^2 : x*y : x*z : y^2 : y*z : z^2) sage: vd(P.subscheme([])) Closed subscheme of Projective Space of dimension 5 over Rational Field defined by: -u^2 + t*v, -s*u + r*v, -s*t + r*u, -s^2 + q*v, -r*s + q*u, -r^2 + q*t """ raise ValueError("(=%s) must be a positive integer"%d) # construct codomain space if not given else: raise TypeError("(=%s) must be a projective space"%CS) raise TypeError("(=%s) has the wrong dimension to serve as the codomain space"%CS)
class ProjectiveSpace_field(ProjectiveSpace_ring): def _point_homset(self, *args, **kwds): """ Construct a point Hom-set.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: P2._point_homset(Spec(GF(3)), P2) Set of rational points of Projective Space of dimension 2 over Finite Field of size 3 """
def _point(self, *args, **kwds): """ Construct a point.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: point_homset = P2._point_homset(Spec(GF(3)), P2) sage: P2._point(point_homset, [1,2,3]) (2 : 1 : 0) """
def _morphism(self, *args, **kwds): """ Construct a morphism.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: P2._morphism(P2.Hom(P2), [x,y,z]) Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3 Defn: Defined on coordinates by sending (x : y : z) to (x : y : z) """
def points_of_bounded_height(self, bound, prec=53): r""" Returns an iterator of the points in self of absolute height of at most the given bound.
Bound check is strict for the rational field. Requires self to be projective space over a number field. Uses the Doyle-Krumm algorithm for computing algebraic numbers up to a given height [Doyle-Krumm]_.
INPUT:
- ``bound`` - a real number.
- ``prec`` - the precision to use to compute the elements of bounded height for number fields.
OUTPUT:
- an iterator of points in this space.
.. WARNING::
In the current implementation, the output of the [Doyle-Krumm]_ algorithm cannot be guaranteed to be correct due to the necessity of floating point computations. In some cases, the default 53-bit precision is considerably lower than would be required for the algorithm to generate correct output.
EXAMPLES::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: list(P.points_of_bounded_height(5)) [(0 : 1), (1 : 1), (-1 : 1), (1/2 : 1), (-1/2 : 1), (2 : 1), (-2 : 1), (1/3 : 1), (-1/3 : 1), (3 : 1), (-3 : 1), (2/3 : 1), (-2/3 : 1), (3/2 : 1), (-3/2 : 1), (1/4 : 1), (-1/4 : 1), (4 : 1), (-4 : 1), (3/4 : 1), (-3/4 : 1), (4/3 : 1), (-4/3 : 1), (1 : 0)]
::
sage: u = QQ['u'].0 sage: P.<x,y,z> = ProjectiveSpace(NumberField(u^2 - 2, 'v'), 2) sage: len(list(P.points_of_bounded_height(1.5))) 57 """ else: raise NotImplementedError("self must be projective space over a number field")
else: # if number field else: # if number field
def subscheme_from_Chow_form(self, Ch, dim): r""" Returns the subscheme defined by the Chow equations associated to the Chow form ``Ch``.
These equations define the subscheme set-theoretically, but only for smooth subschemes and hypersurfaces do they define the subscheme as a scheme.
ALGORITHM:
The Chow form is a polynomial in the Plucker coordinates. The Plucker coordinates are the bracket polynomials. We first re-write the Chow form in terms of the dual Plucker coordinates. Then we expand `Ch(span(p,L)` for a generic point `p` and a generic linear subspace `L`. The coefficients as polynomials in the coordinates of `p` are the equations defining the subscheme. [DalbecSturmfels].
INPUT:
- ``Ch`` - a homogeneous polynomial.
- ``dim`` - the dimension of the associated scheme.
OUTPUT: a projective subscheme.
EXAMPLES::
sage: P = ProjectiveSpace(QQ, 4, 'z') sage: R.<x0,x1,x2,x3,x4> = PolynomialRing(QQ) sage: H = x1^2 + x2^2 + 5*x3*x4 sage: P.subscheme_from_Chow_form(H,3) Closed subscheme of Projective Space of dimension 4 over Rational Field defined by: -5*z0*z1 + z2^2 + z3^2
::
sage: P = ProjectiveSpace(QQ, 3, 'z') sage: R.<x0,x1,x2,x3,x4,x5> = PolynomialRing(QQ) sage: H = x1-x2-x3+x5+2*x0 sage: P.subscheme_from_Chow_form(H, 1) Closed subscheme of Projective Space of dimension 3 over Rational Field defined by: -z1 + z3, z0 + z2 + z3, -z1 - 2*z3, -z0 - z1 + 2*z2
::
sage: P.<x0,x1,x2,x3> = ProjectiveSpace(GF(7), 3) sage: X = P.subscheme([x3^2+x1*x2,x2-x0]) sage: Ch = X.Chow_form();Ch t0^2 - 2*t0*t3 + t3^2 - t2*t4 - t4*t5 sage: Y = P.subscheme_from_Chow_form(Ch, 1); Y Closed subscheme of Projective Space of dimension 3 over Finite Field of size 7 defined by: x1*x2 + x3^2, -x0*x2 + x2^2, -x0*x1 - x1*x2 - 2*x3^2, x0^2 - x0*x2, x0*x1 + x3^2, -2*x0*x3 + 2*x2*x3, 2*x0*x3 - 2*x2*x3, x0^2 - 2*x0*x2 + x2^2 sage: I = Y.defining_ideal() sage: I.saturation(I.ring().ideal(list(I.ring().gens())))[0] Ideal (x0 - x2, x1*x2 + x3^2) of Multivariate Polynomial Ring in x0, x1, x2, x3 over Finite Field of size 7 """ raise ValueError("Chow form must be a homogeneous polynomial") raise ValueError("for given dimension, there should be %d variables in the Chow form" %binomial(n+1,n-dim)) #create the brackets associated to variables #create the dual brackets #create the polys associated to dual brackets else: #substitute in dual brackets to chow form #coefficients are polys in zs which are the chow equations for the chow form else:
def point_transformation_matrix(self, points_source, points_target): r"""
Returns a unique element of PGL that transforms one set of points to another.
Given a projective space of degree n and a set of n+2 source points and a set of n+2 target points in the same projective space, such that no n+1 points of each set are linearly dependent finds the unique element of PGL that translates the source points to the target points.
Warning :: will not work over precision fields
INPUT:
- ``points_source`` - points in source projective space.
- ``points_target`` - points in target projective space.
OUTPUT: Transformation matrix - element of PGL.
EXAMPLES::
sage: P1.<a,b,c>=ProjectiveSpace(QQ, 2) sage: points_source=[P1([1,4,1]),P1([1,2,2]),P1([3,5,1]),P1([1,-1,1])] sage: points_target=[P1([5,-2,7]),P1([3,-2,3]),P1([6,-5,9]), P1([3,6,7])] sage: m = P1.point_transformation_matrix(points_source, points_target); m [ -13/59 -128/59 -25/59] [538/177 8/59 26/177] [ -45/59 -196/59 1] sage: [P1(list(m*vector(list(points_source[i])))) == points_target[i] for i in range(4)] [True, True, True, True]
::
sage: P.<a,b> = ProjectiveSpace(GF(13),1) sage: points_source = [P([-6,7]), P([1,4]), P([3,2])] sage: points_target = [P([-1,2]), P([0,2]), P([-1,6])] sage: P.point_transformation_matrix(points_source, points_target) [10 4] [10 1]
::
sage: P.<a,b> = ProjectiveSpace(QQ,1) sage: points_source = [P([-6,-4]), P([1,4]), P([3,2])] sage: points_target = [P([-1,2]), P([0,2]), P([-7,-3])] sage: P.point_transformation_matrix(points_source, points_target) Traceback (most recent call last): ... ValueError: source points not independent
::
sage: P.<a,b> = ProjectiveSpace(QQ,1) sage: points_source = [P([-6,-1]), P([1,4]), P([3,2])] sage: points_target = [P([-1,2]), P([0,2]), P([-2,4])] sage: P.point_transformation_matrix(points_source, points_target) Traceback (most recent call last): ... ValueError: target points not independent
::
sage: P.<a,b,c>=ProjectiveSpace(QQ, 2) sage: points_source=[P([1,4,1]),P([2,-7,9]),P([3,5,1])] sage: points_target=[P([5,-2,7]),P([3,-2,3]),P([6,-5,9]),P([6,-1,1])] sage: P.point_transformation_matrix(points_source, points_target) Traceback (most recent call last): ... ValueError: incorrect number of points in source, need 4 points
::
sage: P.<a,b,c>=ProjectiveSpace(QQ, 2) sage: points_source=[P([1,4,1]),P([2,-7,9]),P([3,5,1]),P([1,-1,1])] sage: points_target=[P([5,-2,7]),P([3,-2,3]),P([6,-5,9]),P([6,-1,1]),P([7,8,-9])] sage: P.point_transformation_matrix(points_source, points_target) Traceback (most recent call last): ... ValueError: incorrect number of points in target, need 4 points
::
sage: P.<a,b,c>=ProjectiveSpace(QQ, 2) sage: P1.<x,y,z>=ProjectiveSpace(QQ, 2) sage: points_source=[P([1,4,1]),P([2,-7,9]),P([3,5,1]),P1([1,-1,1])] sage: points_target=[P([5,-2,7]),P([3,-2,3]),P([6,-5,9]),P([6,-1,1])] sage: P.point_transformation_matrix(points_source, points_target) Traceback (most recent call last): ... ValueError: source points not in self
::
sage: P.<a,b,c>=ProjectiveSpace(QQ, 2) sage: P1.<x,y,z>=ProjectiveSpace(QQ, 2) sage: points_source=[P([1,4,1]),P([2,-7,9]),P([3,5,1]),P([1,-1,1])] sage: points_target=[P([5,-2,7]),P([3,-2,3]),P([6,-5,9]),P1([6,-1,1])] sage: P.point_transformation_matrix(points_source, points_target) Traceback (most recent call last): ... ValueError: target points not in self """ # makes sure there aren't to few or two many points # putting points as the rows of the matrix #transpose to get image points and then get the list of image points with columns for i in range(0,n+1) for j in range(i+1, n+1)]
def curve(self,F): r""" Return a curve defined by ``F`` in this projective space.
INPUT:
- ``F`` -- a polynomial, or a list or tuple of polynomials in the coordinate ring of this projective space.
EXAMPLES::
sage: P.<x,y,z> = ProjectiveSpace(QQ, 2) sage: P.curve([y^2 - x*z]) Projective Plane Curve over Rational Field defined by y^2 - x*z """
class ProjectiveSpace_finite_field(ProjectiveSpace_field): def _point(self, *args, **kwds): """ Construct a point.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: point_homset = P2._point_homset(Spec(GF(3)), P2) sage: P2._point(point_homset, [1,2,3]) (2 : 1 : 0) """
def _morphism(self, *args, **kwds): """ Construct a morphism.
For internal use only. See :mod:`morphism` for details.
TESTS::
sage: P2.<x,y,z> = ProjectiveSpace(2, GF(3)) sage: P2._morphism(P2.Hom(P2), [x,y,z]) Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3 Defn: Defined on coordinates by sending (x : y : z) to (x : y : z) """
def __iter__(self): r""" Return iterator over the elements of this projective space.
Note that iteration is over the decomposition `\mathbb{P}^n = \mathbb{A}A^n \cup \mathbb{P}^n-1`, where `\mathbb{A}A^n` is the `n`-th affine patch and `\mathbb{P}^n-1` is the hyperplane at infinity `x_n = 0`.
EXAMPLES::
sage: FF = FiniteField(3) sage: PP = ProjectiveSpace(0,FF) sage: [ x for x in PP ] [(1)] sage: PP = ProjectiveSpace(1,FF) sage: [ x for x in PP ] [(0 : 1), (1 : 1), (2 : 1), (1 : 0)] sage: PP = ProjectiveSpace(2,FF) sage: [ x for x in PP ] [(0 : 0 : 1), (1 : 0 : 1), (2 : 0 : 1), (0 : 1 : 1), (1 : 1 : 1), (2 : 1 : 1), (0 : 2 : 1), (1 : 2 : 1), (2 : 2 : 1), (0 : 1 : 0), (1 : 1 : 0), (2 : 1 : 0), (1 : 0 : 0)]
AUTHORS:
- David Kohel
.. TODO::
Iteration for point sets over finite fields, and return of iter of point set over base field. Note that the point set does not know whether this is a projective space or subscheme. """
def rational_points(self, F=None): """ Return the list of ``F``-rational points on this projective space, where ``F`` is a given finite field, or the base ring of this space.
EXAMPLES::
sage: P = ProjectiveSpace(1, GF(3)) sage: P.rational_points() [(0 : 1), (1 : 1), (2 : 1), (1 : 0)] sage: P.rational_points(GF(3^2, 'b')) [(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)] """ raise TypeError("second argument (= %s) must be a finite field"%F)
def rational_points_dictionary(self): r""" Return dictionary of points.
OUTPUT:
- dictionary
EXAMPLES::
sage: P1 = ProjectiveSpace(GF(7),1,'x') sage: P1.rational_points_dictionary() {(0 : 1): 0, (1 : 0): 7, (1 : 1): 1, (2 : 1): 2, (3 : 1): 3, (4 : 1): 4, (5 : 1): 5, (6 : 1): 6} """
class ProjectiveSpace_rational_field(ProjectiveSpace_field): def rational_points(self, bound=0): r""" Returns the projective points `(x_0:\cdots:x_n)` over `\QQ` with `|x_i| \leq` bound.
ALGORITHM:
The very simple algorithm works as follows: every point `(x_0:\cdots:x_n)` in projective space has a unique largest index `i` for which `x_i` is not zero. The algorithm then iterates downward on this index. We normalize by choosing `x_i` positive. Then, the points `x_0,\ldots,x_{i-1}` are the points of affine `i`-space that are relatively prime to `x_i`. We access these by using the Tuples method.
INPUT:
- ``bound`` - integer.
EXAMPLES::
sage: PP = ProjectiveSpace(0, QQ) sage: PP.rational_points(1) [(1)] sage: PP = ProjectiveSpace(1, QQ) sage: PP.rational_points(2) [(-2 : 1), (-1 : 1), (0 : 1), (1 : 1), (2 : 1), (-1/2 : 1), (1/2 : 1), (1 : 0)] sage: PP = ProjectiveSpace(2, QQ) sage: PP.rational_points(2) [(-2 : -2 : 1), (-1 : -2 : 1), (0 : -2 : 1), (1 : -2 : 1), (2 : -2 : 1), (-2 : -1 : 1), (-1 : -1 : 1), (0 : -1 : 1), (1 : -1 : 1), (2 : -1 : 1), (-2 : 0 : 1), (-1 : 0 : 1), (0 : 0 : 1), (1 : 0 : 1), (2 : 0 : 1), (-2 : 1 : 1), (-1 : 1 : 1), (0 : 1 : 1), (1 : 1 : 1), (2 : 1 : 1), (-2 : 2 : 1), (-1 : 2 : 1), (0 : 2 : 1), (1 : 2 : 1), (2 : 2 : 1), (-1/2 : -1 : 1), (1/2 : -1 : 1), (-1 : -1/2 : 1), (-1/2 : -1/2 : 1), (0 : -1/2 : 1), (1/2 : -1/2 : 1), (1 : -1/2 : 1), (-1/2 : 0 : 1), (1/2 : 0 : 1), (-1 : 1/2 : 1), (-1/2 : 1/2 : 1), (0 : 1/2 : 1), (1/2 : 1/2 : 1), (1 : 1/2 : 1), (-1/2 : 1 : 1), (1/2 : 1 : 1), (-2 : 1 : 0), (-1 : 1 : 0), (0 : 1 : 0), (1 : 1 : 0), (2 : 1 : 0), (-1/2 : 1 : 0), (1/2 : 1 : 0), (1 : 0 : 0)]
AUTHORS:
- Benjamin Antieau (2008-01-12) """ raise ValueError("argument bound (= %s) must be a positive integer")
# now do i=0; this is treated as a special case so that # we don't have all points (1:0),(2,0),(3,0),etc.
#fix the pickles from moving projective_space.py from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.schemes.generic.projective_space', 'ProjectiveSpace_field', ProjectiveSpace_field)
register_unpickle_override('sage.schemes.generic.projective_space', 'ProjectiveSpace_rational_field', ProjectiveSpace_rational_field)
|