Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Scheme morphism
.. NOTE::
You should never create the morphisms directly. Instead, use the :meth:`~sage.schemes.generic.scheme.hom` and :meth:`~sage.structure.parent.Hom` methods that are inherited by all schemes.
If you want to extend the Sage library with some new kind of scheme, your new class (say, ``myscheme``) should provide a method
* ``myscheme._morphism(*args, **kwds)`` returning a morphism between two schemes in your category, usually defined via polynomials. Your morphism class should derive from :class:`SchemeMorphism_polynomial`. These morphisms will usually be elements of the Hom-set :class:`~sage.schemes.generic.homset.SchemeHomset_generic`.
Optionally, you can also provide a special Hom-set class for your subcategory of schemes. If you want to do this, you should also provide a method
* ``myscheme._homset(*args, **kwds)`` returning a Hom-set, which must be an element of a derived class of :class:`~sage.schemes.generic.homset.SchemeHomset_generic`. If your new Hom-set class does not use ``myscheme._morphism`` then you do not have to provide it.
Note that points on schemes are morphisms `Spec(K)\to X`, too. But we typically use a different notation, so they are implemented in a different derived class. For this, you should implement a method
* ``myscheme._point(*args, **kwds)`` returning a point, that is, a morphism `Spec(K)\to X`. Your point class should derive from :class:`SchemeMorphism_point`.
Optionally, you can also provide a special Hom-set for the points, for example the point Hom-set can provide a method to enumerate all points. If you want to do this, you should also provide a method
* ``myscheme._point_homset(*args, **kwds)`` returning the :mod:`~sage.schemes.generic.homset` of points. The Hom-sets of points are implemented in classes named ``SchemeHomset_points_...``. If your new Hom-set class does not use ``myscheme._point`` then you do not have to provide it.
AUTHORS:
- David Kohel, William Stein
- William Stein (2006-02-11): fixed bug where P(0,0,0) was allowed as a projective point.
- Volker Braun (2011-08-08): Renamed classes, more documentation, misc cleanups.
- Ben Hutz (June 2012): added support for projective ring
- Simon King (2013-10): copy the changes of :class:`~sage.categories.morphism.Morphism` that have been introduced in :trac:`14711`. """
#***************************************************************************** # Copyright (C) 2013 Simon King <simon.king@uni-jena.de> # Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com> # Copyright (C) 2006 David Kohel <kohel@maths.usyd.edu.au> # Copyright (C) 2006 William Stein <wstein@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
from __future__ import absolute_import, print_function
import operator from sage.structure.element import (AdditiveGroupElement, RingElement, Element, parent, coercion_model) from sage.arith.power import generic_power from sage.structure.richcmp import richcmp from sage.structure.sequence import Sequence from sage.categories.homset import Homset, Hom, End from sage.categories.number_fields import NumberFields from sage.categories.fields import Fields from sage.rings.all import Integer, CIF from sage.rings.fraction_field import FractionField from sage.rings.fraction_field_element import FractionFieldElement from .point import is_SchemeTopologicalPoint from sage.rings.infinity import infinity from . import scheme
from sage.categories.gcd_domains import GcdDomains from sage.rings.qqbar import QQbar from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ from sage.categories.map import FormalCompositeMap, Map from sage.misc.constant_function import ConstantFunction from sage.categories.morphism import SetMorphism from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme
def is_SchemeMorphism(f): """ Test whether ``f`` is a scheme morphism.
INPUT:
- ``f`` -- anything.
OUTPUT:
Boolean. Return ``True`` if ``f`` is a scheme morphism or a point on an elliptic curve.
EXAMPLES::
sage: A.<x,y> = AffineSpace(QQ,2); H = A.Hom(A) sage: f = H([y,x^2+y]); f Scheme endomorphism of Affine Space of dimension 2 over Rational Field Defn: Defined on coordinates by sending (x, y) to (y, x^2 + y) sage: from sage.schemes.generic.morphism import is_SchemeMorphism sage: is_SchemeMorphism(f) True """
class SchemeMorphism(Element): """ Base class for scheme morphisms
INPUT:
- ``parent`` -- the parent of the morphism.
.. TODO::
For historical reasons, :class:`SchemeMorphism` copies code from :class:`~sage.categories.map.Map` rather than inheriting from it. Proper inheritance should be used instead. See :trac:`14711`.
EXAMPLES::
sage: X = Spec(ZZ) sage: Hom = X.Hom(X) sage: from sage.schemes.generic.morphism import SchemeMorphism sage: f = SchemeMorphism(Hom) sage: type(f) <class 'sage.schemes.generic.morphism.SchemeMorphism'>
TESTS::
sage: A2 = AffineSpace(QQ,2) sage: A2.structure_morphism().domain() Affine Space of dimension 2 over Rational Field sage: A2.structure_morphism().category() Category of homsets of schemes """
def __init__(self, parent, codomain=None): """ The Python constructor.
EXAMPLES::
sage: X = Spec(ZZ) sage: Hom = X.Hom(X) sage: from sage.schemes.generic.morphism import SchemeMorphism sage: f = SchemeMorphism(Hom) sage: type(f) <class 'sage.schemes.generic.morphism.SchemeMorphism'> """ parent = Hom(parent, codomain) raise TypeError("parent (=%s) must be a Homspace"%parent)
# We copy methods of sage.categories.map.Map, to make # a future transition of SchemeMorphism to a sub-class of Morphism # easier. def __call__(self, x, *args, **kwds): """ Do not override this method!
For implementing application of maps, implement a method ``_call_(self, x)`` and/or a method ``_call_with_args(x, args, kwds)`. In these methods, you can assume that ``x`` belongs to the domain of this morphism, ``args`` is a tuple and ``kwds`` is a dict.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: H = A.Hom(A) sage: f = H([y,x^2+y]) sage: f([2,3]) # indirect doctest (3, 7)
An example with optional arguments::
sage: PS.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(PS,PS) sage: f=H([x^3,x*y^2]) sage: P=PS(0,1) sage: f(P,check=False) # indirect doctest (0 : 0) """ return self._call_with_args(x, args, kwds) # Is there coercion? # Here, we would like to do ##try: ## x = D(x). ##except (TypeError, NotImplementedError): ## raise TypeError, "%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(x, self.domain()) # However, this would involve a test whether x.codomain() == # self. This would trigger a Groebner basis computation, that # (1) could be slow and (2) could involve an even slower toy # implementation, resulting in a warning. # # Contract: If x is a scheme morphism point, then _call_ knows # what to do with it (e.g., use the _coords attribute). Otherwise, # we can try a conversion into the domain (e.g., if x is a list), # WITHOUT to trigger a Groebner basis computation. except (TypeError, NotImplementedError): raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(x, self.domain())) raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(x, self.domain())) else: x = converter(x) return self._call_with_args(x, args, kwds)
def _repr_defn(self): r""" Return a string representation of the definition of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: X = Spec(ZZ) sage: Hom = X.Hom(X) sage: from sage.schemes.generic.morphism import SchemeMorphism sage: f = SchemeMorphism(Hom) sage: f._repr_defn() Traceback (most recent call last): ... NotImplementedError """
def _repr_type(self): r""" Return a string representation of the type of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A2.structure_morphism() # indirect doctest Scheme morphism: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Rational Field Defn: Structure map """
def _repr_(self): r""" Return a string representation of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: X = Spec(ZZ) sage: Hom = X.Hom(X) sage: from sage.schemes.generic.morphism import SchemeMorphism sage: f = SchemeMorphism(Hom) sage: f._repr_() Traceback (most recent call last): ... NotImplementedError """ else:
def __mul__(self, right): """ We can currently only multiply scheme morphisms.
If one factor is an identity morphism, the other is returned. Otherwise, a formal composition of maps obtained from the scheme morphisms is returned.
EXAMPLES:
Identity maps do not contribute to the product::
sage: X = AffineSpace(QQ,2) sage: id = X.identity_morphism() sage: id^0 # indirect doctest Scheme endomorphism of Affine Space of dimension 2 over Rational Field Defn: Identity map sage: id^2 Scheme endomorphism of Affine Space of dimension 2 over Rational Field Defn: Identity map
Here, we see a formal composition::
sage: X = AffineSpace(QQ,2) sage: f = X.structure_morphism() sage: Y = Spec(QQ) sage: g = Y.structure_morphism() sage: g * f # indirect doctest Composite map: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Integer Ring Defn: Generic morphism: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Rational Field then Generic morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring
Of course, the codomain of the first factor must coincide with the domain of the second factor::
sage: f * g Traceback (most recent call last): ... TypeError: self (=Scheme morphism: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Rational Field Defn: Structure map) domain must equal right (=Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Structure map) codomain """ return self
def __pow__(self, n, dummy=None): """ Exponentiate an endomorphism.
INPUT:
- ``n`` -- integer. The exponent.
OUTPUT:
A composite map that belongs to the same endomorphism set as ``self``.
EXAMPLES::
sage: X = AffineSpace(QQ,2) sage: id = X.identity_morphism() sage: id^0 Scheme endomorphism of Affine Space of dimension 2 over Rational Field Defn: Identity map sage: id^2 Scheme endomorphism of Affine Space of dimension 2 over Rational Field Defn: Identity map """ raise TypeError("self must be an endomorphism.")
def category(self): """ Return the category of the Hom-set.
OUTPUT:
A category.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A2.structure_morphism().category() Category of homsets of schemes """
def category_for(self): """ Return the category which this morphism belongs to.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A2.structure_morphism().category_for() Category of schemes """
def is_endomorphism(self): """ Return wether the morphism is an endomorphism.
OUTPUT:
Boolean. Whether the domain and codomain are identical.
EXAMPLES::
sage: X = AffineSpace(QQ,2) sage: X.structure_morphism().is_endomorphism() False sage: X.identity_morphism().is_endomorphism() True """
def _composition(self, right): """ A helper for multiplying maps by composition.
.. WARNING::
Do not override this method! Override :meth:`_composition_` instead.
EXAMPLES::
sage: X = AffineSpace(QQ,2) sage: f = X.structure_morphism() sage: Y = Spec(QQ) sage: g = Y.structure_morphism() sage: g * f # indirect doctest Composite map: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Integer Ring Defn: Generic morphism: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Rational Field then Generic morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring
sage: f * g Traceback (most recent call last): ... TypeError: self (=Scheme morphism: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Rational Field Defn: Structure map) domain must equal right (=Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Structure map) codomain """
def _composition_(self, right, homset): """ Helper to construct the composition of two morphisms.
Override this if you want to have a different behaviour of composition
INPUT:
- ``right`` -- a map or callable - ``homset`` -- a homset containing the composed map
OUTPUT:
An element of ``homset``. The output is obtained by converting the arguments to :class:`~sage.categories.morphism.SetMorphism` if necessary, and then forming a :class:`~sage.categories.map.FormalCompositeMap`
EXAMPLES::
sage: X = AffineSpace(QQ,2) sage: f = X.structure_morphism() sage: Y = Spec(QQ) sage: g = Y.structure_morphism() sage: g * f # indirect doctest Composite map: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Integer Ring Defn: Generic morphism: From: Affine Space of dimension 2 over Rational Field To: Spectrum of Rational Field then Generic morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring """
def glue_along_domains(self, other): r""" Glue two morphism
INPUT:
- ``other`` -- a scheme morphism with the same domain.
OUTPUT:
Assuming that self and other are open immersions with the same domain, return scheme obtained by gluing along the images.
EXAMPLES:
We construct a scheme isomorphic to the projective line over `\mathrm{Spec}(\QQ)` by gluing two copies of `\mathbb{A}^1` minus a point::
sage: R.<x,y> = PolynomialRing(QQ, 2) sage: S.<xbar, ybar> = R.quotient(x*y - 1) sage: Rx = PolynomialRing(QQ, 'x') sage: i1 = Rx.hom([xbar]) sage: Ry = PolynomialRing(QQ, 'y') sage: i2 = Ry.hom([ybar]) sage: Sch = Schemes() sage: f1 = Sch(i1) sage: f2 = Sch(i2)
Now f1 and f2 have the same domain, which is a `\mathbb{A}^1` minus a point. We glue along the domain::
sage: P1 = f1.glue_along_domains(f2) sage: P1 Scheme obtained by gluing X and Y along U, where X: Spectrum of Univariate Polynomial Ring in x over Rational Field Y: Spectrum of Univariate Polynomial Ring in y over Rational Field U: Spectrum of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x*y - 1)
sage: a, b = P1.gluing_maps() sage: a Affine Scheme morphism: From: Spectrum of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x*y - 1) To: Spectrum of Univariate Polynomial Ring in x over Rational Field Defn: Ring morphism: From: Univariate Polynomial Ring in x over Rational Field To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x*y - 1) Defn: x |--> xbar sage: b Affine Scheme morphism: From: Spectrum of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x*y - 1) To: Spectrum of Univariate Polynomial Ring in y over Rational Field Defn: Ring morphism: From: Univariate Polynomial Ring in y over Rational Field To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x*y - 1) Defn: y |--> ybar """
class SchemeMorphism_id(SchemeMorphism): """ Return the identity morphism from `X` to itself.
INPUT:
- ``X`` -- the scheme.
EXAMPLES::
sage: X = Spec(ZZ) sage: X.identity_morphism() # indirect doctest Scheme endomorphism of Spectrum of Integer Ring Defn: Identity map """ def __init__(self, X): """ The Python constructor.
See :class:`SchemeMorphism_id` for details.
TESTS::
sage: Spec(ZZ).identity_morphism() Scheme endomorphism of Spectrum of Integer Ring Defn: Identity map """
def _repr_defn(self): r""" Return a string representation of the definition of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: Spec(ZZ).identity_morphism()._repr_defn() 'Identity map' """
class SchemeMorphism_structure_map(SchemeMorphism): r""" The structure morphism
INPUT:
- ``parent`` -- Hom-set with codomain equal to the base scheme of the domain.
EXAMPLES::
sage: Spec(ZZ).structure_morphism() # indirect doctest Scheme endomorphism of Spectrum of Integer Ring Defn: Structure map """ def __init__(self, parent, codomain=None): """ The Python constructor.
See :class:`SchemeMorphism_structure_map` for details.
TESTS::
sage: from sage.schemes.generic.morphism import SchemeMorphism_structure_map sage: SchemeMorphism_structure_map( Spec(QQ).Hom(Spec(ZZ)) ) Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Structure map """ raise ValueError("parent must have codomain equal the base scheme of domain.")
def _repr_defn(self): r""" Return a string representation of the definition of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: Spec(ZZ).structure_morphism()._repr_defn() 'Structure map' """
class SchemeMorphism_spec(SchemeMorphism): """ Morphism of spectra of rings
INPUT:
- ``parent`` -- Hom-set whose domain and codomain are affine schemes.
- ``phi`` -- a ring morphism with matching domain and codomain.
- ``check`` -- boolean (optional, default:``True``). Whether to check the input for consistency.
EXAMPLES::
sage: R.<x> = PolynomialRing(QQ) sage: phi = R.hom([QQ(7)]); phi Ring morphism: From: Univariate Polynomial Ring in x over Rational Field To: Rational Field Defn: x |--> 7
sage: X = Spec(QQ); Y = Spec(R) sage: f = X.hom(phi); f Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Univariate Polynomial Ring in x over Rational Field Defn: Ring morphism: From: Univariate Polynomial Ring in x over Rational Field To: Rational Field Defn: x |--> 7
sage: f.ring_homomorphism() Ring morphism: From: Univariate Polynomial Ring in x over Rational Field To: Rational Field Defn: x |--> 7 """ def __init__(self, parent, phi, check=True): """ The Python constructor.
See :class:`SchemeMorphism_structure_map` for details.
TESTS::
sage: from sage.schemes.generic.morphism import SchemeMorphism_spec sage: SchemeMorphism_spec(Spec(QQ).Hom(Spec(ZZ)), ZZ.hom(QQ)) Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Natural morphism: From: Integer Ring To: Rational Field """ raise TypeError("phi (=%s) must be a ring homomorphism" % phi) raise TypeError("phi (=%s) must have domain %s" % (phi, parent.codomain().coordinate_ring())) raise TypeError("phi (=%s) must have codomain %s" % (phi, parent.domain().coordinate_ring()))
def _call_(self, x): r""" Make morphisms callable.
INPUT:
- ``x`` -- a scheme point.
OUTPUT:
The image scheme point.
EXAMPLES:
The following fails because inverse images of prime ideals under ring homomorphisms are not yet implemented::
sage: R.<x> = PolynomialRing(QQ) sage: phi = R.hom([QQ(7)]) sage: X = Spec(QQ); Y = Spec(R) sage: f = X.hom(phi) sage: f(X.an_element()) # indirect doctest Traceback (most recent call last): ... NotImplementedError """ # By virtue of argument preprocessing in __call__, we can assume that # x is a topological scheme point of self return self._codomain(S)
def _repr_type(self): r""" Return a string representation of the type of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: R.<x> = PolynomialRing(QQ) sage: phi = R.hom([QQ(7)]) sage: X = Spec(QQ); Y = Spec(R) sage: f = X.hom(phi) sage: f._repr_type() 'Affine Scheme' """
def _repr_defn(self): r""" Return a string representation of the definition of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: R.<x> = PolynomialRing(QQ) sage: phi = R.hom([QQ(7)]) sage: X = Spec(QQ); Y = Spec(R) sage: f = X.hom(phi) sage: print(f._repr_defn()) Ring morphism: From: Univariate Polynomial Ring in x over Rational Field To: Rational Field Defn: x |--> 7 """
def ring_homomorphism(self): """ Return the underlying ring homomorphism.
OUTPUT:
A ring homomorphism.
EXAMPLES::
sage: R.<x> = PolynomialRing(QQ) sage: phi = R.hom([QQ(7)]) sage: X = Spec(QQ); Y = Spec(R) sage: f = X.hom(phi) sage: f.ring_homomorphism() Ring morphism: From: Univariate Polynomial Ring in x over Rational Field To: Rational Field Defn: x |--> 7 """
############################################################################ # Morphisms between schemes given on points # The _affine and _projective below refer to the CODOMAIN. # The domain can be either affine or projective regardless # of the class ############################################################################ class SchemeMorphism_polynomial(SchemeMorphism): r""" A morphism of schemes determined by polynomials that define what the morphism does on points in the ambient space.
INPUT:
- ``parent`` -- Hom-set whose domain and codomain are affine or projective schemes.
- ``polys`` -- a list/tuple/iterable of polynomials defining the scheme morphism.
- ``check`` -- boolean (optional, default:``True``). Whether to check the input for consistency.
EXAMPLES:
An example involving the affine plane::
sage: R.<x,y> = QQ[] sage: A2 = AffineSpace(R) sage: H = A2.Hom(A2) sage: f = H([x-y, x*y]) sage: f([0,1]) (-1, 0)
An example involving the projective line::
sage: R.<x,y> = QQ[] sage: P1 = ProjectiveSpace(R) sage: H = P1.Hom(P1) sage: f = H([x^2+y^2,x*y]) sage: f([0,1]) (1 : 0)
Some checks are performed to make sure the given polynomials define a morphism::
sage: f = H([exp(x),exp(y)]) Traceback (most recent call last): ... TypeError: polys (=[e^x, e^y]) must be elements of Multivariate Polynomial Ring in x, y over Rational Field
""" def __init__(self, parent, polys, check=True): """ The Python constructor.
See :class:`SchemeMorphism_polynomial` for details.
EXAMPLES::
sage: A2.<x,y> = AffineSpace(QQ,2) sage: H = A2.Hom(A2) sage: H([x-y, x*y]) Scheme endomorphism of Affine Space of dimension 2 over Rational Field Defn: Defined on coordinates by sending (x, y) to (x - y, x*y) """ raise TypeError("polys (=%s) must be a list or tuple"%polys) raise ValueError("there must be %s polynomials"%target.ngens())
def defining_polynomials(self): """ Return the defining polynomials.
OUTPUT:
An immutable sequence of polynomials that defines this scheme morphism.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: H = A.Hom(A) sage: H([x^3+y, 1-x-y]).defining_polynomials() (x^3 + y, -x - y + 1) """
def _call_(self, x): """ Apply this morphism to a point in the domain.
INPUT:
- ``x`` -- a point in the domain or a list or tuple that defines a point in the domain.
OUTPUT:
A point in the codomain.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: H = A.Hom(A) sage: f = H([y,x^2+y]) sage: f([2,3]) # indirect doctest (3, 7)
An example with algebraic schemes::
sage: A.<x,y> = AffineSpace(QQ, 2) sage: X = A.subscheme(x) sage: Y = A.subscheme(y) sage: Hom_XY = X.Hom(Y) sage: f = Hom_XY([y,0]) # (0,y) |-> (y,0) sage: f Scheme morphism: From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x To: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y Defn: Defined on coordinates by sending (x, y) to (y, 0) sage: f([0,3]) (3, 0)
The input must be convertible into the map's domain::
sage: f(0) Traceback (most recent call last): ... TypeError: 0 fails to convert into the map's domain Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x, but a `pushforward` method is not properly implemented
It is possible to avoid the checks on the resulting point which can be useful for indeterminacies, but be careful!! ::
sage: PS.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(PS,PS) sage: f=H([x^3,x*y^2]) sage: P=PS(0,1) sage: f(P,check=False) (0 : 0)
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2) sage: X=P.subscheme(x^2-y^2); sage: H=Hom(X,X) sage: f=H([x^2,y^2,z^2]); sage: f([4,4,1]) (16 : 16 : 1)
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2) sage: X=P.subscheme(x^2-y^2); sage: H=Hom(X,X) sage: f=H([x^2,y^2,z^2]); sage: f(P([4,4,1])) (16 : 16 : 1) """ # Checks were done in __call__
def _call_with_args(self, x, args, kwds): """ Apply this morphism to a point in the domain, with additional arguments
INPUT:
- ``x`` -- a point in the domain or a list or tuple that defines a point in the domain. - ``check``, a boolean, either provided by position or name.
OUTPUT:
A point in the codomain.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: H = A.Hom(A) sage: f = H([y,x^2+y]) sage: f([2,3]) (3, 7)
An example with algebraic schemes::
sage: A.<x,y> = AffineSpace(QQ, 2) sage: X = A.subscheme(x) sage: Y = A.subscheme(y) sage: Hom_XY = X.Hom(Y) sage: f = Hom_XY([y,0]) # (0,y) |-> (y,0) sage: f Scheme morphism: From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x To: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y Defn: Defined on coordinates by sending (x, y) to (y, 0) sage: f([0,3]) (3, 0)
As usual, if the input does not belong to a map's domain, it is first attempted to convert it::
sage: f(0) Traceback (most recent call last): ... TypeError: 0 fails to convert into the map's domain Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x, but a `pushforward` method is not properly implemented
It is possible to avoid the checks on the resulting point which can be useful for indeterminacies, but be careful!! ::
sage: PS.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(PS,PS) sage: f=H([x^3,x*y^2]) sage: P=PS(0,1) sage: f(P,check=False) # indirect doctest (0 : 0)
::
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2) sage: X=P.subscheme(x^2-y^2); sage: H=Hom(X,X) sage: f=H([x^2,y^2,z^2]); sage: f([4,4,1]) (16 : 16 : 1)
::
sage: P.<x,y,z> = ProjectiveSpace(ZZ, 2) sage: P2.<u,v,w,t> = ProjectiveSpace(ZZ, 3) sage: X = P.subscheme(x^2-y^2); sage: H = Hom(X, X) sage: f = H([x^2, y^2, z^2]); sage: f(P2([4,4,1,1])) Traceback (most recent call last): ... TypeError: (4 : 4 : 1 : 1) fails to convert into the map's domain Closed subscheme of Projective Space of dimension 2 over Integer Ring defined by: x^2 - y^2, but a `pushforward` method is not properly implemented """ if args: check = args[0] else: check = kwds.get("check", False) # containment of x in the domain has already been checked, in __call__ P = [f(x._coords) for f in self.defining_polynomials()] return self._codomain.point(P,check)
def _repr_defn(self): """ Return a string representation of the definition of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: H = A.Hom(A) sage: f = H([y,x^2+y]) sage: print(f._repr_defn()) Defined on coordinates by sending (x, y) to (y, x^2 + y) """
def __getitem__(self,i): """ returns the ith poly with self[i]
INPUT:
- ``i``-- integer
OUTPUT:
- element of the coordinate ring of the domain
Examples::
sage: P.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(P,P) sage: f=H([3/5*x^2,6*y^2]) sage: f[1] 6*y^2 """
def __copy__(self): r""" Return a copy of ``self``.
OUTPUT:
- :class:`SchemeMorphism_polynomial`
EXAMPLES::
sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: H = Hom(P, P) sage: f = H([3/5*x^2, 6*y^2]) sage: g = copy(f) sage: f == g True sage: f is g False
::
sage: P.<x,y,z> = ProjectiveSpace(QQ,2) sage: X = P.subscheme(x^2 - y^2); sage: Q = X(23, 23, 46) sage: P = X(1, 1, 1) sage: P != Q True """
def base_ring(self): r""" Return the base ring of ``self``, that is, the ring over which the coefficients of ``self`` is given as polynomials.
OUTPUT:
- ring
EXAMPLES::
sage: P.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(P,P) sage: f=H([3/5*x^2,6*y^2]) sage: f.base_ring() Rational Field
::
sage: R.<t>=PolynomialRing(ZZ,1) sage: P.<x,y>=ProjectiveSpace(R,1) sage: H=Hom(P,P) sage: f=H([3*x^2,y^2]) sage: f.base_ring() Multivariate Polynomial Ring in t over Integer Ring """
def coordinate_ring(self): r""" Returns the coordinate ring of the ambient projective space the multivariable polynomial ring over the base ring
OUTPUT:
- ring
EXAMPLES::
sage: P.<x,y>=ProjectiveSpace(QQ,1) sage: H=Hom(P,P) sage: f=H([3/5*x^2,6*y^2]) sage: f.coordinate_ring() Multivariate Polynomial Ring in x, y over Rational Field
::
sage: R.<t>=PolynomialRing(ZZ,1) sage: P.<x,y>=ProjectiveSpace(R,1) sage: H=Hom(P,P) sage: f=H([3*x^2,y^2]) sage: f.coordinate_ring() Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in t over Integer Ring """
def change_ring(self, R, check=True): r""" Returns a new :class:`SchemeMorphism_polynomial` which is this map coerced to ``R``.
If ``check`` is ``True``, then the initialization checks are performed.
INPUT:
- ``R`` -- ring or morphism.
- ``check`` -- Boolean
OUTPUT:
- A new :class:`SchemeMorphism_polynomial` which is this map coerced to ``R``.
EXAMPLES::
sage: P.<x,y> = ProjectiveSpace(ZZ, 1) sage: H = Hom(P,P) sage: f = H([3*x^2, y^2]) sage: f.change_ring(GF(3)) Traceback (most recent call last): ... ValueError: polys (=[0, y^2]) must be of the same degree
::
sage: P.<x,y,z> = ProjectiveSpace(QQ, 2) sage: H = Hom(P,P) sage: f = H([5/2*x^3 + 3*x*y^2-y^3, 3*z^3 + y*x^2, x^3-z^3]) sage: f.change_ring(GF(3)) Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3 Defn: Defined on coordinates by sending (x : y : z) to (x^3 - y^3 : x^2*y : x^3 - z^3)
::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: X = P.subscheme([5*x^2 - y^2]) sage: H = Hom(X,X) sage: f = H([x, y]) sage: f.change_ring(GF(3)) Scheme endomorphism of Closed subscheme of Projective Space of dimension 1 over Finite Field of size 3 defined by: -x^2 - y^2 Defn: Defined on coordinates by sending (x : y) to (x : y)
Check that :trac:`16834` is fixed::
sage: A.<x,y,z> = AffineSpace(RR, 3) sage: h = Hom(A,A) sage: f = h([x^2+1.5, y^3, z^5-2.0]) sage: f.change_ring(CC) Scheme endomorphism of Affine Space of dimension 3 over Complex Field with 53 bits of precision Defn: Defined on coordinates by sending (x, y, z) to (x^2 + 1.50000000000000, y^3, z^5 - 2.00000000000000)
::
sage: A.<x,y> = ProjectiveSpace(ZZ, 1) sage: B.<u,v> = AffineSpace(QQ, 2) sage: h = Hom(A,B) sage: f = h([x^2, y^2]) sage: f.change_ring(QQ) Scheme morphism: From: Projective Space of dimension 1 over Rational Field To: Affine Space of dimension 2 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^2, y^2)
::
sage: A.<x,y> = AffineSpace(QQ,2) sage: H = Hom(A,A) sage: f = H([3*x^2/y, y^2/x]) sage: f.change_ring(RR) Scheme endomorphism of Affine Space of dimension 2 over Real Field with 53 bits of precision Defn: Defined on coordinates by sending (x, y) to (3.00000000000000*x^2/y, y^2/x)
::
sage: R.<x> = PolynomialRing(QQ) sage: K.<a> = NumberField(x^3-x+1) sage: P.<x,y> = ProjectiveSpace(K, 1) sage: H = End(P) sage: f = H([x^2 + a*x*y + a^2*y^2, y^2]) sage: emb = K.embeddings(QQbar) sage: f.change_ring(emb[0]) Scheme endomorphism of Projective Space of dimension 1 over Algebraic Field Defn: Defined on coordinates by sending (x : y) to (x^2 + (-1.324717957244746?)*x*y + 1.754877666246693?*y^2 : y^2) sage: f.change_ring(emb[1]) Scheme endomorphism of Projective Space of dimension 1 over Algebraic Field Defn: Defined on coordinates by sending (x : y) to (x^2 + (0.6623589786223730? - 0.5622795120623013?*I)*x*y + (0.1225611668766537? - 0.744861766619745?*I)*y^2 : y^2)
::
sage: K.<v> = QuadraticField(2, embedding=QQbar(sqrt(2))) sage: P.<x,y> = ProjectiveSpace(K, 1) sage: H = End(P) sage: f = H([x^2+v*y^2, y^2]) sage: f.change_ring(QQbar) Scheme endomorphism of Projective Space of dimension 1 over Algebraic Field Defn: Defined on coordinates by sending (x : y) to (x^2 + 1.414213562373095?*y^2 : y^2)
::
sage: set_verbose(None) sage: K.<w> = QuadraticField(2, embedding=QQbar(-sqrt(2))) sage: P.<x,y> = ProjectiveSpace(K, 1) sage: X = P.subscheme(x-y) sage: H = End(X) sage: f = H([6*x^2+2*x*y+16*y^2, -w*x^2-4*x*y-4*y^2]) sage: f.change_ring(QQbar) Scheme endomorphism of Closed subscheme of Projective Space of dimension 1 over Algebraic Field defined by: x - y Defn: Defined on coordinates by sending (x : y) to (6*x^2 + 2*x*y + 16*y^2 : 1.414213562373095?*x^2 + (-4)*x*y + (-4)*y^2)
::
sage: R.<x> = QQ[] sage: f = x^6-2 sage: L.<b> = NumberField(f, embedding=f.roots(QQbar)[1][0]) sage: A.<x,y> = AffineSpace(L,2) sage: H = Hom(A,A) sage: F = H([b*x/y, 1+y]) sage: F.change_ring(QQbar) Scheme endomorphism of Affine Space of dimension 2 over Algebraic Field Defn: Defined on coordinates by sending (x, y) to (1.122462048309373?*x/y, y + 1)
::
sage: K.<a> = QuadraticField(-1) sage: A.<x,y> = AffineSpace(K, 2) sage: H = End(A) sage: phi = H([x/y, y]) sage: emb = K.embeddings(QQbar)[0] sage: phi.change_ring(emb) Scheme endomorphism of Affine Space of dimension 2 over Algebraic Field Defn: Defined on coordinates by sending (x, y) to (x/y, y) """ else:
else: else: else:
def specialization(self, D=None, phi=None, homset=None): r""" Specialization of this map.
Given a family of maps defined over a polynomial ring. A specialization is a particular member of that family. The specialization can be specified either by a dictionary or a :class:`SpecializationMorphism`.
INPUT:
- ``D`` -- dictionary (optional)
- ``phi`` -- SpecializationMorphism (optional)
- ``homset`` -- homset of specialized map (optional)
OUTPUT: :class:`SchemeMorphism_polynomial`
EXAMPLES::
sage: R.<c> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(R, 1) sage: H = End(P) sage: f = H([x^2 + c*y^2,y^2]) sage: f.specialization({c:1}) Scheme endomorphism of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^2 + y^2 : y^2)
::
sage: R.<a,b> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(R, 1) sage: H = End(P) sage: f = H([x^3 + a*x*y^2 + b*y^3, y^3]) sage: from sage.rings.polynomial.flatten import SpecializationMorphism sage: phi = SpecializationMorphism(P.coordinate_ring(), dict({a:2,b:-1})) sage: F = f.specialization(phi=phi); F Scheme endomorphism of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^3 + 2*x*y^2 - y^3 : y^3) sage: g = H([x^2 + a*y^2,y^2]) sage: G = g.specialization(phi=phi) sage: G.parent() is F.parent() False sage: G = g.specialization(phi=phi, homset=F.parent()) sage: G.parent() is F.parent() True
::
sage: R.<c> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(R, 1) sage: X = P.subscheme([x - c*y]) sage: H = End(X) sage: f = H([x^2, c*y^2]) sage: f.specialization({c:2}) Scheme endomorphism of Closed subscheme of Projective Space of dimension 1 over Rational Field defined by: x - 2*y Defn: Defined on coordinates by sending (x : y) to (x^2 : 2*y^2)
::
sage: R.<c> = QQ[] sage: P.<x,y> = ProjectiveSpace(R,1) sage: f = DynamicalSystem_projective([x^2 + c*y^2, y^2], domain=P) sage: F = f.dynatomic_polynomial(3) sage: g = F.specialization({c:1}); g x^6 + x^5*y + 4*x^4*y^2 + 3*x^3*y^3 + 7*x^2*y^4 + 4*x*y^5 + 5*y^6 sage: g == f.specialization({c:1}).dynatomic_polynomial(3) True """ raise ValueError("either the dictionary or the specialization must be provided") else: else: else: codomain = self.codomain() if isinstance(codomain, AlgebraicScheme_subscheme): codomain = codomain.specialization(phi=phi) else: codomain = codomain.change_ring(phi.codomain().base_ring()) homset = Hom(domain, codomain)
def _composition_(self, other, homset): r""" Straightforward implementation of composition for scheme morphisms defined by polynomials.
TESTS::
sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: H = Hom(P,P) sage: f = H([x^2 -29/16*y^2, y^2]) sage: g = H([y,x+y]) sage: h = f*g sage: h Scheme endomorphism of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x : y) to (-29/16*x^2 - 29/8*x*y - 13/16*y^2 : x^2 + 2*x*y + y^2) sage: p = P((1,3)) sage: h(p) == f(g(p)) True
sage: Q = ProjectiveSpace(QQ,2) sage: H2 = Hom(P,Q) sage: h2 = H2([x^2+y^2,x^2,y^2+2*x^2]) sage: h2 * f Scheme morphism: From: Projective Space of dimension 1 over Rational Field To: Projective Space of dimension 2 over Rational Field Defn: Defined on coordinates by sending (x : y) to (x^4 - 29/8*x^2*y^2 + 1097/256*y^4 : x^4 - 29/8*x^2*y^2 + 841/256*y^4 : 2*x^4 - 29/4*x^2*y^2 + 969/128*y^4)
::
sage: A.<x,y> = AffineSpace(QQ, 2) sage: A1.<z> = AffineSpace(QQ, 1) sage: H = End(A) sage: f = H([x^2+y^2, y^2/x]) sage: H1 = Hom(A, A1) sage: g = H1([x + y^2]) sage: g*f Scheme morphism: From: Affine Space of dimension 2 over Rational Field To: Affine Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x, y) to ((x^4 + x^2*y^2 + y^4)/x^2) sage: f*g Traceback (most recent call last): ... TypeError: self (=Scheme endomorphism of Affine Space of dimension 2 over Rational Field Defn: Defined on coordinates by sending (x, y) to (x^2 + y^2, y^2/x)) domain must equal right (=Scheme morphism: From: Affine Space of dimension 2 over Rational Field To: Affine Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x, y) to (y^2 + x)) codomain
Not both defined by polynomials::
sage: x = polygen(QQ) sage: K.<a> = NumberField(x^2 - 2) sage: p1, p2 = K.Hom(K) sage: R.<x,y> = K[] sage: q1 = R.Hom(R)(p1) sage: A = AffineSpace(R) sage: f1 = A.Hom(A)(q1) sage: g = A.Hom(A)([x^2-y, y+1]) sage: g*f1 Composite map: From: Affine Space of dimension 2 over Number Field in a with defining polynomial x^2 - 2 To: Affine Space of dimension 2 over Number Field in a with defining polynomial x^2 - 2 Defn: Generic endomorphism of Affine Space of dimension 2 over Number Field in a with defining polynomial x^2 - 2 then Generic endomorphism of Affine Space of dimension 2 over Number Field in a with defining polynomial x^2 - 2 """
############################################################################ # Rational points on schemes, which we view as morphisms determined # by coordinates. ############################################################################
class SchemeMorphism_point(SchemeMorphism): """ Base class for rational points on schemes.
Recall that the `K`-rational points of a scheme `X` over `k` can be identified with the set of morphisms `Spec(K) \to X`. In Sage, the rational points are implemented by such scheme morphisms.
EXAMPLES::
sage: from sage.schemes.generic.morphism import SchemeMorphism sage: f = SchemeMorphism(Spec(ZZ).Hom(Spec(ZZ))) sage: type(f) <class 'sage.schemes.generic.morphism.SchemeMorphism'> """ def _repr_(self): r""" Return a string representation of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: a._repr_() '(1, 2)' """
def _latex_(self): r""" Return a latex representation of ``self``.
OUTPUT:
String.
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: latex(a) == a._latex_() True sage: a._latex_() '\\left(1, 2\\right)' """
def __getitem__(self, n): """ Return the ``n``-th coordinate.
OUTPUT:
The coordinate values as an element of the base ring.
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: a[0] 1 sage: a[1] 2 """
def __iter__(self): """ Iterate over the coordinates of the point.
OUTPUT:
An iterator.
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: iter = a.__iter__() sage: next(iter) 1 sage: next(iter) 2 sage: list(a) [1, 2] """
def __tuple__(self): """ Return the coordinates as a tuple.
OUTPUT:
A tuple.
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: tuple(a) (1, 2) """ return self._coords
def __len__(self): """ Return the number of coordinates.
OUTPUT:
Integer. The number of coordinates used to describe the point.
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: len(a) 2 """
def _richcmp_(self, other, op): """ Compare two scheme morphisms.
INPUT:
- ``other`` -- anything. To compare against the scheme morphism ``self``.
OUTPUT:
boolean
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: b = A(3,4) sage: a < b True sage: a != b True """ try: other = self._codomain.ambient_space()(other) except TypeError: return NotImplemented
def scheme(self): """ Return the scheme whose point is represented.
OUTPUT:
A scheme.
EXAMPLES::
sage: A = AffineSpace(2, QQ) sage: a = A(1,2) sage: a.scheme() Affine Space of dimension 2 over Rational Field """
def change_ring(self, R, check=True): r""" Returns a new :class:`SchemeMorphism_point` which is this point coerced to``R``.
If ``check`` is true, then the initialization checks are performed.
INPUT:
- ``R`` -- ring or morphism.
kwds:
- ``check`` -- Boolean
OUTPUT: :class:`SchemeMorphism_point`
EXAMPLES::
sage: P.<x,y,z> = ProjectiveSpace(ZZ, 2) sage: X = P.subscheme(x^2-y^2) sage: X(23,23,1).change_ring(GF(13)) (10 : 10 : 1)
::
sage: P.<x,y> = ProjectiveSpace(QQ,1) sage: P(-2/3,1).change_ring(CC) (-0.666666666666667 : 1.00000000000000)
::
sage: P.<x,y> = ProjectiveSpace(ZZ,1) sage: P(152,113).change_ring(Zp(5)) (2 + 5^2 + 5^3 + O(5^20) : 3 + 2*5 + 4*5^2 + O(5^20))
::
sage: K.<v> = QuadraticField(-7) sage: O = K.maximal_order() sage: P.<x,y> = ProjectiveSpace(O, 1) sage: H = End(P) sage: F = H([x^2+O(v)*y^2, y^2]) sage: F.change_ring(K).change_ring(K.embeddings(QQbar)[0]) Scheme endomorphism of Projective Space of dimension 1 over Algebraic Field Defn: Defined on coordinates by sending (x : y) to (x^2 + (-2.645751311064591?*I)*y^2 : y^2)
::
sage: R.<x> = PolynomialRing(QQ) sage: K.<a> = NumberField(x^2-x+1) sage: P.<x,y> = ProjectiveSpace(K,1) sage: Q = P([a+1,1]) sage: emb = K.embeddings(QQbar) sage: Q.change_ring(emb[0]) (1.5000000000000000? - 0.866025403784439?*I : 1) sage: Q.change_ring(emb[1]) (1.5000000000000000? + 0.866025403784439?*I : 1)
::
sage: K.<v> = QuadraticField(2) sage: P.<x,y> = ProjectiveSpace(K,1) sage: Q = P([v,1]) sage: Q.change_ring(K.embeddings(QQbar)[0]) (-1.414213562373095? : 1)
::
sage: R.<x> = QQ[] sage: f = x^6-2 sage: L.<b> = NumberField(f, embedding=f.roots(QQbar)[1][0]) sage: A.<x,y> = AffineSpace(L,2) sage: P = A([b,1]) sage: P.change_ring(QQbar) (1.122462048309373?, 1) """
def __copy__(self): r""" Returns a copy of the :class:`SchemeMorphism_point` self coerced to `R`.
OUTPUT:
- :class:`SchemeMorphism_point`
EXAMPLES::
sage: P.<x,y> = ProjectiveSpace(ZZ, 1) sage: Q = P(152, 113) sage: Q2 = copy(Q) sage: Q2 is Q False sage: Q2 == Q True """
def specialization(self, D=None, phi=None, ambient=None): r""" Specialization of this point.
Given a family of points defined over a polynomial ring. A specialization is a particular member of that family. The specialization can be specified either by a dictionary or a :class:`SpecializationMorphism`.
INPUT:
- ``D`` -- dictionary (optional)
- ``phi`` -- SpecializationMorphism (optional)
- ``ambient`` -- ambient space of specialized point (optional)
OUTPUT: :class:`SchemeMorphism_polynomial`
EXAMPLES::
sage: R.<c> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(R, 1) sage: Q = P([c,1]) sage: Q.specialization({c:1}) (1 : 1)
::
sage: R.<a,b> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(R, 1) sage: Q = P([a^2 + 2*a*b + 34, 1]) sage: from sage.rings.polynomial.flatten import SpecializationMorphism sage: phi = SpecializationMorphism(P.coordinate_ring(),dict({a:2,b:-1})) sage: T = Q.specialization(phi=phi); T (34 : 1) sage: Q2 = P([a,1]) sage: T2 = Q2.specialization(phi=phi) sage: T2.codomain() is T.codomain() False sage: T3 = Q2.specialization(phi=phi, ambient=T.codomain()) sage: T3.codomain() is T.codomain() True
::
sage: R.<c> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(R, 1) sage: X = P.subscheme([x - c*y]) sage: Q = X([c, 1]) sage: Q2 = Q.specialization({c:2}); Q2 (2 : 1) sage: Q2.codomain() Closed subscheme of Projective Space of dimension 1 over Rational Field defined by: x - 2*y
::
sage: R.<l> = PolynomialRing(QQ) sage: S.<k,j> = PolynomialRing(R) sage: K.<a,b,c,d> = S[] sage: P.<x,y> = ProjectiveSpace(K, 1) sage: H = End(P) sage: Q = P([a^2,b^2]) sage: Q.specialization({a:2}) (4 : b^2) """ raise ValueError("either the dictionary or the specialization must be provided") else: else:
|