AUTHORS:
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
Bases: sage.structure.unique_representation.UniqueRepresentation, sage.structure.sage_object.SageObject
The base class for modeling mathematical categories, like for example:
See sage.categories.primer for an introduction to categories in Sage, their relevance, purpose, and usage. The documentation below will 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, EuclideanDomains() is the single instance of the class EuclideanDomains.
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 EuclideanDomains() and Algebras()). The elements of the ring are themselves objects.
The class of a category (say EuclideanDomains) can define simultaneously:
This is achieved as follows:
sage: from sage.categories.all import Category
sage: class EuclideanDomains(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 EuclideanDomains.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:
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 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 '__main__.Ds.element_class'>,
<class '__main__.Cs.element_class'>,
<class '__main__.Bs.element_class'>,
<class '__main__.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
The immediate super categories of this category.
This lazy attribute caches the result of the mandatory method super_categories() for speed. It also does some mangling (flattening join categories, sorting, ...).
Whenever speed matters, developers are advised to use this lazy attribute rather than calling super_categories().
Note
This attribute is likely to eventually become a tuple. When this happens, we might as well use Category._sort(), if not Category._sort_uniq().
EXAMPLES:
sage: Rings()._super_categories
[Category of rngs, Category of semirings]
The super categories of this category used for building classes.
This is a close variant of _super_categories() used for constructing the list of the bases for parent_class(), element_class(), and friends. The purpose is ensure that Python will find a proper Method Resolution Order for those classes. For background, see sage.misc.c3_controlled.
See also
_cmp_key().
Note
This attribute is calculated as a by-product of computing _all_super_categories().
EXAMPLES:
sage: Rings()._super_categories_for_classes
[Category of rngs, Category of semirings]
All the super categories of this category, including this category.
Since trac ticket #11943, the order of super categories is determined by Python’s method resolution order C3 algorithm.
See also
Note
this attribute is likely to eventually become a tuple.
Note
this sets _super_categories_for_classes() as a side effect
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 commutative additive groups, ...
Category of sets, Category of sets with partial maps,
Category of objects]
All the proper super categories of this category.
Since trac ticket #11943, the order of super categories is determined by Python’s method resolution order C3 algorithm.
See also
Note
this attribute is likely to eventually become a tuple.
EXAMPLES:
sage: C = Rings(); C
Category of rings
sage: C._all_super_categories_proper
[Category of rngs, Category of semirings, ...
Category of monoids, ...
Category of commutative additive groups, ...
Category of sets, Category of sets with partial maps,
Category of objects]
The frozen set of all proper super categories of this category.
Note
this is used for speeding up category containment tests.
See also
EXAMPLES:
sage: Groups()._set_of_super_categories
frozenset([...])
sage: sorted(Groups()._set_of_super_categories, key=str)
[Category of inverse unital magmas, Category of magmas, Category of monoids,
Category of objects, Category of semigroups, Category of sets,
Category of sets with partial maps, Category of unital magmas]
TESTS:
sage: C = HopfAlgebrasWithBasis(GF(7))
sage: C._set_of_super_categories == frozenset(C._all_super_categories_proper)
True
Construction of the parent/element/... class of self.
INPUT:
ASSUMPTION:
It is assumed that this method is only called from a lazy attribute whose name coincides with the given name.
OUTPUT:
A dynamic class with bases given by the corresponding named classes of self‘s super_categories, and methods taken from the class getattr(self,method_provider).
Note
EXAMPLES:
sage: PC = Rings()._make_named_class("parent_class", "ParentMethods"); PC
<class 'sage.categories.rings.Rings.parent_class'>
sage: type(PC)
<class 'sage.structure.dynamic_class.DynamicMetaclass'>
sage: PC.__bases__
(<class 'sage.categories.rngs.Rngs.parent_class'>,
<class 'sage.categories.semirings.Semirings.parent_class'>)
Note that, by default, the result is not cached:
sage: PC is Rings()._make_named_class("parent_class", "ParentMethods")
False
Indeed this method is only meant to construct lazy attributes like parent_class which already handle this caching:
sage: Rings().parent_class
<class 'sage.categories.rings.Rings.parent_class'>
Reduction for pickling also assumes the existence of this lazy attribute:
sage: PC._reduction
(<built-in function getattr>, (Category of rings, 'parent_class'))
sage: loads(dumps(PC)) is Rings().parent_class
True
TESTS:
sage: class A: pass
sage: class BrokenCategory(Category):
....: def super_categories(self): return []
....: ParentMethods = 1
....: class ElementMethods(A):
....: pass
....: class MorphismMethods(object):
....: pass
sage: C = BrokenCategory()
sage: C._make_named_class("parent_class", "ParentMethods")
Traceback (most recent call last):
...
AssertionError: BrokenCategory.ParentMethods should be a class
sage: C._make_named_class("element_class", "ElementMethods")
doctest:...: UserWarning: BrokenCategory.ElementMethods should not have a super class
<class '__main__.BrokenCategory.element_class'>
sage: C._make_named_class("morphism_class", "MorphismMethods")
<class '__main__.BrokenCategory.morphism_class'>
Return the print representation of this category.
EXAMPLES:
sage: Sets() # indirect doctest
Category of sets
Return the name of the objects of this category.
EXAMPLES:
sage: FiniteGroups()._repr_object_names()
'finite groups'
sage: AlgebrasWithBasis(QQ)._repr_object_names()
'algebras with basis over Rational Field'
Run generic tests on this category
See also
EXAMPLES:
sage: Sets()._test_category()
Let us now write a couple broken categories:
sage: class MyObjects(Category):
....: pass
sage: MyObjects()._test_category()
Traceback (most recent call last):
...
NotImplementedError: <abstract method super_categories at ...>
sage: class MyObjects(Category):
....: def super_categories(self):
....: return tuple()
sage: MyObjects()._test_category()
Traceback (most recent call last):
...
AssertionError: Category of my objects.super_categories() should return a list
sage: class MyObjects(Category):
....: def super_categories(self):
....: return []
sage: MyObjects()._test_category()
Traceback (most recent call last):
...
AssertionError: Category of my objects is not a subcategory of Objects()
Return the subcategory of the objects of self satisfying the given axiom.
INPUT:
EXAMPLES:
sage: Sets()._with_axiom("Finite")
Category of finite sets
sage: type(Magmas().Finite().Commutative())
<class 'sage.categories.category.JoinCategory_with_category'>
sage: Magmas().Finite().Commutative().super_categories()
[Category of commutative magmas, Category of finite sets]
sage: Algebras(QQ).WithBasis().Commutative() is Algebras(QQ).Commutative().WithBasis()
True
When axiom is not defined for self, self is returned:
sage: Sets()._with_axiom("Associative")
Category of sets
Warning
This may be changed in the future to raising an error.
Return a tuple of categories whose join is self._with_axiom().
INPUT:
This is a lazy version of _with_axiom() which is used to avoid recursion loops during join calculations.
Note
The order in the result is irrelevant.
EXAMPLES:
sage: Sets()._with_axiom_as_tuple('Finite')
(Category of finite sets,)
sage: Magmas()._with_axiom_as_tuple('Finite')
(Category of magmas, Category of finite sets)
sage: Rings().Division()._with_axiom_as_tuple('Finite')
(Category of division rings,
Category of finite monoids,
Category of commutative magmas)
sage: HopfAlgebras(QQ)._with_axiom_as_tuple('FiniteDimensional')
(Category of hopf algebras over Rational Field,
Category of finite dimensional modules over Rational Field)
Return the category without the axioms that have been added to create it.
INPUT:
Todo
Improve this explanation.
If named is True, then this stops at the first category that has an explicit name of its own. See category_with_axiom.CategoryWithAxiom._without_axioms()
EXAMPLES:
sage: Sets()._without_axioms()
Category of sets
sage: Semigroups()._without_axioms()
Category of magmas
sage: Algebras(QQ).Commutative().WithBasis()._without_axioms()
Category of magmatic algebras over Rational Field
sage: Algebras(QQ).Commutative().WithBasis()._without_axioms(named=True)
Category of algebras over Rational Field
Return the categories after sorting them decreasingly according to their comparison key.
See also
_cmp_key()
INPUT:
OUTPUT:
A sorted tuple of categories, possibly with repeats.
Note
The auxiliary function \(_flatten_categories\) used in the test below expects a second argument, which is a type such that instances of that type will be replaced by its super categories. Usually, this type is JoinCategory.
EXAMPLES:
sage: Category._sort([Sets(), Objects(), Coalgebras(QQ), Monoids(), Sets().Finite()])
(Category of monoids,
Category of coalgebras over Rational Field,
Category of finite sets,
Category of sets,
Category of objects)
sage: Category._sort([Sets().Finite(), Semigroups().Finite(), Sets().Facade(),Magmas().Commutative()])
(Category of finite semigroups,
Category of commutative magmas,
Category of finite sets,
Category of facade sets)
sage: Category._sort(Category._flatten_categories([Sets().Finite(), Algebras(QQ).WithBasis(), Semigroups().Finite(), Sets().Facade(),Algebras(QQ).Commutative(), Algebras(QQ).Graded().WithBasis()], sage.categories.category.JoinCategory))
(Category of algebras with basis over Rational Field,
Category of algebras with basis over Rational Field,
Category of graded algebras over Rational Field,
Category of commutative algebras over Rational Field,
Category of finite semigroups,
Category of finite sets,
Category of facade sets)
Return the categories after sorting them and removing redundant categories.
Redundant categories include duplicates and categories which are super categories of other categories in the input.
INPUT:
OUTPUT: a sorted tuple of mutually incomparable categories
EXAMPLES:
sage: Category._sort_uniq([Rings(), Monoids(), Coalgebras(QQ)])
(Category of rings, Category of coalgebras over Rational Field)
Note that, in the above example, Monoids() does not appear in the result because it is a super category of Rings().
Input mangling for unique representation.
Let C = Cs(...) be a category. Since trac ticket #12895, the class of C is a dynamic subclass Cs_with_category of Cs in order for C to inherit code from the SubcategoryMethods nested classes of its super categories.
The purpose of this __classcall__ method is to ensure that reconstructing C from its class with Cs_with_category(...) actually calls properly Cs(...) and gives back C.
See also
EXAMPLES:
sage: A = Algebras(QQ)
sage: A.__class__
<class 'sage.categories.algebras.Algebras_with_category'>
sage: A is Algebras(QQ)
True
sage: A is A.__class__(QQ)
True
Initializes this category.
EXAMPLES:
sage: class SemiprimitiveRings(Category):
....: def super_categories(self):
....: return [Rings()]
....:
....: class ParentMethods:
....: def jacobson_radical(self):
....: return self.ideal(0)
....:
sage: C = SemiprimitiveRings()
sage: C
Category of semiprimitive rings
sage: C.__class__
<class '__main__.SemiprimitiveRings_with_category'>
Note
Specifying the name of this category by passing a string is deprecated. If the default name (built from the name of the class) is not adequate, please use _repr_object_names() to customize it.
Return the category of realizations of the parent self or of objects of the category self
INPUT:
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()
See also
Todo
Add an optional argument to allow for:
sage: Realizations(A, category = Blahs()) # todo: not implemented
Returns the category of parents in self endowed with multiple realizations
INPUT:
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.Facade) 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 additive unital additive magmas 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()
[Join of Category of hopf algebras over Rational Field
and Category of graded algebras over Rational Field]
sage: TestSuite(Semigroups().WithRealizations()).run()
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_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 commutative additive groups, ...
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 commutative additive groups, ...
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
Return 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
Return the axioms known to be satisfied by all the objects of self.
Technically, this is the set of all the axioms A such that, if Cs is the category defining A, then self is a subcategory of Cs().A(). Any additional axiom A would yield a strict subcategory of self, at the very least self & Cs().A() where Cs is the category defining A.
EXAMPLES:
sage: Monoids().axioms()
frozenset(['Associative', 'Unital'])
sage: (EnumeratedSets().Infinite() & Sets().Facade()).axioms()
frozenset(['Infinite', 'Facade'])
Return 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
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
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
Returns an object in this category. Most of the time, this is a parent.
This serves three purposes:
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
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
Returns whether this category is abelian.
An abelian category is a category satisfying:
Equivalently, one can define an increasing sequence of conditions:
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
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
Return the join of the input categories in the lattice of categories.
At the level of objects and morphisms, this operation corresponds to intersection: the objects and morphisms of a join category are those that belong to all its super categories.
INPUT:
See also
__and__() for a shortcut
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 magmas,
Category of commutative additive monoids, ..., Category of additive magmas,
Category of sets, ...]
As a short hand, one can use:
sage: Groups() & CommutativeAdditiveMonoids()
Join of Category of groups and Category of commutative additive monoids
This is a commutative and associative operation:
sage: Groups() & Posets()
Join of Category of groups and Category of posets
sage: Posets() & Groups()
Join of Category of groups and Category of posets
sage: Groups() & (CommutativeAdditiveMonoids() & Posets())
Join of Category of groups
and Category of commutative additive monoids
and Category of posets
sage: (Groups() & CommutativeAdditiveMonoids()) & Posets()
Join of Category of groups
and Category of commutative additive monoids
and Category of posets
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
In particular, the unit is the top category Objects:
sage: Groups() & Objects()
Category of groups
If the optional parameter as_list is True, this 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]
sage: Category.join((Modules(ZZ), FiniteFields()), as_list=True)
[Category of finite fields, Category of modules over Integer Ring]
sage: Category.join([], as_list=True)
[]
sage: Category.join([Groups()], as_list=True)
[Category of groups]
sage: Category.join([Groups() & Posets()], as_list=True)
[Category of groups, Category of posets]
Support for axiom categories (TODO: put here meaningfull examples):
sage: Sets().Facade() & Sets().Infinite()
Category of facade infinite sets
sage: Magmas().Infinite() & Sets().Facade()
Category of facade infinite magmas
sage: FiniteSets() & Monoids()
Category of finite monoids
sage: Rings().Commutative() & Sets().Finite()
Category of finite commutative rings
Note that several of the above examples are actually join categories; they are just nicely displayed:
sage: AlgebrasWithBasis(QQ) & FiniteSets().Algebras(QQ)
Join of Category of finite dimensional algebras with basis over Rational Field
and Category of finite set algebras over Rational Field
sage: UniqueFactorizationDomains() & Algebras(QQ)
Join of Category of unique factorization domains
and Category of commutative algebras over Rational Field
TESTS:
sage: Magmas().Unital().Commutative().Finite() is Magmas().Finite().Commutative().Unital()
True
sage: from sage.categories.category_with_axiom import TestObjects
sage: T = TestObjects()
sage: TCF = T.Commutative().Facade(); TCF
Category of facade commutative test objects
sage: TCF is T.Facade().Commutative()
True
sage: TCF is (T.Facade() & T.Commutative())
True
sage: TCF.axioms()
frozenset(['Facade', 'Commutative'])
sage: type(TCF)
<class 'sage.categories.category_with_axiom.TestObjects.Commutative.Facade_with_category'>
sage: TCF = T.Commutative().FiniteDimensional()
sage: TCF is T.FiniteDimensional().Commutative()
True
sage: TCF is T.Commutative() & T.FiniteDimensional()
True
sage: TCF is T.FiniteDimensional() & T.Commutative()
True
sage: type(TCF)
<class 'sage.categories.category_with_axiom.TestObjects.Commutative.FiniteDimensional_with_category'>
sage: TCU = T.Commutative().Unital()
sage: TCU is T.Unital().Commutative()
True
sage: TCU is T.Commutative() & T.Unital()
True
sage: TCU is T.Unital() & T.Commutative()
True
sage: TUCF = T.Unital().Commutative().FiniteDimensional(); TUCF
Category of finite dimensional commutative unital test objects
sage: type(TUCF)
<class 'sage.categories.category_with_axiom.TestObjects.FiniteDimensional.Unital.Commutative_with_category'>
sage: TFFC = T.Facade().FiniteDimensional().Commutative(); TFFC
Category of facade finite dimensional commutative test objects
sage: type(TFFC)
<class 'sage.categories.category.JoinCategory_with_category'>
sage: TFFC.super_categories()
[Category of facade commutative test objects,
Category of finite dimensional commutative test objects]
Returns the meet of a list of categories
INPUT:
See also
__or__() for a shortcut
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
Return category or self if category is None.
INPUT:
OUTPUT:
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((CommutativeAdditiveMonoids(), Groups()))
Join of Category of groups and Category of commutative additive monoids
If join is False, 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`
Otherwise, the two categories are joined together:
sage: Monoids().or_subcategory(EnumeratedSets(), join=True)
Join of Category of monoids and Category of enumerated sets
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.
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': ['algebra_generators']}, 'element': {'required': ['__nonzero__'], 'optional': ['_add_', '_mul_']}}
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.
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'>
Return the immediate super categories of self.
OUTPUT:
Every category should implement this method.
EXAMPLES:
sage: Groups().super_categories()
[Category of monoids, Category of inverse unital magmas]
sage: Objects().super_categories()
[]
Note
Since trac ticket #10963, the order of the categories in the result is irrelevant. For details, see On the order of super categories.
Note
Whenever speed matters, developers are advised to use the lazy attribute _super_categories() instead of calling this method.
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
Return the parent/element/... class of self.
INPUT:
ASSUMPTION:
It is assumed that this method is only called from a lazy attribute whose name coincides with the given name.
OUTPUT:
A dynamic class that has the corresponding named classes of the super categories of self as bases and contains the methods provided by getattr(self, method_provider).
Note
This method overrides Category._make_named_class() so that the returned class only depends on the corresponding named classes of the super categories and on the provided methods. This allows for sharing the named classes across closely related categories providing the same code to their parents, elements and so on.
EXAMPLES:
The categories of bimodules over the fields CC or RR provide the same methods to their parents and elements:
sage: Bimodules(ZZ,RR).parent_class is Bimodules(ZZ,RDF).parent_class #indirect doctest
True
sage: Bimodules(CC,ZZ).element_class is Bimodules(RR,ZZ).element_class
True
On the other hand, modules over a field have more methods than modules over a ring:
sage: Modules(GF(3)).parent_class is Modules(ZZ).parent_class
False
sage: Modules(GF(3)).element_class is Modules(ZZ).element_class
False
For a more subtle example, one could possibly share the classes for GF(3) and GF(2^3, 'x'), but this is not currently the case:
sage: Modules(GF(3)).parent_class is Modules(GF(2^3,'x')).parent_class
False
This is because those two fields do not have the exact same category:
sage: GF(3).category()
Join of Category of finite fields and Category of subquotients of monoids and Category of quotients of semigroups
sage: GF(2^3,'x').category()
Category of finite fields
Similarly for QQ and RR:
sage: QQ.category()
Category of quotient fields
sage: RR.category()
Category of fields
sage: Modules(QQ).parent_class is Modules(RR).parent_class
False
Some other cases where one could potentially share those classes:
sage: Modules(GF(3),dispatch=False).parent_class is Modules(ZZ).parent_class
False
sage: Modules(GF(3),dispatch=False).element_class is Modules(ZZ).element_class
False
TESTS:
sage: PC = Algebras(QQ).parent_class; PC # indirect doctest
<class 'sage.categories.algebras.Algebras.parent_class'>
sage: type(PC)
<class 'sage.structure.dynamic_class.DynamicMetaclass'>
sage: PC.__bases__
(<class 'sage.categories.rings.Rings.parent_class'>,
<class 'sage.categories.associative_algebras.AssociativeAlgebras.parent_class'>,
<class 'sage.categories.unital_algebras.UnitalAlgebras.parent_class'>)
sage: loads(dumps(PC)) is PC
True
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!!!)
If this hom-category is subcategory of a category with a base, return that base.
EXAMPLES:
sage: ModulesWithBasis(ZZ).hom_category().base()
Integer Ring
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()
[]
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]
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 magmas,
Category of commutative additive monoids, ..., 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 group algebras belong to a join category and since the underlying implementation is the same for all finite fields, we have:
sage: G = SymmetricGroup(10)
sage: A3 = G.algebra(GF(3))
sage: A5 = G.algebra(GF(5))
sage: type(A3.category())
<class 'sage.categories.category.JoinCategory_with_category'>
sage: type(A3) is type(A5)
True
Return the name of the objects of this category.
EXAMPLES:
sage: Groups().Finite().Commutative()._repr_(as_join=True)
'Join of Category of finite groups and Category of commutative groups'
sage: Groups().Finite().Commutative()._repr_object_names()
'finite commutative groups'
This uses _without_axioms() which may fail if this category is not obtained by adjoining axioms to some super categories:
sage: Category.join((Groups(), CommutativeAdditiveMonoids()))._repr_object_names()
Traceback (most recent call last):
...
ValueError: This join category isn't built by adding axioms to a single category
Print representation.
INPUT:
EXAMPLES:
sage: Category.join((Groups(), CommutativeAdditiveMonoids())) #indirect doctest
Join of Category of groups and Category of commutative additive monoids
By default, when a join category is built from category by adjoining axioms, a nice name is printed out:
sage: Groups().Facade().Finite()
Category of facade finite groups
But this is in fact really a join category:
sage: Groups().Facade().Finite()._repr_(as_join = True)
'Join of Category of finite groups and Category of facade sets'
The rationale is to make it more readable, and hide the technical details of how this category is constructed internally, especially since this construction is likely to change over time when new axiom categories are implemented.
This join category may possibly be obtained by adding axioms to different categories; so the result is not guaranteed to be unique; when this is not the case the first found is used.
See also
TESTS:
sage: Category.join((Sets().Facade(), Groups()))
Category of facade groups
When adjoining axioms to a category, one often gets a join category; this method tries to recover the original category from this join category.
INPUT:
See Category._without_axioms() for the description of the named parameter.
EXAMPLES:
sage: C = Category.join([Monoids(), Posets()]).Finite()
sage: C._repr_(as_join=True)
'Join of Category of finite monoids and Category of finite posets'
sage: C._without_axioms()
Traceback (most recent call last):
...
ValueError: This join category isn't built by adding axioms to a single category
sage: C = Monoids().Infinite()
sage: C._repr_(as_join=True)
'Join of Category of monoids and Category of infinite sets'
sage: C._without_axioms()
Category of magmas
sage: C._without_axioms(named=True)
Category of monoids
TESTS:
C is in fact a join category:
sage: from sage.categories.category import JoinCategory
sage: isinstance(C, JoinCategory)
True
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
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]
Return the graph of the categories in Sage.
INPUT:
If categories is specified, then the graph contains the mentioned categories together with all their super categories. Otherwise the graph contains (an instance of) each category in sage.categories.all (e.g. Algebras(QQ) for algebras).
For readability, the names of the category are shortened.
Todo
Further remove the base ring (see also trac ticket #15801).
EXAMPLES:
sage: G = sage.categories.category.category_graph(categories = [Groups()])
sage: G.vertices()
['groups', 'inverse unital magmas', 'magmas', 'monoids', 'objects',
'semigroups', 'sets', 'sets with partial maps', 'unital magmas']
sage: G.plot()
sage: sage.categories.category.category_graph().plot()
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,...
Returns True if x is a category.
EXAMPLES:
sage: sage.categories.category.is_Category(CommutativeAdditiveSemigroups())
True
sage: sage.categories.category.is_Category(ZZ)
False