Base class for objects of a category¶
CLASS HIERARCHY:
-
CategoryObject
Many category objects in Sage are equipped with generators, which are
usually 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.
The following examples illustrate these functions in the context of multivariate polynomial rings and free modules.
EXAMPLES:
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')
>>> 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: # 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))
>>> 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.category_object.CategoryObject[source]¶
Bases:
SageObject
An object in some category.
- Hom(codomain, cat=None)[source]¶
Return the homspace
Hom(self, codomain, cat)
of all homomorphisms fromself
tocodomain
in the categorycat
.The default category is determined by
self.category()
andcodomain.category()
.EXAMPLES:
sage: R.<x,y> = PolynomialRing(QQ, 2) sage: R.Hom(QQ) Set of Homomorphisms from Multivariate Polynomial Ring in x, y over Rational Field to Rational Field
>>> from sage.all import * >>> R = PolynomialRing(QQ, Integer(2), names=('x', 'y',)); (x, y,) = R._first_ngens(2) >>> R.Hom(QQ) Set of Homomorphisms from Multivariate Polynomial Ring in x, y over Rational Field to Rational Field
Homspaces are defined for very general Sage objects, even elements of familiar rings.
sage: n = 5; Hom(n,7) Set of Morphisms from 5 to 7 in Category of elements of Integer Ring sage: z = 2/3; Hom(z, 8/1) Set of Morphisms from 2/3 to 8 in Category of elements of Rational Field
>>> from sage.all import * >>> n = Integer(5); Hom(n,Integer(7)) Set of Morphisms from 5 to 7 in Category of elements of Integer Ring >>> z = Integer(2)/Integer(3); Hom(z, Integer(8)/Integer(1)) Set of Morphisms from 2/3 to 8 in Category of elements of Rational Field
This example illustrates the optional third argument:
sage: QQ.Hom(ZZ, Sets()) Set of Morphisms from Rational Field to Integer Ring in Category of sets
>>> from sage.all import * >>> QQ.Hom(ZZ, Sets()) Set of Morphisms from Rational Field to Integer Ring in Category of sets
- base_ring()[source]¶
Return the base ring of
self
.INPUT:
self
– an object over a base ring; typically a module
EXAMPLES:
sage: from sage.modules.module import Module sage: Module(ZZ).base_ring() Integer Ring sage: F = FreeModule(ZZ, 3) # needs sage.modules sage: F.base_ring() # needs sage.modules Integer Ring sage: F.__class__.base_ring # needs sage.modules <method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects>
>>> from sage.all import * >>> from sage.modules.module import Module >>> Module(ZZ).base_ring() Integer Ring >>> F = FreeModule(ZZ, Integer(3)) # needs sage.modules >>> F.base_ring() # needs sage.modules Integer Ring >>> F.__class__.base_ring # needs sage.modules <method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects>
Note that the coordinates of the elements of a module can lie in a bigger ring, the
coordinate_ring
:sage: # needs sage.modules sage: M = (ZZ^2) * (1/2) sage: v = M([1/2, 0]) sage: v.base_ring() Integer Ring sage: parent(v[0]) Rational Field sage: v.coordinate_ring() Rational Field
>>> from sage.all import * >>> # needs sage.modules >>> M = (ZZ**Integer(2)) * (Integer(1)/Integer(2)) >>> v = M([Integer(1)/Integer(2), Integer(0)]) >>> v.base_ring() Integer Ring >>> parent(v[Integer(0)]) Rational Field >>> v.coordinate_ring() Rational Field
More examples:
sage: F = FreeAlgebra(QQ, 'x') # needs sage.combinat sage.modules sage: F.base_ring() # needs sage.combinat sage.modules Rational Field sage: F.__class__.base_ring # needs sage.combinat sage.modules <method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects> sage: # needs sage.modules sage: E = CombinatorialFreeModule(ZZ, [1,2,3]) sage: F = CombinatorialFreeModule(ZZ, [2,3,4]) sage: H = Hom(E, F) sage: H.base_ring() Integer Ring sage: H.__class__.base_ring <method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects>
>>> from sage.all import * >>> F = FreeAlgebra(QQ, 'x') # needs sage.combinat sage.modules >>> F.base_ring() # needs sage.combinat sage.modules Rational Field >>> F.__class__.base_ring # needs sage.combinat sage.modules <method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects> >>> # needs sage.modules >>> E = CombinatorialFreeModule(ZZ, [Integer(1),Integer(2),Integer(3)]) >>> F = CombinatorialFreeModule(ZZ, [Integer(2),Integer(3),Integer(4)]) >>> H = Hom(E, F) >>> H.base_ring() Integer Ring >>> H.__class__.base_ring <method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects>
Todo
Move this method elsewhere (typically in the Modules category) so as not to pollute the namespace of all category objects.
- categories()[source]¶
Return the categories of
self
.EXAMPLES:
sage: ZZ.categories() [Join of Category of Dedekind domains and Category of euclidean domains and Category of noetherian rings and Category of infinite enumerated sets and Category of metric spaces, Category of Dedekind domains, Category of euclidean domains, Category of principal ideal domains, Category of unique factorization domains, Category of gcd domains, Category of integral domains, Category of domains, ... Category of commutative rings, ... Category of monoids, ..., Category of commutative additive groups, ..., Category of sets, ..., Category of objects]
>>> from sage.all import * >>> ZZ.categories() [Join of Category of Dedekind domains and Category of euclidean domains and Category of noetherian rings and Category of infinite enumerated sets and Category of metric spaces, Category of Dedekind domains, Category of euclidean domains, Category of principal ideal domains, Category of unique factorization domains, Category of gcd domains, Category of integral domains, Category of domains, ... Category of commutative rings, ... Category of monoids, ..., Category of commutative additive groups, ..., Category of sets, ..., Category of objects]
- gens_dict(copy=True)[source]¶
Return a dictionary whose entries are
{name:variable,...}
, wherename
stands for the variable names of this object (as strings) andvariable
stands for the corresponding defining generators (as elements of this object).EXAMPLES:
sage: B.<a,b,c,d> = BooleanPolynomialRing() # needs sage.rings.polynomial.pbori sage: B.gens_dict() # needs sage.rings.polynomial.pbori {'a': a, 'b': b, 'c': c, 'd': d}
>>> from sage.all import * >>> B = BooleanPolynomialRing(names=('a', 'b', 'c', 'd',)); (a, b, c, d,) = B._first_ngens(4)# needs sage.rings.polynomial.pbori >>> B.gens_dict() # needs sage.rings.polynomial.pbori {'a': a, 'b': b, 'c': c, 'd': d}
- gens_dict_recursive()[source]¶
Return the dictionary of generators of
self
and its base rings.OUTPUT:
a dictionary with string names of generators as keys and generators of
self
and its base rings as values.
EXAMPLES:
sage: R = QQ['x,y']['z,w'] sage: sorted(R.gens_dict_recursive().items()) [('w', w), ('x', x), ('y', y), ('z', z)]
>>> from sage.all import * >>> R = QQ['x,y']['z,w'] >>> sorted(R.gens_dict_recursive().items()) [('w', w), ('x', x), ('y', y), ('z', z)]
- inject_variables(scope=None, verbose=True)[source]¶
Inject the generators of
self
with their names into the namespace of the Python code from which this function is called.Thus, e.g., if the generators of
self
are labeled ‘a’, ‘b’, and ‘c’, then after calling this method the variables a, b, and c in the current scope will be set equal to the generators ofself
.NOTE: If Foo is a constructor for a Sage object with generators, and Foo is defined in Cython, then it would typically call
inject_variables()
on the object it creates. E.g.,PolynomialRing(QQ, 'y')
does this so that the variable y is the generator of the polynomial ring.
- latex_variable_names()[source]¶
Return the list of variable names suitable for latex output.
All
_SOMETHING
substrings are replaced by_{SOMETHING}
recursively so that subscripts of subscripts work.EXAMPLES:
sage: R, x = PolynomialRing(QQ, 'x', 12).objgens() sage: x (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) sage: R.latex_variable_names () ['x_{0}', 'x_{1}', 'x_{2}', 'x_{3}', 'x_{4}', 'x_{5}', 'x_{6}', 'x_{7}', 'x_{8}', 'x_{9}', 'x_{10}', 'x_{11}'] sage: f = x[0]^3 + 15/3 * x[1]^10 sage: print(latex(f)) 5 x_{1}^{10} + x_{0}^{3}
>>> from sage.all import * >>> R, x = PolynomialRing(QQ, 'x', Integer(12)).objgens() >>> x (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) >>> R.latex_variable_names () ['x_{0}', 'x_{1}', 'x_{2}', 'x_{3}', 'x_{4}', 'x_{5}', 'x_{6}', 'x_{7}', 'x_{8}', 'x_{9}', 'x_{10}', 'x_{11}'] >>> f = x[Integer(0)]**Integer(3) + Integer(15)/Integer(3) * x[Integer(1)]**Integer(10) >>> print(latex(f)) 5 x_{1}^{10} + x_{0}^{3}
- objgen()[source]¶
Return the tuple
(self, self.gen())
.EXAMPLES:
sage: R, x = PolynomialRing(QQ,'x').objgen() sage: R Univariate Polynomial Ring in x over Rational Field sage: x x
>>> from sage.all import * >>> R, x = PolynomialRing(QQ,'x').objgen() >>> R Univariate Polynomial Ring in x over Rational Field >>> x x
- objgens()[source]¶
Return the tuple
(self, self.gens())
.EXAMPLES:
sage: R = PolynomialRing(QQ, 3, 'x'); R Multivariate Polynomial Ring in x0, x1, x2 over Rational Field sage: R.objgens() (Multivariate Polynomial Ring in x0, x1, x2 over Rational Field, (x0, x1, x2))
>>> from sage.all import * >>> R = PolynomialRing(QQ, Integer(3), 'x'); R Multivariate Polynomial Ring in x0, x1, x2 over Rational Field >>> R.objgens() (Multivariate Polynomial Ring in x0, x1, x2 over Rational Field, (x0, x1, x2))
- variable_name()[source]¶
Return the first variable name.
OUTPUT: string
EXAMPLES:
sage: R.<z,y,a42> = ZZ[] sage: R.variable_name() 'z' sage: R.<x> = InfinitePolynomialRing(ZZ) sage: R.variable_name() 'x'
>>> from sage.all import * >>> R = ZZ['z, y, a42']; (z, y, a42,) = R._first_ngens(3) >>> R.variable_name() 'z' >>> R = InfinitePolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> R.variable_name() 'x'
- variable_names()[source]¶
Return the list of variable names corresponding to the generators.
OUTPUT: a tuple of strings
EXAMPLES:
sage: R.<z,y,a42> = QQ[] sage: R.variable_names() ('z', 'y', 'a42') sage: S = R.quotient_ring(z+y) sage: S.variable_names() ('zbar', 'ybar', 'a42bar')
>>> from sage.all import * >>> R = QQ['z, y, a42']; (z, y, a42,) = R._first_ngens(3) >>> R.variable_names() ('z', 'y', 'a42') >>> S = R.quotient_ring(z+y) >>> S.variable_names() ('zbar', 'ybar', 'a42bar')
sage: T.<x> = InfinitePolynomialRing(ZZ) sage: T.variable_names() ('x',)
>>> from sage.all import * >>> T = InfinitePolynomialRing(ZZ, names=('x',)); (x,) = T._first_ngens(1) >>> T.variable_names() ('x',)
- sage.structure.category_object.certify_names(names)[source]¶
Check that
names
are valid variable names.INPUT:
names
– an iterable with strings representing variable names
OUTPUT:
True
(for efficiency of the Cython call)EXAMPLES:
sage: from sage.structure.category_object import certify_names as cn sage: cn(["a", "b", "c"]) 1 sage: cn("abc") 1 sage: cn([]) 1 sage: cn([""]) Traceback (most recent call last): ... ValueError: variable name must be nonempty sage: cn(["_foo"]) Traceback (most recent call last): ... ValueError: variable name '_foo' does not start with a letter sage: cn(["x'"]) Traceback (most recent call last): ... ValueError: variable name "x'" is not alphanumeric sage: cn(["a", "b", "b"]) Traceback (most recent call last): ... ValueError: variable name 'b' appears more than once
>>> from sage.all import * >>> from sage.structure.category_object import certify_names as cn >>> cn(["a", "b", "c"]) 1 >>> cn("abc") 1 >>> cn([]) 1 >>> cn([""]) Traceback (most recent call last): ... ValueError: variable name must be nonempty >>> cn(["_foo"]) Traceback (most recent call last): ... ValueError: variable name '_foo' does not start with a letter >>> cn(["x'"]) Traceback (most recent call last): ... ValueError: variable name "x'" is not alphanumeric >>> cn(["a", "b", "b"]) Traceback (most recent call last): ... ValueError: variable name 'b' appears more than once
- sage.structure.category_object.check_default_category(default_category, category)[source]¶
The resulting category is guaranteed to be a sub-category of the default.
- sage.structure.category_object.normalize_names(ngens, names)[source]¶
Return a tuple of strings of variable names of length ngens given the input names.
INPUT:
ngens
– integer; number of generators. The valuengens=-1
means that the number of generators is unknown a priori.names
– any of the following:a tuple or list of strings, such as
('x', 'y')
a comma-separated string, such as
x,y
a string prefix, such as ‘alpha’
a string of single character names, such as ‘xyz’
OUTPUT: a tuple of
ngens
strings to be used as variable namesEXAMPLES:
sage: from sage.structure.category_object import normalize_names as nn sage: nn(0, "") () sage: nn(0, []) () sage: nn(0, None) () sage: nn(1, 'a') ('a',) sage: nn(2, 'z_z') ('z_z0', 'z_z1') sage: nn(3, 'x, y, z') ('x', 'y', 'z') sage: nn(2, 'ab') ('a', 'b') sage: nn(2, 'x0') ('x00', 'x01') sage: nn(3, (' a ', ' bb ', ' ccc ')) ('a', 'bb', 'ccc') sage: nn(4, ['a1', 'a2', 'b1', 'b11']) ('a1', 'a2', 'b1', 'b11')
>>> from sage.all import * >>> from sage.structure.category_object import normalize_names as nn >>> nn(Integer(0), "") () >>> nn(Integer(0), []) () >>> nn(Integer(0), None) () >>> nn(Integer(1), 'a') ('a',) >>> nn(Integer(2), 'z_z') ('z_z0', 'z_z1') >>> nn(Integer(3), 'x, y, z') ('x', 'y', 'z') >>> nn(Integer(2), 'ab') ('a', 'b') >>> nn(Integer(2), 'x0') ('x00', 'x01') >>> nn(Integer(3), (' a ', ' bb ', ' ccc ')) ('a', 'bb', 'ccc') >>> nn(Integer(4), ['a1', 'a2', 'b1', 'b11']) ('a1', 'a2', 'b1', 'b11')
Arguments are converted to strings:
sage: nn(1, u'a') ('a',) sage: var('alpha') # needs sage.symbolic alpha sage: nn(2, alpha) # needs sage.symbolic ('alpha0', 'alpha1') sage: nn(1, [alpha]) # needs sage.symbolic ('alpha',)
>>> from sage.all import * >>> nn(Integer(1), u'a') ('a',) >>> var('alpha') # needs sage.symbolic alpha >>> nn(Integer(2), alpha) # needs sage.symbolic ('alpha0', 'alpha1') >>> nn(Integer(1), [alpha]) # needs sage.symbolic ('alpha',)
With an unknown number of generators:
sage: nn(-1, 'a') ('a',) sage: nn(-1, 'x, y, z') ('x', 'y', 'z')
>>> from sage.all import * >>> nn(-Integer(1), 'a') ('a',) >>> nn(-Integer(1), 'x, y, z') ('x', 'y', 'z')
Test errors:
sage: nn(3, ["x", "y"]) Traceback (most recent call last): ... IndexError: the number of names must equal the number of generators sage: nn(None, "a") Traceback (most recent call last): ... TypeError: 'NoneType' object cannot be interpreted as an integer sage: nn(1, "") Traceback (most recent call last): ... ValueError: variable name must be nonempty sage: nn(1, "foo@") Traceback (most recent call last): ... ValueError: variable name 'foo@' is not alphanumeric sage: nn(2, "_foo") Traceback (most recent call last): ... ValueError: variable name '_foo0' does not start with a letter sage: nn(1, 3/2) Traceback (most recent call last): ... ValueError: variable name '3/2' is not alphanumeric
>>> from sage.all import * >>> nn(Integer(3), ["x", "y"]) Traceback (most recent call last): ... IndexError: the number of names must equal the number of generators >>> nn(None, "a") Traceback (most recent call last): ... TypeError: 'NoneType' object cannot be interpreted as an integer >>> nn(Integer(1), "") Traceback (most recent call last): ... ValueError: variable name must be nonempty >>> nn(Integer(1), "foo@") Traceback (most recent call last): ... ValueError: variable name 'foo@' is not alphanumeric >>> nn(Integer(2), "_foo") Traceback (most recent call last): ... ValueError: variable name '_foo0' does not start with a letter >>> nn(Integer(1), Integer(3)/Integer(2)) Traceback (most recent call last): ... ValueError: variable name '3/2' is not alphanumeric