@@ -943,6 +943,22 @@ def all_super_categories(self, proper=False):
943943 appropriate. Simply because lazy attributes are much
944944 faster than any method.
945945
946+ .. NOTE::
947+
948+ This is not the same as the concept of super category in mathematics.
949+ In fact, this is not even the opposite relation of :meth:`is_subcategory`::
950+
951+ sage: A = VectorSpaces(QQ); A
952+ Category of vector spaces over Rational Field
953+ sage: B = VectorSpaces(QQ.category()); B
954+ Category of vector spaces over (number fields and quotient fields and metric spaces)
955+ sage: A.is_subcategory(B)
956+ True
957+ sage: B in A.all_super_categories()
958+ False
959+
960+ .. SEEALSO:: :meth:`_test_category_graph`
961+
946962 EXAMPLES::
947963
948964 sage: C = Rings(); C
@@ -1379,7 +1395,16 @@ def _test_category_graph(self, **options):
13791395 method resolution order of the parent and element
13801396 classes. This method checks this.
13811397
1382- .. TODO:: currently, this won't work for hom categories.
1398+ Note that if
1399+ :meth:`~sage.structure.category_object.CategoryObject._refine_category_`
1400+ is called at unexpected times, the invariant might be false. Most
1401+ commonly, this happens with rings like ``Zmod(n)`` or ``SR``, where
1402+ a check like ``Zmod(n) in Fields()`` is needed (which checks the primality
1403+ of `n`) to refine their category to be a subcategory of fields.
1404+
1405+ .. SEEALSO::
1406+
1407+ :meth:`CategoryWithParameters._make_named_class_key`
13831408
13841409 EXAMPLES::
13851410
@@ -1615,6 +1640,11 @@ def subcategory_class(self):
16151640 sage: isinstance(AlgebrasWithBasis(QQ), cls)
16161641 True
16171642
1643+ .. NOTE::
1644+
1645+ See the note about :meth:`_test_category_graph` regarding Python
1646+ class hierarchy.
1647+
16181648 TESTS::
16191649
16201650 sage: cls = Algebras(QQ).subcategory_class; cls
@@ -1667,6 +1697,11 @@ def parent_class(self):
16671697 :class:`~sage.categories.bimodules.Bimodules`,
16681698 :class:`~sage.categories.category_types.Category_over_base` and
16691699 :class:`sage.categories.category.JoinCategory`.
1700+
1701+ .. NOTE::
1702+
1703+ See the note about :meth:`_test_category_graph` regarding Python
1704+ class hierarchy.
16701705 """
16711706 return self ._make_named_class ('parent_class' , 'ParentMethods' )
16721707
@@ -1713,6 +1748,11 @@ def element_class(self):
17131748 0
17141749
17151750 .. SEEALSO:: :meth:`parent_class`
1751+
1752+ .. NOTE::
1753+
1754+ See the note about :meth:`_test_category_graph` regarding Python
1755+ class hierarchy.
17161756 """
17171757 return self ._make_named_class ('element_class' , 'ElementMethods' )
17181758
@@ -1757,7 +1797,7 @@ def required_methods(self):
17571797 # Operations on the lattice of categories
17581798 def is_subcategory (self , c ):
17591799 """
1760- Return ``True`` if ``self`` is naturally embedded as a subcategory of `c`.
1800+ Return ``True`` if there is a natural forgetful functor from ``self`` to `c`.
17611801
17621802 EXAMPLES::
17631803
@@ -2046,13 +2086,18 @@ def _with_axiom(self, axiom):
20462086 Return the subcategory of the objects of ``self`` satisfying
20472087 the given ``axiom``.
20482088
2089+ Note that this is a private method thus should not be directly
2090+ used, see below.
2091+
20492092 INPUT:
20502093
20512094 - ``axiom`` -- string, the name of an axiom
20522095
20532096 EXAMPLES::
20542097
2055- sage: Sets()._with_axiom("Finite")
2098+ sage: Sets()._with_axiom("Finite") # not idiomatic
2099+ Category of finite sets
2100+ sage: Sets().Finite() # recommended
20562101 Category of finite sets
20572102
20582103 sage: type(Magmas().Finite().Commutative())
@@ -2068,7 +2113,7 @@ def _with_axiom(self, axiom):
20682113 sage: Sets()._with_axiom("Associative")
20692114 Category of sets
20702115
2071- .. WARNING:: This may be changed in the future to raising an error.
2116+ .. WARNING:: This may be changed in the future to raise an error.
20722117 """
20732118 return Category .join (self ._with_axiom_as_tuple (axiom ))
20742119
@@ -2718,6 +2763,10 @@ def _make_named_class(self, name, method_provider, cache=False, **options):
27182763
27192764 It is assumed that this method is only called from a lazy
27202765 attribute whose name coincides with the given ``name``.
2766+ Currently, this means :meth:`Category.subcategory_class`,
2767+ :meth:`Category.parent_class` or :meth:`element_class`.
2768+
2769+ Subclasses need to implement :meth:`_make_named_class_key`.
27212770
27222771 OUTPUT:
27232772
@@ -2810,6 +2859,10 @@ def _make_named_class(self, name, method_provider, cache=False, **options):
28102859 pass
28112860 result = Category ._make_named_class (self , name , method_provider ,
28122861 cache = cache , ** options )
2862+ if key [2 ] != self ._make_named_class_key (name ):
2863+ # the object in the parameter may have had its category refined, which might modify the key
2864+ # throw result away and recompute
2865+ return self ._make_named_class (name , method_provider , cache = cache , ** options )
28132866 self ._make_named_class_cache [key ] = result
28142867 return result
28152868
@@ -2818,6 +2871,50 @@ def _make_named_class_key(self, name):
28182871 r"""
28192872 Return what the element/parent/... class depend on.
28202873
2874+ This method starts as an optimization to allow different related
2875+ categories to share the Python types, see :issue:`11935`.
2876+ However, because of the guarantees stated in :meth:`Category._test_category_graph`,
2877+ the following rules must be followed::
2878+
2879+ - If two categories have different lists of supercategories, they must return
2880+ different keys::
2881+
2882+ sage: Zmod(5) in Fields()
2883+ True
2884+ sage: Algebras(Zmod(5)).all_super_categories()
2885+ [..., Category of vector spaces over Ring of integers modulo 5, ...]
2886+ sage: Zmod(6) in Fields()
2887+ False
2888+ sage: Algebras(Zmod(6)).all_super_categories() # of course don't have category of vector spaces
2889+ [..., Category of modules over Ring of integers modulo 6, ...]
2890+ sage: # therefore:
2891+ sage: Algebras(Zmod(5))._make_named_class_key("parent_class") != Algebras(Zmod(6))._make_named_class_key("parent_class")
2892+ True
2893+ sage: Algebras(Zmod(5)).parent_class != Algebras(Zmod(6)).parent_class
2894+ True
2895+
2896+ - If category ``A`` is a supercategory of category ``B``,
2897+ and category ``B`` uses the optimization, then so must ``A``.
2898+
2899+ For example, ``Modules(ZZ)`` is a supercategory of ``Algebras(ZZ)``,
2900+ and ``Algebras(ZZ)`` implements the optimization::
2901+
2902+ sage: from sage.categories.category import CategoryWithParameters
2903+ sage: isinstance(Algebras(ZZ), CategoryWithParameters)
2904+ True
2905+ sage: Algebras(ZZ).parent_class is Algebras(ZZ.category()).parent_class
2906+ True
2907+ sage: Modules(ZZ) in Algebras(ZZ).all_super_categories()
2908+ True
2909+
2910+ This forces ``Modules(ZZ)`` to also implement the optimization::
2911+
2912+ sage: Modules(ZZ).parent_class is Modules(ZZ.category()).parent_class
2913+ True
2914+
2915+ As a complication, computing the exact category might require some potentially
2916+ expensive test. See :meth:`Category._test_category_graph` for more details.
2917+
28212918 INPUT:
28222919
28232920 - ``name`` -- string; the name of the class as an attribute
@@ -2826,6 +2923,9 @@ def _make_named_class_key(self, name):
28262923 .. SEEALSO::
28272924
28282925 - :meth:`_make_named_class`
2926+
2927+ The following can be read for typical implementations of this method.
2928+
28292929 - :meth:`sage.categories.category_types.Category_over_base._make_named_class_key`
28302930 - :meth:`sage.categories.bimodules.Bimodules._make_named_class_key`
28312931 - :meth:`JoinCategory._make_named_class_key`
@@ -3064,6 +3164,9 @@ def _with_axiom(self, axiom):
30643164 """
30653165 Return the category obtained by adding an axiom to ``self``.
30663166
3167+ As mentioned in :meth:`Category._with_axiom`, this method should not be used directly
3168+ except in internal code.
3169+
30673170 .. NOTE::
30683171
30693172 This is just an optimization of
@@ -3073,7 +3176,9 @@ def _with_axiom(self, axiom):
30733176 EXAMPLES::
30743177
30753178 sage: C = Category.join([Monoids(), Posets()])
3076- sage: C._with_axioms(["Finite"])
3179+ sage: C._with_axioms(["Finite"]) # not idiomatic
3180+ Join of Category of finite monoids and Category of finite posets
3181+ sage: C.Finite() # recommended
30773182 Join of Category of finite monoids and Category of finite posets
30783183
30793184 TESTS:
0 commit comments