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""" Set of homomorphisms between two schemes
For schemes `X` and `Y`, this module implements the set of morphisms `Hom(X,Y)`. This is done by :class:`SchemeHomset_generic`.
As a special case, the Hom-sets can also represent the points of a scheme. 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. This is done by :class:`SchemeHomset_points` and its subclasses.
.. note::
You should not create the Hom-sets manually. Instead, use the :meth:`~sage.structure.parent.Hom` method that is inherited by all schemes.
AUTHORS:
- William Stein (2006): initial version.
- Volker Braun (2011-08-11): significant improvement and refactoring.
- Ben Hutz (June 2012): added support for projective ring """
#***************************************************************************** # Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com> # 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 print_function
from sage.categories.homset import HomsetWithBase from sage.structure.factory import UniqueFactory
from sage.rings.all import ZZ, QQ, CommutativeRing from sage.arith.all import gcd
from sage.rings.rational_field import is_RationalField from sage.rings.finite_rings.finite_field_constructor import is_FiniteField from sage.rings.ring import CommutativeRing
from sage.schemes.generic.scheme import AffineScheme, is_AffineScheme from sage.schemes.generic.morphism import ( SchemeMorphism, SchemeMorphism_structure_map, SchemeMorphism_spec )
def is_SchemeHomset(H): r""" Test whether ``H`` is a scheme Hom-set.
EXAMPLES::
sage: f = Spec(QQ).identity_morphism(); f Scheme endomorphism of Spectrum of Rational Field Defn: Identity map sage: from sage.schemes.generic.homset import is_SchemeHomset sage: is_SchemeHomset(f) False sage: is_SchemeHomset(f.parent()) True sage: is_SchemeHomset('a string') False """
#******************************************************************* # Factory for Hom sets of schemes #******************************************************************* class SchemeHomsetFactory(UniqueFactory): """ Factory for Hom-sets of schemes.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A3 = AffineSpace(QQ,3) sage: Hom = A3.Hom(A2)
The Hom-sets are uniquely determined by domain and codomain::
sage: Hom is copy(Hom) True sage: Hom is A3.Hom(A2) True
The Hom-sets are identical if the domains and codomains are identical::
sage: loads(Hom.dumps()) is Hom True sage: A3_iso = AffineSpace(QQ,3) sage: A3_iso is A3 True sage: Hom_iso = A3_iso.Hom(A2) sage: Hom_iso is Hom True
TESTS::
sage: Hom.base() Integer Ring sage: Hom.base_ring() Integer Ring """
def create_key_and_extra_args(self, X, Y, category=None, base=ZZ, check=True, as_point_homset=False): """ Create a key that uniquely determines the Hom-set.
INPUT:
- ``X`` -- a scheme. The domain of the morphisms.
- ``Y`` -- a scheme. The codomain of the morphisms.
- ``category`` -- a category for the Hom-sets (default: schemes over given base).
- ``base`` -- a scheme or a ring. The base scheme of domain and codomain schemes. If a ring is specified, the spectrum of that ring will be used as base scheme.
- ``check`` -- boolean (default: ``True``).
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A3 = AffineSpace(QQ,3) sage: A3.Hom(A2) # indirect doctest Set of morphisms From: Affine Space of dimension 3 over Rational Field To: Affine Space of dimension 2 over Rational Field sage: from sage.schemes.generic.homset import SchemeHomsetFactory sage: SHOMfactory = SchemeHomsetFactory('test') sage: key, extra = SHOMfactory.create_key_and_extra_args(A3,A2,check=False) sage: key (..., ..., Category of schemes over Integer Ring, False) sage: extra {'X': Affine Space of dimension 3 over Rational Field, 'Y': Affine Space of dimension 2 over Rational Field, 'base_ring': Integer Ring, 'check': False} """ X = AffineScheme(X) Y = AffineScheme(Y) base_spec = base base_ring = base.coordinate_ring() else: raise ValueError('base must be a commutative ring or its spectrum')
def create_object(self, version, key, **extra_args): """ Create a :class:`SchemeHomset_generic`.
INPUT:
- ``version`` -- object version. Currently not used.
- ``key`` -- a key created by :meth:`create_key_and_extra_args`.
- ``extra_args`` -- a dictionary of extra keyword arguments.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A3 = AffineSpace(QQ,3) sage: A3.Hom(A2) is A3.Hom(A2) # indirect doctest True sage: from sage.schemes.generic.homset import SchemeHomsetFactory sage: SHOMfactory = SchemeHomsetFactory('test') sage: SHOMfactory.create_object(0, [id(A3), id(A2), A3.category(), False], ....: check=True, X=A3, Y=A2, base_ring=QQ) Set of morphisms From: Affine Space of dimension 3 over Rational Field To: Affine Space of dimension 2 over Rational Field """
SchemeHomset = SchemeHomsetFactory('sage.schemes.generic.homset.SchemeHomset')
#******************************************************************* # Base class #******************************************************************* class SchemeHomset_generic(HomsetWithBase): r""" The base class for Hom-sets of schemes.
INPUT:
- ``X`` -- a scheme. The domain of the Hom-set.
- ``Y`` -- a scheme. The codomain of the Hom-set.
- ``category`` -- a category (optional). The category of the Hom-set.
- ``check`` -- boolean (optional, default=``True``). Whether to check the defining data for consistency.
EXAMPLES::
sage: from sage.schemes.generic.homset import SchemeHomset_generic sage: A2 = AffineSpace(QQ,2) sage: Hom = SchemeHomset_generic(A2, A2); Hom Set of morphisms From: Affine Space of dimension 2 over Rational Field To: Affine Space of dimension 2 over Rational Field sage: Hom.category() Category of endsets of schemes over Rational Field """ Element = SchemeMorphism
def __reduce__(self): """ Used in pickling.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A3 = AffineSpace(QQ,3) sage: Hom = A3.Hom(A2) sage: loads(Hom.dumps()) == Hom True """ self.base_ring(), False, False)
def __call__(self, *args, **kwds): r""" Make Hom-sets callable.
See the ``_call_()`` method of the derived class. All arguments are handed through.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: A2(4,5) (4, 5) """ # Homset (base of HomsetWithBase) overrides __call__ @#$
def _repr_(self): r""" Return a string representation.
OUTPUT:
A string.
EXAMPLES::
sage: A = AffineSpace(4, QQ) sage: print(A.structure_morphism()._repr_()) Scheme morphism: From: Affine Space of dimension 4 over Rational Field To: Spectrum of Rational Field Defn: Structure map """
def natural_map(self): r""" Return a natural map in the Hom space.
OUTPUT:
A :class:`SchemeMorphism` if there is a natural map from domain to codomain. Otherwise, a ``NotImplementedError`` is raised.
EXAMPLES::
sage: A = AffineSpace(4, QQ) sage: A.structure_morphism() # indirect doctest Scheme morphism: From: Affine Space of dimension 4 over Rational Field To: Spectrum of Rational Field Defn: Structure map """ raise NotImplementedError
def _element_constructor_(self, x, check=True): """ Construct a scheme morphism.
INPUT:
- `x` -- a ring morphism, or a list or a tuple that define a ring morphism.
- ``check`` -- boolean (default: ``True``) passed onto functions called by this one to be more careful about input argument type checking.
EXAMPLES::
sage: f = ZZ.hom(QQ); f Natural morphism: From: Integer Ring To: Rational Field
sage: H = Hom(Spec(QQ, ZZ), Spec(ZZ)); H Set of morphisms From: Spectrum of Rational Field To: Spectrum of Integer Ring
sage: phi = H(f); phi Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Natural morphism: From: Integer Ring To: Rational Field
TESTS::
sage: H._element_constructor_(f) Affine Scheme morphism: From: Spectrum of Rational Field To: Spectrum of Integer Ring Defn: Natural morphism: From: Integer Ring To: Rational Field
We illustrate input type checking::
sage: R.<x,y> = QQ[] sage: A.<x,y> = AffineSpace(R) sage: C = A.subscheme(x*y-1) sage: H = C.Hom(C); H Set of morphisms From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x*y - 1 To: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x*y - 1 sage: H(1) Traceback (most recent call last): ... TypeError: x must be a ring homomorphism, list or tuple """
# x is a morphism of Rings
#******************************************************************* # Base class for points #******************************************************************* class SchemeHomset_points(SchemeHomset_generic): """ Set of rational points of the scheme.
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.
If a scheme has a finite number of points, then the homset is supposed to implement the Python iterator interface. See :class:`~sage.schemes.toric.homset.SchemeHomset_points_toric_field` for example.
INPUT:
See :class:`SchemeHomset_generic`.
EXAMPLES::
sage: from sage.schemes.generic.homset import SchemeHomset_points sage: SchemeHomset_points(Spec(QQ), AffineSpace(ZZ,2)) Set of rational points of Affine Space of dimension 2 over Rational Field """
def __init__(self, X, Y, category=None, check=True, base=ZZ): """ Python constructor.
INPUT:
See :class:`SchemeHomset_generic`.
EXAMPLES::
sage: from sage.schemes.generic.homset import SchemeHomset_points sage: SchemeHomset_points(Spec(QQ), AffineSpace(ZZ,2)) Set of rational points of Affine Space of dimension 2 over Rational Field """ raise ValueError('The domain must be an affine scheme.')
def __reduce__(self): """ Used in pickling.
EXAMPLES::
sage: A2 = AffineSpace(QQ,2) sage: Hom = A2(QQ) sage: loads(Hom.dumps()) == Hom True """ self.base_ring(), False, True)
def _coerce_map_from_(self, other): r""" Return true if ``other`` canonically coerces to ``self``.
EXAMPLES::
sage: R.<t> = QQ[] sage: P = ProjectiveSpace(QQ, 1, 'x') sage: P2 = ProjectiveSpace(R, 1, 'x') sage: P2(R)._coerce_map_from_(P(QQ)) True sage: P(QQ)._coerce_map_from_(P2(R)) False
::
sage: P = ProjectiveSpace(QQ, 1, 'x') sage: P2 = ProjectiveSpace(CC, 1, 'y') sage: P2(CC)._coerce_map_from_(P(QQ)) False
::
sage: A.<x,y,z> = AffineSpace(QQ, 3) sage: H = A.subscheme(z) sage: L = A.subscheme([z, y+z]) sage: A(QQ)._coerce_map_from_(H(QQ)) True sage: H(QQ)._coerce_map_from_(L(QQ)) True sage: L(QQ).has_coerce_map_from(H(QQ)) False sage: A(CC)._coerce_map_from_(H(QQ)) True sage: H(CC)._coerce_map_from_(L(RR)) True
::
sage: A.<x,y,z> = AffineSpace(QQ, 3) sage: A2.<u,v> = AffineSpace(QQ, 2) sage: A(QQ).has_coerce_map_from(A2(QQ)) False
::
sage: A.<x,y> = AffineSpace(QQ, 2) sage: P.<u,v,w> = ProjectiveSpace(QQ, 2) sage: A(QQ).has_coerce_map_from(P(QQ)) False
::
sage: A = AffineSpace(QQ, 1) sage: A(QQ)._coerce_map_from_(ZZ) True
::
sage: PS = ProjectiveSpace(ZZ, 1, 'x') sage: PS2 = ProjectiveSpace(Zp(7), 1, 'x') sage: PS(ZZ).has_coerce_map_from(PS2(Zp(7))) False sage: PS2(Zp(7)).has_coerce_map_from(PS(ZZ)) True
::
sage: PP1 = ProductProjectiveSpaces(ZZ, [2,1], 'x') sage: PP1(QQ)._coerce_map_from_(PP1(ZZ)) True sage: PP2 = ProductProjectiveSpaces(QQ, [1,2], 'x') sage: PP2(QQ)._coerce_map_from_(PP1(ZZ)) False sage: PP3 = ProductProjectiveSpaces(QQ, [2,1], 'y') sage: PP3(QQ)._coerce_map_from_(PP1(ZZ)) False
::
sage: K.<w> = QuadraticField(2) sage: A.<x,y,z> = AffineSpace(QQ, 3) sage: H = A.subscheme(z) sage: A(K).has_coerce_map_from(H(QQ)) True
TESTS::
sage: P.<x,y> = ProjectiveSpace(QQ, 1) sage: X = P. subscheme ([x-y]) sage: P(1,1) == X(1,1) True
::
sage: A = AffineSpace(QQ, 1, 'x') sage: AC = AffineSpace(CC, 1, 'x') sage: A(3/2) == AC(3/2) True
::
sage: A = AffineSpace(QQ, 1) sage: A(0) == 0 True """ #ring elements can be coerced to a space if we're affine dimension 1 #and the base rings are coercible and target.ambient_space().dimension_relative() == 1: else: #we are converting between scheme points #subscheme coerce when there is containment else: #if the target is an ambient space, we can coerce if the base rings coerce #and they are the same type: affine, projective, etc and have the same #variable names #for projective and affine varieties, we check dimension #and matching variable names or (is_AffineSpace(ta) and is_AffineSpace(sa)): else: #for products of projective spaces, we check dimension of #components and matching variable names and (ta.variable_names() == sa.variable_names()): else:
def _element_constructor_(self, *v, **kwds): """ The element constructor.
INPUT:
- ``v`` -- anything that determines a scheme morphism in the Hom-set.
OUTPUT:
The scheme morphism determined by ``v``.
EXAMPLES::
sage: A2 = AffineSpace(ZZ,2) sage: F = GF(3) sage: F_points = A2(F); type(F_points) <class 'sage.schemes.affine.affine_homset.SchemeHomset_points_affine_with_category'> sage: F_points([2,5]) (2, 2)
sage: P2 = ProjectiveSpace(GF(3),2) sage: F.<a> = GF(9,'a') sage: F_points = P2(F) sage: type(F_points) <class 'sage.schemes.projective.projective_homset.SchemeHomset_points_projective_field_with_category'> sage: F_points([4,2*a]) (1 : 2*a : 1)
TESTS::
sage: F_points._element_constructor_([4,2*a]) (1 : 2*a : 1) """
def extended_codomain(self): """ Return the codomain with extended base, if necessary.
OUTPUT:
The codomain scheme, with its base ring extended to the codomain. That is, the codomain is of the form `Spec(R)` and the base ring of the domain is extended to `R`.
EXAMPLES::
sage: P2 = ProjectiveSpace(QQ,2) sage: K.<a> = NumberField(x^2 + x - (3^3-3)) sage: K_points = P2(K); K_points Set of rational points of Projective Space of dimension 2 over Number Field in a with defining polynomial x^2 + x - 24
sage: K_points.codomain() Projective Space of dimension 2 over Rational Field
sage: K_points.extended_codomain() Projective Space of dimension 2 over Number Field in a with defining polynomial x^2 + x - 24 """ else:
def _repr_(self): """ Return a string representation of ``self``.
OUTPUT:
A string.
EXAMPLES::
sage: P2 = ProjectiveSpace(ZZ,2) sage: P2(QQ)._repr_() 'Set of rational points of Projective Space of dimension 2 over Rational Field' """
def value_ring(self): """ Return `R` for a point Hom-set `X(Spec(R))`.
OUTPUT:
A commutative ring.
EXAMPLES::
sage: P2 = ProjectiveSpace(ZZ,2) sage: P2(QQ).value_ring() Rational Field """ raise ValueError("value rings are defined for affine domains only")
def cardinality(self): """ Return the number of points.
OUTPUT:
An integer or infinity.
EXAMPLES::
sage: toric_varieties.P2().point_set().cardinality() +Infinity
sage: P2 = toric_varieties.P2(base_ring=GF(3)) sage: P2.point_set().cardinality() 13 """ from sage.rings.infinity import Infinity return Infinity
__len__ = cardinality
def list(self): """ Return a tuple containing all points.
OUTPUT:
A tuple containing all points of the toric variety.
EXAMPLES::
sage: P1 = toric_varieties.P1(base_ring=GF(3)) sage: P1.point_set().list() ([0 : 1], [1 : 0], [1 : 1], [1 : 2]) """ |