Base class for old-style parent objects with generators - Parents and Elements

Skip to content
Back to top
View this page
Edit this page

# Base class for old-style parent objects with generators

Note

This class is being deprecated, see `sage.structure.parent.Parent` and `sage.structure.category_object.CategoryObject` for the new model.

Many parent objects in Sage are equipped with generators, which are special elements of the object. For example, the polynomial ring \(\ZZ[x,y,z]\) is generated by \(x\), \(y\), and \(z\). In Sage the \(i\)-th generator of an object `X` is obtained using the notation `X.gen(i)`. From the Sage interactive prompt, the shorthand notation `X.i` is also allowed.

REQUIRED: A class that derives from ParentWithGens must define the ngens() and gen(i) methods.

OPTIONAL: It is also good if they define gens() to return all gens, but this is not necessary.

The `gens` function returns a tuple of all generators, the `ngens` function returns the number of generators.

The `_assign_names` functions is for internal use only, and is called when objects are created to set the generator names. It can only be called once.

The following examples illustrate these functions in the context of multivariate polynomial rings and free modules.

EXAMPLES:

Sage

    sage: R = PolynomialRing(ZZ, 3, 'x')
    sage: R.ngens()
    3
    sage: R.gen(0)
    x0
    sage: R.gens()
    (x0, x1, x2)
    sage: R.variable_names()
    ('x0', 'x1', 'x2')

Python

    >>> from sage.all import *
    >>> R = PolynomialRing(ZZ, Integer(3), 'x')
    >>> R.ngens()
    3
    >>> R.gen(Integer(0))
    x0
    >>> R.gens()
    (x0, x1, x2)
    >>> R.variable_names()
    ('x0', 'x1', 'x2')

This example illustrates generators for a free module over \(\ZZ\).

Sage

    sage: # needs sage.modules
    sage: M = FreeModule(ZZ, 4)
    sage: M
    Ambient free module of rank 4 over the principal ideal domain Integer Ring
    sage: M.ngens()
    4
    sage: M.gen(0)
    (1, 0, 0, 0)
    sage: M.gens()
    ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1))

[Python]

    >>> from sage.all import *
    >>> # needs sage.modules
    >>> M = FreeModule(ZZ, Integer(4))
    >>> M
    Ambient free module of rank 4 over the principal ideal domain Integer Ring
    >>> M.ngens()
    4
    >>> M.gen(Integer(0))
    (1, 0, 0, 0)
    >>> M.gens()
    ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1))

class sage.structure.parent_gens.ParentWithGens

  Bases: `ParentWithBase`

  EXAMPLES:

  Sage

      sage: from sage.structure.parent_gens import ParentWithGens
      sage: class MyParent(ParentWithGens):
      ....:     def ngens(self): return 3
      sage: P = MyParent(base=QQ, names='a,b,c', normalize=True, category=Groups())
      sage: P.category()
      Category of groups
      sage: P._names
      ('a', 'b', 'c')

  Python

      >>> from sage.all import *
      >>> from sage.structure.parent_gens import ParentWithGens
      >>> class MyParent(ParentWithGens):
      ...     def ngens(self): return Integer(3)
      >>> P = MyParent(base=QQ, names='a,b,c', normalize=True, category=Groups())
      >>> P.category()
      Category of groups
      >>> P._names
      ('a', 'b', 'c')

  gen(i=0)
  gens()

    Return a tuple whose entries are the generators for this object, in order.

  hom(im_gens, codomain=None, base_map=None, category=None, check=True)

    Return the unique homomorphism from `self` to codomain that sends `self.gens()` to the entries of `im_gens` and induces the map `base_map` on the base ring.

    This raises a `TypeError` if there is no such homomorphism.

    INPUT:

    - `im_gens` – the images in the codomain of the generators of this object under the homomorphism

    - `codomain` – the codomain of the homomorphism

    - `base_map` – a map from the base ring of the domain into something that coerces into the codomain

    - `category` – the category of the resulting morphism

    - `check` – whether to verify that the images of generators extend to define a map (using only canonical coercions)

    OUTPUT: a homomorphism `self --> codomain`

    Note

    As a shortcut, one can also give an object X instead of `im_gens`, in which case return the (if it exists) natural map to X.

    EXAMPLES: Polynomial Ring We first illustrate construction of a few homomorphisms involving a polynomial ring.

    Sage

        sage: R.<x> = PolynomialRing(ZZ)
        sage: f = R.hom([5], QQ)
        sage: f(x^2 - 19)
        6

        sage: R.<x> = PolynomialRing(QQ)
        sage: f = R.hom([5], GF(7))
        Traceback (most recent call last):
        ...
        ValueError: relations do not all (canonically) map to 0
        under map determined by images of generators

        sage: # needs sage.rings.finite_rings
        sage: R.<x> = PolynomialRing(GF(7))
        sage: f = R.hom([3], GF(49, 'a'))
        sage: f
        Ring morphism:
          From: Univariate Polynomial Ring in x over Finite Field of size 7
          To:   Finite Field in a of size 7^2
          Defn: x |--> 3
        sage: f(x + 6)
        2
        sage: f(x^2 + 1)
        3

    Python

        >>> from sage.all import *
        >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1)
        >>> f = R.hom([Integer(5)], QQ)
        >>> f(x**Integer(2) - Integer(19))
        6

        >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
        >>> f = R.hom([Integer(5)], GF(Integer(7)))
        Traceback (most recent call last):
        ...
        ValueError: relations do not all (canonically) map to 0
        under map determined by images of generators

        >>> # needs sage.rings.finite_rings
        >>> R = PolynomialRing(GF(Integer(7)), names=('x',)); (x,) = R._first_ngens(1)
        >>> f = R.hom([Integer(3)], GF(Integer(49), 'a'))
        >>> f
        Ring morphism:
          From: Univariate Polynomial Ring in x over Finite Field of size 7
          To:   Finite Field in a of size 7^2
          Defn: x |--> 3
        >>> f(x + Integer(6))
        2
        >>> f(x**Integer(2) + Integer(1))
        3

    EXAMPLES: Natural morphism

    Sage

        sage: f = ZZ.hom(GF(5))
        sage: f(7)
        2
        sage: f
        Natural morphism:
          From: Integer Ring
          To:   Finite Field of size 5

    [Python]

        >>> from sage.all import *
        >>> f = ZZ.hom(GF(Integer(5)))
        >>> f(Integer(7))
        2
        >>> f
        Natural morphism:
          From: Integer Ring
          To:   Finite Field of size 5

    There might not be a natural morphism, in which case a `TypeError` exception is raised.

    Sage

        sage: QQ.hom(ZZ)
        Traceback (most recent call last):
        ...
        TypeError: natural coercion morphism from Rational Field to Integer Ring not defined

    Python

        >>> from sage.all import *
        >>> QQ.hom(ZZ)
        Traceback (most recent call last):
        ...
        TypeError: natural coercion morphism from Rational Field to Integer Ring not defined

    You can specify a map on the base ring:

    Sage

        sage: # needs sage.rings.finite_rings
        sage: k = GF(2)
        sage: R.<a> = k[]
        sage: l.<a> = k.extension(a^3 + a^2 + 1)
        sage: R.<b> = l[]
        sage: m.<b> = l.extension(b^2 + b + a)
        sage: n.<z> = GF(2^6)
        sage: m.hom([z^4 + z^3 + 1], base_map=l.hom([z^5 + z^4 + z^2]))
        Ring morphism:
          From: Univariate Quotient Polynomial Ring in b over
                Finite Field in a of size 2^3 with modulus b^2 + b + a
          To:   Finite Field in z of size 2^6
          Defn: b |--> z^4 + z^3 + 1
                with map of base ring

    [Python]

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> k = GF(Integer(2))
        >>> R = k['a']; (a,) = R._first_ngens(1)
        >>> l = k.extension(a**Integer(3) + a**Integer(2) + Integer(1), names=('a',)); (a,) = l._first_ngens(1)
        >>> R = l['b']; (b,) = R._first_ngens(1)
        >>> m = l.extension(b**Integer(2) + b + a, names=('b',)); (b,) = m._first_ngens(1)
        >>> n = GF(Integer(2)**Integer(6), names=('z',)); (z,) = n._first_ngens(1)
        >>> m.hom([z**Integer(4) + z**Integer(3) + Integer(1)], base_map=l.hom([z**Integer(5) + z**Integer(4) + z**Integer(2)]))
        Ring morphism:
          From: Univariate Quotient Polynomial Ring in b over
                Finite Field in a of size 2^3 with modulus b^2 + b + a
          To:   Finite Field in z of size 2^6
          Defn: b |--> z^4 + z^3 + 1
                with map of base ring

  ngens()

class sage.structure.parent_gens.localvars

  Bases: `object`

  Context manager for safely temporarily changing the variables names of an object with generators.

  Objects with named generators are globally unique in Sage. Sometimes, though, it is very useful to be able to temporarily display the generators differently. The new Python `with` statement and the localvars context manager make this easy and safe (and fun!)

  Suppose X is any object with generators. Write

      with localvars(X, names[, latex_names] [,normalize=False]):
           some code
           ...

  and the indented code will be run as if the names in X are changed to the new names. If you give normalize=True, then the names are assumed to be a tuple of the correct number of strings.

  EXAMPLES:

  Sage

      sage: R.<x,y> = PolynomialRing(QQ, 2)
      sage: with localvars(R, 'z,w'):
      ....:     print(x^3 + y^3 - x*y)
      z^3 + w^3 - z*w

  Python

      >>> from sage.all import *
      >>> R = PolynomialRing(QQ, Integer(2), names=('x', 'y',)); (x, y,) = R._first_ngens(2)
      >>> with localvars(R, 'z,w'):
      ...     print(x**Integer(3) + y**Integer(3) - x*y)
      z^3 + w^3 - z*w

  Note

  I wrote this because it was needed to print elements of the quotient of a ring R by an ideal I using the print function for elements of R. See the code in `quotient_ring_element.pyx`.

  AUTHOR:

  - William Stein (2006-10-31)