Path: blob/master/sage/schemes/generic/algebraic_scheme.py
4096 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.generic.affine_space.AffineSpace_generic>`),89* Projective spaces (:class:`ProjectiveSpace10<sage.schemes.generic.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 (134is_Ideal,135is_MPolynomialRing,136is_FiniteField,137is_RationalField,138ZZ)139140from sage.misc.latex import latex141from sage.misc.misc import is_iterator142from sage.structure.all import Sequence143from sage.calculus.functions import jacobian144import ambient_space145import affine_space146import projective_space147import morphism148import 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 coordiante 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'>547"""548return self.__A._homset(*args, **kwds)549550def _point_homset(self, *args, **kwds):551return self.__A._point_homset(*args, **kwds)552553def _point(self, *args, **kwds):554return self.__A._point(*args, **kwds)555556557558#*******************************************************************559class AlgebraicScheme_quasi(AlgebraicScheme):560"""561The quasi-affine or quasi-projective scheme `X - Y`, where `X` and `Y`562are both closed subschemes of a common ambient affine or projective563space.564565.. WARNING::566567You should not create objects of this class directly. The568preferred method to construct such subschemes is to use569:meth:`complement` method of algebraic schemes.570571OUTPUT:572573An instance of :class:`AlgebraicScheme_quasi`.574575EXAMPLES::576577sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)578sage: S = P.subscheme([])579sage: T = P.subscheme([x-y])580sage: T.complement(S)581Quasi-projective subscheme X - Y of Projective Space of dimension 2 over582Integer Ring, where X is defined by:583(no polynomials)584and Y is defined by:585x - y586"""587588def __init__(self, X, Y):589"""590The constructor.591592INPUT:593594- ``X``, ``Y`` -- two subschemes of the same ambient space.595596TESTS::597598sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)599sage: S = P.subscheme([])600sage: T = P.subscheme([x-y])601sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_quasi602sage: AlgebraicScheme_quasi(S, T)603Quasi-projective subscheme X - Y of Projective Space of dimension 2 over Integer Ring, where X is defined by:604(no polynomials)605and Y is defined by:606x - y607"""608self.__X = X609self.__Y = Y610if not isinstance(X, AlgebraicScheme_subscheme):611raise TypeError, "X must be a closed subscheme of an ambient space."612if not isinstance(Y, AlgebraicScheme_subscheme):613raise TypeError, "Y must be a closed subscheme of an ambient space."614if X.ambient_space() != Y.ambient_space():615raise ValueError, "X and Y must be embedded in the same ambient space."616# _latex_ and _repr_ assume all of the above conditions and should be617# probably changed if they are relaxed!618A = X.ambient_space()619self._base_ring = A.base_ring()620AlgebraicScheme.__init__(self, A)621622def _latex_(self):623"""624Return a LaTeX representation of this algebraic scheme.625626EXAMPLES::627628sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_quasi629sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)630sage: S = P.subscheme([])631sage: T = P.subscheme([x-y])632sage: U = AlgebraicScheme_quasi(S, T); U633Quasi-projective subscheme X - Y of Projective Space of dimension 2634over Integer Ring, where X is defined by:635(no polynomials)636and Y is defined by:637x - y638sage: U._latex_()639'\\text{Quasi-projective subscheme }640(X\\setminus Y)\\subset {\\mathbf P}_{\\Bold{Z}}^2,\\text{ where }641X \\text{ is defined by }\\text{no polynomials},\\text{ and }642Y \\text{ is defined by } x - y.'643"""644if affine_space.is_AffineSpace(self.ambient_space()):645t = "affine"646else:647t = "projective"648X = ', '.join(latex(f) for f in self.__X.defining_polynomials())649if not X:650X = r"\text{no polynomials}"651Y = ', '.join(latex(f) for f in self.__Y.defining_polynomials())652if not Y:653Y = r"\text{no polynomials}"654return (r"\text{Quasi-%s subscheme } (X\setminus Y)\subset %s,"655r"\text{ where } X \text{ is defined by }%s,"656r"\text{ and } Y \text{ is defined by } %s."657% (t, latex(self.ambient_space()), X, Y))658659def _repr_(self):660"""661Return a string representation of this algebraic scheme.662663EXAMPLES::664665sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_quasi666sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)667sage: S = P.subscheme([])668sage: T = P.subscheme([x-y])669sage: U = AlgebraicScheme_quasi(S, T); U670Quasi-projective subscheme X - Y of Projective Space of dimension 2 over Integer Ring, where X is defined by:671(no polynomials)672and Y is defined by:673x - y674sage: U._repr_()675'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'676"""677if affine_space.is_AffineSpace(self.ambient_space()):678t = "affine"679else:680t = "projective"681return ("Quasi-%s subscheme X - Y of %s, where X is defined by:\n%s\n"682"and Y is defined by:\n%s"683% (t, self.ambient_space(), str(self.__X).split("\n", 1)[1],684str(self.__Y).split("\n", 1)[1]))685686def X(self):687"""688Return the scheme `X` such that self is represented as `X - Y`.689690EXAMPLES::691692sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)693sage: S = P.subscheme([])694sage: T = P.subscheme([x-y])695sage: U = T.complement(S)696sage: U.X() is S697True698"""699return self.__X700701def Y(self):702"""703Return the scheme `Y` such that self is represented as `X - Y`.704705EXAMPLES::706707sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)708sage: S = P.subscheme([])709sage: T = P.subscheme([x-y])710sage: U = T.complement(S)711sage: U.Y() is T712True713"""714return self.__Y715716def _check_satisfies_equations(self, v):717"""718Verify that the coordinates of v define a point on this scheme, or719raise a TypeError.720721EXAMPLES::722723sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)724sage: S = P.subscheme([])725sage: T = P.subscheme([x-y])726sage: U = T.complement(S)727sage: U._check_satisfies_equations([1, 2, 0])728True729sage: U._check_satisfies_equations([1, 1, 0])730Traceback (most recent call last):731...732TypeError: Coordinates [1, 1, 0] do not define a point on733Quasi-projective subscheme X - Y of Projective Space of dimension 2734over Integer Ring, where X is defined by:735(no polynomials)736and Y is defined by:737x - y738739sage: U._check_satisfies_equations([1, 4])740Traceback (most recent call last):741...742TypeError: number of arguments does not match number of variables in parent743744sage: A.<x, y> = AffineSpace(2, GF(7))745sage: S = A.subscheme([x^2-y])746sage: T = A.subscheme([x-y])747sage: U = T.complement(S)748sage: U._check_satisfies_equations([2, 4])749True750sage: U.point([2,4])751(2, 4)752sage: U._check_satisfies_equations(_)753True754sage: U._check_satisfies_equations([1, 1])755Traceback (most recent call last):756...757TypeError: Coordinates [1, 1] do not define a point on Quasi-affine758subscheme X - Y of Affine Space of dimension 2 over Finite759Field of size 7, where X is defined by:760x^2 - y761and Y is defined by:762x - y763sage: U._check_satisfies_equations([1, 0])764Traceback (most recent call last):765...766TypeError: Coordinates [1, 0] do not define a point on Quasi-affine767subscheme X - Y of Affine Space of dimension 2 over Finite768Field of size 7, where X is defined by:769x^2 - y770and Y is defined by:771x - y772773TESTS:774775The bug reported at #12211 has been fixed::776777sage: P.<x, y, z, w> = ProjectiveSpace(3, QQ)778sage: S = P.subscheme([x])779sage: T = P.subscheme([y, z])780sage: U = T.complement(S)781sage: U._check_satisfies_equations([0, 0, 1, 1])782True783"""784coords = list(v)785for f in self.__X.defining_polynomials():786if f(coords) != 0:787raise TypeError, "Coordinates %s do not define a point on %s"%(v,self)788for f in self.__Y.defining_polynomials():789if f(coords) != 0:790return True791raise TypeError, "Coordinates %s do not define a point on %s"%(v,self)792793def rational_points(self, F=None, bound=0):794"""795Return the set of rational points on this algebraic scheme796over the field `F`.797798EXAMPLES::799800sage: A.<x, y> = AffineSpace(2, GF(7))801sage: S = A.subscheme([x^2-y])802sage: T = A.subscheme([x-y])803sage: U = T.complement(S)804sage: U.rational_points()805[(2, 4), (3, 2), (4, 2), (5, 4), (6, 1)]806sage: U.rational_points(GF(7^2, 'b'))807[(2, 4), (3, 2), (4, 2), (5, 4), (6, 1), (b, b + 4), (b + 1, 3*b + 5), (b + 2, 5*b + 1),808(b + 3, 6), (b + 4, 2*b + 6), (b + 5, 4*b + 1), (b + 6, 6*b + 5), (2*b, 4*b + 2),809(2*b + 1, b + 3), (2*b + 2, 5*b + 6), (2*b + 3, 2*b + 4), (2*b + 4, 6*b + 4),810(2*b + 5, 3*b + 6), (2*b + 6, 3), (3*b, 2*b + 1), (3*b + 1, b + 2), (3*b + 2, 5),811(3*b + 3, 6*b + 3), (3*b + 4, 5*b + 3), (3*b + 5, 4*b + 5), (3*b + 6, 3*b + 2),812(4*b, 2*b + 1), (4*b + 1, 3*b + 2), (4*b + 2, 4*b + 5), (4*b + 3, 5*b + 3),813(4*b + 4, 6*b + 3), (4*b + 5, 5), (4*b + 6, b + 2), (5*b, 4*b + 2), (5*b + 1, 3),814(5*b + 2, 3*b + 6), (5*b + 3, 6*b + 4), (5*b + 4, 2*b + 4), (5*b + 5, 5*b + 6),815(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),816(6*b + 4, 6), (6*b + 5, 5*b + 1), (6*b + 6, 3*b + 5)]817"""818if F is None:819F = self.base_ring()820821if bound == 0:822if is_RationalField(F):823raise TypeError, "A positive bound (= %s) must be specified."%bound824if not is_FiniteField(F):825raise TypeError, "Argument F (= %s) must be a finite field."%F826pts = []827for P in self.ambient_space().rational_points(F):828try:829if self._check_satisfies_equations(list(P)):830pts.append(P)831except TypeError:832pass833pts.sort()834return pts835836837838#*******************************************************************839class AlgebraicScheme_subscheme(AlgebraicScheme):840"""841An algebraic scheme presented as a closed subscheme is defined by842explicit polynomial equations. This is as opposed to a general843scheme, which could, e.g., be the Neron model of some object, and844for which we do not want to give explicit equations.845846INPUT:847848- ``A`` - ambient space (e.g. affine or projective `n`-space)849850- ``polynomials`` - single polynomial, ideal or iterable of defining851polynomials; in any case polynomials must belong to the coordinate852ring of the ambient space and define valid polynomial functions (e.g.853they should be homogeneous in the case of a projective space)854855OUTPUT:856857- algebraic scheme858859EXAMPLES::860861sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme862sage: P.<x, y, z> = ProjectiveSpace(2, QQ)863sage: P.subscheme([x^2-y*z])864Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:865x^2 - y*z866sage: AlgebraicScheme_subscheme(P, [x^2-y*z])867Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:868x^2 - y*z869"""870871def __init__(self, A, polynomials):872"""873See ``AlgebraicScheme_subscheme`` for documentation.874875TESTS::876877sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme878sage: P.<x, y, z> = ProjectiveSpace(2, QQ)879sage: P.subscheme([x^2-y*z])880Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:881x^2 - y*z882sage: AlgebraicScheme_subscheme(P, [x^2-y*z])883Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:884x^2 - y*z885"""886from sage.rings.polynomial.multi_polynomial_sequence import is_PolynomialSequence887888AlgebraicScheme.__init__(self, A)889self._base_ring = A.base_ring()890R = A.coordinate_ring()891if is_Ideal(polynomials):892I = polynomials893polynomials = I.gens()894if I.ring() is R: # Otherwise we will recompute I later after895self.__I = I # converting generators to the correct ring896if isinstance(polynomials, tuple) or is_PolynomialSequence(polynomials) or is_iterator(polynomials):897polynomials = list(polynomials)898elif not isinstance(polynomials, list):899# Looks like we got a single polynomial900polynomials = [polynomials]901for n, f in enumerate(polynomials):902try:903polynomials[n] = R(f)904except TypeError:905raise TypeError("%s cannot be converted to a polynomial in "906"the coordinate ring of this %s!" % (f, A))907polynomials = tuple(polynomials)908self.__polys = A._validate(polynomials)909910def _check_satisfies_equations(self, v):911"""912Verify that the coordinates of v define a point on this scheme, or913raise a TypeError.914915EXAMPLES::916917sage: P.<x, y, z> = ProjectiveSpace(2, QQ)918sage: S = P.subscheme([x^2-y*z])919sage: S._check_satisfies_equations([1, 1, 1])920True921sage: S._check_satisfies_equations([1, 0, 1])922Traceback (most recent call last):923...924TypeError: Coordinates [1, 0, 1] do not define a point on Closed subscheme925of Projective Space of dimension 2 over Rational Field defined by:926x^2 - y*z927sage: S._check_satisfies_equations([0, 0, 0])928Traceback (most recent call last):929...930TypeError: Coordinates [0, 0, 0] do not define a point on Closed subscheme931of Projective Space of dimension 2 over Rational Field defined by:932x^2 - y*z933"""934coords = list(v)935for f in self.defining_polynomials():936if f(coords) != 0: # it must be "!=0" instead of "if f(v)", e.g.,937# because of p-adic base rings.938raise TypeError, "Coordinates %s do not define a point on %s"%(coords,self)939try:940return self.ambient_space()._check_satisfies_equations(coords)941except TypeError:942raise TypeError, "Coordinates %s do not define a point on %s"%(coords,self)943944def base_extend(self, R):945"""946Return the base change to the ring `R` of this scheme.947948EXAMPLES::949950sage: P.<x, y, z> = ProjectiveSpace(2, GF(11))951sage: S = P.subscheme([x^2-y*z])952sage: S.base_extend(GF(11^2, 'b'))953Closed subscheme of Projective Space of dimension 2 over Finite Field in b of size 11^2 defined by:954x^2 - y*z955sage: S.base_extend(ZZ)956Traceback (most recent call last):957...958ValueError: no natural map from the base ring (=Finite Field of size 11) to R (=Integer Ring)!959"""960A = self.ambient_space().base_extend(R)961return A.subscheme(self.__polys)962963def __cmp__(self, other):964"""965EXAMPLES::966967sage: A.<x, y, z> = AffineSpace(3, QQ)968sage: X = A.subscheme([x*y, z])969sage: X == A.subscheme([z, x*y])970True971sage: X == A.subscheme([x*y, z^2])972False973sage: B.<u, v, t> = AffineSpace(3, QQ)974sage: X == B.subscheme([u*v, t])975False976"""977if not isinstance(other, AlgebraicScheme_subscheme):978return -1979A = self.ambient_space()980if other.ambient_space() != A:981return -1982return cmp(self.defining_ideal(), other.defining_ideal())983984def _latex_(self):985"""986Return a LaTeX representation of this scheme.987988EXAMPLES::989990sage: P.<x, y, z> = ProjectiveSpace(2, GF(11))991sage: S = P.subscheme([x^2-y*z])992sage: S993Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:994x^2 - y*z995sage: S._latex_()996'\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^2 \\text{ defined by } x^{2} - y z'997sage: S = P.subscheme([x^2-y*z, x^5])998sage: S999Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:1000x^2 - y*z,1001x^51002sage: S._latex_()1003'\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^2 \\text{ defined by } x^{2} - y z, x^{5}'1004"""1005polynomials = ', '.join(latex(f) for f in self.defining_polynomials())1006if not polynomials:1007polynomials = r"\text{no polynomials}"1008return (r"\text{Closed subscheme of } %s \text{ defined by } %s"1009% (latex(self.ambient_space()), polynomials))10101011def _repr_(self):1012"""1013Return a string representation of this scheme.10141015EXAMPLES::10161017sage: P.<x, y, z> = ProjectiveSpace(2, GF(11))1018sage: S = P.subscheme([x^2-y*z])1019sage: S1020Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:1021x^2 - y*z1022sage: S._repr_()1023'Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:\n x^2 - y*z'1024sage: S = P.subscheme([x^2-y*z, x^5])1025sage: S1026Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:1027x^2 - y*z,1028x^51029sage: S._repr_()1030'Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by:\n x^2 - y*z,\n x^5'1031"""1032polynomials = ',\n '.join(str(f) for f in self.defining_polynomials())1033if not polynomials:1034polynomials = '(no polynomials)'1035return ("Closed subscheme of %s defined by:\n %s"1036% (self.ambient_space(), polynomials))10371038def defining_polynomials(self):1039"""1040Return the polynomials that define this scheme as a subscheme1041of its ambient space.10421043OUTPUT:10441045A tuple of polynomials in the coordinate ring of the ambient1046space.10471048EXAMPLES::10491050sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)1051sage: S = P.subscheme([x^2-y*z, x^3+z^3])1052sage: S.defining_polynomials()1053(x^2 - y*z, x^3 + z^3)1054"""1055return self.__polys10561057def defining_ideal(self):1058"""1059Return the ideal that defines this scheme as a subscheme1060of its ambient space.10611062OUTPUT:10631064An ideal in the coordinate ring of the ambient space.10651066EXAMPLES::10671068sage: P.<x, y, z> = ProjectiveSpace(2, ZZ)1069sage: S = P.subscheme([x^2-y*z, x^3+z^3])1070sage: S.defining_ideal()1071Ideal (x^2 - y*z, x^3 + z^3) of Multivariate Polynomial Ring in x, y, z over Integer Ring1072"""1073try:1074return self.__I1075except AttributeError:1076R = self.ambient_space().coordinate_ring()1077self.__I = R.ideal(self.defining_polynomials())1078return self.__I10791080# Note: dimension must be implemented by the derived classes1081def codimension(self):1082r"""1083Return the codimension of the algebraic subscheme.10841085OUTPUT:10861087Integer.10881089EXAMPLES::10901091sage: PP.<x,y,z,w,v> = ProjectiveSpace(4,QQ)1092sage: V = PP.subscheme(x*y)1093sage: V.codimension()109411095sage: V.dimension()109631097"""1098return self.ambient_space().dimension() - self.dimension()10991100def irreducible_components(self):1101r"""1102Return the irreducible components of this algebraic scheme, as1103subschemes of the same ambient space.11041105OUTPUT: an immutable sequence of irreducible subschemes of the1106ambient space of this scheme11071108The components are cached.11091110EXAMPLES:11111112We define what is clearly a union of four hypersurfaces in1113`\P^4_{\QQ}` then find the irreducible components::11141115sage: PP.<x,y,z,w,v> = ProjectiveSpace(4,QQ)1116sage: V = PP.subscheme( (x^2 - y^2 - z^2)*(w^5 - 2*v^2*z^3)* w * (v^3 - x^2*z) )1117sage: V.irreducible_components()1118[1119Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1120w,1121Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1122x^2 - y^2 - z^2,1123Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1124x^2*z - v^3,1125Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1126w^5 - 2*z^3*v^21127]11281129We verify that the irrelevant ideal isn't accidently returned1130(see trac 6920)::11311132sage: PP.<x,y,z,w> = ProjectiveSpace(3,QQ)1133sage: f = x^3 + y^3 + z^3 + w^31134sage: R = f.parent()1135sage: I = [f] + [f.derivative(zz) for zz in PP.gens()]1136sage: V = PP.subscheme(I)1137sage: V.irreducible_components()1138[1139<BLANKLINE>1140]11411142The same polynomial as above defines a scheme with a1143nontrivial irreducible component in affine space (instead of1144the empty scheme as above)::11451146sage: AA.<x,y,z,w> = AffineSpace(4,QQ)1147sage: V = AA.subscheme(I)1148sage: V.irreducible_components()1149[1150Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:1151w,1152z,1153y,1154x1155]1156"""1157try:1158return self.__irreducible_components1159except AttributeError:1160pass1161I = self.defining_ideal()1162P = I.associated_primes()1163if self.is_projective():1164# In the projective case, we must exclude the prime ideals1165# that contain the irrelevant ideal, which is the ideal1166# generated by the variables, which are the gens of the1167# base ring.1168G = I.ring().gens()1169# We make a list of ideals with the property that "any"1170# of the elements of G are not in the ideal.1171P = [J for J in P if any(g not in J for g in G)]11721173A = self.ambient_space()1174C = Sequence([A.subscheme(X) for X in P], check=False, cr=True)1175C.sort()1176C.set_immutable()1177self.__irreducible_components = C1178return C11791180def Jacobian_matrix(self):1181r"""1182Return the matrix `\frac{\partial f_i}{\partial x_j}` of1183(formal) partial derivatives.11841185OUTPUT:11861187A matrix of polynomials.11881189EXAMPLES::11901191sage: P3.<w,x,y,z> = ProjectiveSpace(3, QQ)1192sage: twisted_cubic = P3.subscheme(matrix([[w, x, y],[x, y, z]]).minors(2))1193sage: twisted_cubic.Jacobian_matrix()1194[ y -2*x w 0]1195[ z -y -x w]1196[ 0 z -2*y x]1197"""1198R = self.ambient_space().coordinate_ring()1199return jacobian(self.defining_polynomials(), R.gens())12001201def Jacobian(self):1202r"""1203Return the Jacobian ideal.12041205This is the ideal generated by12061207* the `d\times d` minors of the Jacobian matrix, where `d` is1208the :meth:`codimension` of the algebraic scheme, and12091210* the defining polynomials of the algebraic scheme. Note that1211some authors do not include these in the definition of the1212Jacobian ideal. An example of a reference that does include1213the defining equations is [LazarsfeldJacobian].12141215OUTPUT:12161217An ideal in the coordinate ring of the ambient space.12181219REFERENCES:12201221.. [LazarsfeldJacobian]1222Robert Lazarsfeld:1223Positivity in algebraic geometry II;1224Positivity for Vector Bundles, and Multiplier Ideals,1225page 181.12261227EXAMPLES::12281229sage: P3.<w,x,y,z> = ProjectiveSpace(3, QQ)1230sage: twisted_cubic = P3.subscheme(matrix([[w, x, y],[x, y, z]]).minors(2))1231sage: twisted_cubic.Jacobian()1232Ideal (-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,1233w^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,1234w*y) of Multivariate Polynomial Ring in w, x, y, z over Rational Field1235sage: twisted_cubic.defining_ideal()1236Ideal (-x^2 + w*y, -x*y + w*z, -y^2 + x*z) of Multivariate Polynomial Ring1237in w, x, y, z over Rational Field1238"""1239d = self.codimension()1240minors = self.Jacobian_matrix().minors(d)1241I = self.defining_ideal()1242minors = tuple([ I.reduce(m) for m in minors ])1243return I.ring().ideal(I.gens() + minors)12441245def reduce(self):1246r"""1247Return the corresponding reduced algebraic space associated to this1248scheme.12491250EXAMPLES: First we construct the union of a doubled and tripled1251line in the affine plane over `\QQ` ::12521253sage: A.<x,y> = AffineSpace(2, QQ)1254sage: X = A.subscheme([(x-1)^2*(x-y)^3]); X1255Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1256x^5 - 3*x^4*y + 3*x^3*y^2 - x^2*y^3 - 2*x^4 + 6*x^3*y1257- 6*x^2*y^2 + 2*x*y^3 + x^3 - 3*x^2*y + 3*x*y^2 - y^31258sage: X.dimension()1259112601261Then we compute the corresponding reduced scheme::12621263sage: Y = X.reduce(); Y1264Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1265x^2 - x*y - x + y12661267Finally, we verify that the reduced scheme `Y` is the union1268of those two lines::12691270sage: L1 = A.subscheme([x-1]); L11271Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1272x - 11273sage: L2 = A.subscheme([x-y]); L21274Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1275x - y1276sage: W = L1.union(L2); W # taken in ambient space1277Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1278x^2 - x*y - x + y1279sage: Y == W1280True1281"""1282try:1283return self._reduce1284except AttributeError:1285r = self.defining_ideal().radical()1286A = self.ambient_space()1287V = A.subscheme(r)1288V._reduce = V # so knows it is already reduced!1289self._reduce = V1290return V12911292def union(self, other):1293"""1294Return the scheme-theoretic union of self and other in their common1295ambient space.12961297EXAMPLES: We construct the union of a line and a tripled-point on1298the line.12991300::13011302sage: A.<x,y> = AffineSpace(2, QQ)1303sage: I = ideal([x,y])^31304sage: P = A.subscheme(I)1305sage: L = A.subscheme([y-1])1306sage: S = L.union(P); S1307Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1308y^4 - y^3,1309x*y^3 - x*y^2,1310x^2*y^2 - x^2*y,1311x^3*y - x^31312sage: S.dimension()131311314sage: S.reduce()1315Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1316y^2 - y,1317x*y - x13181319We can also use the notation "+" for the union::13201321sage: A.subscheme([x]) + A.subscheme([y^2 - (x^3+1)])1322Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1323x^4 - x*y^2 + x13241325Saving and loading::13261327sage: loads(S.dumps()) == S1328True1329"""1330if not isinstance(other, AlgebraicScheme_subscheme):1331raise TypeError, "other (=%s) must be a closed algebraic subscheme of an ambient space"%other1332A = self.ambient_space()1333if other.ambient_space() != A:1334raise ValueError, "other (=%s) must be in the same ambient space as self"%other1335return A.subscheme(self.defining_ideal().intersection(other.defining_ideal()))13361337__add__ = union13381339def intersection(self, other):1340"""1341Return the scheme-theoretic intersection of self and other in their1342common ambient space.13431344EXAMPLES::13451346sage: A.<x, y> = AffineSpace(2, ZZ)1347sage: X = A.subscheme([x^2-y])1348sage: Y = A.subscheme([y])1349sage: X.intersection(Y)1350Closed subscheme of Affine Space of dimension 2 over Integer Ring defined by:1351x^2 - y,1352y1353"""1354if not isinstance(other, AlgebraicScheme_subscheme):1355raise TypeError, "other (=%s) must be a closed algebraic subscheme of an ambient space"%other1356A = self.ambient_space()1357if other.ambient_space() != A:1358raise ValueError, "other (=%s) must be in the same ambient space as self"%other1359return A.subscheme(self.defining_ideal() + other.defining_ideal())13601361def complement(self, other=None):1362"""1363Return the scheme-theoretic complement other - self, where1364self and other are both closed algebraic subschemes of the1365same ambient space.13661367If other is unspecified, it is taken to be the ambient space1368of self.13691370EXAMPLES::13711372sage: A.<x, y, z> = AffineSpace(3, ZZ)1373sage: X = A.subscheme([x+y-z])1374sage: Y = A.subscheme([x-y+z])1375sage: Y.complement(X)1376Quasi-affine subscheme X - Y of Affine Space of1377dimension 3 over Integer Ring, where X is defined by:1378x + y - z1379and Y is defined by:1380x - y + z1381sage: Y.complement()1382Quasi-affine subscheme X - Y of Affine Space of1383dimension 3 over Integer Ring, where X is defined by:1384(no polynomials)1385and Y is defined by:1386x - y + z1387sage: P.<x, y, z> = ProjectiveSpace(2, QQ)1388sage: X = P.subscheme([x^2+y^2+z^2])1389sage: Y = P.subscheme([x*y+y*z+z*x])1390sage: Y.complement(X)1391Quasi-projective subscheme X - Y of Projective Space of1392dimension 2 over Rational Field, where X is defined by:1393x^2 + y^2 + z^21394and Y is defined by:1395x*y + x*z + y*z1396sage: Y.complement(P)1397Quasi-projective subscheme X - Y of Projective Space of1398dimension 2 over Rational Field, where X is defined by:1399(no polynomials)1400and Y is defined by:1401x*y + x*z + y*z1402"""1403A = self.ambient_space()1404if other is None:1405other = A.subscheme([])1406elif not isinstance(other, AlgebraicScheme_subscheme):1407if other == A:1408other = A.subscheme([])1409else:1410raise TypeError, \1411"Argument other (=%s) must be a closed algebraic subscheme of an ambient space"%other1412if other.ambient_space() != A:1413raise ValueError, "other (=%s) must be in the same ambient space as self"%other1414return AlgebraicScheme_quasi(other, self)14151416def rational_points(self, F=None, bound=0):1417"""1418Return the rational points on the algebraic subscheme.14191420EXAMPLES:14211422One can enumerate points up to a given bound on a projective scheme1423over the rationals::14241425sage: E = EllipticCurve('37a')1426sage: E.rational_points(bound=8)1427[(-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)]14281429For a small finite field, the complete set of points can be1430enumerated. ::14311432sage: Etilde = E.base_extend(GF(3))1433sage: Etilde.rational_points()1434[(0 : 0 : 1), (0 : 1 : 0), (0 : 2 : 1), (1 : 0 : 1),1435(1 : 2 : 1), (2 : 0 : 1), (2 : 2 : 1)]14361437The class of hyperelliptic curves does not (yet) support1438desingularization of the places at infinity into two points::14391440sage: FF = FiniteField(7)1441sage: P.<x> = PolynomialRing(FiniteField(7))1442sage: C = HyperellipticCurve(x^8+x+1)1443sage: C.rational_points()1444[(0 : 1 : 0), (0 : 1 : 1), (0 : 6 : 1), (2 : 0 : 1),1445(4 : 0 : 1), (6 : 1 : 1), (6 : 6 : 1)]14461447TODO:144814491. The above algorithms enumerate all projective points and1450test whether they lie on the scheme; Implement a more naive1451sieve at least for covers of the projective line.145214532. Implement Stoll's model in weighted projective space to1454resolve singularities and find two points (1 : 1 : 0) and1455(-1 : 1 : 0) at infinity.1456"""1457if F == None:1458F = self.base_ring()1459X = self(F)1460if is_RationalField(F) or F == ZZ:1461if not bound > 0:1462raise TypeError, "A positive bound (= %s) must be specified."%bound1463try:1464return X.points(bound)1465except TypeError:1466raise TypeError, "Unable to enumerate points over %s."%F1467try:1468return X.points()1469except TypeError:1470raise TypeError, "Unable to enumerate points over %s."%F1471147214731474#*******************************************************************1475# Affine varieties1476#*******************************************************************1477class AlgebraicScheme_subscheme_affine(AlgebraicScheme_subscheme):1478"""1479Construct an algebraic subscheme of affine space.14801481.. WARNING::14821483You should not create objects of this class directly. The1484preferred method to construct such subschemes is to use1485:meth:`~sage.schemes.generic.affine_space.AffineSpace_generic.subscheme`1486method of :class:`affine space1487<sage.schemes.generic.affine_space.AffineSpace_generic>`.14881489INPUT:14901491- ``A`` -- ambient :class:`affine space1492<sage.schemes.generic.affine_space.AffineSpace_generic>`14931494- ``polynomials`` -- single polynomial, ideal or iterable of1495defining polynomials.14961497EXAMPLES::14981499sage: A3.<x, y, z> = AffineSpace(3, QQ)1500sage: A3.subscheme([x^2-y*z])1501Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:1502x^2 - y*z15031504TESTS::15051506sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_affine1507sage: AlgebraicScheme_subscheme_affine(A3, [x^2-y*z])1508Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:1509x^2 - y*z1510"""15111512def _morphism(self, *args, **kwds):1513return morphism.SchemeMorphism_polynomial_affine_space(*args, **kwds)15141515def dimension(self):1516"""1517Return the dimension of the affine algebraic subscheme.15181519OUTPUT:15201521Integer.15221523EXAMPLES::15241525sage: A.<x,y> = AffineSpace(2, QQ)1526sage: A.subscheme([]).dimension()152721528sage: A.subscheme([x]).dimension()152911530sage: A.subscheme([x^5]).dimension()153111532sage: A.subscheme([x^2 + y^2 - 1]).dimension()153311534sage: A.subscheme([x*(x-1), y*(y-1)]).dimension()1535015361537Something less obvious::15381539sage: A.<x,y,z,w> = AffineSpace(4, QQ)1540sage: X = A.subscheme([x^2, x^2*y^2 + z^2, z^2 - w^2, 10*x^2 + w^2 - z^2])1541sage: X1542Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:1543x^2,1544x^2*y^2 + z^2,1545z^2 - w^2,154610*x^2 - z^2 + w^21547sage: X.dimension()154811549"""1550try:1551return self.__dimension1552except AttributeError:1553self.__dimension = self.defining_ideal().dimension()1554return self.__dimension15551556def projective_embedding(self, i=None, X=None):1557"""1558Returns a morphism from this affine scheme into an ambient1559projective space of the same dimension.15601561INPUT:15621563- ``i`` -- integer (default: dimension of self = last1564coordinate) determines which projective embedding to compute. The1565embedding is that which has a 1 in the i-th coordinate, numbered1566from 0.156715681569- ``X`` -- (default: None) projective scheme, i.e., codomain of1570morphism; this is constructed if it is not given.15711572EXAMPLES::15731574sage: A.<x, y, z> = AffineSpace(3, ZZ)1575sage: S = A.subscheme([x*y-z])1576sage: S.projective_embedding()1577Scheme morphism:1578From: Closed subscheme of Affine Space of dimension 3 over Integer Ring defined by:1579x*y - z1580To: Closed subscheme of Projective Space of dimension 3 over Integer Ring defined by:1581x0*x1 - x2*x31582Defn: Defined on coordinates by sending (x, y, z) to1583(x : y : z : 1)1584"""1585AA = self.ambient_space()1586n = AA.dimension_relative()1587if i is None:1588try:1589i = self._default_embedding_index1590except AttributeError:1591i = int(n)1592else:1593i = int(i)1594if i < 0 or i > n:1595raise ValueError, \1596"Argument i (=%s) must be between 0 and %s, inclusive"%(i, n)1597try:1598return self.__projective_embedding[i]1599except AttributeError:1600self.__projective_embedding = {}1601except KeyError:1602pass1603if X is None:1604PP = projective_space.ProjectiveSpace(n, AA.base_ring())1605v = list(PP.gens())1606z = v.pop(i)1607v.append(z)1608polys = self.defining_polynomials()1609X = PP.subscheme([ f.homogenize()(v) for f in polys ])1610R = AA.coordinate_ring()1611v = list(R.gens())1612v.insert(i, R(1))1613phi = self.hom(v, X)1614self.__projective_embedding[i] = phi1615return phi16161617def is_smooth(self, point=None):1618r"""1619Test whether the algebraic subscheme is smooth.16201621INPUT:16221623- ``point`` -- A point or ``None`` (default). The point to1624test smoothness at.16251626OUTPUT:16271628Boolean. If no point was specified, returns whether the1629algebraic subscheme is smooth everywhere. Otherwise,1630smoothness at the specified point is tested.16311632EXAMPLES::16331634sage: A2.<x,y> = AffineSpace(2,QQ)1635sage: cuspidal_curve = A2.subscheme([y^2-x^3])1636sage: cuspidal_curve1637Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1638-x^3 + y^21639sage: smooth_point = cuspidal_curve.point([1,1])1640sage: smooth_point in cuspidal_curve1641True1642sage: singular_point = cuspidal_curve.point([0,0])1643sage: singular_point in cuspidal_curve1644True1645sage: cuspidal_curve.is_smooth(smooth_point)1646True1647sage: cuspidal_curve.is_smooth(singular_point)1648False1649sage: cuspidal_curve.is_smooth()1650False1651"""1652R = self.ambient_space().coordinate_ring()1653if not point is None:1654self._check_satisfies_equations(point)1655point_subs = dict(zip(R.gens(), point))1656Jac = self.Jacobian().subs(point_subs)1657return not Jac.is_zero()16581659# testing smoothness everywhere tends to be expensive1660try:1661return self._smooth1662except AttributeError:1663pass1664sing_dim = self.Jacobian().dimension()1665self._smooth = (sing_dim == -1)1666return self._smooth1667166816691670#*******************************************************************1671# Projective varieties1672#*******************************************************************1673class AlgebraicScheme_subscheme_projective(AlgebraicScheme_subscheme):1674"""1675Construct an algebraic subscheme of projective space.16761677.. WARNING::16781679You should not create objects of this class directly. The1680preferred method to construct such subschemes is to use1681:meth:`~sage.schemes.generic.projective_space.ProjectiveSpace_field.subscheme`1682method of :class:`projective space1683<sage.schemes.generic.projective_space.ProjectiveSpace_field>`.16841685INPUT:16861687- ``A`` -- ambient :class:`projective space1688<sage.schemes.generic.projective_space.ProjectiveSpace_field>`.16891690- ``polynomials`` -- single polynomial, ideal or iterable of1691defining homogeneous polynomials.16921693EXAMPLES::16941695sage: P.<x, y, z> = ProjectiveSpace(2, QQ)1696sage: P.subscheme([x^2-y*z])1697Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1698x^2 - y*z16991700TESTS::17011702sage: from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_projective1703sage: AlgebraicScheme_subscheme_projective(P, [x^2-y*z])1704Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1705x^2 - y*z1706"""17071708def _morphism(self, *args, **kwds):1709r"""1710Construct a morphism determined by action on points of ``self``.17111712For internal use only.17131714INPUT:17151716- same as for1717:class:`~sage.schemes.generic.morphism.SchemeMorphism_polynomial_projective_space`.17181719OUPUT:17201721- :class:`~sage.schemes.generic.morphism.SchemeMorphism_polynomial_projective_space`.17221723TESTS::17241725sage: P1.<x,y> = ProjectiveSpace(1,QQ)1726sage: P2 = ProjectiveSpace(2,QQ)1727sage: H12 = P1.Hom(P2)1728sage: H12([x^2,x*y, y^2]) # indirect doctest1729Scheme morphism:1730From: Projective Space of dimension 1 over Rational Field1731To: Projective Space of dimension 2 over Rational Field1732Defn: Defined on coordinates by sending (x : y) to1733(x^2 : x*y : y^2)1734sage: P1._morphism(H12, [x^2,x*y, y^2])1735Scheme morphism:1736From: Projective Space of dimension 1 over Rational Field1737To: Projective Space of dimension 2 over Rational Field1738Defn: Defined on coordinates by sending (x : y) to1739(x^2 : x*y : y^2)1740"""1741return morphism.SchemeMorphism_polynomial_projective_space(*args, **kwds)17421743def dimension(self):1744"""1745Return the dimension of the projective algebraic subscheme.17461747OUTPUT:17481749Integer.17501751EXAMPLES::17521753sage: P2.<x,y,z> = ProjectiveSpace(2, QQ)1754sage: P2.subscheme([]).dimension()175521756sage: P2.subscheme([x]).dimension()175711758sage: P2.subscheme([x^5]).dimension()175911760sage: P2.subscheme([x^2 + y^2 - z^2]).dimension()176111762sage: P2.subscheme([x*(x-z), y*(y-z)]).dimension()1763017641765Something less obvious::17661767sage: P3.<x,y,z,w,t> = ProjectiveSpace(4, QQ)1768sage: X = P3.subscheme([x^2, x^2*y^2 + z^2*t^2, z^2 - w^2, 10*x^2 + w^2 - z^2])1769sage: X1770Closed subscheme of Projective Space of dimension 4 over Rational Field defined by:1771x^2,1772x^2*y^2 + z^2*t^2,1773z^2 - w^2,177410*x^2 - z^2 + w^21775sage: X.dimension()177611777"""1778try:1779return self.__dimension1780except AttributeError:1781self.__dimension = self.defining_ideal().dimension() - 11782return self.__dimension17831784def affine_patch(self, i):1785r"""1786Return the `i^{th}` affine patch of this projective scheme.1787This is the intersection with this `i^{th}` affine patch of1788its ambient space.17891790INPUT:17911792- ``i`` -- integer between 0 and dimension of self, inclusive.17931794OUTPUT:17951796An affine algebraic scheme with fixed1797:meth:`embedding_morphism` equal to the default1798:meth:`projective_embedding` map`.17991800EXAMPLES::18011802sage: PP = ProjectiveSpace(2, QQ, names='X,Y,Z')1803sage: X,Y,Z = PP.gens()1804sage: C = PP.subscheme(X^3*Y + Y^3*Z + Z^3*X)1805sage: U = C.affine_patch(0)1806sage: U1807Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1808x0^3*x1 + x1^3 + x01809sage: U.embedding_morphism()1810Scheme morphism:1811From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1812x0^3*x1 + x1^3 + x01813To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1814X^3*Y + Y^3*Z + X*Z^31815Defn: Defined on coordinates by sending (x0, x1) to1816(1 : x0 : x1)1817sage: U.projective_embedding() is U.embedding_morphism()1818True1819"""1820i = int(i) # implicit type checking1821PP = self.ambient_space()1822n = PP.dimension()1823if i < 0 or i > n:1824raise ValueError, "Argument i (= %s) must be between 0 and %s."%(i, n)1825try:1826return self.__affine_patches[i]1827except AttributeError:1828self.__affine_patches = {}1829except KeyError:1830pass1831AA = PP.affine_patch(i)1832phi = AA.projective_embedding()1833polys = self.defining_polynomials()1834xi = phi.defining_polynomials()1835U = AA.subscheme([ f(xi) for f in polys ])1836U._default_embedding_index = i1837phi = U.projective_embedding(i, self)1838self.__affine_patches[i] = U1839U._embedding_morphism = phi1840return U18411842def _best_affine_patch(self, point):1843r"""1844Return the best affine patch of the ambient projective space.18451846The "best" affine patch is where you end up dividing by the1847homogeneous coordinate with the largest absolutue1848value. Division by small numbers is numerically unstable.18491850INPUT:18511852- ``point`` -- a point of the algebraic subscheme.18531854OUTPUT:18551856Integer. The index of the patch. See :meth:`affine_patch`.18571858EXAMPLES::18591860sage: P.<x,y,z>= ProjectiveSpace(QQ,2)1861sage: S = P.subscheme(x+2*y+3*z)1862sage: S._best_affine_patch(P.point([0,-3,2]))186311864sage: S._best_affine_patch([0,-3,2])1865118661867TESTS::18681869sage: F = GF(3)1870sage: P.<x,y,z>= ProjectiveSpace(F,2)1871sage: S._best_affine_patch([0,1,2])187221873"""1874point = list(point)1875try:1876abs_point = map(abs, point)1877except ArithmeticError:1878# our base ring does not know abs1879abs_point = point1880# find best patch1881i_max = 01882p_max = abs_point[i_max]1883for i in range(1,len(point)):1884if abs_point[i]>p_max:1885i_max = i1886p_max = abs_point[i_max]1887return i_max18881889def neighborhood(self, point):1890r"""1891Return an affine algebraic subscheme isomorphic to a1892neighborhood of the ``point``.18931894INPUT:18951896- ``point`` -- a point of the projective subscheme.18971898OUTPUT18991900An affine algebraic scheme (polynomial equations in affine1901space) ``result`` such that19021903* :meth:`embedding_morphism1904<AlgebraicScheme.embedding_morphism>` is an isomorphism to a1905neighborhood of ``point``19061907* :meth:`embedding_center <AlgebraicScheme.embedding_center>`1908is mapped to ``point``.19091910EXAMPLES::19111912sage: P.<x,y,z>= ProjectiveSpace(QQ,2)1913sage: S = P.subscheme(x+2*y+3*z)1914sage: s = S.point([0,-3,2]); s1915(0 : -3/2 : 1)1916sage: patch = S.neighborhood(s); patch1917Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1918x0 + 3*x11919sage: patch.embedding_morphism()1920Scheme morphism:1921From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:1922x0 + 3*x11923To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1924x + 2*y + 3*z1925Defn: Defined on coordinates by sending (x0, x1) to1926(-3*x1 : -3/2 : x1 + 1)1927sage: patch.embedding_center()1928(0, 0)1929sage: patch.embedding_morphism()([0,0])1930(0 : -3/2 : 1)1931sage: patch.embedding_morphism()(patch.embedding_center())1932(0 : -3/2 : 1)1933"""1934point = list(point)1935self._check_satisfies_equations(point)1936PP = self.ambient_space()1937n = PP.dimension()1938i = self._best_affine_patch(point)19391940patch_cover = PP.affine_patch(i)1941R = patch_cover.coordinate_ring()19421943phi = list(point)1944for j in range(0,i):1945phi[j] = phi[j] + R.gen(j)1946for j in range(i,n):1947phi[j+1] = phi[j+1] + R.gen(j)19481949pullback_polys = [f(phi) for f in self.defining_polynomials()]1950patch = patch_cover.subscheme(pullback_polys)1951patch_hom = patch.hom(phi,self)1952patch._embedding_center = patch.point([0]*n)1953patch._embedding_morphism = patch_hom1954return patch19551956def is_smooth(self, point=None):1957r"""1958Test whether the algebraic subscheme is smooth.19591960INPUT:19611962- ``point`` -- A point or ``None`` (default). The point to1963test smoothness at.19641965OUTPUT:19661967Boolean. If no point was specified, returns whether the1968algebraic subscheme is smooth everywhere. Otherwise,1969smoothness at the specified point is tested.19701971EXAMPLES::19721973sage: P2.<x,y,z> = ProjectiveSpace(2,QQ)1974sage: cuspidal_curve = P2.subscheme([y^2*z-x^3])1975sage: cuspidal_curve1976Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:1977-x^3 + y^2*z1978sage: cuspidal_curve.is_smooth([1,1,1])1979True1980sage: cuspidal_curve.is_smooth([0,0,1])1981False1982sage: cuspidal_curve.is_smooth()1983False1984sage: P2.subscheme([y^2*z-x^3+z^3+1/10*x*y*z]).is_smooth()1985True19861987TESTS::19881989sage: H = P2.subscheme(x)1990sage: H.is_smooth() # one of the few cases where the cone over the subvariety is smooth1991True1992"""1993if not point is None:1994self._check_satisfies_equations(point)1995R = self.ambient_space().coordinate_ring()1996point_subs = dict(zip(R.gens(), point))1997Jac = self.Jacobian().subs(point_subs)1998return not Jac.is_zero()19992000# testing smoothness everywhere tends to be expensive2001try:2002return self._smooth2003except AttributeError:2004pass2005sing_dim = self.Jacobian().dimension()2006# We really test the affine cone here; the origin is always a singular point:2007self._smooth = (sing_dim <= 0)2008return self._smooth200920102011#*******************************************************************2012# Toric varieties2013#*******************************************************************2014class AlgebraicScheme_subscheme_toric(AlgebraicScheme_subscheme):2015r"""2016Construct an algebraic subscheme of a toric variety.20172018.. WARNING::20192020You should not create objects of this class directly. The2021preferred method to construct such subschemes is to use2022:meth:`~ToricVariety_field.subscheme` method of :class:`toric2023varieties2024<sage.schemes.toric.variety.ToricVariety_field>`.20252026INPUT:20272028- ``toric_variety`` -- ambient :class:`toric variety2029<ToricVariety_field>`;20302031- ``polynomials`` -- single polynomial, list, or ideal of defining2032polynomials in the coordinate ring of ``toric_variety``.20332034OUTPUT:20352036- :class:`algebraic subscheme of a toric variety2037<AlgebraicScheme_subscheme_toric>`.20382039TESTS::20402041sage: fan = FaceFan(lattice_polytope.octahedron(2))2042sage: P1xP1 = ToricVariety(fan, "x s y t")2043sage: P1xP1.inject_variables()2044Defining x, s, y, t2045sage: import sage.schemes.generic.algebraic_scheme as SCM2046sage: X = SCM.AlgebraicScheme_subscheme_toric(2047... P1xP1, [x*s + y*t, x^3+y^3])2048sage: X2049Closed subscheme of 2-d toric variety2050covered by 4 affine patches defined by:2051x*s + y*t,2052x^3 + y^320532054A better way to construct the same scheme as above::20552056sage: P1xP1.subscheme([x*s + y*t, x^3+y^3])2057Closed subscheme of 2-d toric variety2058covered by 4 affine patches defined by:2059x*s + y*t,2060x^3 + y^32061"""20622063# Implementation note: if the toric variety is affine you should2064# construct instances of the derived class2065# AlgebraicScheme_subscheme_affine_toric instead.20662067def __init__(self, toric_variety, polynomials):2068r"""2069See :class:`AlgebraicScheme_subscheme_toric` for documentation.20702071TESTS::20722073sage: fan = FaceFan(lattice_polytope.octahedron(2))2074sage: P1xP1 = ToricVariety(fan, "x s y t")2075sage: P1xP1.inject_variables()2076Defining x, s, y, t2077sage: import sage.schemes.generic.algebraic_scheme as SCM2078sage: X = SCM.AlgebraicScheme_subscheme_toric(2079... P1xP1, [x*s + y*t, x^3+y^3])2080sage: X2081Closed subscheme of 2-d toric variety2082covered by 4 affine patches defined by:2083x*s + y*t,2084x^3 + y^32085"""2086# Just to make sure that keyword arguments will be passed correctly2087super(AlgebraicScheme_subscheme_toric, self).__init__(toric_variety,2088polynomials)20892090def _morphism(self, *args, **kwds):2091r"""2092Construct a morphism determined by action on points of ``self``.20932094INPUT:20952096- same as for2097:class:`~sage.schemes.toric.morphism.SchemeMorphism_polynomial_toric_variety`.20982099OUPUT:21002101- :class:`~sage.schemes.toric.morphism.SchemeMorphism_polynomial_toric_variety`.21022103TESTS::21042105sage: fan = FaceFan(lattice_polytope.octahedron(2))2106sage: P1xP1 = ToricVariety(fan)2107sage: P1xP1.inject_variables()2108Defining z0, z1, z2, z32109sage: P1 = P1xP1.subscheme(z0-z2)2110sage: H = P1.Hom(P1xP1)2111sage: H([z0,z1,z0,z3])2112Scheme morphism:2113From: Closed subscheme of 2-d toric variety2114covered by 4 affine patches defined by:2115z0 - z22116To: 2-d toric variety covered by 4 affine patches2117Defn: Defined on coordinates by sending [z0 : z1 : z2 : z3] to2118[z2 : z1 : z2 : z3]21192120sage: P1._morphism(H, [z0,z1,z0,z3])2121Scheme morphism:2122From: Closed subscheme of 2-d toric variety2123covered by 4 affine patches defined by:2124z0 - z22125To: 2-d toric variety covered by 4 affine patches2126Defn: Defined on coordinates by sending [z0 : z1 : z2 : z3] to2127[z2 : z1 : z2 : z3]2128"""2129from sage.schemes.toric.morphism import SchemeMorphism_polynomial_toric_variety2130return SchemeMorphism_polynomial_toric_variety(*args, **kwds)21312132def fan(self):2133"""2134Return the fan of the ambient space.21352136OUTPUT:21372138A fan.21392140EXAMPLES::21412142sage: P2.<x,y,z> = toric_varieties.P(2)2143sage: E = P2.subscheme([x^2+y^2+z^2])2144sage: E.fan()2145Rational polyhedral fan in 2-d lattice N2146"""2147return self.ambient_space().fan()21482149def affine_patch(self, i):2150r"""2151Return the ``i``-th affine patch of ``self`` as an affine2152toric algebraic scheme.21532154INPUT:21552156- ``i`` -- integer, index of a generating cone of the fan of the2157ambient space of ``self``.21582159OUTPUT:21602161- subscheme of an affine :class:`toric variety2162<sage.schemes.toric.variety.ToricVariety_field>`2163corresponding to the pull-back of ``self`` by the embedding2164morphism of the ``i``-th :meth:`affine patch of the ambient2165space2166<sage.schemes.toric.variety.ToricVariety_field.affine_patch>`2167of ``self``.21682169The result is cached, so the ``i``-th patch is always the same object2170in memory.21712172EXAMPLES::21732174sage: fan = FaceFan(lattice_polytope.octahedron(2))2175sage: P1xP1 = ToricVariety(fan, "x s y t")2176sage: patch1 = P1xP1.affine_patch(1)2177sage: patch1.embedding_morphism()2178Scheme morphism:2179From: 2-d affine toric variety2180To: 2-d toric variety covered by 4 affine patches2181Defn: Defined on coordinates by sending [y : t] to2182[1 : 1 : y : t]2183sage: P1xP1.inject_variables()2184Defining x, s, y, t2185sage: P1 = P1xP1.subscheme(x-y)2186sage: subpatch = P1.affine_patch(1)2187sage: subpatch2188Closed subscheme of 2-d affine toric variety defined by:2189-y + 12190"""2191i = int(i) # implicit type checking2192try:2193return self._affine_patches[i]2194except AttributeError:2195self._affine_patches = dict()2196except KeyError:2197pass2198ambient_patch = self.ambient_space().affine_patch(i)2199phi_p = ambient_patch.embedding_morphism().defining_polynomials()2200patch = ambient_patch.subscheme(2201[p(phi_p) for p in self.defining_polynomials()])2202patch._embedding_morphism = patch.hom(phi_p, self, check=False)2203self._affine_patches[i] = patch2204return patch22052206def affine_algebraic_patch(self, cone=None, names=None):2207r"""2208Return the affine patch corresponding to ``cone`` as an affine2209algebraic scheme.22102211INPUT:22122213- ``cone`` -- a :class:`Cone2214<sage.geometry.cone.ConvexRationalPolyhedralCone>` `\sigma`2215of the fan. It can be omitted for an affine toric variety,2216in which case the single generating cone is used.22172218OUTPUT:22192220An :class:`affine algebraic subscheme2221<sage.schemes.generic.algebraic_scheme.AlgebraicScheme_subscheme_affine>`2222corresponding to the patch `\mathop{Spec}(\sigma^\vee \cap M)`2223associated to the cone `\sigma`.22242225See also :meth:`affine_patch`, which expresses the patches as2226subvarieties of affine toric varieties instead.22272228REFERENCES:22292230..22312232David A. Cox, "The Homogeneous Coordinate Ring of a Toric2233Variety", Lemma 2.2.2234http://www.arxiv.org/abs/alg-geom/9210008v222352236EXAMPLES::22372238sage: P2.<x,y,z> = toric_varieties.P2()2239sage: cone = P2.fan().generating_cone(0)2240sage: V = P2.subscheme(x^3+y^3+z^3)2241sage: V.affine_algebraic_patch(cone)2242Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:2243z0^3 + z1^3 + 122442245sage: cone = Cone([(0,1),(2,1)])2246sage: A2Z2.<x,y> = AffineToricVariety(cone)2247sage: A2Z2.affine_algebraic_patch()2248Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:2249-z0*z1 + z2^22250sage: V = A2Z2.subscheme(x^2+y^2-1)2251sage: patch = V.affine_algebraic_patch(); patch2252Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:2253-z0*z1 + z2^2,2254z0 + z1 - 12255sage: nbhd_patch = V.neighborhood([1,0]).affine_algebraic_patch(); nbhd_patch2256Closed subscheme of Affine Space of dimension 3 over Rational Field defined by:2257-z0*z1 + z2^2,2258z0 + z1 - 12259sage: nbhd_patch.embedding_center()2260(0, 1, 0)22612262Here we got two defining equations. The first one describes2263the singularity of the ambient space and the second is the2264pull-back of `x^2+y^2-1` ::22652266sage: lp = LatticePolytope([(1,0,0),(1,1,0),(1,1,1),(1,0,1),(-2,-1,-1)])2267sage: X.<x,y,u,v,t> = CPRFanoToricVariety(Delta_polar=lp)2268sage: Y = X.subscheme(x*v+y*u+t)2269sage: cone = Cone([(1,0,0),(1,1,0),(1,1,1),(1,0,1)])2270sage: Y.affine_algebraic_patch(cone)2271Closed subscheme of Affine Space of dimension 4 over Rational Field defined by:2272z0*z2 - z1*z3,2273z1 + z3 + 12274"""2275from sage.modules.all import vector2276from sage.misc.all import prod2277ambient = self.ambient_space()2278fan = ambient.fan()2279if cone is None:2280assert ambient.is_affine()2281cone = fan.generating_cone(0)2282else:2283cone = fan.embed(cone)2284# R/I = C[sigma^dual cap M]2285R, I, dualcone = ambient._semigroup_ring(cone, names)22862287# inhomogenize the Cox homogeneous polynomial with respect to the given cone2288inhomogenize = dict( (ambient.coordinate_ring().gen(i), 1)2289for i in range(0,fan.nrays())2290if not i in cone.ambient_ray_indices() )2291polynomials = [ p.subs(inhomogenize) for p in self.defining_polynomials() ]22922293# map the monomial x^{D_m} to m, see reference.2294n_rho_matrix = cone.ray_matrix()2295def pullback_polynomial(p):2296result = R.zero()2297for coefficient, monomial in p:2298exponent = monomial.exponents()[0]2299exponent = [ exponent[i] for i in cone.ambient_ray_indices() ]2300exponent = vector(ZZ,exponent)2301m = n_rho_matrix.solve_left(exponent)2302assert all(x in ZZ for x in m), \2303'The polynomial '+str(p)+' does not define a ZZ-divisor!'2304m_coeffs = dualcone.Hilbert_coefficients(m)2305result += coefficient * prod(R.gen(i)**m_coeffs[i]2306for i in range(0,R.ngens()))2307return result23082309# construct the affine algebraic scheme to use as patch2310polynomials = map(pullback_polynomial, polynomials)2311patch_cover = affine_space.AffineSpace(R)2312polynomials = list(I.gens()) + polynomials2313polynomials = filter( lambda x:not x.is_zero(), polynomials)2314patch = patch_cover.subscheme(polynomials)23152316# TODO: If the cone is not smooth, then the coordinate_ring()2317# of the affine toric variety is wrong; it should be the2318# G-invariant part. So we can't construct the embedding2319# morphism in that case.2320if cone.is_smooth():2321x = ambient.coordinate_ring().gens()2322phi = []2323for i in range(0,fan.nrays()):2324if i in cone.ambient_ray_indices():2325phi.append(pullback_polynomial(x[i]))2326else:2327phi.append(1)2328patch._embedding_morphism = patch.hom(phi, self)2329else:2330patch._embedding_morphism = (NotImplementedError,2331'I only know how to construct embedding morphisms for smooth patches')23322333try:2334point = self.embedding_center()2335except AttributeError:2336return patch23372338# it remains to find the preimage of point2339# map m to the monomial x^{D_m}, see reference.2340F = ambient.coordinate_ring().fraction_field()2341image = []2342for m in dualcone.Hilbert_basis():2343x_Dm = prod([ F.gen(i)**(m*n) for i,n in enumerate(fan.rays()) ])2344image.append(x_Dm)2345patch._embedding_center = tuple( f(list(point)) for f in image )2346return patch23472348def _best_affine_patch(self, point):2349r"""2350Return the best affine patch of the ambient toric variety.23512352INPUT:23532354- ``point`` -- a point of the algebraic subscheme.23552356OUTPUT:23572358Integer. The index of the patch. See :meth:`affine_patch`.23592360EXAMPLES::23612362sage: P.<x,y,z>= toric_varieties.P2()2363sage: S = P.subscheme(x+2*y+3*z)2364sage: S._best_affine_patch(P.point([2,-3,0]))236512366sage: S._best_affine_patch([2,-3,0])236712368"""2369# TODO: this method should pick a "best" patch in the sense2370# that it is numerically stable to dehomogenize, see the2371# corresponding method for projective varieties.2372point = list(point)2373zeros = set(i for i, coord in enumerate(point) if coord == 0)2374for cone_idx, cone in enumerate(self.ambient_space().fan().generating_cones()):2375if zeros.issubset(cone.ambient_ray_indices()):2376return cone_idx2377assert False, 'The point must not have been a point of the toric variety.'23782379def neighborhood(self, point):2380r"""2381Return an toric algebraic scheme isomorphic to neighborhood of2382the ``point``.23832384INPUT:23852386- ``point`` -- a point of the toric algebraic scheme.23872388OUTPUT23892390An affine toric algebraic scheme (polynomial equations in an2391affine toric variety) with fixed2392:meth:`~AlgebraicScheme.embedding_morphism` and2393:meth:`~AlgebraicScheme.embedding_center`.23942395EXAMPLES::23962397sage: P.<x,y,z>= toric_varieties.P2()2398sage: S = P.subscheme(x+2*y+3*z)2399sage: s = S.point([0,-3,2]); s2400[0 : -3 : 2]2401sage: patch = S.neighborhood(s); patch2402Closed subscheme of 2-d affine toric variety defined by:2403x + 2*y + 62404sage: patch.embedding_morphism()2405Scheme morphism:2406From: Closed subscheme of 2-d affine toric variety defined by:2407x + 2*y + 62408To: Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by:2409x + 2*y + 3*z2410Defn: Defined on coordinates by sending [x : y] to2411[-2*y - 6 : y : 2]2412sage: patch.embedding_center()2413[0 : -3]2414sage: patch.embedding_morphism()(patch.embedding_center())2415[0 : -3 : 2]24162417A more complicated example::24182419sage: dP6.<x0,x1,x2,x3,x4,x5> = toric_varieties.dP6()2420sage: twoP1 = dP6.subscheme(x0*x3)2421sage: patch = twoP1.neighborhood([0,1,2, 3,4,5]); patch2422Closed subscheme of 2-d affine toric variety defined by:24233*x02424sage: patch.embedding_morphism()2425Scheme morphism:2426From: Closed subscheme of 2-d affine toric variety defined by:24273*x02428To: Closed subscheme of 2-d CPR-Fano toric variety covered by 6 affine patches defined by:2429x0*x32430Defn: Defined on coordinates by sending [x0 : x1] to2431[0 : x1 : 2 : 3 : 4 : 5]2432sage: patch.embedding_center()2433[0 : 1]2434sage: patch.embedding_morphism()(patch.embedding_center())2435[0 : 1 : 2 : 3 : 4 : 5]2436"""2437point = list(point)2438self._check_satisfies_equations(point)2439PP = self.ambient_space()2440n = PP.dimension()2441fan = PP.fan()2442cone_idx = self._best_affine_patch(point)2443cone = fan.generating_cone(cone_idx)24442445patch_cover = PP.affine_patch(cone_idx)2446R = patch_cover.coordinate_ring()2447phi = []2448point_preimage = []2449for i in range(0,fan.nrays()):2450try:2451ray_index = cone.ambient_ray_indices().index(i)2452phi.append(R.gen(ray_index))2453point_preimage.append(point[i])2454except ValueError:2455phi.append(point[i])2456pullback_polys = [f(phi) for f in self.defining_polynomials()]2457patch = patch_cover.subscheme(pullback_polys)24582459patch._embedding_center = patch(point_preimage)2460patch._embedding_morphism = patch.hom(phi,self)2461return patch24622463def dimension(self):2464"""2465Return the dimension of ``self``.24662467OUTPUT:24682469Integer. If ``self`` is empty, `-1` is returned.24702471EXAMPLES::24722473sage: fan = FaceFan(lattice_polytope.octahedron(2))2474sage: P1xP1 = ToricVariety(fan)2475sage: P1xP1.inject_variables()2476Defining z0, z1, z2, z32477sage: P1 = P1xP1.subscheme(z0-z2)2478sage: P1.dimension()247912480sage: P1xP1.subscheme([z0-z2, (z0-z2)^2]).dimension()248112482sage: P1xP1.subscheme([z0,z2]).dimension()2483-12484"""2485if '_dimension' in self.__dict__:2486return self._dimension2487npatches = self.ambient_space().fan().ngenerating_cones()2488dims = [ self.affine_patch(i).dimension() for i in range(0,npatches) ]2489self._dimension = max(dims)2490return self._dimension24912492def is_smooth(self, point=None):2493r"""2494Test whether the algebraic subscheme is smooth.24952496INPUT:24972498- ``point`` -- A point or ``None`` (default). The point to2499test smoothness at.25002501OUTPUT:25022503Boolean. If no point was specified, returns whether the2504algebraic subscheme is smooth everywhere. Otherwise,2505smoothness at the specified point is tested.25062507EXAMPLES::25082509sage: P2.<x,y,z> = toric_varieties.P2()2510sage: cuspidal_curve = P2.subscheme([y^2*z-x^3])2511sage: cuspidal_curve2512Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by:2513-x^3 + y^2*z2514sage: cuspidal_curve.is_smooth([1,1,1])2515True2516sage: cuspidal_curve.is_smooth([0,0,1])2517False2518sage: cuspidal_curve.is_smooth()2519False25202521Any sufficiently generic cubic hypersurface is smooth::25222523sage: P2.subscheme([y^2*z-x^3+z^3+1/10*x*y*z]).is_smooth()2524True25252526A more complicated example::25272528sage: dP6.<x0,x1,x2,x3,x4,x5> = toric_varieties.dP6()2529sage: disjointP1s = dP6.subscheme(x0*x3)2530sage: disjointP1s.is_smooth()2531True2532sage: intersectingP1s = dP6.subscheme(x0*x1)2533sage: intersectingP1s.is_smooth()2534False25352536A smooth hypersurface in a compact singular toric variety::25372538sage: lp = LatticePolytope(matrix([(1,0,0),(1,1,0),(1,1,1),(1,0,1),(-2,-1,-1)]).transpose())2539sage: X.<x,y,u,v,t> = CPRFanoToricVariety(Delta_polar=lp)2540sage: Y = X.subscheme(x*v+y*u+t)2541sage: cone = Cone([(1,0,0),(1,1,0),(1,1,1),(1,0,1)])2542sage: Y.is_smooth()2543True2544"""2545if not point is None:2546toric_patch = self.neighborhood(point)2547return toric_patch.is_smooth(toric_patch.embedding_center())25482549# testing smoothness everywhere tends to be expensive2550if '_smooth' in self.__dict__:2551return self._smooth2552npatches = self.ambient_space().fan().ngenerating_cones()2553self._smooth = all(self.affine_patch(i).is_smooth() for i in range(0,npatches))2554return self._smooth255525562557class AlgebraicScheme_subscheme_affine_toric(AlgebraicScheme_subscheme_toric):2558r"""2559Construct an algebraic subscheme of an affine toric variety.25602561.. WARNING::25622563You should not create objects of this class directly. The preferred2564method to construct such subschemes is to use2565:meth:`~ToricVariety_field.subscheme` method of2566:class:`toric varieties <ToricVariety_field>`.25672568INPUT:25692570- ``toric_variety`` -- ambient :class:`affine toric variety2571<ToricVariety_field>`;25722573- ``polynomials`` -- single polynomial, list, or ideal of defining2574polynomials in the coordinate ring of ``toric_variety``.25752576OUTPUT:25772578A :class:`algebraic subscheme of an affine toric variety2579<AlgebraicScheme_subscheme_affine_toric>`.25802581TESTS::25822583sage: fan = FaceFan(lattice_polytope.octahedron(2))2584sage: P1xP1 = ToricVariety(fan, "x s y t")2585sage: P1xP1.inject_variables()2586Defining x, s, y, t2587sage: import sage.schemes.generic.algebraic_scheme as SCM2588sage: X = SCM.AlgebraicScheme_subscheme_toric(2589... P1xP1, [x*s + y*t, x^3+y^3])2590sage: X2591Closed subscheme of 2-d toric variety2592covered by 4 affine patches defined by:2593x*s + y*t,2594x^3 + y^325952596A better way to construct the same scheme as above::25972598sage: P1xP1.subscheme([x*s + y*t, x^3+y^3])2599Closed subscheme of 2-d toric variety2600covered by 4 affine patches defined by:2601x*s + y*t,2602x^3 + y^32603"""26042605def __init__(self, toric_variety, polynomials):2606r"""2607See :class:`AlgebraicScheme_subscheme_toric` for documentation.26082609TESTS::26102611sage: fan = FaceFan(lattice_polytope.octahedron(2))2612sage: P1xP1 = ToricVariety(fan, "x s y t")2613sage: P1xP1.inject_variables()2614Defining x, s, y, t2615sage: import sage.schemes.generic.algebraic_scheme as SCM2616sage: X = SCM.AlgebraicScheme_subscheme_toric(2617... P1xP1, [x*s + y*t, x^3+y^3])2618sage: X2619Closed subscheme of 2-d toric variety2620covered by 4 affine patches defined by:2621x*s + y*t,2622x^3 + y^32623"""2624assert toric_variety.is_affine(), 'The toric variety must be affine!'2625# Just to make sure that keyword arguments will be passed correctly2626super(AlgebraicScheme_subscheme_affine_toric, self).__init__(toric_variety,2627polynomials)26282629def dimension(self):2630"""2631Return the dimension of ``self``.26322633OUTPUT:26342635- integer.26362637EXAMPLES::26382639sage: P1xP1.<s0,s1,t0,t1> = toric_varieties.P1xP1()2640sage: P1 = P1xP1.subscheme(s0-s1)2641sage: P1.dimension()2642126432644A more complicated example where the ambient toric variety is2645not smooth::26462647sage: X.<x,y> = toric_varieties.A2_Z2()2648sage: X.is_smooth()2649False2650sage: Y = X.subscheme([x*y, x^2])2651sage: Y2652Closed subscheme of 2-d affine toric variety defined by:2653x*y,2654x^22655sage: Y.dimension()265612657"""2658if '_dimension' in self.__dict__:2659return self._dimension26602661if self.ambient_space().is_smooth():2662self._dimension = self.defining_ideal().dimension()2663else:2664self._dimension = self.affine_algebraic_patch().dimension()2665return self._dimension26662667def is_smooth(self, point=None):2668r"""2669Test whether the algebraic subscheme is smooth.26702671INPUT:26722673- ``point`` -- A point or ``None`` (default). The point to2674test smoothness at.26752676OUTPUT:26772678Boolean. If no point was specified, returns whether the2679algebraic subscheme is smooth everywhere. Otherwise,2680smoothness at the specified point is tested.26812682EXAMPLES::26832684sage: A2.<x,y> = toric_varieties.A2()2685sage: cuspidal_curve = A2.subscheme([y^2-x^3])2686sage: cuspidal_curve2687Closed subscheme of 2-d affine toric variety defined by:2688-x^3 + y^22689sage: cuspidal_curve.is_smooth([1,1])2690True2691sage: cuspidal_curve.is_smooth([0,0])2692False2693sage: cuspidal_curve.is_smooth()2694False2695sage: circle = A2.subscheme(x^2+y^2-1)2696sage: circle.is_smooth([1,0])2697True2698sage: circle.is_smooth()2699True27002701A more complicated example where the ambient toric variety is2702not smooth::27032704sage: X.<x,y> = toric_varieties.A2_Z2() # 2-d affine space mod Z/22705sage: X.is_smooth()2706False2707sage: Y = X.subscheme([x*y, x^2]) # (twice the x=0 curve) mod Z/22708sage: Y2709Closed subscheme of 2-d affine toric variety defined by:2710x*y,2711x^22712sage: Y.dimension() # Y is a Weil divisor but not Cartier271312714sage: Y.is_smooth()2715True2716sage: Y.is_smooth([0,0])2717True2718"""2719if not point is None:2720self._check_satisfies_equations(point)2721if self.ambient_space().is_smooth():2722R = self.ambient_space().coordinate_ring()2723point_subs = dict(zip(R.gens(), point))2724Jac = self.Jacobian().subs(point_subs)2725return not Jac.is_zero()2726else:2727self._embedding_center = self.point(point)2728affine = self.affine_algebraic_patch()2729return affine.is_smooth(affine.embedding_center())27302731# testing smoothness everywhere tends to be expensive2732if '_smooth' in self.__dict__:2733return self._smooth27342735if self.ambient_space().is_smooth():2736sing_dim = self.Jacobian().dimension()2737self._smooth = (sing_dim == -1)2738else:2739self._smooth = self.affine_algebraic_patch().is_smooth()27402741return self._smooth274227432744274527462747