Categories

AUTHORS:

  • David Kohel, William Stein and Nicolas M. Thiery

Every Sage object lies in a category. Categories in Sage are modeled on the mathematical idea of category, and are distinct from Python classes, which are a programming construct.

In most cases, typing x.category() returns the category to which x belongs. If C is a category and x is any object, C(x) tries to make an object in C from x. Checking if x belongs to C is done as usually by x in C.

See Category and sage.categories.primer for more details.

EXAMPLES:

We create a couple of categories:

sage: Sets()
Category of sets
sage: GSets(AbelianGroup([2,4,9]))
Category of G-sets for Multiplicative Abelian group isomorphic to C2 x C4 x C9
sage: Semigroups()
Category of semigroups
sage: VectorSpaces(FiniteField(11))
Category of vector spaces over Finite Field of size 11
sage: Ideals(IntegerRing())
Category of ring ideals in Integer Ring

Let’s request the category of some objects:

sage: V = VectorSpace(RationalField(), 3)
sage: V.category()
Category of vector spaces over Rational Field
sage: G = SymmetricGroup(9)
sage: G.category()
Join of Category of finite permutation groups and Category of finite weyl groups
sage: P = PerfectMatchings(3)
sage: P.category()
Category of finite enumerated sets

Let’s check some memberships:

sage: V in VectorSpaces(QQ)
True
sage: V in VectorSpaces(FiniteField(11))
False
sage: G in Monoids()
True
sage: P in Rings()
False

For parametrized categories one can use the following shorthand:

sage: V in VectorSpaces
True
sage: G in VectorSpaces
False

A parent P is in a category C if P.category() is a subcategory of C.

Note

Any object of a category should be an instance of CategoryObject.

For backward compatibilty this is not yet enforced:

sage: class A:
...     def category(self):
...         return Fields()
sage: A() in Rings()
True

By default, the category of an element \(x\) of a parent \(P\) is the category of all objects of \(P\) (this is dubious an may be deprecated):

sage: V = VectorSpace(RationalField(), 3)
sage: v = V.gen(1)
sage: v.category()
Category of elements of Vector space of dimension 3 over Rational Field
class sage.categories.category.Category(s=None)

Bases: sage.structure.unique_representation.UniqueRepresentation, sage.structure.sage_object.SageObject

The base class for modeling mathematical categories, like for example:

  • Groups(): the category of groups
  • EuclideanRings(): the category of euclidean rings
  • VectorSpaces(QQ): the category of vector spaces over the field of rational

See sage.categories.primer for an introduction to categories in Sage, their relevance, purpose and usage. The documentation below focus on their implementation.

Technically, a category is an instance of the class Category or some of its subclasses. Some categories, like VectorSpaces, are parametrized: VectorSpaces(QQ) is one of many instances of the class VectorSpaces. On the other hand, EuclideanRings() is the single instance of the class EuclideanRings.

Recall that an algebraic structure (say the ring QQ[x]) is modelled in Sage by an object which is called a parent. This object belongs to certain categories (here EuclideanRings() and Algebras()). The elements of the ring are themselves objects.

The class of a category (say EuclideanRings) can define simultaneously:

  • Operations on the category itself (what are its super categories, its category of morphisms?, its dual category)
  • Generic operations on parents in this category, like the ring QQ[x]
  • Generic operations on elements of this ring (Euclide algorithm for computing gcds)

This is achieved as follows:

sage: from sage.categories.all import Category
sage: class EuclideanRings(Category):
...       # operations on the category itself
...       def super_categories(self):
...           [Rings()]
...
...       def dummy(self): # TODO: find some good examples
...            pass
...
...       class ParentMethods: # holds the generic operations on parents
...            # find a good example of operation
...            pass
...
...       class ElementMethods:# holds the generic operations on elements
...            def gcd(x,y):
...                # Euclid algorithms
...                pass

Note that the EuclideanRings.ParentMethods and .Element class above do not inherit from anything. They are merely containers of operations. The hierarchy between the different categories is defined once at the level of the categories. Behind the scene, a parallel hierarchy of classes is built automatically from all the .ParentMethods classes. Then, a parent in a category receives the appropriate operations from all the super categories by usual class inheritance. Similarly, a third hierarchy of classes is built for elements from the .Elements.

EXAMPLES:

We define a hierarchy of four categories As(), Bs(), Cs(), Ds() with a diamond inheritance. Think for example:

  • As(): the category of sets
  • Bs(): the category of additive groups
  • Cs(): the category of multiplicative monoids
  • Ds(): the category of rings
sage: from sage.categories.all import Category
sage: from sage.misc.lazy_attribute import lazy_attribute
sage: class As (Category):
...       def super_categories(self):
...           return []
...
...       class ParentMethods:
...           def fA(self):
...               return "A"
...           f = fA
...
sage: class Bs (Category):
...       def super_categories(self):
...           return [As()]
...
...       class ParentMethods:
...           def fB(self):
...               return "B"
...
sage: class Cs (Category):
...       def super_categories(self):
...           return [As()]
...
...       class ParentMethods:
...           def fC(self):
...               return "C"
...           f = fC
...
sage: class Ds (Category):
...       def super_categories(self):
...           return [Bs(),Cs()]
...
...       class ParentMethods:
...           def fD(self):
...               return "D"
...

Categories should always have unique representation; by trac ticket #12215, this means that it will be kept in cache, but only if there is still some strong reference to it.

We check this before proceeding:

sage: import gc
sage: idAs = id(As())
sage: _ = gc.collect()
sage: n == id(As())
False
sage: a = As()
sage: id(As()) == id(As())
True
sage: As().parent_class == As().parent_class
True

We construct a parent in the category Ds() (that is an instance of Ds().parent_class), and check that it has access to all the methods provided by all the categories, with the appropriate inheritance order.

sage: D = Ds().parent_class()
sage: [ D.fA(), D.fB(), D.fC(), D.fD() ]
['A', 'B', 'C', 'D']
sage: D.f()
'C'
sage: C = Cs().parent_class()
sage: [ C.fA(), C.fC() ]
['A', 'C']
sage: C.f()
'C'

Here is the parallel hierarchy of classes which has been built automatically, together with the method resolution order (.mro()):

sage: As().parent_class
<class '__main__.As.parent_class'>
sage: As().parent_class.__bases__
(<type 'object'>,)
sage: As().parent_class.mro()
[<class '__main__.As.parent_class'>, <type 'object'>]
sage: Bs().parent_class
<class '__main__.Bs.parent_class'>
sage: Bs().parent_class.__bases__
(<class '__main__.As.parent_class'>,)
sage: Bs().parent_class.mro()
[<class '__main__.Bs.parent_class'>, <class '__main__.As.parent_class'>, <type 'object'>]
sage: Cs().parent_class
<class '__main__.Cs.parent_class'>
sage: Cs().parent_class.__bases__
(<class '__main__.As.parent_class'>,)
sage: Cs().parent_class.__mro__
(<class '__main__.Cs.parent_class'>, <class '__main__.As.parent_class'>, <type 'object'>)
sage: Ds().parent_class
<class '__main__.Ds.parent_class'>
sage: Ds().parent_class.__bases__
(<class '__main__.Cs.parent_class'>, <class '__main__.Bs.parent_class'>)
sage: Ds().parent_class.mro()
[<class '__main__.Ds.parent_class'>, <class '__main__.Cs.parent_class'>, <class '__main__.Bs.parent_class'>, <class '__main__.As.parent_class'>, <type 'object'>]

Note that that two categories in the same class need not have the same super_categories. For example, Algebras(QQ) has VectorSpaces(QQ) as super category, whereas Algebras(ZZ) only has Modules(ZZ) as super category. In particular, the constructed parent class and element class will differ (inheriting, or not, methods specific for vector spaces):

sage: Algebras(QQ).parent_class is Algebras(ZZ).parent_class
False
sage: issubclass(Algebras(QQ).parent_class, VectorSpaces(QQ).parent_class)
True

On the other hand, identical hierarchies of classes are, preferably, built only once (e.g. for categories over a base ring):

sage: Algebras(GF(5)).parent_class is Algebras(GF(7)).parent_class
True
sage: Coalgebras(QQ).parent_class is Coalgebras(FractionField(QQ[x])).parent_class
True

We now construct a parent in the usual way:

sage: class myparent(Parent):
...       def __init__(self):
...           Parent.__init__(self, category=Ds())
...       def g(self):
...           return "myparent"
...       class Element:
...           pass
sage: D = myparent()
sage: D.__class__
<class '__main__.myparent_with_category'>
sage: D.__class__.__bases__
(<class '__main__.myparent'>, <class '__main__.Ds.parent_class'>)
sage: D.__class__.mro()
[<class '__main__.myparent_with_category'>,
<class '__main__.myparent'>,
<type 'sage.structure.parent.Parent'>,
<type 'sage.structure.category_object.CategoryObject'>,
<type 'sage.structure.sage_object.SageObject'>,
<class '__main__.Ds.parent_class'>,
<class '__main__.Cs.parent_class'>,
<class '__main__.Bs.parent_class'>,
<class '__main__.As.parent_class'>,
<type 'object'>]
sage: D.fA()
'A'
sage: D.fB()
'B'
sage: D.fC()
'C'
sage: D.fD()
'D'
sage: D.f()
'C'
sage: D.g()
'myparent'
sage: D.element_class
<class '__main__.myparent_with_category.element_class'>
sage: D.element_class.mro()
[<class '__main__.myparent_with_category.element_class'>,
<class __main__.Element at ...>,
<class 'sage.categories.category.Ds.element_class'>,
<class 'sage.categories.category.Cs.element_class'>,
<class 'sage.categories.category.Bs.element_class'>,
<class 'sage.categories.category.As.element_class'>,
<type 'object'>]

TESTS:

sage: import __main__
sage: __main__.myparent = myparent
sage: __main__.As = As
sage: __main__.Bs = Bs
sage: __main__.Cs = Cs
sage: __main__.Ds = Ds
sage: loads(dumps(Ds)) is Ds
True
sage: loads(dumps(Ds())) is Ds()
True
sage: loads(dumps(Ds().element_class)) is Ds().element_class
True
Algebras(base_ring)

INPUT:

  • self – a subcategory of Sets()
  • base_ring – a ring

Returns the category of objects constructed as algebras of objects of self over base_ring.

EXAMPLES:

sage: Monoids().Algebras(QQ)
Category of monoid algebras over Rational Field

sage: Groups().Algebras(QQ)
Category of group algebras over Rational Field

sage: M = Monoids().example(); M
An example of a monoid: the free monoid generated by ('a', 'b', 'c', 'd')
sage: A = M.algebra(QQ); A
Free module generated by An example of a monoid: the free monoid generated by ('a', 'b', 'c', 'd') over Rational Field
sage: A.category()
Category of monoid algebras over Rational Field
CartesianProducts()

INPUT:

  • self – a concrete category

Returns the category of parents constructed as cartesian products of parents in self.

See CartesianProductFunctor for more information

EXAMPLES:

sage: Sets().CartesianProducts()
Category of Cartesian products of sets
sage: Semigroups().CartesianProducts()
Category of Cartesian products of semigroups
sage: EuclideanDomains().CartesianProducts()
Category of Cartesian products of monoids
DualObjects()

Returns the category of duals of objects of self.

INPUT:

  • self – a subcategory of vector spaces over some base ring

The dual of a vector space \(V\) is the space consisting of all linear functionals on \(V\) (http://en.wikipedia.org/wiki/Dual_space). Additional structure on \(V\) can endow its dual with additional structure; e.g. if \(V\) is an algebra, then its dual is a coalgebra.

This returns the category of dual of spaces in self endowed with the appropriate additional structure.

See also CovariantFunctorialConstruction.

TODO: add support for graded duals.

EXAMPLES:

sage: VectorSpaces(QQ).DualObjects()
Category of duals of vector spaces over Rational Field

The dual of a vector space is a vector space:

sage: VectorSpaces(QQ).DualObjects().super_categories()
[Category of vector spaces over Rational Field]

The dual of an algebra space is a coalgebra:

sage: Algebras(QQ).DualObjects().super_categories()
[Category of coalgebras over Rational Field, Category of duals of vector spaces over Rational Field]

The dual of a coalgebra space is an algebra:

sage: Coalgebras(QQ).DualObjects().super_categories()
[Category of algebras over Rational Field, Category of duals of vector spaces over Rational Field]

As a shorthand, this category can be accessed with the dual() method:

sage: VectorSpaces(QQ).dual()
Category of duals of vector spaces over Rational Field

TESTS:

sage: C = VectorSpaces(QQ).DualObjects()
sage: C.base_category()
Category of vector spaces over Rational Field
sage: C.super_categories()
[Category of vector spaces over Rational Field]
sage: latex(C)
\mathbf{DualObjects}(\mathbf{VectorSpaces}_{\Bold{Q}})
sage: TestSuite(C).run()
class ElementMethods

Put methods for elements here.

Category.IsomorphicObjects()
INPUT:
  • self – a concrete category

Given a concrete category As() (i.e. a subcategory of Sets()), As().IsomorphicObjects() returns the category of objects of As() endowed with a distinguished description as the image of some other object of As() by an isomorphism.

See Subquotients() for background.

EXAMPLES:

sage: C = Sets().IsomorphicObjects(); C
Category of isomorphic objects of sets

sage: C.super_categories()
[Category of subobjects of sets, Category of quotients of sets]

sage: C.all_super_categories()
[Category of isomorphic objects of sets,
 Category of subobjects of sets,
 Category of quotients of sets,
 Category of subquotients of sets,
 Category of sets,
 Category of sets with partial maps,
 Category of objects]

Unless something specific about isomorphic objects is implemented for this category, one actually get an optimized super category:

sage: C = Semigroups().IsomorphicObjects(); C
Join of Category of quotients of semigroups and Category of isomorphic objects of sets

TESTS:

sage: TestSuite(Sets().IsomorphicObjects()).run()
class Category.ParentMethods

Put methods for parents here.

Category.Quotients()
INPUT:
  • self – a concrete category

Given a concrete category As() (i.e. a subcategory of Sets()), As().Quotients() returns the category of objects of As() endowed with a distinguished description as quotient of some other object of As().

See Subquotients() for background.

EXAMPLES:

sage: C = Semigroups().Quotients(); C
Category of quotients of semigroups
sage: C.super_categories()
[Category of subquotients of semigroups, Category of quotients of sets]
sage: C.all_super_categories()
[Category of quotients of semigroups,
 Category of subquotients of semigroups,
 Category of semigroups,
 Category of subquotients of magmas,
 Category of magmas,
 Category of quotients of sets,
 Category of subquotients of sets,
 Category of sets,
 Category of sets with partial maps,
 Category of objects]

The caller is responsible for checking that the given category admits a well defined category of quotients:

sage: EuclideanDomains().Quotients()
Join of Category of euclidean domains and Category of subquotients of monoids and Category of quotients of semigroups

TESTS:

sage: TestSuite(C).run()
Category.Realizations()

Return the category of realizations of the parent self or of objects of the category self

INPUT:

  • self – a parent or a concrete category

Note

this function is actually inserted as a method in the class Category (see Realizations()). It is defined here for code locality reasons.

EXAMPLES:

The category of realizations of some algebra:

sage: Algebras(QQ).Realizations()
Join of Category of algebras over Rational Field and Category of realizations of magmas

The category of realizations of a given algebra:

sage: A = Sets().WithRealizations().example(); A
The subset algebra of {1, 2, 3} over Rational Field
sage: A.Realizations()
Category of realizations of The subset algebra of {1, 2, 3} over Rational Field

sage: C = GradedHopfAlgebrasWithBasis(QQ).Realizations(); C
Join of Category of graded hopf algebras with basis over Rational Field and Category of realizations of hopf algebras over Rational Field
sage: C.super_categories()
[Category of graded hopf algebras with basis over Rational Field, Category of realizations of hopf algebras over Rational Field]

sage: TestSuite(C).run()

Todo

Add an optional argument to allow for:

sage: Realizations(A, category = Blahs()) # todo: not implemented
Category.Subobjects()
INPUT:
  • self – a concrete category

Given a concrete category As() (i.e. a subcategory of Sets()), As().Subobjects() returns the category of objects of As() endowed with a distinguished description as subobject of some other object of As().

See Subquotients() for background.

EXAMPLES:

sage: C = Sets().Subobjects(); C
Category of subobjects of sets

sage: C.super_categories()
[Category of subquotients of sets]

sage: C.all_super_categories()
[Category of subobjects of sets,
 Category of subquotients of sets,
 Category of sets,
 Category of sets with partial maps,
 Category of objects]

Unless something specific about subobjects is implemented for this category, one actually get an optimized super category:

sage: C = Semigroups().Subobjects(); C
Join of Category of subquotients of semigroups and Category of subobjects of sets

The caller is responsible for checking that the given category admits a well defined category of subobjects.

TESTS:

sage: Semigroups().Subobjects().is_subcategory(Semigroups().Subquotients())
True
sage: TestSuite(C).run()
Category.Subquotients()
INPUT:
  • self – a concrete category

Given a concrete category self == As() (i.e. a subcategory of Sets()), As().Subquotients() returns the category of objects of As() endowed with a distinguished description as subquotient of some other object of As().

EXAMPLES:

sage: Monoids().Subquotients()
Category of subquotients of monoids

A parent \(A\) in As() is further in As().Subquotients() if there is a distinguished parent \(B\) in As(), called the ambient space, a subspace \(B'\) of \(B\) and a pair of structure preserving maps:

\[l: A \mapsto B' \text{ and } r: B' \mapsto A\]

called respectively the lifting map and retract map such that \(r \circ l\) is the identity of \(A\). What exactly structure preserving means is explicited in each category; this typically states that, for each operation \(op\) of the category, there is a commutative diagram such that:

for all \(e\in A\), one has \(op_A(e) = r(op_B(l(e)))\)

This allows for deriving the operations on \(A\) from those on \(B\).

Note: this is a slightly weaker definition than that found on http://en.wikipedia.org/wiki/Subquotient: B’ is not necessarily required to be a subobject of B.

Assumptions:

  • For any category As(), As().Subquotients() is a subcategory of As().

    Example: a subquotient of a group is a group (e.g. a left or right quotients of a group by a non normal subgroup is not in this category).

  • This construction is covariant: if As() is a subcategory of Bs(), then As().Subquotients() is a subcategory of Bs().Subquotients()

    Example: if \(A\) is a distinguished subquotient of \(B\) in the category of groups, then is is also a subquotient of \(B\) in the category of monoids.

  • If the user (or a program) calls As().Subquotients(), then it is assumed that subquotients are well defined in this category. This is not checked, and probably never will. Note that, if a category \(As()\) does not specify anything about its subquotients, then it’s subquotient category looks like this:

    sage: EuclideanDomains().Subquotients()
    Join of Category of euclidean domains and Category of subquotients of monoids
    

Interface: the ambient space of \(B\) is given by B.ambient(). The lifting and retract map are implemented respectively as methods B.lift(b) and B.retract(a). As a shorthand, one can use alternatively b.lift():

sage: S = Semigroups().Subquotients().example(); S
An example of a (sub)quotient semigroup: a quotient of the left zero semigroup
sage: S.ambient()
An example of a semigroup: the left zero semigroup
sage: S(3).lift().parent()
An example of a semigroup: the left zero semigroup
sage: S(3) * S(1) == S.retract( S(3).lift() * S(1).lift() )
True

See S? for more.

TODO: use a more interesting example, like \(\ZZ/n\ZZ\).

The two most common use cases are:

  • quotients, when \(A'=A\) and \(r\) is a morphism; then \(r\) is a canonical quotient map from \(A\) to \(B\))
  • subobjects (when \(l\) is an embedding from \(B\) into \(A\)).

See respectively Quotients and Subobjects.

TESTS:

sage: TestSuite(Sets().Subquotients()).run()
Category.TensorProducts()

INPUT:

  • self – a subcategory of ModulesWithBasis(...)

Returns the category of objects constructed as tensor products of objects of self.

See TensorProductFunctor for more information

EXAMPLES:

sage: ModulesWithBasis(QQ).TensorProducts()
Category of tensor products of modules with basis over Rational Field
Category.WithRealizations()

Returns the category of parents in self endowed with multiple realizations

INPUT:

  • self – a category

See also

Note

this function is actually inserted as a method in the class Category (see WithRealizations()). It is defined here for code locality reasons.

EXAMPLES:

sage: Sets().WithRealizations()
Category of sets with realizations

Parent with realizations

Let us now explain the concept of realizations. A parent with realizations is a facade parent (see Sets.Facades) admitting multiple concrete realizations where its elements are represented. Consider for example an algebra \(A\) which admits several natural bases:

sage: A = Sets().WithRealizations().example(); A
The subset algebra of {1, 2, 3} over Rational Field

For each such basis \(B\) one implements a parent \(P_B\) which realizes \(A\) with its elements represented by expanding them on the basis \(B\):

sage: A.F()
The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis
sage: A.Out()
The subset algebra of {1, 2, 3} over Rational Field in the Out basis
sage: A.In()
The subset algebra of {1, 2, 3} over Rational Field in the In basis

sage: A.an_element()
F[{}] + 2*F[{1}] + 3*F[{2}] + F[{1, 2}]

If \(B\) and \(B'\) are two bases, then the change of basis from \(B\) to \(B'\) is implemented by a canonical coercion between \(P_B\) and \(P_{B'}\):

sage: F = A.F(); In = A.In(); Out = A.Out()
sage: i = In.an_element(); i
In[{}] + 2*In[{1}] + 3*In[{2}] + In[{1, 2}]
sage: F(i)
7*F[{}] + 3*F[{1}] + 4*F[{2}] + F[{1, 2}]
sage: F.coerce_map_from(Out)
Generic morphism:
  From: The subset algebra of {1, 2, 3} over Rational Field in the Out basis
  To:   The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis

allowing for mixed arithmetic:

sage: (1 + Out.from_set(1)) * In.from_set(2,3)
Out[{}] + 2*Out[{1}] + 2*Out[{2}] + 2*Out[{3}] + 2*Out[{1, 2}] + 2*Out[{1, 3}] + 4*Out[{2, 3}] + 4*Out[{1, 2, 3}]

In our example, there are three realizations:

sage: A.realizations()
[The subset algebra of {1, 2, 3} over Rational Field in the Fundamental basis,
 The subset algebra of {1, 2, 3} over Rational Field in the In basis,
 The subset algebra of {1, 2, 3} over Rational Field in the Out basis]

The set of all realizations of \(A\), together with the coercion morphisms is a category (whose class inherits from Category_realization_of_parent):

sage: A.Realizations()
Category of realizations of The subset algebra of {1, 2, 3} over Rational Field

The various parent realizing \(A\) belong to this category:

sage: A.F() in A.Realizations()
True

\(A\) itself is in the category of algebras with realizations:

sage: A in Algebras(QQ).WithRealizations()
True

The (mostly technical) WithRealizations categories are the analogs of the *WithSeveralBases categories in MuPAD-Combinat. They provide support tools for handling the different realizations and the morphisms between them.

Typically, FiniteDimensionalVectorSpaces(QQ).WithRealizations() will eventually be in charge, whenever a coercion \(\phi: A\mapsto B\) is registered, to register \(\phi^{-1}\) as coercion \(B \mapsto A\) if there is none defined yet. To achieve this, FiniteDimensionalVectorSpaces would provide a nested class WithRealizations implementing the appropriate logic.

WithRealizations is a regressive covariant functorial construction. On our example, this simply means that \(A\) is automatically in the category of rings with realizations (covariance):

sage: A in Rings().WithRealizations()
True

and in the category of algebras (regressiveness):

sage: A in Algebras(QQ)
True

Note

For C a category, C.WithRealizations() in fact calls sage.categories.with_realizations.Realizations(C). The later is responsible for building the hierarchy of the categories with realizations in parallel to that of their base categories, optimizing away those categories that do not provide a WithRealizations nested class. See sage.categories.covariant_functorial_construction for the technical details.

Note

Design question: currently WithRealizations is a regressive construction. That is self.WithRealizations() is a subcategory of self by default:

sage: Algebras(QQ).WithRealizations().super_categories()
[Category of algebras over Rational Field, Category of monoids with realizations, Category of commutative additive monoids with realizations]

Is this always desirable? For example, AlgebrasWithBasis(QQ).WithRealizations() should certainly be a subcategory of Algebras(QQ), but not of AlgebrasWithBasis(QQ). This is because AlgebrasWithBasis(QQ) is specifying something about the concrete realization.

TESTS:

sage: Semigroups().WithRealizations()
Join of Category of semigroups and Category of sets with realizations
sage: C = GradedHopfAlgebrasWithBasis(QQ).WithRealizations(); C
Category of graded hopf algebras with basis over Rational Field with realizations
sage: C.super_categories()
[Category of graded hopf algebras over Rational Field]
sage: C.all_super_categories()
[Category of graded hopf algebras with basis over Rational Field with realizations,
 Category of graded hopf algebras over Rational Field,
 Category of graded bialgebras over Rational Field,
 Category of graded algebras over Rational Field,
 ...]

sage: TestSuite(Semigroups().WithRealizations()).run()
Category.all_super_categories(proper=False)

Returns the list of all super categories of this category.

INPUT:

  • proper – a boolean (default: False); whether to exclude this category.

Since trac ticket #11943, the order of super categories is determined by Python’s method resolution order C3 algorithm.

Note

Whenever speed matters, the developers are advised to use instead the lazy attributes _all_super_categories(), _all_super_categories_proper(), or _set_of_all_super_categories(), as appropriate. Simply because lazy attributes are much faster than any method.

EXAMPLES:

sage: C = Rings(); C
Category of rings
sage: C.all_super_categories()
[Category of rings,
 Category of rngs,
 Category of semirings,
 Category of monoids,
 Category of semigroups,
 Category of magmas,
 Category of commutative additive groups,
 Category of commutative additive monoids,
 Category of commutative additive semigroups,
 Category of additive magmas,
 Category of sets,
 Category of sets with partial maps,
 Category of objects]

sage: C.all_super_categories(proper = True)
[Category of rngs,
 Category of semirings,
 Category of monoids,
 Category of semigroups,
 Category of magmas,
 Category of commutative additive groups,
 Category of commutative additive monoids,
 Category of commutative additive semigroups,
 Category of additive magmas,
 Category of sets,
 Category of sets with partial maps,
 Category of objects]

sage: Sets().all_super_categories()
[Category of sets, Category of sets with partial maps, Category of objects]
sage: Sets().all_super_categories(proper=True)
[Category of sets with partial maps, Category of objects]
sage: Sets().all_super_categories() is Sets()._all_super_categories
True
sage: Sets().all_super_categories(proper=True) is Sets()._all_super_categories_proper
True
classmethod Category.an_instance()

Returns an instance of this class

EXAMPLES:

sage: Rings.an_instance()
Category of rings

Parametrized categories should overload this default implementation to provide appropriate arguments:

sage: Algebras.an_instance()
Category of algebras over Rational Field
sage: Bimodules.an_instance()
Category of bimodules over Rational Field on the left and Real Field with 53 bits of precision on the right
sage: AlgebraIdeals.an_instance()
Category of algebra ideals in Univariate Polynomial Ring in x over Rational Field
Category.category()

Returns the category of this category. So far all categories are in the category of objects.

EXAMPLES:

sage: Sets().category()
Category of objects
sage: VectorSpaces(QQ).category()
Category of objects
Category.category_graph()

Returns the graph of all super categories of this category

EXAMPLES:

sage: C = Algebras(QQ)
sage: G = C.category_graph()
sage: G.is_directed_acyclic()
True
sage: G.girth()
4
Category.dual()

Returns the category of duals of objects of self.

INPUT:

  • self – a subcategory of vector spaces over some base ring

The dual of a vector space \(V\) is the space consisting of all linear functionals on \(V\) (http://en.wikipedia.org/wiki/Dual_space). Additional structure on \(V\) can endow its dual with additional structure; e.g. if \(V\) is an algebra, then its dual is a coalgebra.

This returns the category of dual of spaces in self endowed with the appropriate additional structure.

See also CovariantFunctorialConstruction.

TODO: add support for graded duals.

EXAMPLES:

sage: VectorSpaces(QQ).DualObjects()
Category of duals of vector spaces over Rational Field

The dual of a vector space is a vector space:

sage: VectorSpaces(QQ).DualObjects().super_categories()
[Category of vector spaces over Rational Field]

The dual of an algebra space is a coalgebra:

sage: Algebras(QQ).DualObjects().super_categories()
[Category of coalgebras over Rational Field, Category of duals of vector spaces over Rational Field]

The dual of a coalgebra space is an algebra:

sage: Coalgebras(QQ).DualObjects().super_categories()
[Category of algebras over Rational Field, Category of duals of vector spaces over Rational Field]

As a shorthand, this category can be accessed with the dual() method:

sage: VectorSpaces(QQ).dual()
Category of duals of vector spaces over Rational Field

TESTS:

sage: C = VectorSpaces(QQ).DualObjects()
sage: C.base_category()
Category of vector spaces over Rational Field
sage: C.super_categories()
[Category of vector spaces over Rational Field]
sage: latex(C)
\mathbf{DualObjects}(\mathbf{VectorSpaces}_{\Bold{Q}})
sage: TestSuite(C).run()
Category.element_class()

A common super class for all elements of parents in this category.

EXAMPLES:

sage: C = Algebras(QQ).element_class; C
<class 'sage.categories.algebras.Algebras.element_class'>
sage: type(C)
<class 'sage.structure.dynamic_class.DynamicMetaclass'>

By trac ticket #11935, some categories share their element classes. For example, the element class of an algebra only depends on the category of the base. A typical example is the category of algebras over a field versus algebras over a non-field:

sage: Algebras(GF(5)).element_class is Algebras(GF(3)).element_class
True
sage: Algebras(QQ).element_class is Algebras(ZZ).element_class
False
sage: Algebras(ZZ['t']).element_class is Algebras(ZZ['t','x']).element_class
True

See also

parent_class()

Category.example(*args, **keywords)

Returns an object in this category. Most of the time, this is a parent.

This serves three purposes:

  • Give a typical example to better explain what the category is all about. (and by the way prove that the category is non empty :-) )
  • Provide a minimal template for implementing other objects in this category
  • Provide an object on which to test generic code implemented by the category

For all those applications, the implementation of the object shall be kept to a strict minimum. The object is therefore not meant to be used for other applications; most of the time a full featured version is available elsewhere in Sage, and should be used insted.

Technical note: by default FooBar(...).example() is constructed by looking up sage.categories.examples.foo_bar.Example and calling it as Example(). Extra positional or named parameters are also passed down. For a category over base ring, the base ring is further passed down as an optional argument.

Categories are welcome to override this default implementation.

EXAMPLES:

sage: Semigroups().example()
An example of a semigroup: the left zero semigroup

sage: Monoids().Subquotients().example()
NotImplemented
Category.hom_category()

Returns the category for homsets between objects this category.

A category which needs to give specific information about this category should provide a HomCategory class.

To avoid generating billions of categories, if there is nothing specific for homsets of this category, then this just returns the join of the categories of homsets of the super categories.

EXAMPLES:

sage: Sets().hom_category()
Category of hom sets in Category of sets
Category.is_abelian()

Returns whether this category is abelian.

An abelian category is a category satisfying:

  • It has a zero object;
  • It has all pullbacks and pushouts;
  • All monomorphisms and epimorphisms are normal.

Equivalently, one can define an increasing sequence of conditions:

  • A category is pre-additive if it is enriched over abelian groups (all homsets are abelian groups and composition is bilinear);
  • A pre-additive category is additive if every finite set of objects has a biproduct (we can form direct sums and direct products);
  • An additive category is pre-abelian if every morphism has both a kernel and a cokernel;
  • A pre-abelian category is abelian if every monomorphism is the kernel of some morphism and every epimorphism is the cokernel of some morphism.

EXAMPLES:

sage: Modules(ZZ).is_abelian()
True
sage: FreeModules(ZZ).is_abelian()
False
sage: FreeModules(QQ).is_abelian()
True
sage: CommutativeAdditiveGroups().is_abelian()
True
sage: Semigroups().is_abelian()
Traceback (most recent call last):
NotImplementedError: is_abelian
Category.is_subcategory(c)

Returns True if self is naturally embedded as a subcategory of c.

EXAMPLES:

sage: AbGrps = CommutativeAdditiveGroups()
sage: Rings().is_subcategory(AbGrps)
True
sage: AbGrps.is_subcategory(Rings())
False

The is_subcategory function takes into account the base.

sage: M3 = VectorSpaces(FiniteField(3))
sage: M9 = VectorSpaces(FiniteField(9, 'a'))
sage: M3.is_subcategory(M9)
False

Join categories are properly handled:

sage: CatJ = Category.join((CommutativeAdditiveGroups(), Semigroups()))
sage: Rings().is_subcategory(CatJ)
True
sage: V3 = VectorSpaces(FiniteField(3))
sage: POSet = PartiallyOrderedSets()
sage: PoV3 = Category.join((V3, POSet))
sage: A3 = AlgebrasWithBasis(FiniteField(3))
sage: PoA3 = Category.join((A3, POSet))
sage: PoA3.is_subcategory(PoV3)
True
sage: PoV3.is_subcategory(PoV3)
True
sage: PoV3.is_subcategory(PoA3)
False
static Category.join(categories, as_list=False)

Returns the join of the input categories in the lattice of categories

INPUT:

  • a sequence of categories (FIXME: should this be a list or iterable?)
  • as_list: a boolean, False by default (keyword only)

EXAMPLES:

sage: J = Category.join((Groups(), CommutativeAdditiveMonoids())); J
Join of Category of groups and Category of commutative additive monoids
sage: J.super_categories()
[Category of groups, Category of commutative additive monoids]
sage: J.all_super_categories(proper=True)
[Category of groups,
 Category of monoids,
 Category of semigroups,
 Category of magmas,
 Category of commutative additive monoids,
 Category of commutative additive semigroups,
 Category of additive magmas,
 Category of sets,
 Category of sets with partial maps,
 Category of objects]

This is an associative operation:

sage: Category.join((Objects(), Sets(), Category.join((Monoids(), Sets(), Monoids())), Category.join((Objects(), CommutativeAdditiveGroups()))))
Join of Category of monoids and Category of commutative additive groups

The join of a single category is the category itself:

sage: Category.join((Monoids(),))
Category of monoids

Similarly, the join of several mutually comparable categories is the smallest one:

sage: Category.join((Sets(), Rings(), Monoids()))
Category of rings

If the optional parameter as_list is True, this just returns the super categories of the join as a list, without constructing the join category itself:

sage: Category.join((Groups(), CommutativeAdditiveMonoids()), as_list=True)
[Category of groups, Category of commutative additive monoids]
sage: Category.join((Sets(), Rings(), Monoids()), as_list=True)
[Category of rings]
static Category.meet(categories)

Returns the meet of a list of categories

INPUT:

  • categories - a non empty list (or iterable) of categories

EXAMPLES:

sage: Category.meet([Algebras(ZZ), Algebras(QQ), Groups()])
Category of monoids

That meet of an empty list should be a category which is a subcategory of all categories, which does not make practical sense:

sage: Category.meet([])
Traceback (most recent call last):
...
ValueError: The meet of an empty list of categories is not implemented
Category.or_subcategory(category=None)

INPUT:

  • category - a sub category of self, tuple/list thereof, or None

OUTPUT:

  • a category

Returns category or self if category is None.

EXAMPLES:

sage: Monoids().or_subcategory(Groups())
Category of groups
sage: Monoids().or_subcategory(None)
Category of monoids

If category is a list/tuple, then a join category is returned:

sage: Monoids().or_subcategory((FiniteEnumeratedSets(), Groups()))
Join of Category of groups and Category of finite enumerated sets

An error if raised if category is not a subcategory of self.

sage: Monoids().or_subcategory(EnumeratedSets())
Traceback (most recent call last):
...
AssertionError: Subcategory of `Category of enumerated sets` required; got `Category of monoids`
Category.parent_class()

A common super class for all parents in this category.

EXAMPLES:

sage: C = Algebras(QQ).parent_class; C
<class 'sage.categories.algebras.Algebras.parent_class'>
sage: type(C)
<class 'sage.structure.dynamic_class.DynamicMetaclass'>

By trac ticket #11935, some categories share their parent classes. For example, the parent class of an algebra only depends on the category of the base ring. A typical example is the category of algebras over a finite field versus algebras over a non-field:

sage: Algebras(GF(7)).parent_class is Algebras(GF(5)).parent_class
True
sage: Algebras(QQ).parent_class is Algebras(ZZ).parent_class
False
sage: Algebras(ZZ['t']).parent_class is Algebras(ZZ['t','x']).parent_class
True

See CategoryWithParameters for an abstract base class for categories that depend on parameters, even though the parent and element classes only depend on the parent or element classes of its super categories. It is used in Bimodules, Category_over_base and sage.categories.category.JoinCategory.

Category.required_methods()

Returns the methods that are required and optional for parents in this category and their elements.

EXAMPLES:

sage: Algebras(QQ).required_methods()
{'parent': {'required': ['__contains__'], 'optional': []}, 'element': {'required': ['__nonzero__'], 'optional': ['_add_', '_mul_']}}
Category.subcategory_class()

A common superclass for all subcategories of this category (including this one).

This class derives from D.subcategory_class for each super category \(D\) of self, and includes all the methods from the nested class self.SubcategoryMethods, if it exists.

See also

EXAMPLES:

sage: cls = Rings().subcategory_class; cls
<class 'sage.categories.rings.Rings.subcategory_class'>
sage: type(cls)
<class 'sage.structure.dynamic_class.DynamicMetaclass'>

Rings() is an instance of this class, as well as all its subcategories:

sage: isinstance(Rings(), cls)
True
sage: isinstance(AlgebrasWithBasis(QQ), cls)
True

TESTS:

sage: cls = Algebras(QQ).subcategory_class; cls
<class 'sage.categories.algebras.Algebras.subcategory_class'>
sage: type(cls)
<class 'sage.structure.dynamic_class.DynamicMetaclass'>
Category.super_categories()

Returns the immediate super categories of self

Every category should implement this method.

EXAMPLES:

sage: Groups().super_categories()
[Category of monoids]
sage: Objects().super_categories()
[]

Note

Mathematically speaking, the order of the super categories should be irrelevant. However, in practice, this order influences the result of all_super_categories(), and accordingly of the method resolution order for parent and element classes. Namely, since ticket 11943, Sage uses the same \(C3\) algorithm for determining the order on the list of all super categories as Python is using for the method resolution order of new style classes.

Note

Whenever speed matters, developers are advised to use the lazy attribute _super_categories() instead of calling this method.

class sage.categories.category.CategoryWithParameters(s=None)

Bases: sage.categories.category.Category

A parametrized category whose parent/element classes depend only on its super categories.

Many categories in Sage are parametrized, like C = Algebras(K) which takes a base ring as parameter. In many cases, however, the operations provided by C in the parent class and element class depend only on the super categories of C. For example, the vector space operations are provided if and only if K is a field, since VectorSpaces(K) is a super category of C only in that case. In such cases, and as an optimization (see trac ticket #11935), we want to use the same parent and element class for all fields. This is the purpose of this abstract class.

Currently, JoinCategory, Category_over_base and Bimodules inherit from this class.

EXAMPLES:

sage: C1 = Algebras(GF(5))
sage: C2 = Algebras(GF(3))
sage: C3 = Algebras(ZZ)
sage: from sage.categories.category import CategoryWithParameters
sage: isinstance(C1, CategoryWithParameters)
True
sage: C1.parent_class is C2.parent_class
True
sage: C1.parent_class is C3.parent_class
False
class sage.categories.category.HomCategory(category, name=None)

Bases: sage.categories.category.Category

An abstract base class for all categories of homsets

Todo

Get a consistent hierarchy of homset categories. Currently, it is built in parallel to that of their base categories (which is plain wrong!!!)

base()

If this hom-category is subcategory of a category with a base, return that base.

EXAMPLES:

sage: ModulesWithBasis(ZZ).hom_category().base()
Integer Ring
extra_super_categories()

The super categories of self that are not derived from the inheritance diagram of the base category, as a list.

EXAMPLES:

sage: HomCategory(Sets()).extra_super_categories()
[]
super_categories()

Returns the immediate super categories, as per Category.super_categories().

EXAMPLES:

sage: HomCategory(Sets()).super_categories()
[Category of hom sets in Category of sets with partial maps]
class sage.categories.category.JoinCategory(super_categories, **kwds)

Bases: sage.categories.category.CategoryWithParameters

A class for joins of several categories. Do not use directly; see Category.join instead.

EXAMPLES:

sage: from sage.categories.category import JoinCategory
sage: J = JoinCategory((Groups(), CommutativeAdditiveMonoids())); J
Join of Category of groups and Category of commutative additive monoids
sage: J.super_categories()
[Category of groups, Category of commutative additive monoids]
sage: J.all_super_categories(proper=True)
[Category of groups, Category of monoids, Category of semigroups, Category of magmas, Category of commutative additive monoids, Category of commutative additive semigroups, Category of additive magmas, Category of sets, Category of sets with partial maps, Category of objects]

By trac ticket #11935, join categories and categories over base rings inherit from CategoryWithParameters. This allows for sharing parent and element classes between similar categories. For example, since polynomial rings belong to a join category and since the underlying implementation is the same for all finite fields, we have:

sage: GF(3)['x'].category()
Join of Category of euclidean domains and Category of commutative algebras over Finite Field of size 3
sage: type(GF(3)['x']) is type(GF(5)['z'])
True
is_subcategory(C)

Check whether this join category is subcategory of another category C.

EXAMPLES:

sage: Category.join([Rings(),Modules(QQ)]).is_subcategory(Category.join([Rngs(),Bimodules(QQ,QQ)]))
True
super_categories()

Returns the immediate super categories, as per Category.super_categories().

EXAMPLES:

sage: from sage.categories.category import JoinCategory
sage: JoinCategory((Semigroups(), FiniteEnumeratedSets())).super_categories()
[Category of semigroups, Category of finite enumerated sets]
sage.categories.category.category_graph(categories=None)

Returns the graph of the categories in Sage

INPUT:

  • categories – a list (or iterable) of categories

If categories is specified, then the graph will contain the mentionned categories together with all their super categories. Otherwise the graph will contain (an instance of) each category in sage.categories.all (e.g. Algebras(QQ) for algebras).

For readability, the names of the category are shortened, and in particular do not contain base rings.

EXAMPLES:

sage: G = sage.categories.category.category_graph(categories = [Rings()])
sage: G.vertices()
['additive magmas',
 'commutative additive groups',
 'commutative additive monoids',
 'commutative additive semigroups',
 'magmas',
 'monoids',
 'objects',
 'rings',
 'rngs',
 'semigroups',
 'semirings',
 'sets',
 'sets with partial maps']
sage: G.plot()

sage: sage.categories.category.category_graph().plot()
sage.categories.category.category_sample()

Return a sample of categories.

It is constructed by looking for all concrete category classes declared in sage.categories.all, calling Category.an_instance() on those and taking all their super categories.

EXAMPLES:

sage: from sage.categories.category import category_sample
sage: sorted(category_sample(), key=str)
[Category of G-sets for Symmetric group of order 8! as a permutation group,
 Category of Hecke modules over Rational Field,
 Category of additive magmas, ...,
 Category of fields, ...,
 Category of graded hopf algebras with basis over Rational Field, ...,
 Category of modular abelian varieties over Rational Field, ...,
 Category of simplicial complexes, ...,
 Category of vector spaces over Rational Field, ...,
 Category of weyl groups,...
sage.categories.category.is_Category(x)

Returns True if x is a category.

EXAMPLES:

sage: sage.categories.category.is_Category(CommutativeAdditiveSemigroups())
True
sage: sage.categories.category.is_Category(ZZ)
False

Previous topic

Implementing a new parent: a (draft of) tutorial

Next topic

Specific category classes

This Page