Path: blob/master/src/sage/schemes/generic/algebraic_scheme.py
8820 views
r"""1Algebraic schemes23An algebraic scheme is defined by a set of polynomials in some4suitable affine or projective coordinates. Possible ambient spaces are56* Affine spaces (:class:`AffineSpace7<sage.schemes.affine.affine_space.AffineSpace_generic>`),89* Projective spaces (:class:`ProjectiveSpace10<sage.schemes.projective.projective_space.ProjectiveSpace_ring>`), or1112* Toric varieties (:class:`ToricVariety13<sage.schemes.toric.variety.ToricVariety_field>`).1415Note that while projective spaces are of course toric varieties themselves,16they are implemented differently in Sage due to efficiency considerations.17You still can create a projective space as a toric variety if you wish.1819In the following, we call the corresponding subschemes affine20algebraic schemes, projective algebraic schemes, or toric algebraic21schemes. In the future other ambient spaces, perhaps by means of22gluing relations, may be intoduced.2324Generally, polynomials `p_0, p_1, \dots, p_n` define an ideal25`I=\left<p_0, p_1, \dots, p_n\right>`. In the projective and toric case, the26polynomials (and, therefore, the ideal) must be homogeneous. The27associated subscheme `V(I)` of the ambient space is, roughly speaking,28the subset of the ambient space on which all polynomials vanish simultaneously.2930.. WARNING::3132You should not construct algebraic scheme objects directly. Instead, use33``.subscheme()`` methods of ambient spaces. See below for examples.3435EXAMPLES:3637We first construct the ambient space, here the affine space `\QQ^2`::3839sage: A2 = AffineSpace(2, QQ, 'x, y')40sage: A2.coordinate_ring().inject_variables()41Defining x, y4243Now we can write polynomial equations in the variables `x` and `y`. For44example, one equation cuts out a curve (a one-dimensional subscheme)::4546sage: V = A2.subscheme([x^2+y^2-1]); V47Closed subscheme of Affine Space of dimension 248over Rational Field defined by:49x^2 + y^2 - 150sage: V.dimension()5115253Here is a more complicated example in a projective space::5455sage: P3 = ProjectiveSpace(3, QQ, 'x')56sage: P3.inject_variables()57Defining x0, x1, x2, x358sage: Q = matrix([[x0, x1, x2], [x1, x2, x3]]).minors(2); Q59[-x1^2 + x0*x2, -x1*x2 + x0*x3, -x2^2 + x1*x3]60sage: twisted_cubic = P3.subscheme(Q)61sage: twisted_cubic62Closed subscheme of Projective Space of dimension 363over Rational Field defined by:64-x1^2 + x0*x2,65-x1*x2 + x0*x3,66-x2^2 + x1*x367sage: twisted_cubic.dimension()6816970Note that there are 3 equations in the 3-dimensional ambient space,71yet the subscheme is 1-dimensional. One can show that it is not72possible to eliminate any of the equations, that is, the twisted cubic73is **not** a complete intersection of two polynomial equations.7475Let us look at one affine patch, for example the one where `x_0=1` ::7677sage: patch = twisted_cubic.affine_patch(0)78sage: patch79Closed subscheme of Affine Space of dimension 380over Rational Field defined by:81-x0^2 + x1,82-x0*x1 + x2,83-x1^2 + x0*x284sage: patch.embedding_morphism()85Scheme morphism:86From: Closed subscheme of Affine Space of dimension 387over Rational Field defined by:88-x0^2 + x1,89-x0*x1 + x2,90-x1^2 + x0*x291To: Closed subscheme of Projective Space of dimension 392over Rational Field defined by:93-x1^2 + x0*x2,94-x1*x2 + x0*x3,95-x2^2 + x1*x396Defn: Defined on coordinates by sending (x0, x1, x2) to97(1 : x0 : x1 : x2)9899100AUTHORS:101102- David Kohel (2005): initial version.103- William Stein (2005): initial version.104- Andrey Novoseltsev (2010-05-17): subschemes of toric varieties.105- Volker Braun (2010-12-24): documentation of schemes and106refactoring. Added coordinate neighborhoods and is_smooth()107"""108109#*****************************************************************************110# Copyright (C) 2010 Volker Braun <[email protected]>111# Copyright (C) 2005 David Kohel <[email protected]>112# Copyright (C) 2010 Andrey Novoseltsev <[email protected]>113# Copyright (C) 2005 William Stein <[email protected]>114#115# Distributed under the terms of the GNU General Public License (GPL)116# as published by the Free Software Foundation; either version 2 of117# the License, or (at your option) any later version.118# http://www.gnu.org/licenses/119#*****************************************************************************120121122#*** A quick overview over the class hierarchy:123# class AlgebraicScheme(scheme.Scheme)124# class AlgebraicScheme_subscheme125# class AlgebraicScheme_subscheme_affine126# class AlgebraicScheme_subscheme_projective127# class AlgebraicScheme_subscheme_toric128# class AlgebraicScheme_subscheme_affine_toric129# class AlgebraicScheme_quasi130131132133from sage.rings.all import ZZ134135from sage.rings.ideal import is_Ideal136from sage.rings.rational_field import is_RationalField137from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing138from sage.rings.finite_rings.constructor import is_FiniteField139140from sage.misc.latex import latex141from sage.misc.misc import is_iterator142from sage.structure.all import Sequence143from sage.calculus.functions import jacobian144145import sage.schemes.projective146import sage.schemes.affine147import ambient_space148import scheme149150151152#*******************************************************************153def is_AlgebraicScheme(x):154"""155Test whether ``x`` is an algebraic scheme.156157INPUT:158159- ``x`` -- anything.160161OUTPUT:162163Boolean. Whether ``x`` is an an algebraic scheme, that is, a164subscheme of an ambient space over a ring defined by polynomial165equations.166167EXAMPLES::168169sage: A2 = AffineSpace(2, QQ, 'x, y')170sage: A2.coordinate_ring().inject_variables()171Defining x, y172sage: V = A2.subscheme([x^2+y^2]); V173Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:174x^2 + y^2175sage: from sage.schemes.generic.algebraic_scheme import is_AlgebraicScheme176sage: is_AlgebraicScheme(V)177True178179Affine space is itself not an algebraic scheme, though the closed180subscheme defined by no equations is::181182sage: from sage.schemes.generic.algebraic_scheme import is_AlgebraicScheme183sage: is_AlgebraicScheme(AffineSpace(10, QQ))184False185sage: V = AffineSpace(10, QQ).subscheme([]); V186Closed subscheme of Affine Space of dimension 10 over Rational Field defined by:187(no polynomials)188sage: is_AlgebraicScheme(V)189True190191We create a more complicated closed subscheme::192193sage: A, x = AffineSpace(10, QQ).objgens()194sage: X = A.subscheme([sum(x)]); X195Closed subscheme of Affine Space of dimension 10 over Rational Field defined by:196x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9197sage: is_AlgebraicScheme(X)198True199200::201202sage: is_AlgebraicScheme(QQ)203False204sage: S = Spec(QQ)205sage: is_AlgebraicScheme(S)206False207"""208return isinstance(x, AlgebraicScheme)209210211212#*******************************************************************213class AlgebraicScheme(scheme.Scheme):214"""215An algebraic scheme presented as a subscheme in an ambient space.216217This is the base class for all algebraic schemes, that is, schemes218defined by equations in affine, projective, or toric ambient219spaces.220"""221222def __init__(self, A):223"""224TESTS::225226sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme227sage: P = ProjectiveSpace(3, ZZ)228sage: P.category()229Category of schemes over Integer Ring230sage: S = AlgebraicScheme(P); S231Subscheme of Projective Space of dimension 3 over Integer Ring232sage: S.category()233Category of schemes over Integer Ring234"""235if not ambient_space.is_AmbientSpace(A):236raise TypeError, "A (=%s) must be an ambient space"237self.__A = A238self.__divisor_group = {}239scheme.Scheme.__init__(self, A.base_scheme())240241def _latex_(self):242"""243Return a LaTeX representation of this algebraic scheme.244245TESTS::246247sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme248sage: P = ProjectiveSpace(3, ZZ)249sage: S = AlgebraicScheme(P); S250Subscheme of Projective Space of dimension 3 over Integer Ring251sage: S._latex_()252'\text{Subscheme of } {\\mathbf P}_{\\Bold{Z}}^3'253"""254return "\text{Subscheme of } %s" % latex(self.__A)255256def is_projective(self):257"""258Return True if self is presented as a subscheme of an ambient259projective space.260261OUTPUT:262263Boolean.264265EXAMPLES::266267sage: PP.<x,y,z,w> = ProjectiveSpace(3,QQ)268sage: f = x^3 + y^3 + z^3 + w^3269sage: R = f.parent()270sage: I = [f] + [f.derivative(zz) for zz in PP.gens()]271sage: V = PP.subscheme(I)272sage: V.is_projective()273True274sage: AA.<x,y,z,w> = AffineSpace(4,QQ)275sage: V = AA.subscheme(I)276sage: V.is_projective()277False278279Note that toric varieties are implemented differently than280projective spaces. This is why this method returns ``False``281for toric varieties::282283sage: PP.<x,y,z,w> = toric_varieties.P(3)284sage: V = PP.subscheme(x^3 + y^3 + z^3 + w^3)285sage: V.is_projective()286False287"""288return self.ambient_space().is_projective()289290def coordinate_ring(self):291"""292Return the coordinate ring of this algebraic scheme. The293result is cached.294295OUTPUT:296297The coordinate ring. Usually a polynomial ring, or a quotient298thereof.299300EXAMPLES::301302sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)303sage: S = P.subscheme([x-y, x-z])304sage: S.coordinate_ring()305Quotient of Multivariate Polynomial Ring in x, y, z over Integer Ring by the ideal (x - y, x - z)306"""307try:308return self._coordinate_ring309except AttributeError:310R = self.__A.coordinate_ring()311I = self.defining_ideal()312Q = R.quotient(I)313self._coordinate_ring = Q314return Q315316def ambient_space(self):317"""318Return the ambient space of this algebraic scheme.319320EXAMPLES::321322sage: A.<x, y> = AffineSpace(2, GF(5))323sage: S = A.subscheme([])324sage: S.ambient_space()325Affine Space of dimension 2 over Finite Field of size 5326327sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)328sage: S = P.subscheme([x-y, x-z])329sage: S.ambient_space() is P330True331"""332return self.__A333334def embedding_morphism(self):335r"""336Return the default embedding morphism of ``self``.337338If the scheme `Y` was constructed as a neighbourhood of a339point `p \in X`, then :meth:`embedding_morphism` returns a340local isomorphism `f:Y\to X` around the preimage point341`f^{-1}(p)`. The latter is returned by342:meth:`embedding_center`.343344If the algebraic scheme `Y` was not constructed as a345neighbourhood of a point, then the embedding in its346:meth:`ambient_space` is returned.347348OUTPUT:349350A scheme morphism whose351:meth:`~morphism.SchemeMorphism.domain` is ``self``.352353* By default, it is the tautological embedding into its own354ambient space :meth:`ambient_space`.355356* If the algebraic scheme (which itself is a subscheme of an357auxiliary :meth:`ambient_space`) was constructed as a patch358or neighborhood of a point then the embedding is the359embedding into the original scheme.360361* A ``NotImplementedError`` is raised if the construction of362the embedding morphism is not implemented yet.363364EXAMPLES::365366sage: A2.<x,y> = AffineSpace(QQ,2)367sage: C = A2.subscheme(x^2+y^2-1)368sage: C.embedding_morphism()369Scheme morphism:370From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:371x^2 + y^2 - 1372To: Affine Space of dimension 2 over Rational Field373Defn: Defined on coordinates by sending (x, y) to374(x, y)375sage: P1xP1.<x,y,u,v> = toric_varieties.P1xP1()376sage: P1 = P1xP1.subscheme(x-y)377sage: P1.embedding_morphism()378Scheme morphism:379From: Closed subscheme of 2-d CPR-Fano toric variety covered380by 4 affine patches defined by:381x - y382To: 2-d CPR-Fano toric variety covered by 4 affine patches383Defn: Defined on coordinates by sending [x : y : u : v] to384[y : y : u : v]385386So far, the embedding was just in the own ambient space. Now a387bit more interesting examples::388389sage: P2.<x,y,z> = ProjectiveSpace(QQ,2)390sage: X = P2.subscheme((x^2-y^2)*z)391sage: p = (1,1,0)392sage: nbhd = X.neighborhood(p)393sage: nbhd394Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:395-x0^2*x1 - 2*x0*x1396397Note that `p=(1,1,0)` is a singular point of `X`. So the398neighborhood of `p` is not just affine space. The399:meth:neighborhood` method returns a presentation of400the neighborhood as a subscheme of an auxiliary 2-dimensional401affine space::402403sage: nbhd.ambient_space()404Affine Space of dimension 2 over Rational Field405406But its :meth:`embedding_morphism` is not into this auxiliary407affine space, but the original subscheme `X`::408409sage: nbhd.embedding_morphism()410Scheme morphism:411From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:412-x0^2*x1 - 2*x0*x1413To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:414x^2*z - y^2*z415Defn: Defined on coordinates by sending (x0, x1) to416(1 : x0 + 1 : x1)417418A couple more examples::419420sage: patch1 = P1xP1.affine_patch(1)421sage: patch14222-d affine toric variety423sage: patch1.embedding_morphism()424Scheme morphism:425From: 2-d affine toric variety426To: 2-d CPR-Fano toric variety covered by 4 affine patches427Defn: Defined on coordinates by sending [y : u] to428[1 : y : u : 1]429sage: subpatch = P1.affine_patch(1)430sage: subpatch431Closed subscheme of 2-d affine toric variety defined by:432-y + 1433sage: subpatch.embedding_morphism()434Scheme morphism:435From: Closed subscheme of 2-d affine toric variety defined by:436-y + 1437To: Closed subscheme of 2-d CPR-Fano toric variety covered438by 4 affine patches defined by:439x - y440Defn: Defined on coordinates by sending [y : u] to441[1 : y : u : 1]442"""443if '_embedding_morphism' in self.__dict__:444hom = self._embedding_morphism445if isinstance(hom, tuple):446raise(hom[0], hom[1])447return hom448ambient = self.ambient_space()449return self.hom(ambient.coordinate_ring().gens(), ambient)450451def embedding_center(self):452r"""453Return the distinguished point, if there is any.454455If the scheme `Y` was constructed as a neighbourhood of a456point `p \in X`, then :meth:`embedding_morphism` returns a457local isomorphism `f:Y\to X` around the preimage point458`f^{-1}(p)`. The latter is returned by459:meth:`embedding_center`.460461OUTPUT:462463A point of ``self``. Raises ``AttributeError`` if there is no464distinguished point, depending on how ``self`` was465constructed.466467EXAMPLES::468469sage: P3.<w,x,y,z> = ProjectiveSpace(QQ,3)470sage: X = P3.subscheme( (w^2-x^2)*(y^2-z^2) )471sage: p = [1,-1,3,4]472sage: nbhd = X.neighborhood(p); nbhd473Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:474x0^2*x2^2 - x1^2*x2^2 + 6*x0^2*x2 - 6*x1^2*x2 + 2*x0*x2^2 +4752*x1*x2^2 - 7*x0^2 + 7*x1^2 + 12*x0*x2 + 12*x1*x2 - 14*x0 - 14*x1476sage: nbhd.embedding_center()477(0, 0, 0)478sage: nbhd.embedding_morphism()(nbhd.embedding_center())479(1/4 : -1/4 : 3/4 : 1)480sage: nbhd.embedding_morphism()481Scheme morphism:482From: Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:483x0^2*x2^2 - x1^2*x2^2 + 6*x0^2*x2 - 6*x1^2*x2 + 2*x0*x2^2 +4842*x1*x2^2 - 7*x0^2 + 7*x1^2 + 12*x0*x2 + 12*x1*x2 - 14*x0 - 14*x1485To: Closed subscheme of Projective Space of dimension 3 over Rational Field defined by:486w^2*y^2 - x^2*y^2 - w^2*z^2 + x^2*z^2487Defn: Defined on coordinates by sending (x0, x1, x2) to488(x0 + 1 : x1 - 1 : x2 + 3 : 4)489"""490if '_embedding_center' in self.__dict__:491return self._embedding_center492raise AttributeError, 'This algebraic scheme does not have a designated point.'493494def ngens(self):495"""496Return the number of generators of the ambient space of this497algebraic scheme.498499EXAMPLES::500501sage: A.<x, y> = AffineSpace(2, GF(5))502sage: S = A.subscheme([])503sage: S.ngens()5042505sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)506sage: S = P.subscheme([x-y, x-z])507sage: P.ngens()5083509"""510return self.__A.ngens()511512def _repr_(self):513"""514Return a string representation of this algebraic scheme.515516TESTS::517518sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme519sage: P = ProjectiveSpace(3, ZZ)520sage: S = AlgebraicScheme(P); S521Subscheme of Projective Space of dimension 3 over Integer Ring522sage: S._repr_()523'Subscheme of Projective Space of dimension 3 over Integer Ring'524"""525return "Subscheme of %s"%self.__A526527def _homset(self, *args, **kwds):528"""529Construct the Hom-set530531INPUT:532533Same as :class:`sage.schemes.generic.homset.SchemeHomset_generic`.534535OUTPUT:536537The Hom-set of the ambient space.538539EXAMPLES::540541sage: P1.<x,y> = toric_varieties.P1()542sage: type(P1.Hom(P1))543<class 'sage.schemes.toric.homset.SchemeHomset_toric_variety_with_category'>544sage: X = P1.subscheme(x-y)545sage: type(X.Hom(X))546<class 'sage.schemes.toric.homset.SchemeHomset_toric_variety_with_category'>547548::549550sage: P1xP1 = toric_varieties.P1xP1()551sage: P1 = toric_varieties.P1()552sage: P1xP1._homset(P1xP1,P1)553Set of morphisms554From: 2-d CPR-Fano toric variety covered by 4 affine patches555To: 1-d CPR-Fano toric variety covered by 2 affine patches556"""557return self.__A._homset(*args, **kwds)558559def _point_homset(self, *args, **kwds):560"""561Construct a point Hom-set. For internal use only.562563TESTS::564565sage: P2.<x,y,z> = ProjectiveSpace(2, ZZ)566sage: P2._point_homset(Spec(ZZ), P2)567Set of rational points of Projective Space of dimension 2 over Integer Ring568"""569return self.__A._point_homset(*args, **kwds)570571def _point(self, *args, **kwds):572r"""573Construct a point of ``self``. For internal use only.574575TESTS::576577sage: P2.<x,y,z> = ProjectiveSpace(2, QQ)578sage: point_homset = P2._point_homset(Spec(QQ), P2)579sage: P2._point(point_homset, [1,2,1])580(1 : 2 : 1)581"""582return self.__A._point(*args, **kwds)583584585586#*******************************************************************587class AlgebraicScheme_quasi(AlgebraicScheme):588"""589The quasi-affine or quasi-projective scheme `X - Y`, where `X` and `Y`590are both closed subschemes of a common ambient affine or projective591space.592593.. WARNING::594595You should not create objects of this class directly. The596preferred method to construct such subschemes is to use597:meth:`complement` method of algebraic schemes.598599OUTPUT:600601An instance of :class:`AlgebraicScheme_quasi`.602603EXAMPLES::604605sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)606sage: S = P.subscheme([])607sage: T = P.subscheme([x-y])608sage: T.complement(S)609Quasi-projective subscheme X - Y of Projective Space of dimension 2 over610Integer Ring, where X is defined by:611(no polynomials)612and Y is defined by:613x - y614"""615616def __init__(self, X, Y):617"""618The constructor.619620INPUT:621622- ``X``, ``Y`` -- two subschemes of the same ambient space.623624TESTS::625626sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)627sage: S = P.subscheme([])628sage: T = P.subscheme([x-y])629sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_quasi630sage: AlgebraicScheme_quasi(S, T)631Quasi-projective subscheme X - Y of Projective Space of dimension 2 over Integer Ring, where X is defined by:632(no polynomials)633and Y is defined by:634x - y635"""636self.__X = X637self.__Y = Y638if not isinstance(X, AlgebraicScheme_subscheme):639raise TypeError, "X must be a closed subscheme of an ambient space."640if not isinstance(Y, AlgebraicScheme_subscheme):641raise TypeError, "Y must be a closed subscheme of an ambient space."642if X.ambient_space() != Y.ambient_space():643raise ValueError, "X and Y must be embedded in the same ambient space."644# _latex_ and _repr_ assume all of the above conditions and should be645# probably changed if they are relaxed!646A = X.ambient_space()647self._base_ring = A.base_ring()648AlgebraicScheme.__init__(self, A)649650def _latex_(self):651"""652Return a LaTeX representation of this algebraic scheme.653654EXAMPLES::655656sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_quasi657sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)658sage: S = P.subscheme([])659sage: T = P.subscheme([x-y])660sage: U = AlgebraicScheme_quasi(S, T); U661Quasi-projective subscheme X - Y of Projective Space of dimension 2662over Integer Ring, where X is defined by:663(no polynomials)664and Y is defined by:665x - y666sage: U._latex_()667'\\text{Quasi-projective subscheme }668(X\\setminus Y)\\subset {\\mathbf P}_{\\Bold{Z}}^2,\\text{ where }669X \\text{ is defined by }\\text{no polynomials},\\text{ and }670Y \\text{ is defined by } x - y.'671"""672if sage.schemes.affine.affine_space.is_AffineSpace(self.ambient_space()):673t = "affine"674else:675t = "projective"676X = ', '.join(latex(f) for f in self.__X.defining_polynomials())677if not X:678X = r"\text{no polynomials}"679Y = ', '.join(latex(f) for f in self.__Y.defining_polynomials())680if not Y:681Y = r"\text{no polynomials}"682return (r"\text{Quasi-%s subscheme } (X\setminus Y)\subset %s,"683r"\text{ where } X \text{ is defined by }%s,"684r"\text{ and } Y \text{ is defined by } %s."685% (t, latex(self.ambient_space()), X, Y))686687def _repr_(self):688"""689Return a string representation of this algebraic scheme.690691EXAMPLES::692693sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_quasi694sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)695sage: S = P.subscheme([])696sage: T = P.subscheme([x-y])697sage: U = AlgebraicScheme_quasi(S, T); U698Quasi-projective subscheme X - Y of Projective Space of dimension 2 over Integer Ring, where X is defined by:699(no polynomials)700and Y is defined by:701x - y702sage: U._repr_()703'Quasi-projective subscheme X - Y of Projective Space of dimension 2 over Integer Ring, where X is defined by:\n (no polynomials)\nand Y is defined by:\n x - y'704"""705if sage.schemes.affine.affine_space.is_AffineSpace(self.ambient_space()):706t = "affine"707else:708t = "projective"709return ("Quasi-%s subscheme X - Y of %s, where X is defined by:\n%s\n"710"and Y is defined by:\n%s"711% (t, self.ambient_space(), str(self.__X).split("\n", 1)[1],712str(self.__Y).split("\n", 1)[1]))713714def X(self):715"""716Return the scheme `X` such that self is represented as `X - Y`.717718EXAMPLES::719720sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)721sage: S = P.subscheme([])722sage: T = P.subscheme([x-y])723sage: U = T.complement(S)724sage: U.X() is S725True726"""727return self.__X728729def Y(self):730"""731Return the scheme `Y` such that self is represented as `X - Y`.732733EXAMPLES::734735sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)736sage: S = P.subscheme([])737sage: T = P.subscheme([x-y])738sage: U = T.complement(S)739sage: U.Y() is T740True741"""742return self.__Y743744def _check_satisfies_equations(self, v):745"""746Verify that the coordinates of v define a point on this scheme, or747raise a TypeError.748749EXAMPLES::750751sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)752sage: S = P.subscheme([])753sage: T = P.subscheme([x-y])754sage: U = T.complement(S)755sage: U._check_satisfies_equations([1, 2, 0])756True757sage: U._check_satisfies_equations([1, 1, 0])758Traceback (most recent call last):759...760TypeError: Coordinates [1, 1, 0] do not define a point on761Quasi-projective subscheme X - Y of Projective Space of dimension 2762over Integer Ring, where X is defined by:763(no polynomials)764and Y is defined by:765x - y766767sage: U._check_satisfies_equations([1, 4])768Traceback (most recent call last):769...770TypeError: number of arguments does not match number of variables in parent771772sage: A.<x, y> = AffineSpace(2, GF(7))773sage: S = A.subscheme([x^2-y])774sage: T = A.subscheme([x-y])775sage: U = T.complement(S)776sage: U._check_satisfies_equations([2, 4])777True778sage: U.point([2,4])779(2, 4)780sage: U._check_satisfies_equations(_)781True782sage: U._check_satisfies_equations([1, 1])783Traceback (most recent call last):784...785TypeError: Coordinates [1, 1] do not define a point on Quasi-affine786subscheme X - Y of Affine Space of dimension 2 over Finite787Field of size 7, where X is defined by:788x^2 - y789and Y is defined by:790x - y791sage: U._check_satisfies_equations([1, 0])792Traceback (most recent call last):793...794TypeError: Coordinates [1, 0] do not define a point on Quasi-affine795subscheme X - Y of Affine Space of dimension 2 over Finite796Field of size 7, where X is defined by:797x^2 - y798and Y is defined by:799x - y800801TESTS:802803The bug reported at #12211 has been fixed::804805sage: P.<x, y, z, w> = ProjectiveSpace(3, QQ)806sage: S = P.subscheme([x])807sage: T = P.subscheme([y, z])808sage: U = T.complement(S)809sage: U._check_satisfies_equations([0, 0, 1, 1])810True811"""812coords = list(v)813for f in self.__X.defining_polynomials():814if f(coords) != 0:815raise TypeError, "Coordinates %s do not define a point on %s"%(v,self)816for f in self.__Y.defining_polynomials():817if f(coords) != 0:818return True819raise TypeError, "Coordinates %s do not define a point on %s"%(v,self)820821def rational_points(self, F=None, bound=0):822"""823Return the set of rational points on this algebraic scheme824over the field `F`.825826EXAMPLES::827828sage: A.<x, y> = AffineSpace(2, GF(7))829sage: S = A.subscheme([x^2-y])830sage: T = A.subscheme([x-y])831sage: U = T.complement(S)832sage: U.rational_points()833[(2, 4), (3, 2), (4, 2), (5, 4), (6, 1)]834sage: U.rational_points(GF(7^2, 'b'))835[(2, 4), (3, 2), (4, 2), (5, 4), (6, 1), (b, b + 4), (b + 1, 3*b + 5), (b + 2, 5*b + 1),836(b + 3, 6), (b + 4, 2*b + 6), (b + 5, 4*b + 1), (b + 6, 6*b + 5), (2*b, 4*b + 2),837(2*b + 1, b + 3), (2*b + 2, 5*b + 6), (2*b + 3, 2*b + 4), (2*b + 4, 6*b + 4),838(2*b + 5, 3*b + 6), (2*b + 6, 3), (3*b, 2*b + 1), (3*b + 1, b + 2), (3*b + 2, 5),839(3*b + 3, 6*b + 3), (3*b + 4, 5*b + 3), (3*b + 5, 4*b + 5), (3*b + 6, 3*b + 2),840(4*b, 2*b + 1), (4*b + 1, 3*b + 2), (4*b + 2, 4*b + 5), (4*b + 3, 5*b + 3),841(4*b + 4, 6*b + 3), (4*b + 5, 5), (4*b + 6, b + 2), (5*b, 4*b + 2), (5*b + 1, 3),842(5*b + 2, 3*b + 6), (5*b + 3, 6*b + 4), (5*b + 4, 2*b + 4), (5*b + 5, 5*b + 6),843(5*b + 6, b + 3), (6*b, b + 4), (6*b + 1, 6*b + 5), (6*b + 2, 4*b + 1), (6*b + 3, 2*b + 6),844(6*b + 4, 6), (6*b + 5, 5*b + 1), (6*b + 6, 3*b + 5)]845"""846if F is None:847F = self.base_ring()848849if bound == 0:850if is_RationalField(F):851raise TypeError, "A positive bound (= %s) must be specified."%bound852if not is_FiniteField(F):853raise TypeError, "Argument F (= %s) must be a finite field."%F854pts = []855for P in self.ambient_space().rational_points(F):856try:857if self._check_satisfies_equations(list(P)):858pts.append(P)859except TypeError:860pass861pts.sort()862return pts863864865866#*******************************************************************867class AlgebraicScheme_subscheme(AlgebraicScheme):868"""869An algebraic scheme presented as a closed subscheme is defined by870explicit polynomial equations. This is as opposed to a general871scheme, which could, e.g., be the Neron model of some object, and872for which we do not want to give explicit equations.873874INPUT:875876- ``A`` - ambient space (e.g. affine or projective `n`-space)877878- ``polynomials`` - single polynomial, ideal or iterable of defining879polynomials; in any case polynomials must belong to the coordinate880ring of the ambient space and define valid polynomial functions (e.g.881they should be homogeneous in the case of a projective space)882883OUTPUT:884885- algebraic scheme886887EXAMPLES::888889sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme890sage: P.<x, y, z> = ProjectiveSpace(2, QQ)891sage: P.subscheme([x^2-y*z])892Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:893x^2 - y*z894sage: AlgebraicScheme_subscheme(P, [x^2-y*z])895Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:896x^2 - y*z897"""898899def __init__(self, A, polynomials):900"""901See ``AlgebraicScheme_subscheme`` for documentation.902903TESTS::904905sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme906sage: P.<x, y, z> = ProjectiveSpace(2, QQ)907sage: P.subscheme([x^2-y*z])908Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:909x^2 - y*z910sage: AlgebraicScheme_subscheme(P, [x^2-y*z])911Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:912x^2 - y*z913"""914from sage.rings.polynomial.multi_polynomial_sequence import is_PolynomialSequence915916AlgebraicScheme.__init__(self, A)917self._base_ring = A.base_ring()918R = A.coordinate_ring()919if is_Ideal(polynomials):920I = polynomials921polynomials = I.gens()922if I.ring() is R: # Otherwise we will recompute I later after923self.__I = I # converting generators to the correct ring924if isinstance(polynomials, tuple) or is_PolynomialSequence(polynomials) or is_iterator(polynomials):925polynomials = list(polynomials)926elif not isinstance(polynomials, list):927# Looks like we got a single polynomial928polynomials = [polynomials]929for n, f in enumerate(polynomials):930try:931polynomials[n] = R(f)932except TypeError:933raise TypeError("%s cannot be converted to a polynomial in "934"the coordinate ring of this %s!" % (f, A))935polynomials = tuple(polynomials)936self.__polys = A._validate(polynomials)937938def _check_satisfies_equations(self, v):939"""940Verify that the coordinates of v define a point on this scheme, or941raise a TypeError.942943EXAMPLES::944945sage: P.<x, y, z> = ProjectiveSpace(2, QQ)946sage: S = P.subscheme([x^2-y*z])947sage: S._check_satisfies_equations([1, 1, 1])948True949sage: S._check_satisfies_equations([1, 0, 1])950Traceback (most recent call last):951...952TypeError: Coordinates [1, 0, 1] do not define a point on Closed subscheme953of Projective Space of dimension 2 over Rational Field defined by:954x^2 - y*z955sage: S._check_satisfies_equations([0, 0, 0])956Traceback (most recent call last):957...958TypeError: Coordinates [0, 0, 0] do not define a point on Closed subscheme959of Projective Space of dimension 2 over Rational Field defined by:960x^2 - y*z961"""962coords = list(v)963for f in self.defining_polynomials():964if f(coords) != 0: # it must be "!=0" instead of "if f(v)", e.g.,965# because of p-adic base rings.966raise TypeError, "Coordinates %s do not define a point on %s"%(coords,self)967try:968return self.ambient_space()._check_satisfies_equations(coords)969except TypeError:970raise TypeError, "Coordinates %s do not define a point on %s"%(coords,self)971972def base_extend(self, R):973"""974Return the base change to the ring `R` of this scheme.975976EXAMPLES::977978sage: P.<x, y, z> = ProjectiveSpace(2, GF(11))979sage: S = P.subscheme([x^2-y*z])980sage: S.base_extend(GF(11^2, 'b'))981Closed subscheme of Projective Space of dimension 2 over Finite Field in b of size 11^2 defined by:982x^2 - y*z983sage: S.base_extend(ZZ)984Traceback (most recent call last):985...986ValueError: no natural map from the base ring (=Finite Field of size 11) to R (=Integer Ring)!987"""988A = self.ambient_space().base_extend(R)989return A.subscheme(self.__polys)990991def __cmp__(self, other):992"""993EXAMPLES::994995sage: A.<x, y, z> = AffineSpace(3, QQ)996sage: X = A.subscheme([x*y, z])997sage: X == A.subscheme([z, x*y])998True999sage: X == A.subscheme([x*y, z^2])1000False1001sage: B.<u, v, t> = AffineSpace(3, QQ)1002sage: X == B.subscheme([u*v, t])1003False1004"""1005if not isinstance(other, AlgebraicScheme_subscheme):1006return -11007A = self.ambient_space()1008if other.ambient_space() != A:1009return -11010return cmp(self.defining_ideal(), other.defining_ideal())10111012def _latex_(self):1013"""1014Return a LaTeX representation of this scheme.10151016EXAMPLES::10171018sage: P.<x, y, z> = ProjectiveSpace(2, GF(11))1019sage: S = P.subscheme([x^2-y*z])1020sage: S1021Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:1022x^2 - y*z1023sage: S._latex_()1024'\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^2 \\text{ defined by } x^{2} - y z'1025sage: S = P.subscheme([x^2-y*z, x^5])1026sage: S1027Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:1028x^2 - y*z,1029x^51030sage: S._latex_()1031'\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^2 \\text{ defined by } x^{2} - y z, x^{5}'1032"""1033polynomials = ', '.join(latex(f) for f in self.defining_polynomials())1034if not polynomials:1035polynomials = r"\text{no polynomials}"1036return (r"\text{Closed subscheme of } %s \text{ defined by } %s"1037% (latex(self.ambient_space()), polynomials))10381039def _repr_(self):1040"""1041Return a string representation of this scheme.10421043EXAMPLES::10441045sage: P.<x, y, z> = ProjectiveSpace(2, GF(11))1046sage: S = P.subscheme([x^2-y*z])1047sage: S1048Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:1049x^2 - y*z1050sage: S._repr_()1051'Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:\n x^2 - y*z'1052sage: S = P.subscheme([x^2-y*z, x^5])1053sage: S1054Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:1055x^2 - y*z,1056x^51057sage: S._repr_()1058'Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:\n x^2 - y*z,\n x^5'1059"""1060polynomials = ',\n '.join(str(f) for f in self.defining_polynomials())1061if not polynomials:1062polynomials = '(no polynomials)'1063return ("Closed subscheme of %s defined by:\n %s"1064% (self.ambient_space(), polynomials))10651066def defining_polynomials(self):1067"""1068Return the polynomials that define this scheme as a subscheme1069of its ambient space.10701071OUTPUT:10721073A tuple of polynomials in the coordinate ring of the ambient1074space.10751076EXAMPLES::10771078sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)1079sage: S = P.subscheme([x^2-y*z, x^3+z^3])1080sage: S.defining_polynomials()1081(x^2 - y*z, x^3 + z^3)1082"""1083return self.__polys10841085def defining_ideal(self):1086"""1087Return the ideal that defines this scheme as a subscheme1088of its ambient space.10891090OUTPUT:10911092An ideal in the coordinate ring of the ambient space.10931094EXAMPLES::10951096sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)1097sage: S = P.subscheme([x^2-y*z, x^3+z^3])1098sage: S.defining_ideal()1099Ideal (x^2 - y*z, x^3 + z^3) of Multivariate Polynomial Ring in x, y, z over Integer Ring1100"""1101try:1102return self.__I1103except AttributeError:1104R = self.ambient_space().coordinate_ring()1105self.__I = R.ideal(self.defining_polynomials())1106return self.__I11071108# Note: dimension must be implemented by the derived classes1109def codimension(self):1110r"""1111Return the codimension of the algebraic subscheme.11121113OUTPUT:11141115Integer.11161117EXAMPLES::11181119sage: PP.<x,y,z,w,v> = ProjectiveSpace(4,QQ)1120sage: V = PP.subscheme(x*y)1121sage: V.codimension()112211123sage: V.dimension()112431125"""1126return self.ambient_space().dimension() - self.dimension()11271128def irreducible_components(self):1129r"""1130Return the irreducible components of this algebraic scheme, as1131subschemes of the same ambient space.11321133OUTPUT: an immutable sequence of irreducible subschemes of the1134ambient space of this scheme11351136The components are cached.11371138EXAMPLES:11391140We define what is clearly a union of four hypersurfaces in1141`\P^4_{\QQ}` then find the irreducible components::11421143sage: PP.<x,y,z,w,v> = ProjectiveSpace(4,QQ)1144sage: V = PP.subscheme( (x^2 - y^2 - z^2)*(w^5 - 2*v^2*z^3)* w * (v^3 - x^2*z) )1145sage: V.irreducible_components()1146[1147Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1148w,1149Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1150x^2 - y^2 - z^2,1151Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1152x^2*z - v^3,1153Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1154w^5 - 2*z^3*v^21155]11561157We verify that the irrelevant ideal isn't accidently returned1158(see trac 6920)::11591160sage: PP.<x,y,z,w> = ProjectiveSpace(3,QQ)1161sage: f = x^3 + y^3 + z^3 + w^31162sage: R = f.parent()1163sage: I = [f] + [f.derivative(zz) for zz in PP.gens()]1164sage: V = PP.subscheme(I)1165sage: V.irreducible_components()1166[1167<BLANKLINE>1168]11691170The same polynomial as above defines a scheme with a1171nontrivial irreducible component in affine space (instead of1172the empty scheme as above)::11731174sage: AA.<x,y,z,w> = AffineSpace(4,QQ)1175sage: V = AA.subscheme(I)1176sage: V.irreducible_components()1177[1178Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:1179w,1180z,1181y,1182x1183]1184"""1185try:1186return self.__irreducible_components1187except AttributeError:1188pass1189I = self.defining_ideal()1190P = I.associated_primes()1191if self.is_projective():1192# In the projective case, we must exclude the prime ideals1193# that contain the irrelevant ideal, which is the ideal1194# generated by the variables, which are the gens of the1195# base ring.1196G = I.ring().gens()1197# We make a list of ideals with the property that "any"1198# of the elements of G are not in the ideal.1199P = [J for J in P if any(g not in J for g in G)]12001201A = self.ambient_space()1202C = Sequence([A.subscheme(X) for X in P], check=False, cr=True)1203C.sort()1204C.set_immutable()1205self.__irreducible_components = C1206return C12071208def Jacobian_matrix(self):1209r"""1210Return the matrix `\frac{\partial f_i}{\partial x_j}` of1211(formal) partial derivatives.12121213OUTPUT:12141215A matrix of polynomials.12161217EXAMPLES::12181219sage: P3.<w,x,y,z> = ProjectiveSpace(3, QQ)1220sage: twisted_cubic = P3.subscheme(matrix([[w, x, y],[x, y, z]]).minors(2))1221sage: twisted_cubic.Jacobian_matrix()1222[ y -2*x w 0]1223[ z -y -x w]1224[ 0 z -2*y x]1225"""1226R = self.ambient_space().coordinate_ring()1227return jacobian(self.defining_polynomials(), R.gens())12281229def Jacobian(self):1230r"""1231Return the Jacobian ideal.12321233This is the ideal generated by12341235* the `d\times d` minors of the Jacobian matrix, where `d` is1236the :meth:`codimension` of the algebraic scheme, and12371238* the defining polynomials of the algebraic scheme. Note that1239some authors do not include these in the definition of the1240Jacobian ideal. An example of a reference that does include1241the defining equations is [LazarsfeldJacobian].12421243OUTPUT:12441245An ideal in the coordinate ring of the ambient space.12461247REFERENCES:12481249.. [LazarsfeldJacobian]1250Robert Lazarsfeld:1251Positivity in algebraic geometry II;1252Positivity for Vector Bundles, and Multiplier Ideals,1253page 181.12541255EXAMPLES::12561257sage: P3.<w,x,y,z> = ProjectiveSpace(3, QQ)1258sage: twisted_cubic = P3.subscheme(matrix([[w, x, y],[x, y, z]]).minors(2))1259sage: twisted_cubic.Jacobian()1260Ideal (-x^2 + w*y, -x*y + w*z, -y^2 + x*z, x*z, -2*w*z, w*y, 3*w*y, -2*w*x,1261w^2, y*z, -2*x*z, w*z, 3*w*z, -2*w*y, w*x, z^2, -2*y*z, x*z, 3*x*z, -2*w*z,1262w*y) of Multivariate Polynomial Ring in w, x, y, z over Rational Field1263sage: twisted_cubic.defining_ideal()1264Ideal (-x^2 + w*y, -x*y + w*z, -y^2 + x*z) of Multivariate Polynomial Ring1265in w, x, y, z over Rational Field1266"""1267d = self.codimension()1268minors = self.Jacobian_matrix().minors(d)1269I = self.defining_ideal()1270minors = tuple([ I.reduce(m) for m in minors ])1271return I.ring().ideal(I.gens() + minors)12721273def reduce(self):1274r"""1275Return the corresponding reduced algebraic space associated to this1276scheme.12771278EXAMPLES: First we construct the union of a doubled and tripled1279line in the affine plane over `\QQ` ::12801281sage: A.<x,y> = AffineSpace(2, QQ)1282sage: X = A.subscheme([(x-1)^2*(x-y)^3]); X1283Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1284x^5 - 3*x^4*y + 3*x^3*y^2 - x^2*y^3 - 2*x^4 + 6*x^3*y1285- 6*x^2*y^2 + 2*x*y^3 + x^3 - 3*x^2*y + 3*x*y^2 - y^31286sage: X.dimension()1287112881289Then we compute the corresponding reduced scheme::12901291sage: Y = X.reduce(); Y1292Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1293x^2 - x*y - x + y12941295Finally, we verify that the reduced scheme `Y` is the union1296of those two lines::12971298sage: L1 = A.subscheme([x-1]); L11299Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1300x - 11301sage: L2 = A.subscheme([x-y]); L21302Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1303x - y1304sage: W = L1.union(L2); W # taken in ambient space1305Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1306x^2 - x*y - x + y1307sage: Y == W1308True1309"""1310try:1311return self._reduce1312except AttributeError:1313r = self.defining_ideal().radical()1314A = self.ambient_space()1315V = A.subscheme(r)1316V._reduce = V # so knows it is already reduced!1317self._reduce = V1318return V13191320def union(self, other):1321"""1322Return the scheme-theoretic union of self and other in their common1323ambient space.13241325EXAMPLES: We construct the union of a line and a tripled-point on1326the line.13271328::13291330sage: A.<x,y> = AffineSpace(2, QQ)1331sage: I = ideal([x,y])^31332sage: P = A.subscheme(I)1333sage: L = A.subscheme([y-1])1334sage: S = L.union(P); S1335Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1336y^4 - y^3,1337x*y^3 - x*y^2,1338x^2*y^2 - x^2*y,1339x^3*y - x^31340sage: S.dimension()134111342sage: S.reduce()1343Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1344y^2 - y,1345x*y - x13461347We can also use the notation "+" for the union::13481349sage: A.subscheme([x]) + A.subscheme([y^2 - (x^3+1)])1350Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1351x^4 - x*y^2 + x13521353Saving and loading::13541355sage: loads(S.dumps()) == S1356True1357"""1358if not isinstance(other, AlgebraicScheme_subscheme):1359raise TypeError, "other (=%s) must be a closed algebraic subscheme of an ambient space"%other1360A = self.ambient_space()1361if other.ambient_space() != A:1362raise ValueError, "other (=%s) must be in the same ambient space as self"%other1363return A.subscheme(self.defining_ideal().intersection(other.defining_ideal()))13641365__add__ = union13661367def intersection(self, other):1368"""1369Return the scheme-theoretic intersection of self and other in their1370common ambient space.13711372EXAMPLES::13731374sage: A.<x, y> = AffineSpace(2, ZZ)1375sage: X = A.subscheme([x^2-y])1376sage: Y = A.subscheme([y])1377sage: X.intersection(Y)1378Closed subscheme of Affine Space of dimension 2 over Integer Ring defined by:1379x^2 - y,1380y1381"""1382if not isinstance(other, AlgebraicScheme_subscheme):1383raise TypeError, "other (=%s) must be a closed algebraic subscheme of an ambient space"%other1384A = self.ambient_space()1385if other.ambient_space() != A:1386raise ValueError, "other (=%s) must be in the same ambient space as self"%other1387return A.subscheme(self.defining_ideal() + other.defining_ideal())13881389def complement(self, other=None):1390"""1391Return the scheme-theoretic complement other - self, where1392self and other are both closed algebraic subschemes of the1393same ambient space.13941395If other is unspecified, it is taken to be the ambient space1396of self.13971398EXAMPLES::13991400sage: A.<x, y, z> = AffineSpace(3, ZZ)1401sage: X = A.subscheme([x+y-z])1402sage: Y = A.subscheme([x-y+z])1403sage: Y.complement(X)1404Quasi-affine subscheme X - Y of Affine Space of1405dimension 3 over Integer Ring, where X is defined by:1406x + y - z1407and Y is defined by:1408x - y + z1409sage: Y.complement()1410Quasi-affine subscheme X - Y of Affine Space of1411dimension 3 over Integer Ring, where X is defined by:1412(no polynomials)1413and Y is defined by:1414x - y + z1415sage: P.<x, y, z> = ProjectiveSpace(2, QQ)1416sage: X = P.subscheme([x^2+y^2+z^2])1417sage: Y = P.subscheme([x*y+y*z+z*x])1418sage: Y.complement(X)1419Quasi-projective subscheme X - Y of Projective Space of1420dimension 2 over Rational Field, where X is defined by:1421x^2 + y^2 + z^21422and Y is defined by:1423x*y + x*z + y*z1424sage: Y.complement(P)1425Quasi-projective subscheme X - Y of Projective Space of1426dimension 2 over Rational Field, where X is defined by:1427(no polynomials)1428and Y is defined by:1429x*y + x*z + y*z1430"""1431A = self.ambient_space()1432if other is None:1433other = A.subscheme([])1434elif not isinstance(other, AlgebraicScheme_subscheme):1435if other == A:1436other = A.subscheme([])1437else:1438raise TypeError, \1439"Argument other (=%s) must be a closed algebraic subscheme of an ambient space"%other1440if other.ambient_space() != A:1441raise ValueError, "other (=%s) must be in the same ambient space as self"%other1442return AlgebraicScheme_quasi(other, self)14431444def rational_points(self, F=None, bound=0):1445"""1446Return the rational points on the algebraic subscheme.14471448EXAMPLES:14491450One can enumerate points up to a given bound on a projective scheme1451over the rationals::14521453sage: E = EllipticCurve('37a')1454sage: E.rational_points(bound=8)1455[(-1 : -1 : 1), (-1 : 0 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 0), (1/4 : -5/8 : 1), (1/4 : -3/8 : 1), (1 : -1 : 1), (1 : 0 : 1), (2 : -3 : 1), (2 : 2 : 1)]14561457For a small finite field, the complete set of points can be1458enumerated. ::14591460sage: Etilde = E.base_extend(GF(3))1461sage: Etilde.rational_points()1462[(0 : 0 : 1), (0 : 1 : 0), (0 : 2 : 1), (1 : 0 : 1),1463(1 : 2 : 1), (2 : 0 : 1), (2 : 2 : 1)]14641465The class of hyperelliptic curves does not (yet) support1466desingularization of the places at infinity into two points::14671468sage: FF = FiniteField(7)1469sage: P.<x> = PolynomialRing(FiniteField(7))1470sage: C = HyperellipticCurve(x^8+x+1)1471sage: C.rational_points()1472[(0 : 1 : 0), (0 : 1 : 1), (0 : 6 : 1), (2 : 0 : 1),1473(4 : 0 : 1), (6 : 1 : 1), (6 : 6 : 1)]14741475TODO:147614771. The above algorithms enumerate all projective points and1478test whether they lie on the scheme; Implement a more naive1479sieve at least for covers of the projective line.148014812. Implement Stoll's model in weighted projective space to1482resolve singularities and find two points (1 : 1 : 0) and1483(-1 : 1 : 0) at infinity.1484"""1485if F == None:1486F = self.base_ring()1487X = self(F)1488if is_RationalField(F) or F == ZZ:1489if not bound > 0:1490raise TypeError, "A positive bound (= %s) must be specified."%bound1491try:1492return X.points(bound)1493except TypeError:1494raise TypeError, "Unable to enumerate points over %s."%F1495try:1496return X.points()1497except TypeError:1498raise TypeError, "Unable to enumerate points over %s."%F14991500def change_ring(self,R):1501r"""1502Returns a new projective subscheme whose base ring is self coerced to R.15031504EXAMPLES::15051506sage: P.<x,y>=ProjectiveSpace(QQ,1)1507sage: X=P.subscheme([3*x^2-y^2])1508sage: H=Hom(X,X)1509sage: X.change_ring(GF(3))1510Closed subscheme of Projective Space of dimension 1 over Finite Field of size 3 defined by:1511-y^21512"""1513A=self.ambient_space().change_ring(R)1514I=self.defining_ideal().change_ring(A.coordinate_ring())1515return(A.subscheme(I))15161517#*******************************************************************1518# Affine varieties1519#*******************************************************************1520class AlgebraicScheme_subscheme_affine(AlgebraicScheme_subscheme):1521"""1522Construct an algebraic subscheme of affine space.15231524.. WARNING::15251526You should not create objects of this class directly. The1527preferred method to construct such subschemes is to use1528:meth:`~sage.schemes.affine.affine_space.AffineSpace_generic.subscheme`1529method of :class:`affine space1530<sage.schemes.affine.affine_space.AffineSpace_generic>`.15311532INPUT:15331534- ``A`` -- ambient :class:`affine space1535<sage.schemes.affine.affine_space.AffineSpace_generic>`15361537- ``polynomials`` -- single polynomial, ideal or iterable of1538defining polynomials.15391540EXAMPLES::15411542sage: A3.<x, y, z> = AffineSpace(3, QQ)1543sage: A3.subscheme([x^2-y*z])1544Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:1545x^2 - y*z15461547TESTS::15481549sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_affine1550sage: AlgebraicScheme_subscheme_affine(A3, [x^2-y*z])1551Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:1552x^2 - y*z1553"""15541555def _morphism(self, *args, **kwds):1556"""1557A morphism between two schemes in your category, usually defined via1558polynomials. Your morphism class should derive from1559:class:`SchemeMorphism_polynomial`. These morphisms will usually be1560elements of the Hom-set1561:class:`~sage.schemes.generic.homset.SchemeHomset_generic`.15621563EXAMPLES::15641565sage: P2.<x,y,z> = ProjectiveSpace(2, ZZ)1566sage: P2._morphism(P2.Hom(P2), [x,y,z])1567Scheme endomorphism of Projective Space of dimension 2 over Integer Ring1568Defn: Defined on coordinates by sending (x : y : z) to1569(x : y : z)15701571"""1572return self.ambient_space()._morphism(*args, **kwds)15731574def dimension(self):1575"""1576Return the dimension of the affine algebraic subscheme.15771578OUTPUT:15791580Integer.15811582EXAMPLES::15831584sage: A.<x,y> = AffineSpace(2, QQ)1585sage: A.subscheme([]).dimension()158621587sage: A.subscheme([x]).dimension()158811589sage: A.subscheme([x^5]).dimension()159011591sage: A.subscheme([x^2 + y^2 - 1]).dimension()159211593sage: A.subscheme([x*(x-1), y*(y-1)]).dimension()1594015951596Something less obvious::15971598sage: A.<x,y,z,w> = AffineSpace(4, QQ)1599sage: X = A.subscheme([x^2, x^2*y^2 + z^2, z^2 - w^2, 10*x^2 + w^2 - z^2])1600sage: X1601Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:1602x^2,1603x^2*y^2 + z^2,1604z^2 - w^2,160510*x^2 - z^2 + w^21606sage: X.dimension()160711608"""1609try:1610return self.__dimension1611except AttributeError:1612self.__dimension = self.defining_ideal().dimension()1613return self.__dimension16141615def projective_embedding(self, i=None, X=None):1616"""1617Returns a morphism from this affine scheme into an ambient1618projective space of the same dimension.16191620INPUT:16211622- ``i`` -- integer (default: dimension of self = last1623coordinate) determines which projective embedding to compute. The1624embedding is that which has a 1 in the i-th coordinate, numbered1625from 0.162616271628- ``X`` -- (default: None) projective scheme, i.e., codomain of1629morphism; this is constructed if it is not given.16301631EXAMPLES::16321633sage: A.<x, y, z> = AffineSpace(3, ZZ)1634sage: S = A.subscheme([x*y-z])1635sage: S.projective_embedding()1636Scheme morphism:1637From: Closed subscheme of Affine Space of dimension 3 over Integer Ring defined by:1638x*y - z1639To: Closed subscheme of Projective Space of dimension 3 over Integer Ring defined by:1640x0*x1 - x2*x31641Defn: Defined on coordinates by sending (x, y, z) to1642(x : y : z : 1)1643"""1644AA = self.ambient_space()1645n = AA.dimension_relative()1646if i is None:1647try:1648i = self._default_embedding_index1649except AttributeError:1650i = int(n)1651else:1652i = int(i)1653if i < 0 or i > n:1654raise ValueError, \1655"Argument i (=%s) must be between 0 and %s, inclusive"%(i, n)1656try:1657return self.__projective_embedding[i]1658except AttributeError:1659self.__projective_embedding = {}1660except KeyError:1661pass1662if X is None:1663PP = sage.schemes.projective.projective_space.ProjectiveSpace(n, AA.base_ring())1664v = list(PP.gens())1665z = v.pop(i)1666v.append(z)1667polys = self.defining_polynomials()1668X = PP.subscheme([ f.homogenize()(v) for f in polys ])1669R = AA.coordinate_ring()1670v = list(R.gens())1671v.insert(i, R(1))1672phi = self.hom(v, X)1673self.__projective_embedding[i] = phi1674return phi16751676def is_smooth(self, point=None):1677r"""1678Test whether the algebraic subscheme is smooth.16791680INPUT:16811682- ``point`` -- A point or ``None`` (default). The point to1683test smoothness at.16841685OUTPUT:16861687Boolean. If no point was specified, returns whether the1688algebraic subscheme is smooth everywhere. Otherwise,1689smoothness at the specified point is tested.16901691EXAMPLES::16921693sage: A2.<x,y> = AffineSpace(2,QQ)1694sage: cuspidal_curve = A2.subscheme([y^2-x^3])1695sage: cuspidal_curve1696Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1697-x^3 + y^21698sage: smooth_point = cuspidal_curve.point([1,1])1699sage: smooth_point in cuspidal_curve1700True1701sage: singular_point = cuspidal_curve.point([0,0])1702sage: singular_point in cuspidal_curve1703True1704sage: cuspidal_curve.is_smooth(smooth_point)1705True1706sage: cuspidal_curve.is_smooth(singular_point)1707False1708sage: cuspidal_curve.is_smooth()1709False1710"""1711R = self.ambient_space().coordinate_ring()1712if not point is None:1713self._check_satisfies_equations(point)1714point_subs = dict(zip(R.gens(), point))1715Jac = self.Jacobian().subs(point_subs)1716return not Jac.is_zero()17171718# testing smoothness everywhere tends to be expensive1719try:1720return self._smooth1721except AttributeError:1722pass1723sing_dim = self.Jacobian().dimension()1724self._smooth = (sing_dim == -1)1725return self._smooth1726172717281729#*******************************************************************1730# Projective varieties1731#*******************************************************************1732class AlgebraicScheme_subscheme_projective(AlgebraicScheme_subscheme):1733"""1734Construct an algebraic subscheme of projective space.17351736.. WARNING::17371738You should not create objects of this class directly. The1739preferred method to construct such subschemes is to use1740:meth:`~sage.schemes.projective.projective_space.ProjectiveSpace_field.subscheme`1741method of :class:`projective space1742<sage.schemes.projective.projective_space.ProjectiveSpace_field>`.17431744INPUT:17451746- ``A`` -- ambient :class:`projective space1747<sage.schemes.projective.projective_space.ProjectiveSpace_field>`.17481749- ``polynomials`` -- single polynomial, ideal or iterable of1750defining homogeneous polynomials.17511752EXAMPLES::17531754sage: P.<x, y, z> = ProjectiveSpace(2, QQ)1755sage: P.subscheme([x^2-y*z])1756Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1757x^2 - y*z17581759TESTS::17601761sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_projective1762sage: AlgebraicScheme_subscheme_projective(P, [x^2-y*z])1763Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1764x^2 - y*z1765"""17661767def _morphism(self, *args, **kwds):1768r"""1769Construct a morphism determined by action on points of ``self``.17701771For internal use only.17721773INPUT:17741775- same as for1776:class:`~sage.schemes.projective.projective_morphism.SchemeMorphism_polynomial_projective_space`.17771778OUPUT:17791780- :class:`~sage.schemes.projective.projective_morphism.SchemeMorphism_polynomial_projective_space`.17811782TESTS::17831784sage: P1.<x,y> = ProjectiveSpace(1,QQ)1785sage: P2 = ProjectiveSpace(2,QQ)1786sage: H12 = P1.Hom(P2)1787sage: H12([x^2,x*y, y^2]) # indirect doctest1788Scheme morphism:1789From: Projective Space of dimension 1 over Rational Field1790To: Projective Space of dimension 2 over Rational Field1791Defn: Defined on coordinates by sending (x : y) to1792(x^2 : x*y : y^2)1793sage: P1._morphism(H12, [x^2,x*y, y^2])1794Scheme morphism:1795From: Projective Space of dimension 1 over Rational Field1796To: Projective Space of dimension 2 over Rational Field1797Defn: Defined on coordinates by sending (x : y) to1798(x^2 : x*y : y^2)1799"""1800return self.ambient_space()._morphism(*args, **kwds)18011802def dimension(self):1803"""1804Return the dimension of the projective algebraic subscheme.18051806OUTPUT:18071808Integer.18091810EXAMPLES::18111812sage: P2.<x,y,z> = ProjectiveSpace(2, QQ)1813sage: P2.subscheme([]).dimension()181421815sage: P2.subscheme([x]).dimension()181611817sage: P2.subscheme([x^5]).dimension()181811819sage: P2.subscheme([x^2 + y^2 - z^2]).dimension()182011821sage: P2.subscheme([x*(x-z), y*(y-z)]).dimension()1822018231824Something less obvious::18251826sage: P3.<x,y,z,w,t> = ProjectiveSpace(4, QQ)1827sage: X = P3.subscheme([x^2, x^2*y^2 + z^2*t^2, z^2 - w^2, 10*x^2 + w^2 - z^2])1828sage: X1829Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1830x^2,1831x^2*y^2 + z^2*t^2,1832z^2 - w^2,183310*x^2 - z^2 + w^21834sage: X.dimension()183511836"""1837try:1838return self.__dimension1839except AttributeError:1840self.__dimension = self.defining_ideal().dimension() - 11841return self.__dimension18421843def affine_patch(self, i):1844r"""1845Return the `i^{th}` affine patch of this projective scheme.1846This is the intersection with this `i^{th}` affine patch of1847its ambient space.18481849INPUT:18501851- ``i`` -- integer between 0 and dimension of self, inclusive.18521853OUTPUT:18541855An affine algebraic scheme with fixed1856:meth:`embedding_morphism` equal to the default1857:meth:`projective_embedding` map`.18581859EXAMPLES::18601861sage: PP = ProjectiveSpace(2, QQ, names='X,Y,Z')1862sage: X,Y,Z = PP.gens()1863sage: C = PP.subscheme(X^3*Y + Y^3*Z + Z^3*X)1864sage: U = C.affine_patch(0)1865sage: U1866Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1867x0^3*x1 + x1^3 + x01868sage: U.embedding_morphism()1869Scheme morphism:1870From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1871x0^3*x1 + x1^3 + x01872To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1873X^3*Y + Y^3*Z + X*Z^31874Defn: Defined on coordinates by sending (x0, x1) to1875(1 : x0 : x1)1876sage: U.projective_embedding() is U.embedding_morphism()1877True1878"""1879i = int(i) # implicit type checking1880PP = self.ambient_space()1881n = PP.dimension()1882if i < 0 or i > n:1883raise ValueError, "Argument i (= %s) must be between 0 and %s."%(i, n)1884try:1885return self.__affine_patches[i]1886except AttributeError:1887self.__affine_patches = {}1888except KeyError:1889pass1890AA = PP.affine_patch(i)1891phi = AA.projective_embedding()1892polys = self.defining_polynomials()1893xi = phi.defining_polynomials()1894U = AA.subscheme([ f(xi) for f in polys ])1895U._default_embedding_index = i1896phi = U.projective_embedding(i, self)1897self.__affine_patches[i] = U1898U._embedding_morphism = phi1899return U19001901def _best_affine_patch(self, point):1902r"""1903Return the best affine patch of the ambient projective space.19041905The "best" affine patch is where you end up dividing by the1906homogeneous coordinate with the largest absolutue1907value. Division by small numbers is numerically unstable.19081909INPUT:19101911- ``point`` -- a point of the algebraic subscheme.19121913OUTPUT:19141915Integer. The index of the patch. See :meth:`affine_patch`.19161917EXAMPLES::19181919sage: P.<x,y,z>= ProjectiveSpace(QQ,2)1920sage: S = P.subscheme(x+2*y+3*z)1921sage: S._best_affine_patch(P.point([0,-3,2]))192211923sage: S._best_affine_patch([0,-3,2])1924119251926TESTS::19271928sage: F = GF(3)1929sage: P.<x,y,z>= ProjectiveSpace(F,2)1930sage: S._best_affine_patch([0,1,2])193121932"""1933point = list(point)1934try:1935abs_point = map(abs, point)1936except ArithmeticError:1937# our base ring does not know abs1938abs_point = point1939# find best patch1940i_max = 01941p_max = abs_point[i_max]1942for i in range(1,len(point)):1943if abs_point[i]>p_max:1944i_max = i1945p_max = abs_point[i_max]1946return i_max19471948def neighborhood(self, point):1949r"""1950Return an affine algebraic subscheme isomorphic to a1951neighborhood of the ``point``.19521953INPUT:19541955- ``point`` -- a point of the projective subscheme.19561957OUTPUT19581959An affine algebraic scheme (polynomial equations in affine1960space) ``result`` such that19611962* :meth:`embedding_morphism1963<AlgebraicScheme.embedding_morphism>` is an isomorphism to a1964neighborhood of ``point``19651966* :meth:`embedding_center <AlgebraicScheme.embedding_center>`1967is mapped to ``point``.19681969EXAMPLES::19701971sage: P.<x,y,z>= ProjectiveSpace(QQ,2)1972sage: S = P.subscheme(x+2*y+3*z)1973sage: s = S.point([0,-3,2]); s1974(0 : -3/2 : 1)1975sage: patch = S.neighborhood(s); patch1976Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1977x0 + 3*x11978sage: patch.embedding_morphism()1979Scheme morphism:1980From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1981x0 + 3*x11982To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1983x + 2*y + 3*z1984Defn: Defined on coordinates by sending (x0, x1) to1985(x0 : -3/2 : x1 + 1)1986sage: patch.embedding_center()1987(0, 0)1988sage: patch.embedding_morphism()([0,0])1989(0 : -3/2 : 1)1990sage: patch.embedding_morphism()(patch.embedding_center())1991(0 : -3/2 : 1)1992"""1993point = list(point)1994self._check_satisfies_equations(point)1995PP = self.ambient_space()1996n = PP.dimension()1997i = self._best_affine_patch(point)19981999patch_cover = PP.affine_patch(i)2000R = patch_cover.coordinate_ring()20012002phi = list(point)2003for j in range(0,i):2004phi[j] = phi[j] + R.gen(j)2005for j in range(i,n):2006phi[j+1] = phi[j+1] + R.gen(j)20072008pullback_polys = [f(phi) for f in self.defining_polynomials()]2009patch = patch_cover.subscheme(pullback_polys)2010patch_hom = patch.hom(phi,self)2011patch._embedding_center = patch.point([0]*n)2012patch._embedding_morphism = patch_hom2013return patch20142015def is_smooth(self, point=None):2016r"""2017Test whether the algebraic subscheme is smooth.20182019INPUT:20202021- ``point`` -- A point or ``None`` (default). The point to2022test smoothness at.20232024OUTPUT:20252026Boolean. If no point was specified, returns whether the2027algebraic subscheme is smooth everywhere. Otherwise,2028smoothness at the specified point is tested.20292030EXAMPLES::20312032sage: P2.<x,y,z> = ProjectiveSpace(2,QQ)2033sage: cuspidal_curve = P2.subscheme([y^2*z-x^3])2034sage: cuspidal_curve2035Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:2036-x^3 + y^2*z2037sage: cuspidal_curve.is_smooth([1,1,1])2038True2039sage: cuspidal_curve.is_smooth([0,0,1])2040False2041sage: cuspidal_curve.is_smooth()2042False2043sage: P2.subscheme([y^2*z-x^3+z^3+1/10*x*y*z]).is_smooth()2044True20452046TESTS::20472048sage: H = P2.subscheme(x)2049sage: H.is_smooth() # one of the few cases where the cone over the subvariety is smooth2050True2051"""2052if not point is None:2053self._check_satisfies_equations(point)2054R = self.ambient_space().coordinate_ring()2055point_subs = dict(zip(R.gens(), point))2056Jac = self.Jacobian().subs(point_subs)2057return not Jac.is_zero()20582059# testing smoothness everywhere tends to be expensive2060try:2061return self._smooth2062except AttributeError:2063pass2064sing_dim = self.Jacobian().dimension()2065# We really test the affine cone here; the origin is always a singular point:2066self._smooth = (sing_dim <= 0)2067return self._smooth206820692070#*******************************************************************2071# Toric varieties2072#*******************************************************************2073class AlgebraicScheme_subscheme_toric(AlgebraicScheme_subscheme):2074r"""2075Construct an algebraic subscheme of a toric variety.20762077.. WARNING::20782079You should not create objects of this class directly. The2080preferred method to construct such subschemes is to use2081:meth:`~ToricVariety_field.subscheme` method of :class:`toric2082varieties2083<sage.schemes.toric.variety.ToricVariety_field>`.20842085INPUT:20862087- ``toric_variety`` -- ambient :class:`toric variety2088<ToricVariety_field>`;20892090- ``polynomials`` -- single polynomial, list, or ideal of defining2091polynomials in the coordinate ring of ``toric_variety``.20922093OUTPUT:20942095- :class:`algebraic subscheme of a toric variety2096<AlgebraicScheme_subscheme_toric>`.20972098TESTS::20992100sage: fan = FaceFan(lattice_polytope.octahedron(2))2101sage: P1xP1 = ToricVariety(fan, "x s y t")2102sage: P1xP1.inject_variables()2103Defining x, s, y, t2104sage: import sage.schemes.generic.algebraic_scheme as SCM2105sage: X = SCM.AlgebraicScheme_subscheme_toric(2106... P1xP1, [x*s + y*t, x^3+y^3])2107sage: X2108Closed subscheme of 2-d toric variety2109covered by 4 affine patches defined by:2110x*s + y*t,2111x^3 + y^321122113A better way to construct the same scheme as above::21142115sage: P1xP1.subscheme([x*s + y*t, x^3+y^3])2116Closed subscheme of 2-d toric variety2117covered by 4 affine patches defined by:2118x*s + y*t,2119x^3 + y^32120"""21212122# Implementation note: if the toric variety is affine you should2123# construct instances of the derived class2124# AlgebraicScheme_subscheme_affine_toric instead.21252126def __init__(self, toric_variety, polynomials):2127r"""2128See :class:`AlgebraicScheme_subscheme_toric` for documentation.21292130TESTS::21312132sage: fan = FaceFan(lattice_polytope.octahedron(2))2133sage: P1xP1 = ToricVariety(fan, "x s y t")2134sage: P1xP1.inject_variables()2135Defining x, s, y, t2136sage: import sage.schemes.generic.algebraic_scheme as SCM2137sage: X = SCM.AlgebraicScheme_subscheme_toric(2138... P1xP1, [x*s + y*t, x^3+y^3])2139sage: X2140Closed subscheme of 2-d toric variety2141covered by 4 affine patches defined by:2142x*s + y*t,2143x^3 + y^32144"""2145# Just to make sure that keyword arguments will be passed correctly2146super(AlgebraicScheme_subscheme_toric, self).__init__(toric_variety,2147polynomials)21482149def _morphism(self, *args, **kwds):2150r"""2151Construct a morphism determined by action on points of ``self``.21522153INPUT:21542155- same as for2156:class:`~sage.schemes.toric.morphism.SchemeMorphism_polynomial_toric_variety`.21572158OUPUT:21592160- :class:`~sage.schemes.toric.morphism.SchemeMorphism_polynomial_toric_variety`.21612162TESTS::21632164sage: fan = FaceFan(lattice_polytope.octahedron(2))2165sage: P1xP1 = ToricVariety(fan)2166sage: P1xP1.inject_variables()2167Defining z0, z1, z2, z32168sage: P1 = P1xP1.subscheme(z0-z2)2169sage: H = P1.Hom(P1xP1)2170sage: H([z0,z1,z0,z3])2171Scheme morphism:2172From: Closed subscheme of 2-d toric variety2173covered by 4 affine patches defined by:2174z0 - z22175To: 2-d toric variety covered by 4 affine patches2176Defn: Defined on coordinates by sending [z0 : z1 : z2 : z3] to2177[z2 : z1 : z2 : z3]21782179sage: P1._morphism(H, [z0,z1,z0,z3])2180Scheme morphism:2181From: Closed subscheme of 2-d toric variety2182covered by 4 affine patches defined by:2183z0 - z22184To: 2-d toric variety covered by 4 affine patches2185Defn: Defined on coordinates by sending [z0 : z1 : z2 : z3] to2186[z2 : z1 : z2 : z3]2187"""2188from sage.schemes.toric.morphism import SchemeMorphism_polynomial_toric_variety2189return SchemeMorphism_polynomial_toric_variety(*args, **kwds)21902191def _point_homset(self, *args, **kwds):2192r"""2193Construct a Hom-set for ``self``.21942195INPUT:21962197- same as for2198:class:`~sage.schemes.generic.homset.SchemeHomset_points_toric_field`.21992200OUPUT:22012202:class:`~sage.schemes.toric.homset.SchemeHomset_points_subscheme_toric_field`.22032204TESTS::22052206sage: P2.<x,y,z> = toric_varieties.P2()2207sage: quadric = P2.subscheme([x^2 + y^2 + z^2])2208sage: quadric._point_homset(Spec(QQ), quadric)2209Set of rational points of Closed subscheme of 2-d CPR-Fano2210toric variety covered by 3 affine patches defined by:2211x^2 + y^2 + z^22212sage: type(quadric.point_set())2213<class 'sage.schemes.toric.homset.SchemeHomset_points_subscheme_toric_field_with_category'>2214"""2215from sage.schemes.toric.homset import SchemeHomset_points_subscheme_toric_field2216return SchemeHomset_points_subscheme_toric_field(*args, **kwds)22172218def fan(self):2219"""2220Return the fan of the ambient space.22212222OUTPUT:22232224A fan.22252226EXAMPLES::22272228sage: P2.<x,y,z> = toric_varieties.P(2)2229sage: E = P2.subscheme([x^2+y^2+z^2])2230sage: E.fan()2231Rational polyhedral fan in 2-d lattice N2232"""2233return self.ambient_space().fan()22342235def affine_patch(self, i):2236r"""2237Return the ``i``-th affine patch of ``self`` as an affine2238toric algebraic scheme.22392240INPUT:22412242- ``i`` -- integer, index of a generating cone of the fan of the2243ambient space of ``self``.22442245OUTPUT:22462247- subscheme of an affine :class:`toric variety2248<sage.schemes.toric.variety.ToricVariety_field>`2249corresponding to the pull-back of ``self`` by the embedding2250morphism of the ``i``-th :meth:`affine patch of the ambient2251space2252<sage.schemes.toric.variety.ToricVariety_field.affine_patch>`2253of ``self``.22542255The result is cached, so the ``i``-th patch is always the same object2256in memory.22572258EXAMPLES::22592260sage: fan = FaceFan(lattice_polytope.octahedron(2))2261sage: P1xP1 = ToricVariety(fan, "x s y t")2262sage: patch1 = P1xP1.affine_patch(1)2263sage: patch1.embedding_morphism()2264Scheme morphism:2265From: 2-d affine toric variety2266To: 2-d toric variety covered by 4 affine patches2267Defn: Defined on coordinates by sending [y : t] to2268[1 : 1 : y : t]2269sage: P1xP1.inject_variables()2270Defining x, s, y, t2271sage: P1 = P1xP1.subscheme(x-y)2272sage: subpatch = P1.affine_patch(1)2273sage: subpatch2274Closed subscheme of 2-d affine toric variety defined by:2275-y + 12276"""2277i = int(i) # implicit type checking2278try:2279return self._affine_patches[i]2280except AttributeError:2281self._affine_patches = dict()2282except KeyError:2283pass2284ambient_patch = self.ambient_space().affine_patch(i)2285phi_p = ambient_patch.embedding_morphism().defining_polynomials()2286patch = ambient_patch.subscheme(2287[p(phi_p) for p in self.defining_polynomials()])2288patch._embedding_morphism = patch.hom(phi_p, self, check=False)2289self._affine_patches[i] = patch2290return patch22912292def affine_algebraic_patch(self, cone=None, names=None):2293r"""2294Return the affine patch corresponding to ``cone`` as an affine2295algebraic scheme.22962297INPUT:22982299- ``cone`` -- a :class:`Cone2300<sage.geometry.cone.ConvexRationalPolyhedralCone>` `\sigma`2301of the fan. It can be omitted for an affine toric variety,2302in which case the single generating cone is used.23032304OUTPUT:23052306An :class:`affine algebraic subscheme2307<sage.schemes.generic.algebraic_scheme.AlgebraicScheme_subscheme_affine>`2308corresponding to the patch `\mathop{Spec}(\sigma^\vee \cap M)`2309associated to the cone `\sigma`.23102311See also :meth:`affine_patch`, which expresses the patches as2312subvarieties of affine toric varieties instead.23132314REFERENCES:23152316..23172318David A. Cox, "The Homogeneous Coordinate Ring of a Toric2319Variety", Lemma 2.2.2320http://www.arxiv.org/abs/alg-geom/9210008v223212322EXAMPLES::23232324sage: P2.<x,y,z> = toric_varieties.P2()2325sage: cone = P2.fan().generating_cone(0)2326sage: V = P2.subscheme(x^3+y^3+z^3)2327sage: V.affine_algebraic_patch(cone)2328Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:2329z0^3 + z1^3 + 123302331sage: cone = Cone([(0,1),(2,1)])2332sage: A2Z2.<x,y> = AffineToricVariety(cone)2333sage: A2Z2.affine_algebraic_patch()2334Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:2335-z0*z1 + z2^22336sage: V = A2Z2.subscheme(x^2+y^2-1)2337sage: patch = V.affine_algebraic_patch(); patch2338Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:2339-z0*z1 + z2^2,2340z0 + z1 - 12341sage: nbhd_patch = V.neighborhood([1,0]).affine_algebraic_patch(); nbhd_patch2342Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:2343-z0*z1 + z2^2,2344z0 + z1 - 12345sage: nbhd_patch.embedding_center()2346(0, 1, 0)23472348Here we got two defining equations. The first one describes2349the singularity of the ambient space and the second is the2350pull-back of `x^2+y^2-1` ::23512352sage: lp = LatticePolytope([(1,0,0),(1,1,0),(1,1,1),(1,0,1),(-2,-1,-1)])2353sage: X.<x,y,u,v,t> = CPRFanoToricVariety(Delta_polar=lp)2354sage: Y = X.subscheme(x*v+y*u+t)2355sage: cone = Cone([(1,0,0),(1,1,0),(1,1,1),(1,0,1)])2356sage: Y.affine_algebraic_patch(cone)2357Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:2358z0*z2 - z1*z3,2359z1 + z3 + 12360"""2361from sage.modules.all import vector2362from sage.misc.all import prod2363ambient = self.ambient_space()2364fan = ambient.fan()2365if cone is None:2366assert ambient.is_affine()2367cone = fan.generating_cone(0)2368else:2369cone = fan.embed(cone)2370# R/I = C[sigma^dual cap M]2371R, I, dualcone = ambient._semigroup_ring(cone, names)23722373# inhomogenize the Cox homogeneous polynomial with respect to the given cone2374inhomogenize = dict( (ambient.coordinate_ring().gen(i), 1)2375for i in range(0,fan.nrays())2376if not i in cone.ambient_ray_indices() )2377polynomials = [ p.subs(inhomogenize) for p in self.defining_polynomials() ]23782379# map the monomial x^{D_m} to m, see reference.2380n_rho_matrix = cone.rays().matrix()2381def pullback_polynomial(p):2382result = R.zero()2383for coefficient, monomial in p:2384exponent = monomial.exponents()[0]2385exponent = [ exponent[i] for i in cone.ambient_ray_indices() ]2386exponent = vector(ZZ,exponent)2387m = n_rho_matrix.solve_right(exponent)2388assert all(x in ZZ for x in m), \2389'The polynomial '+str(p)+' does not define a ZZ-divisor!'2390m_coeffs = dualcone.Hilbert_coefficients(m)2391result += coefficient * prod(R.gen(i)**m_coeffs[i]2392for i in range(0,R.ngens()))2393return result23942395# construct the affine algebraic scheme to use as patch2396polynomials = map(pullback_polynomial, polynomials)2397patch_cover = sage.schemes.affine.affine_space.AffineSpace(R)2398polynomials = list(I.gens()) + polynomials2399polynomials = filter( lambda x:not x.is_zero(), polynomials)2400patch = patch_cover.subscheme(polynomials)24012402# TODO: If the cone is not smooth, then the coordinate_ring()2403# of the affine toric variety is wrong; it should be the2404# G-invariant part. So we can't construct the embedding2405# morphism in that case.2406if cone.is_smooth():2407x = ambient.coordinate_ring().gens()2408phi = []2409for i in range(0,fan.nrays()):2410if i in cone.ambient_ray_indices():2411phi.append(pullback_polynomial(x[i]))2412else:2413phi.append(1)2414patch._embedding_morphism = patch.hom(phi, self)2415else:2416patch._embedding_morphism = (NotImplementedError,2417'I only know how to construct embedding morphisms for smooth patches')24182419try:2420point = self.embedding_center()2421except AttributeError:2422return patch24232424# it remains to find the preimage of point2425# map m to the monomial x^{D_m}, see reference.2426F = ambient.coordinate_ring().fraction_field()2427image = []2428for m in dualcone.Hilbert_basis():2429x_Dm = prod([ F.gen(i)**(m*n) for i,n in enumerate(fan.rays()) ])2430image.append(x_Dm)2431patch._embedding_center = tuple( f(list(point)) for f in image )2432return patch24332434def _best_affine_patch(self, point):2435r"""2436Return the best affine patch of the ambient toric variety.24372438INPUT:24392440- ``point`` -- a point of the algebraic subscheme.24412442OUTPUT:24432444Integer. The index of the patch. See :meth:`affine_patch`.24452446EXAMPLES::24472448sage: P.<x,y,z>= toric_varieties.P2()2449sage: S = P.subscheme(x+2*y+3*z)2450sage: S._best_affine_patch(P.point([2,-3,0]))245112452sage: S._best_affine_patch([2,-3,0])245312454"""2455# TODO: this method should pick a "best" patch in the sense2456# that it is numerically stable to dehomogenize, see the2457# corresponding method for projective varieties.2458point = list(point)2459zeros = set(i for i, coord in enumerate(point) if coord == 0)2460for cone_idx, cone in enumerate(self.ambient_space().fan().generating_cones()):2461if zeros.issubset(cone.ambient_ray_indices()):2462return cone_idx2463assert False, 'The point must not have been a point of the toric variety.'24642465def neighborhood(self, point):2466r"""2467Return an toric algebraic scheme isomorphic to neighborhood of2468the ``point``.24692470INPUT:24712472- ``point`` -- a point of the toric algebraic scheme.24732474OUTPUT24752476An affine toric algebraic scheme (polynomial equations in an2477affine toric variety) with fixed2478:meth:`~AlgebraicScheme.embedding_morphism` and2479:meth:`~AlgebraicScheme.embedding_center`.24802481EXAMPLES::24822483sage: P.<x,y,z>= toric_varieties.P2()2484sage: S = P.subscheme(x+2*y+3*z)2485sage: s = S.point([0,-3,2]); s2486[0 : -3 : 2]2487sage: patch = S.neighborhood(s); patch2488Closed subscheme of 2-d affine toric variety defined by:2489x + 2*y + 62490sage: patch.embedding_morphism()2491Scheme morphism:2492From: Closed subscheme of 2-d affine toric variety defined by:2493x + 2*y + 62494To: Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by:2495x + 2*y + 3*z2496Defn: Defined on coordinates by sending [x : y] to2497[-2*y - 6 : y : 2]2498sage: patch.embedding_center()2499[0 : -3]2500sage: patch.embedding_morphism()(patch.embedding_center())2501[0 : -3 : 2]25022503A more complicated example::25042505sage: dP6.<x0,x1,x2,x3,x4,x5> = toric_varieties.dP6()2506sage: twoP1 = dP6.subscheme(x0*x3)2507sage: patch = twoP1.neighborhood([0,1,2, 3,4,5]); patch2508Closed subscheme of 2-d affine toric variety defined by:25093*x02510sage: patch.embedding_morphism()2511Scheme morphism:2512From: Closed subscheme of 2-d affine toric variety defined by:25133*x02514To: Closed subscheme of 2-d CPR-Fano toric variety covered by 6 affine patches defined by:2515x0*x32516Defn: Defined on coordinates by sending [x0 : x1] to2517[0 : x1 : 2 : 3 : 4 : 5]2518sage: patch.embedding_center()2519[0 : 1]2520sage: patch.embedding_morphism()(patch.embedding_center())2521[0 : 1 : 2 : 3 : 4 : 5]2522"""2523point = list(point)2524self._check_satisfies_equations(point)2525PP = self.ambient_space()2526n = PP.dimension()2527fan = PP.fan()2528cone_idx = self._best_affine_patch(point)2529cone = fan.generating_cone(cone_idx)25302531patch_cover = PP.affine_patch(cone_idx)2532R = patch_cover.coordinate_ring()2533phi = []2534point_preimage = []2535for i in range(0,fan.nrays()):2536try:2537ray_index = cone.ambient_ray_indices().index(i)2538phi.append(R.gen(ray_index))2539point_preimage.append(point[i])2540except ValueError:2541phi.append(point[i])2542pullback_polys = [f(phi) for f in self.defining_polynomials()]2543patch = patch_cover.subscheme(pullback_polys)25442545patch._embedding_center = patch(point_preimage)2546patch._embedding_morphism = patch.hom(phi,self)2547return patch25482549def dimension(self):2550"""2551Return the dimension of ``self``.25522553OUTPUT:25542555Integer. If ``self`` is empty, `-1` is returned.25562557EXAMPLES::25582559sage: fan = FaceFan(lattice_polytope.octahedron(2))2560sage: P1xP1 = ToricVariety(fan)2561sage: P1xP1.inject_variables()2562Defining z0, z1, z2, z32563sage: P1 = P1xP1.subscheme(z0-z2)2564sage: P1.dimension()256512566sage: P1xP1.subscheme([z0-z2, (z0-z2)^2]).dimension()256712568sage: P1xP1.subscheme([z0,z2]).dimension()2569-12570"""2571if '_dimension' in self.__dict__:2572return self._dimension2573npatches = self.ambient_space().fan().ngenerating_cones()2574dims = [ self.affine_patch(i).dimension() for i in range(0,npatches) ]2575self._dimension = max(dims)2576return self._dimension25772578def is_smooth(self, point=None):2579r"""2580Test whether the algebraic subscheme is smooth.25812582INPUT:25832584- ``point`` -- A point or ``None`` (default). The point to2585test smoothness at.25862587OUTPUT:25882589Boolean. If no point was specified, returns whether the2590algebraic subscheme is smooth everywhere. Otherwise,2591smoothness at the specified point is tested.25922593EXAMPLES::25942595sage: P2.<x,y,z> = toric_varieties.P2()2596sage: cuspidal_curve = P2.subscheme([y^2*z-x^3])2597sage: cuspidal_curve2598Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by:2599-x^3 + y^2*z2600sage: cuspidal_curve.is_smooth([1,1,1])2601True2602sage: cuspidal_curve.is_smooth([0,0,1])2603False2604sage: cuspidal_curve.is_smooth()2605False26062607Any sufficiently generic cubic hypersurface is smooth::26082609sage: P2.subscheme([y^2*z-x^3+z^3+1/10*x*y*z]).is_smooth()2610True26112612A more complicated example::26132614sage: dP6.<x0,x1,x2,x3,x4,x5> = toric_varieties.dP6()2615sage: disjointP1s = dP6.subscheme(x0*x3)2616sage: disjointP1s.is_smooth()2617True2618sage: intersectingP1s = dP6.subscheme(x0*x1)2619sage: intersectingP1s.is_smooth()2620False26212622A smooth hypersurface in a compact singular toric variety::26232624sage: lp = LatticePolytope(matrix([(1,0,0),(1,1,0),(1,1,1),(1,0,1),(-2,-1,-1)]).transpose())2625sage: X.<x,y,u,v,t> = CPRFanoToricVariety(Delta_polar=lp)2626sage: Y = X.subscheme(x*v+y*u+t)2627sage: cone = Cone([(1,0,0),(1,1,0),(1,1,1),(1,0,1)])2628sage: Y.is_smooth()2629True2630"""2631if not point is None:2632toric_patch = self.neighborhood(point)2633return toric_patch.is_smooth(toric_patch.embedding_center())26342635# testing smoothness everywhere tends to be expensive2636if '_smooth' in self.__dict__:2637return self._smooth2638npatches = self.ambient_space().fan().ngenerating_cones()2639self._smooth = all(self.affine_patch(i).is_smooth() for i in range(0,npatches))2640return self._smooth264126422643class AlgebraicScheme_subscheme_affine_toric(AlgebraicScheme_subscheme_toric):2644r"""2645Construct an algebraic subscheme of an affine toric variety.26462647.. WARNING::26482649You should not create objects of this class directly. The preferred2650method to construct such subschemes is to use2651:meth:`~ToricVariety_field.subscheme` method of2652:class:`toric varieties <ToricVariety_field>`.26532654INPUT:26552656- ``toric_variety`` -- ambient :class:`affine toric variety2657<ToricVariety_field>`;26582659- ``polynomials`` -- single polynomial, list, or ideal of defining2660polynomials in the coordinate ring of ``toric_variety``.26612662OUTPUT:26632664A :class:`algebraic subscheme of an affine toric variety2665<AlgebraicScheme_subscheme_affine_toric>`.26662667TESTS::26682669sage: fan = FaceFan(lattice_polytope.octahedron(2))2670sage: P1xP1 = ToricVariety(fan, "x s y t")2671sage: P1xP1.inject_variables()2672Defining x, s, y, t2673sage: import sage.schemes.generic.algebraic_scheme as SCM2674sage: X = SCM.AlgebraicScheme_subscheme_toric(2675... P1xP1, [x*s + y*t, x^3+y^3])2676sage: X2677Closed subscheme of 2-d toric variety2678covered by 4 affine patches defined by:2679x*s + y*t,2680x^3 + y^326812682A better way to construct the same scheme as above::26832684sage: P1xP1.subscheme([x*s + y*t, x^3+y^3])2685Closed subscheme of 2-d toric variety2686covered by 4 affine patches defined by:2687x*s + y*t,2688x^3 + y^32689"""26902691def __init__(self, toric_variety, polynomials):2692r"""2693See :class:`AlgebraicScheme_subscheme_toric` for documentation.26942695TESTS::26962697sage: fan = FaceFan(lattice_polytope.octahedron(2))2698sage: P1xP1 = ToricVariety(fan, "x s y t")2699sage: P1xP1.inject_variables()2700Defining x, s, y, t2701sage: import sage.schemes.generic.algebraic_scheme as SCM2702sage: X = SCM.AlgebraicScheme_subscheme_toric(2703... P1xP1, [x*s + y*t, x^3+y^3])2704sage: X2705Closed subscheme of 2-d toric variety2706covered by 4 affine patches defined by:2707x*s + y*t,2708x^3 + y^32709"""2710assert toric_variety.is_affine(), 'The toric variety must be affine!'2711# Just to make sure that keyword arguments will be passed correctly2712super(AlgebraicScheme_subscheme_affine_toric, self).__init__(toric_variety,2713polynomials)27142715def dimension(self):2716"""2717Return the dimension of ``self``.27182719OUTPUT:27202721- integer.27222723EXAMPLES::27242725sage: P1xP1.<s0,s1,t0,t1> = toric_varieties.P1xP1()2726sage: P1 = P1xP1.subscheme(s0-s1)2727sage: P1.dimension()2728127292730A more complicated example where the ambient toric variety is2731not smooth::27322733sage: X.<x,y> = toric_varieties.A2_Z2()2734sage: X.is_smooth()2735False2736sage: Y = X.subscheme([x*y, x^2])2737sage: Y2738Closed subscheme of 2-d affine toric variety defined by:2739x*y,2740x^22741sage: Y.dimension()274212743"""2744if '_dimension' in self.__dict__:2745return self._dimension27462747if self.ambient_space().is_smooth():2748self._dimension = self.defining_ideal().dimension()2749else:2750self._dimension = self.affine_algebraic_patch().dimension()2751return self._dimension27522753def is_smooth(self, point=None):2754r"""2755Test whether the algebraic subscheme is smooth.27562757INPUT:27582759- ``point`` -- A point or ``None`` (default). The point to2760test smoothness at.27612762OUTPUT:27632764Boolean. If no point was specified, returns whether the2765algebraic subscheme is smooth everywhere. Otherwise,2766smoothness at the specified point is tested.27672768EXAMPLES::27692770sage: A2.<x,y> = toric_varieties.A2()2771sage: cuspidal_curve = A2.subscheme([y^2-x^3])2772sage: cuspidal_curve2773Closed subscheme of 2-d affine toric variety defined by:2774-x^3 + y^22775sage: cuspidal_curve.is_smooth([1,1])2776True2777sage: cuspidal_curve.is_smooth([0,0])2778False2779sage: cuspidal_curve.is_smooth()2780False2781sage: circle = A2.subscheme(x^2+y^2-1)2782sage: circle.is_smooth([1,0])2783True2784sage: circle.is_smooth()2785True27862787A more complicated example where the ambient toric variety is2788not smooth::27892790sage: X.<x,y> = toric_varieties.A2_Z2() # 2-d affine space mod Z/22791sage: X.is_smooth()2792False2793sage: Y = X.subscheme([x*y, x^2]) # (twice the x=0 curve) mod Z/22794sage: Y2795Closed subscheme of 2-d affine toric variety defined by:2796x*y,2797x^22798sage: Y.dimension() # Y is a Weil divisor but not Cartier279912800sage: Y.is_smooth()2801True2802sage: Y.is_smooth([0,0])2803True2804"""2805if not point is None:2806self._check_satisfies_equations(point)2807if self.ambient_space().is_smooth():2808R = self.ambient_space().coordinate_ring()2809point_subs = dict(zip(R.gens(), point))2810Jac = self.Jacobian().subs(point_subs)2811return not Jac.is_zero()2812else:2813self._embedding_center = self.point(point)2814affine = self.affine_algebraic_patch()2815return affine.is_smooth(affine.embedding_center())28162817# testing smoothness everywhere tends to be expensive2818if '_smooth' in self.__dict__:2819return self._smooth28202821if self.ambient_space().is_smooth():2822sing_dim = self.Jacobian().dimension()2823self._smooth = (sing_dim == -1)2824else:2825self._smooth = self.affine_algebraic_patch().is_smooth()28262827return self._smooth282828292830283128322833