passagemath-objects 10.6.41__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. passagemath_objects/__init__.py +3 -0
  2. passagemath_objects-10.6.41.dist-info/DELVEWHEEL +2 -0
  3. passagemath_objects-10.6.41.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.41.dist-info/RECORD +281 -0
  5. passagemath_objects-10.6.41.dist-info/WHEEL +5 -0
  6. passagemath_objects-10.6.41.dist-info/top_level.txt +3 -0
  7. passagemath_objects.libs/libgmp-10-79b4110c7ea2b760f16cfef97e8a8a34.dll +0 -0
  8. sage/all__sagemath_objects.py +46 -0
  9. sage/arith/all__sagemath_objects.py +5 -0
  10. sage/arith/long.pxd +411 -0
  11. sage/arith/numerical_approx.cp312-win_amd64.pyd +0 -0
  12. sage/arith/numerical_approx.pxd +35 -0
  13. sage/arith/numerical_approx.pyx +75 -0
  14. sage/arith/power.cp312-win_amd64.pyd +0 -0
  15. sage/arith/power.pxd +31 -0
  16. sage/arith/power.pyx +127 -0
  17. sage/categories/action.cp312-win_amd64.pyd +0 -0
  18. sage/categories/action.pxd +29 -0
  19. sage/categories/action.pyx +641 -0
  20. sage/categories/algebra_functor.py +745 -0
  21. sage/categories/all__sagemath_objects.py +33 -0
  22. sage/categories/basic.py +71 -0
  23. sage/categories/cartesian_product.py +295 -0
  24. sage/categories/category.py +3401 -0
  25. sage/categories/category_cy_helper.cp312-win_amd64.pyd +0 -0
  26. sage/categories/category_cy_helper.pxd +8 -0
  27. sage/categories/category_cy_helper.pyx +322 -0
  28. sage/categories/category_singleton.cp312-win_amd64.pyd +0 -0
  29. sage/categories/category_singleton.pxd +3 -0
  30. sage/categories/category_singleton.pyx +342 -0
  31. sage/categories/category_types.py +637 -0
  32. sage/categories/category_with_axiom.py +2885 -0
  33. sage/categories/covariant_functorial_construction.py +703 -0
  34. sage/categories/facade_sets.py +228 -0
  35. sage/categories/functor.cp312-win_amd64.pyd +0 -0
  36. sage/categories/functor.pxd +7 -0
  37. sage/categories/functor.pyx +691 -0
  38. sage/categories/homset.py +1338 -0
  39. sage/categories/homsets.py +364 -0
  40. sage/categories/isomorphic_objects.py +73 -0
  41. sage/categories/map.cp312-win_amd64.pyd +0 -0
  42. sage/categories/map.pxd +34 -0
  43. sage/categories/map.pyx +2112 -0
  44. sage/categories/morphism.cp312-win_amd64.pyd +0 -0
  45. sage/categories/morphism.pxd +14 -0
  46. sage/categories/morphism.pyx +895 -0
  47. sage/categories/objects.py +167 -0
  48. sage/categories/primer.py +1696 -0
  49. sage/categories/pushout.py +4834 -0
  50. sage/categories/quotients.py +64 -0
  51. sage/categories/realizations.py +200 -0
  52. sage/categories/sets_cat.py +3228 -0
  53. sage/categories/sets_with_partial_maps.py +52 -0
  54. sage/categories/subobjects.py +64 -0
  55. sage/categories/subquotients.py +21 -0
  56. sage/categories/with_realizations.py +311 -0
  57. sage/cpython/__init__.py +28 -0
  58. sage/cpython/_py2_random.py +619 -0
  59. sage/cpython/all.py +3 -0
  60. sage/cpython/atexit.cp312-win_amd64.pyd +0 -0
  61. sage/cpython/atexit.pyx +269 -0
  62. sage/cpython/builtin_types.cp312-win_amd64.pyd +0 -0
  63. sage/cpython/builtin_types.pyx +7 -0
  64. sage/cpython/cython_metaclass.cp312-win_amd64.pyd +0 -0
  65. sage/cpython/cython_metaclass.h +117 -0
  66. sage/cpython/cython_metaclass.pxd +3 -0
  67. sage/cpython/cython_metaclass.pyx +130 -0
  68. sage/cpython/debug.cp312-win_amd64.pyd +0 -0
  69. sage/cpython/debug.pyx +302 -0
  70. sage/cpython/dict_del_by_value.cp312-win_amd64.pyd +0 -0
  71. sage/cpython/dict_del_by_value.pxd +9 -0
  72. sage/cpython/dict_del_by_value.pyx +191 -0
  73. sage/cpython/dict_internal.h +245 -0
  74. sage/cpython/getattr.cp312-win_amd64.pyd +0 -0
  75. sage/cpython/getattr.pxd +9 -0
  76. sage/cpython/getattr.pyx +439 -0
  77. sage/cpython/pycore_long.h +97 -0
  78. sage/cpython/pycore_long.pxd +10 -0
  79. sage/cpython/python_debug.h +44 -0
  80. sage/cpython/python_debug.pxd +47 -0
  81. sage/cpython/pyx_visit.h +13 -0
  82. sage/cpython/string.cp312-win_amd64.pyd +0 -0
  83. sage/cpython/string.pxd +76 -0
  84. sage/cpython/string.pyx +34 -0
  85. sage/cpython/string_impl.h +60 -0
  86. sage/cpython/type.cp312-win_amd64.pyd +0 -0
  87. sage/cpython/type.pxd +2 -0
  88. sage/cpython/type.pyx +40 -0
  89. sage/cpython/wrapperdescr.pxd +67 -0
  90. sage/ext/all__sagemath_objects.py +3 -0
  91. sage/ext/ccobject.h +64 -0
  92. sage/ext/cplusplus.pxd +17 -0
  93. sage/ext/mod_int.h +30 -0
  94. sage/ext/mod_int.pxd +24 -0
  95. sage/ext/stdsage.pxd +39 -0
  96. sage/groups/all__sagemath_objects.py +1 -0
  97. sage/groups/group.cp312-win_amd64.pyd +0 -0
  98. sage/groups/group.pxd +14 -0
  99. sage/groups/group.pyx +322 -0
  100. sage/groups/old.cp312-win_amd64.pyd +0 -0
  101. sage/groups/old.pxd +14 -0
  102. sage/groups/old.pyx +219 -0
  103. sage/libs/all__sagemath_objects.py +3 -0
  104. sage/libs/gmp/__init__.py +1 -0
  105. sage/libs/gmp/all.pxd +6 -0
  106. sage/libs/gmp/binop.pxd +23 -0
  107. sage/libs/gmp/misc.pxd +8 -0
  108. sage/libs/gmp/mpf.pxd +88 -0
  109. sage/libs/gmp/mpn.pxd +57 -0
  110. sage/libs/gmp/mpq.pxd +57 -0
  111. sage/libs/gmp/mpz.pxd +202 -0
  112. sage/libs/gmp/pylong.cp312-win_amd64.pyd +0 -0
  113. sage/libs/gmp/pylong.pxd +12 -0
  114. sage/libs/gmp/pylong.pyx +150 -0
  115. sage/libs/gmp/random.pxd +25 -0
  116. sage/libs/gmp/randomize.pxd +59 -0
  117. sage/libs/gmp/types.pxd +53 -0
  118. sage/libs/gmpxx.pxd +19 -0
  119. sage/misc/abstract_method.py +276 -0
  120. sage/misc/all__sagemath_objects.py +43 -0
  121. sage/misc/bindable_class.py +253 -0
  122. sage/misc/c3_controlled.cp312-win_amd64.pyd +0 -0
  123. sage/misc/c3_controlled.pxd +2 -0
  124. sage/misc/c3_controlled.pyx +1402 -0
  125. sage/misc/cachefunc.cp312-win_amd64.pyd +0 -0
  126. sage/misc/cachefunc.pxd +43 -0
  127. sage/misc/cachefunc.pyx +3781 -0
  128. sage/misc/call.py +188 -0
  129. sage/misc/classcall_metaclass.cp312-win_amd64.pyd +0 -0
  130. sage/misc/classcall_metaclass.pxd +14 -0
  131. sage/misc/classcall_metaclass.pyx +599 -0
  132. sage/misc/constant_function.cp312-win_amd64.pyd +0 -0
  133. sage/misc/constant_function.pyx +130 -0
  134. sage/misc/decorators.py +747 -0
  135. sage/misc/fast_methods.cp312-win_amd64.pyd +0 -0
  136. sage/misc/fast_methods.pxd +20 -0
  137. sage/misc/fast_methods.pyx +351 -0
  138. sage/misc/flatten.py +90 -0
  139. sage/misc/fpickle.cp312-win_amd64.pyd +0 -0
  140. sage/misc/fpickle.pyx +177 -0
  141. sage/misc/function_mangling.cp312-win_amd64.pyd +0 -0
  142. sage/misc/function_mangling.pxd +11 -0
  143. sage/misc/function_mangling.pyx +308 -0
  144. sage/misc/inherit_comparison.cp312-win_amd64.pyd +0 -0
  145. sage/misc/inherit_comparison.pxd +5 -0
  146. sage/misc/inherit_comparison.pyx +105 -0
  147. sage/misc/instancedoc.cp312-win_amd64.pyd +0 -0
  148. sage/misc/instancedoc.pyx +331 -0
  149. sage/misc/lazy_attribute.cp312-win_amd64.pyd +0 -0
  150. sage/misc/lazy_attribute.pyx +607 -0
  151. sage/misc/lazy_format.py +135 -0
  152. sage/misc/lazy_import.cp312-win_amd64.pyd +0 -0
  153. sage/misc/lazy_import.pyx +1299 -0
  154. sage/misc/lazy_import_cache.py +36 -0
  155. sage/misc/lazy_list.cp312-win_amd64.pyd +0 -0
  156. sage/misc/lazy_list.pxd +19 -0
  157. sage/misc/lazy_list.pyx +1187 -0
  158. sage/misc/lazy_string.cp312-win_amd64.pyd +0 -0
  159. sage/misc/lazy_string.pxd +7 -0
  160. sage/misc/lazy_string.pyx +546 -0
  161. sage/misc/misc.py +1066 -0
  162. sage/misc/misc_c.cp312-win_amd64.pyd +0 -0
  163. sage/misc/misc_c.pxd +3 -0
  164. sage/misc/misc_c.pyx +766 -0
  165. sage/misc/namespace_package.py +37 -0
  166. sage/misc/nested_class.cp312-win_amd64.pyd +0 -0
  167. sage/misc/nested_class.pxd +3 -0
  168. sage/misc/nested_class.pyx +394 -0
  169. sage/misc/persist.cp312-win_amd64.pyd +0 -0
  170. sage/misc/persist.pyx +1251 -0
  171. sage/misc/prandom.py +418 -0
  172. sage/misc/randstate.cp312-win_amd64.pyd +0 -0
  173. sage/misc/randstate.pxd +30 -0
  174. sage/misc/randstate.pyx +1059 -0
  175. sage/misc/repr.py +203 -0
  176. sage/misc/reset.cp312-win_amd64.pyd +0 -0
  177. sage/misc/reset.pyx +196 -0
  178. sage/misc/sage_ostools.cp312-win_amd64.pyd +0 -0
  179. sage/misc/sage_ostools.pyx +323 -0
  180. sage/misc/sage_timeit.py +276 -0
  181. sage/misc/sage_timeit_class.cp312-win_amd64.pyd +0 -0
  182. sage/misc/sage_timeit_class.pyx +120 -0
  183. sage/misc/sage_unittest.py +637 -0
  184. sage/misc/sageinspect.py +2768 -0
  185. sage/misc/session.cp312-win_amd64.pyd +0 -0
  186. sage/misc/session.pyx +392 -0
  187. sage/misc/superseded.py +557 -0
  188. sage/misc/test_nested_class.py +228 -0
  189. sage/misc/timing.py +264 -0
  190. sage/misc/unknown.py +222 -0
  191. sage/misc/verbose.py +253 -0
  192. sage/misc/weak_dict.cp312-win_amd64.pyd +0 -0
  193. sage/misc/weak_dict.pxd +15 -0
  194. sage/misc/weak_dict.pyx +1231 -0
  195. sage/modules/all__sagemath_objects.py +1 -0
  196. sage/modules/module.cp312-win_amd64.pyd +0 -0
  197. sage/modules/module.pxd +5 -0
  198. sage/modules/module.pyx +329 -0
  199. sage/rings/all__sagemath_objects.py +3 -0
  200. sage/rings/integer_fake.h +22 -0
  201. sage/rings/integer_fake.pxd +55 -0
  202. sage/sets/all__sagemath_objects.py +3 -0
  203. sage/sets/pythonclass.cp312-win_amd64.pyd +0 -0
  204. sage/sets/pythonclass.pxd +9 -0
  205. sage/sets/pythonclass.pyx +247 -0
  206. sage/structure/__init__.py +13 -0
  207. sage/structure/all.py +30 -0
  208. sage/structure/category_object.cp312-win_amd64.pyd +0 -0
  209. sage/structure/category_object.pxd +28 -0
  210. sage/structure/category_object.pyx +1087 -0
  211. sage/structure/coerce.cp312-win_amd64.pyd +0 -0
  212. sage/structure/coerce.pxd +44 -0
  213. sage/structure/coerce.pyx +2107 -0
  214. sage/structure/coerce_actions.cp312-win_amd64.pyd +0 -0
  215. sage/structure/coerce_actions.pxd +27 -0
  216. sage/structure/coerce_actions.pyx +988 -0
  217. sage/structure/coerce_dict.cp312-win_amd64.pyd +0 -0
  218. sage/structure/coerce_dict.pxd +51 -0
  219. sage/structure/coerce_dict.pyx +1557 -0
  220. sage/structure/coerce_exceptions.py +23 -0
  221. sage/structure/coerce_maps.cp312-win_amd64.pyd +0 -0
  222. sage/structure/coerce_maps.pxd +28 -0
  223. sage/structure/coerce_maps.pyx +718 -0
  224. sage/structure/debug_options.cp312-win_amd64.pyd +0 -0
  225. sage/structure/debug_options.pxd +6 -0
  226. sage/structure/debug_options.pyx +54 -0
  227. sage/structure/dynamic_class.py +541 -0
  228. sage/structure/element.cp312-win_amd64.pyd +0 -0
  229. sage/structure/element.pxd +272 -0
  230. sage/structure/element.pyx +4772 -0
  231. sage/structure/element_wrapper.cp312-win_amd64.pyd +0 -0
  232. sage/structure/element_wrapper.pxd +12 -0
  233. sage/structure/element_wrapper.pyx +582 -0
  234. sage/structure/factorization.py +1422 -0
  235. sage/structure/factorization_integer.py +105 -0
  236. sage/structure/factory.cp312-win_amd64.pyd +0 -0
  237. sage/structure/factory.pyx +786 -0
  238. sage/structure/formal_sum.py +489 -0
  239. sage/structure/gens_py.py +73 -0
  240. sage/structure/global_options.py +1743 -0
  241. sage/structure/indexed_generators.py +863 -0
  242. sage/structure/list_clone.cp312-win_amd64.pyd +0 -0
  243. sage/structure/list_clone.pxd +65 -0
  244. sage/structure/list_clone.pyx +1867 -0
  245. sage/structure/list_clone_demo.cp312-win_amd64.pyd +0 -0
  246. sage/structure/list_clone_demo.pyx +248 -0
  247. sage/structure/list_clone_timings.py +179 -0
  248. sage/structure/list_clone_timings_cy.cp312-win_amd64.pyd +0 -0
  249. sage/structure/list_clone_timings_cy.pyx +86 -0
  250. sage/structure/mutability.cp312-win_amd64.pyd +0 -0
  251. sage/structure/mutability.pxd +21 -0
  252. sage/structure/mutability.pyx +348 -0
  253. sage/structure/nonexact.py +69 -0
  254. sage/structure/parent.cp312-win_amd64.pyd +0 -0
  255. sage/structure/parent.pxd +112 -0
  256. sage/structure/parent.pyx +3093 -0
  257. sage/structure/parent_base.cp312-win_amd64.pyd +0 -0
  258. sage/structure/parent_base.pxd +13 -0
  259. sage/structure/parent_base.pyx +44 -0
  260. sage/structure/parent_gens.cp312-win_amd64.pyd +0 -0
  261. sage/structure/parent_gens.pxd +22 -0
  262. sage/structure/parent_gens.pyx +377 -0
  263. sage/structure/parent_old.cp312-win_amd64.pyd +0 -0
  264. sage/structure/parent_old.pxd +25 -0
  265. sage/structure/parent_old.pyx +294 -0
  266. sage/structure/proof/__init__.py +1 -0
  267. sage/structure/proof/all.py +243 -0
  268. sage/structure/proof/proof.py +300 -0
  269. sage/structure/richcmp.cp312-win_amd64.pyd +0 -0
  270. sage/structure/richcmp.pxd +213 -0
  271. sage/structure/richcmp.pyx +495 -0
  272. sage/structure/sage_object.cp312-win_amd64.pyd +0 -0
  273. sage/structure/sage_object.pxd +3 -0
  274. sage/structure/sage_object.pyx +988 -0
  275. sage/structure/sage_object_test.py +19 -0
  276. sage/structure/sequence.py +937 -0
  277. sage/structure/set_factories.py +1178 -0
  278. sage/structure/set_factories_example.py +527 -0
  279. sage/structure/support_view.py +179 -0
  280. sage/structure/test_factory.py +56 -0
  281. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,3401 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Categories
4
+
5
+ AUTHORS:
6
+
7
+ - David Kohel, William Stein and Nicolas M. Thiery
8
+
9
+ Every Sage object lies in a category. Categories in Sage are
10
+ modeled on the mathematical idea of category, and are distinct from
11
+ Python classes, which are a programming construct.
12
+
13
+ In most cases, typing ``x.category()`` returns the category to which ``x``
14
+ belongs. If ``C`` is a category and ``x`` is any object, ``C(x)`` tries to
15
+ make an object in ``C`` from ``x``. Checking if ``x`` belongs to ``C`` is done
16
+ as usually by ``x in C``.
17
+
18
+ See :class:`Category` and :mod:`sage.categories.primer` for more details.
19
+
20
+ EXAMPLES:
21
+
22
+ We create a couple of categories::
23
+
24
+ sage: Sets()
25
+ Category of sets
26
+ sage: GSets(AbelianGroup([2, 4, 9])) # needs sage.groups sage.modules
27
+ Category of G-sets for Multiplicative Abelian group isomorphic to C2 x C4 x C9
28
+ sage: Semigroups()
29
+ Category of semigroups
30
+ sage: VectorSpaces(FiniteField(11))
31
+ Category of vector spaces over Finite Field of size 11
32
+ sage: Ideals(IntegerRing())
33
+ Category of ring ideals in Integer Ring
34
+
35
+ Let's request the category of some objects::
36
+
37
+ sage: V = VectorSpace(RationalField(), 3) # needs sage.modules
38
+ sage: V.category() # needs sage.modules
39
+ Category of finite dimensional vector spaces with basis
40
+ over (number fields and quotient fields and metric spaces)
41
+
42
+ sage: G = SymmetricGroup(9) # needs sage.groups
43
+ sage: G.category() # needs sage.groups
44
+ Join of
45
+ Category of finite enumerated permutation groups and
46
+ Category of finite Weyl groups and
47
+ Category of well generated finite irreducible complex reflection groups
48
+
49
+ sage: P = PerfectMatchings(3) # needs sage.combinat
50
+ sage: P.category() # needs sage.combinat
51
+ Category of finite enumerated sets
52
+
53
+ Let's check some memberships::
54
+
55
+ sage: V in VectorSpaces(QQ) # needs sage.modules
56
+ True
57
+ sage: V in VectorSpaces(FiniteField(11)) # needs sage.modules
58
+ False
59
+ sage: G in Monoids() # needs sage.groups
60
+ True
61
+ sage: P in Rings() # needs sage.combinat
62
+ False
63
+
64
+ For parametrized categories one can use the following shorthand::
65
+
66
+ sage: V in VectorSpaces # needs sage.modules
67
+ True
68
+ sage: G in VectorSpaces # needs sage.groups
69
+ False
70
+
71
+ A parent ``P`` is in a category ``C`` if ``P.category()`` is a subcategory of
72
+ ``C``.
73
+
74
+ .. NOTE::
75
+
76
+ Any object of a category should be an instance of
77
+ :class:`~sage.structure.category_object.CategoryObject`.
78
+
79
+ For backward compatibility this is not yet enforced::
80
+
81
+ sage: class A:
82
+ ....: def category(self):
83
+ ....: return Fields()
84
+ sage: A() in Rings()
85
+ True
86
+
87
+ By default, the category of an element `x` of a parent `P` is the category
88
+ of all objects of `P` (this is dubious and may be deprecated)::
89
+
90
+ sage: V = VectorSpace(RationalField(), 3) # needs sage.modules
91
+ sage: v = V.gen(1) # needs sage.modules
92
+ sage: v.category() # needs sage.modules
93
+ Category of elements of Vector space of dimension 3 over Rational Field
94
+ """
95
+
96
+ # ****************************************************************************
97
+ # Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu> and
98
+ # William Stein <wstein@math.ucsd.edu>
99
+ # 2008-2014 Nicolas M. Thiery <nthiery at users.sf.net>
100
+ #
101
+ # Distributed under the terms of the GNU General Public License (GPL)
102
+ # https://www.gnu.org/licenses/
103
+ # ****************************************************************************
104
+
105
+ import inspect
106
+ try:
107
+ from typing import Self # type: ignore (Python >= 3.11)
108
+ except ImportError:
109
+ from typing_extensions import Self # type: ignore (Python 3.10)
110
+ from warnings import warn
111
+
112
+ from sage.categories.category_cy_helper import (
113
+ _flatten_categories,
114
+ _sort_uniq,
115
+ category_sort_key,
116
+ join_as_tuple,
117
+ )
118
+ from sage.misc.abstract_method import abstract_method, abstract_methods_of_class
119
+ from sage.misc.c3_controlled import C3_sorted_merge, _cmp_key, _cmp_key_named
120
+ from sage.misc.cachefunc import cached_function, cached_method
121
+ from sage.misc.lazy_attribute import lazy_attribute
122
+ from sage.misc.unknown import Unknown
123
+ from sage.misc.weak_dict import WeakValueDictionary
124
+ from sage.structure.dynamic_class import DynamicMetaclass, dynamic_class
125
+ from sage.structure.sage_object import SageObject
126
+ from sage.structure.unique_representation import UniqueRepresentation
127
+
128
+ _join_cache = WeakValueDictionary()
129
+
130
+
131
+ HALL_OF_FAME = ['Coxeter', 'Hopf', 'Weyl', 'Lie', 'Hecke', 'Dedekind']
132
+
133
+
134
+ class Category(UniqueRepresentation, SageObject):
135
+ r"""
136
+ The base class for modeling mathematical categories, like for example:
137
+
138
+ - ``Groups()`` -- the category of groups
139
+ - ``EuclideanDomains()`` -- the category of euclidean rings
140
+ - ``VectorSpaces(QQ)`` -- the category of vector spaces over the field of
141
+ rationals
142
+
143
+ See :mod:`sage.categories.primer` for an introduction to
144
+ categories in Sage, their relevance, purpose, and usage. The
145
+ documentation below will focus on their implementation.
146
+
147
+ Technically, a category is an instance of the class
148
+ :class:`Category` or some of its subclasses. Some categories, like
149
+ :class:`VectorSpaces`, are parametrized: ``VectorSpaces(QQ)`` is one of
150
+ many instances of the class :class:`VectorSpaces`. On the other
151
+ hand, ``EuclideanDomains()`` is the single instance of the class
152
+ :class:`EuclideanDomains`.
153
+
154
+ Recall that an algebraic structure (say, the ring `\QQ[x]`) is
155
+ modelled in Sage by an object which is called a parent. This
156
+ object belongs to certain categories (here ``EuclideanDomains()`` and
157
+ ``Algebras()``). The elements of the ring are themselves objects.
158
+
159
+ The class of a category (say :class:`EuclideanDomains`) can define simultaneously:
160
+
161
+ - Operations on the category itself (what is its super categories?
162
+ its category of morphisms? its dual category?).
163
+ - Generic operations on parents in this category, like the ring `\QQ[x]`.
164
+ - Generic operations on elements of such parents (e. g., the
165
+ Euclidean algorithm for computing gcds).
166
+ - Generic operations on morphisms of this category.
167
+
168
+ This is achieved as follows::
169
+
170
+ sage: from sage.categories.category import Category
171
+ sage: class EuclideanDomains(Category):
172
+ ....: # operations on the category itself
173
+ ....: def super_categories(self):
174
+ ....: [Rings()]
175
+ ....:
176
+ ....: def dummy(self): # TODO: find some good examples
177
+ ....: pass
178
+ ....:
179
+ ....: class ParentMethods: # holds the generic operations on parents
180
+ ....: # TODO: find a good example of an operation
181
+ ....: pass
182
+ ....:
183
+ ....: class ElementMethods:# holds the generic operations on elements
184
+ ....: def gcd(x, y):
185
+ ....: # Euclid algorithms
186
+ ....: pass
187
+ ....:
188
+ ....: class MorphismMethods: # holds the generic operations on morphisms
189
+ ....: # TODO: find a good example of an operation
190
+ ....: pass
191
+ ....:
192
+
193
+ Note that the nested class ``ParentMethods`` is merely a container
194
+ of operations, and does not inherit from anything. Instead, the
195
+ hierarchy relation is defined once at the level of the categories,
196
+ and the actual hierarchy of classes is built in parallel from all
197
+ the ``ParentMethods`` nested classes, and stored in the attributes
198
+ ``parent_class``. Then, a parent in a category ``C`` receives the
199
+ appropriate operations from all the super categories by usual
200
+ class inheritance from ``C.parent_class``.
201
+
202
+ Similarly, two other hierarchies of classes, for elements and
203
+ morphisms respectively, are built from all the ``ElementMethods``
204
+ and ``MorphismMethods`` nested classes.
205
+
206
+ EXAMPLES:
207
+
208
+ We define a hierarchy of four categories ``As()``, ``Bs()``,
209
+ ``Cs()``, ``Ds()`` with a diamond inheritance. Think for example:
210
+
211
+ - ``As()`` -- the category of sets
212
+ - ``Bs()`` -- the category of additive groups
213
+ - ``Cs()`` -- the category of multiplicative monoids
214
+ - ``Ds()`` -- the category of rings
215
+
216
+ ::
217
+
218
+ sage: from sage.categories.category import Category
219
+ sage: from sage.misc.lazy_attribute import lazy_attribute
220
+ sage: class As (Category):
221
+ ....: def super_categories(self):
222
+ ....: return []
223
+ ....:
224
+ ....: class ParentMethods:
225
+ ....: def fA(self):
226
+ ....: return "A"
227
+ ....: f = fA
228
+
229
+ sage: class Bs (Category):
230
+ ....: def super_categories(self):
231
+ ....: return [As()]
232
+ ....:
233
+ ....: class ParentMethods:
234
+ ....: def fB(self):
235
+ ....: return "B"
236
+
237
+ sage: class Cs (Category):
238
+ ....: def super_categories(self):
239
+ ....: return [As()]
240
+ ....:
241
+ ....: class ParentMethods:
242
+ ....: def fC(self):
243
+ ....: return "C"
244
+ ....: f = fC
245
+
246
+ sage: class Ds (Category):
247
+ ....: def super_categories(self):
248
+ ....: return [Bs(),Cs()]
249
+ ....:
250
+ ....: class ParentMethods:
251
+ ....: def fD(self):
252
+ ....: return "D"
253
+
254
+ Categories should always have unique representation; by :issue:`12215`,
255
+ this means that it will be kept in cache, but only
256
+ if there is still some strong reference to it.
257
+
258
+ We check this before proceeding::
259
+
260
+ sage: import gc
261
+ sage: idAs = id(As())
262
+ sage: _ = gc.collect()
263
+ sage: n == id(As())
264
+ False
265
+ sage: a = As()
266
+ sage: id(As()) == id(As())
267
+ True
268
+ sage: As().parent_class == As().parent_class
269
+ True
270
+
271
+ We construct a parent in the category ``Ds()`` (that, is an instance
272
+ of ``Ds().parent_class``), and check that it has access to all the
273
+ methods provided by all the categories, with the appropriate
274
+ inheritance order::
275
+
276
+ sage: D = Ds().parent_class()
277
+ sage: [ D.fA(), D.fB(), D.fC(), D.fD() ]
278
+ ['A', 'B', 'C', 'D']
279
+ sage: D.f()
280
+ 'C'
281
+
282
+ ::
283
+
284
+ sage: C = Cs().parent_class()
285
+ sage: [ C.fA(), C.fC() ]
286
+ ['A', 'C']
287
+ sage: C.f()
288
+ 'C'
289
+
290
+ Here is the parallel hierarchy of classes which has been built
291
+ automatically, together with the method resolution order (``.mro()``)::
292
+
293
+ sage: As().parent_class
294
+ <class '__main__.As.parent_class'>
295
+ sage: As().parent_class.__bases__
296
+ (<... 'object'>,)
297
+ sage: As().parent_class.mro()
298
+ [<class '__main__.As.parent_class'>, <... 'object'>]
299
+
300
+ ::
301
+
302
+ sage: Bs().parent_class
303
+ <class '__main__.Bs.parent_class'>
304
+ sage: Bs().parent_class.__bases__
305
+ (<class '__main__.As.parent_class'>,)
306
+ sage: Bs().parent_class.mro()
307
+ [<class '__main__.Bs.parent_class'>, <class '__main__.As.parent_class'>, <... 'object'>]
308
+
309
+ ::
310
+
311
+ sage: Cs().parent_class
312
+ <class '__main__.Cs.parent_class'>
313
+ sage: Cs().parent_class.__bases__
314
+ (<class '__main__.As.parent_class'>,)
315
+ sage: Cs().parent_class.__mro__
316
+ (<class '__main__.Cs.parent_class'>, <class '__main__.As.parent_class'>, <... 'object'>)
317
+
318
+ ::
319
+
320
+ sage: Ds().parent_class
321
+ <class '__main__.Ds.parent_class'>
322
+ sage: Ds().parent_class.__bases__
323
+ (<class '__main__.Cs.parent_class'>, <class '__main__.Bs.parent_class'>)
324
+ sage: Ds().parent_class.mro()
325
+ [<class '__main__.Ds.parent_class'>, <class '__main__.Cs.parent_class'>,
326
+ <class '__main__.Bs.parent_class'>, <class '__main__.As.parent_class'>, <... 'object'>]
327
+
328
+ Note that two categories in the same class need not have the
329
+ same ``super_categories``. For example, ``Algebras(QQ)`` has
330
+ ``VectorSpaces(QQ)`` as super category, whereas ``Algebras(ZZ)``
331
+ only has ``Modules(ZZ)`` as super category. In particular, the
332
+ constructed parent class and element class will differ (inheriting,
333
+ or not, methods specific for vector spaces)::
334
+
335
+ sage: Algebras(QQ).parent_class is Algebras(ZZ).parent_class
336
+ False
337
+ sage: issubclass(Algebras(QQ).parent_class, VectorSpaces(QQ).parent_class)
338
+ True
339
+
340
+ On the other hand, identical hierarchies of classes are,
341
+ preferably, built only once (e.g. for categories over a base ring)::
342
+
343
+ sage: Algebras(GF(5)).parent_class is Algebras(GF(7)).parent_class
344
+ True
345
+ sage: F = FractionField(ZZ['t'])
346
+ sage: Coalgebras(F).parent_class is Coalgebras(FractionField(F['x'])).parent_class
347
+ True
348
+
349
+ We now construct a parent in the usual way::
350
+
351
+ sage: class myparent(Parent):
352
+ ....: def __init__(self):
353
+ ....: Parent.__init__(self, category=Ds())
354
+ ....: def g(self):
355
+ ....: return "myparent"
356
+ ....: class Element():
357
+ ....: pass
358
+ sage: D = myparent()
359
+ sage: D.__class__
360
+ <class '__main__.myparent_with_category'>
361
+ sage: D.__class__.__bases__
362
+ (<class '__main__.myparent'>, <class '__main__.Ds.parent_class'>)
363
+ sage: D.__class__.mro()
364
+ [<class '__main__.myparent_with_category'>,
365
+ <class '__main__.myparent'>,
366
+ <class 'sage.structure.parent.Parent'>,
367
+ <class 'sage.structure.category_object.CategoryObject'>,
368
+ <class 'sage.structure.sage_object.SageObject'>,
369
+ <class '__main__.Ds.parent_class'>,
370
+ <class '__main__.Cs.parent_class'>,
371
+ <class '__main__.Bs.parent_class'>,
372
+ <class '__main__.As.parent_class'>,
373
+ <... 'object'>]
374
+ sage: D.fA()
375
+ 'A'
376
+ sage: D.fB()
377
+ 'B'
378
+ sage: D.fC()
379
+ 'C'
380
+ sage: D.fD()
381
+ 'D'
382
+ sage: D.f()
383
+ 'C'
384
+ sage: D.g()
385
+ 'myparent'
386
+
387
+ ::
388
+
389
+ sage: D.element_class
390
+ <class '__main__.myparent_with_category.element_class'>
391
+ sage: D.element_class.mro()
392
+ [<class '__main__.myparent_with_category.element_class'>,
393
+ <class ...__main__....Element...>,
394
+ <class '__main__.Ds.element_class'>,
395
+ <class '__main__.Cs.element_class'>,
396
+ <class '__main__.Bs.element_class'>,
397
+ <class '__main__.As.element_class'>,
398
+ <... 'object'>]
399
+
400
+
401
+ TESTS::
402
+
403
+ sage: import __main__
404
+ sage: __main__.myparent = myparent
405
+ sage: __main__.As = As
406
+ sage: __main__.Bs = Bs
407
+ sage: __main__.Cs = Cs
408
+ sage: __main__.Ds = Ds
409
+ sage: loads(dumps(Ds)) is Ds
410
+ True
411
+ sage: loads(dumps(Ds())) is Ds()
412
+ True
413
+ sage: loads(dumps(Ds().element_class)) is Ds().element_class
414
+ True
415
+
416
+ .. automethod:: Category._super_categories
417
+ .. automethod:: Category._super_categories_for_classes
418
+ .. automethod:: Category._all_super_categories
419
+ .. automethod:: Category._all_super_categories_proper
420
+ .. automethod:: Category._set_of_super_categories
421
+ .. automethod:: Category._make_named_class
422
+ .. automethod:: Category._repr_
423
+ .. automethod:: Category._repr_object_names
424
+ .. automethod:: Category._test_category
425
+ .. automethod:: Category._with_axiom
426
+ .. automethod:: Category._with_axiom_as_tuple
427
+ .. automethod:: Category._without_axioms
428
+ .. automethod:: Category._sort
429
+ .. automethod:: Category._sort_uniq
430
+ .. automethod:: Category.__classcall__
431
+ .. automethod:: Category.__init__
432
+ """
433
+ @staticmethod
434
+ def __classcall__(cls, *args, **options):
435
+ """
436
+ Input mangling for unique representation.
437
+
438
+ Let ``C = Cs(...)`` be a category. Since :issue:`12895`, the
439
+ class of ``C`` is a dynamic subclass ``Cs_with_category`` of
440
+ ``Cs`` in order for ``C`` to inherit code from the
441
+ ``SubcategoryMethods`` nested classes of its super categories.
442
+
443
+ The purpose of this ``__classcall__`` method is to ensure that
444
+ reconstructing ``C`` from its class with
445
+ ``Cs_with_category(...)`` actually calls properly ``Cs(...)``
446
+ and gives back ``C``.
447
+
448
+ .. SEEALSO:: :meth:`subcategory_class`
449
+
450
+ EXAMPLES::
451
+
452
+ sage: A = Algebras(QQ)
453
+ sage: A.__class__
454
+ <class 'sage.categories.algebras.Algebras_with_category'>
455
+ sage: A is Algebras(QQ)
456
+ True
457
+ sage: A is A.__class__(QQ)
458
+ True
459
+ """
460
+ if isinstance(cls, DynamicMetaclass):
461
+ cls = cls.__base__
462
+ return super().__classcall__(cls, *args, **options)
463
+
464
+ def __init__(self):
465
+ """
466
+ Initialize this category.
467
+
468
+ EXAMPLES::
469
+
470
+ sage: class SemiprimitiveRings(Category):
471
+ ....: def super_categories(self):
472
+ ....: return [Rings()]
473
+ ....: class ParentMethods:
474
+ ....: def jacobson_radical(self):
475
+ ....: return self.ideal(0)
476
+ sage: C = SemiprimitiveRings()
477
+ sage: C
478
+ Category of semiprimitive rings
479
+ sage: C.__class__
480
+ <class '__main__.SemiprimitiveRings_with_category'>
481
+
482
+ .. NOTE::
483
+
484
+ If the default name of the category (built from the name of
485
+ the class) is not adequate, please implement
486
+ :meth:`_repr_object_names` to customize it.
487
+ """
488
+ self.__class__ = dynamic_class("{}_with_category".format(self.__class__.__name__),
489
+ (self.__class__, self.subcategory_class, ),
490
+ cache=False, reduction=None,
491
+ doccls=self.__class__)
492
+
493
+ @lazy_attribute
494
+ def _label(self):
495
+ """
496
+ A short name of ``self``, obtained from its type.
497
+
498
+ EXAMPLES::
499
+
500
+ sage: Rings()._label
501
+ 'Rings'
502
+ """
503
+ t = str(self.__class__.__base__)
504
+ t = t[t.rfind('.') + 1:]
505
+ return t[:t.rfind("'")]
506
+
507
+ def _repr_object_names(self):
508
+ """
509
+ Return the name of the objects of this category.
510
+
511
+ EXAMPLES::
512
+
513
+ sage: FiniteGroups()._repr_object_names()
514
+ 'finite groups'
515
+ sage: AlgebrasWithBasis(QQ)._repr_object_names()
516
+ 'algebras with basis over Rational Field'
517
+
518
+ TESTS::
519
+
520
+ sage: Rings()
521
+ Category of rings
522
+ sage: Rings()._repr_object_names()
523
+ 'rings'
524
+ sage: PrincipalIdealDomains()._repr_object_names()
525
+ 'principal ideal domains'
526
+ """
527
+ words = "".join(letter if not letter.isupper() else ";" + letter
528
+ for letter in self._label).split(";")
529
+ return " ".join(w if w in HALL_OF_FAME else w.lower()
530
+ for w in words).lstrip()
531
+
532
+ def _short_name(self):
533
+ """
534
+ Return a CamelCase name for this category.
535
+
536
+ EXAMPLES::
537
+
538
+ sage: CoxeterGroups()._short_name()
539
+ 'CoxeterGroups'
540
+
541
+ sage: AlgebrasWithBasis(QQ)._short_name()
542
+ 'AlgebrasWithBasis'
543
+
544
+ Conventions for short names should be discussed at the level
545
+ of Sage, and only then applied accordingly here.
546
+ """
547
+ return self._label
548
+
549
+ @classmethod
550
+ def an_instance(cls):
551
+ """
552
+ Return an instance of this class.
553
+
554
+ EXAMPLES::
555
+
556
+ sage: Rings.an_instance()
557
+ Category of rings
558
+
559
+ Parametrized categories should overload this default
560
+ implementation to provide appropriate arguments::
561
+
562
+ sage: Algebras.an_instance()
563
+ Category of algebras over Rational Field
564
+ sage: Bimodules.an_instance() # needs sage.rings.real_mpfr
565
+ Category of bimodules over Rational Field on the left
566
+ and Real Field with 53 bits of precision on the right
567
+ sage: AlgebraIdeals.an_instance()
568
+ Category of algebra ideals
569
+ in Univariate Polynomial Ring in x over Rational Field
570
+ """
571
+ return cls()
572
+
573
+ def __call__(self, x, *args, **opts):
574
+ """
575
+ Construct an object in this category from the data in ``x``,
576
+ or throw :exc:`TypeError` or :exc:`NotImplementedError`.
577
+
578
+ If ``x`` is readily in ``self`` it is returned unchanged.
579
+ Categories wishing to extend this minimal behavior should
580
+ implement :meth:`._call_`.
581
+
582
+ EXAMPLES::
583
+
584
+ sage: Rings()(ZZ)
585
+ Integer Ring
586
+ """
587
+ if x in self:
588
+ return x
589
+ return self._call_(x, *args, **opts)
590
+
591
+ def _call_(self, x):
592
+ """
593
+ Construct an object in this category from the data in ``x``,
594
+ or throw :exc:`NotImplementedError`.
595
+
596
+ EXAMPLES::
597
+
598
+ sage: Semigroups()._call_(3)
599
+ Traceback (most recent call last):
600
+ ...
601
+ NotImplementedError
602
+ """
603
+ raise NotImplementedError
604
+
605
+ def _repr_(self):
606
+ """
607
+ Return the print representation of this category.
608
+
609
+ EXAMPLES::
610
+
611
+ sage: Sets() # indirect doctest
612
+ Category of sets
613
+ """
614
+ return "Category of {}".format(self._repr_object_names())
615
+
616
+ def _latex_(self):
617
+ r"""
618
+ Return the latex representation of this category.
619
+
620
+ EXAMPLES::
621
+
622
+ sage: latex(Sets()) # indirect doctest
623
+ \mathbf{Sets}
624
+ sage: latex(CommutativeAdditiveSemigroups())
625
+ \mathbf{CommutativeAdditiveSemigroups}
626
+ """
627
+ return "\\mathbf{%s}" % self._short_name()
628
+
629
+ # The convention for which hash function to use should be decided at the level of UniqueRepresentation
630
+ # The implementation below is bad (hash independent of the base ring)
631
+ # def __hash__(self):
632
+ # """
633
+ # Returns a hash for this category.
634
+ #
635
+ # Currently this is just the hash of the string representing the category.
636
+ #
637
+ # EXAMPLES::
638
+ #
639
+ # sage: hash(Algebras(QQ)) #indirect doctest
640
+ # 699942203
641
+ # sage: hash(Algebras(ZZ))
642
+ # 699942203
643
+ # """
644
+ # return hash(self.__category) # Any reason not to use id?
645
+
646
+ def _subcategory_hook_(self, category):
647
+ """
648
+ Quick subcategory check.
649
+
650
+ INPUT:
651
+
652
+ - ``category`` -- a category
653
+
654
+ OUTPUT:
655
+
656
+ - ``True``, if ``category`` is a subcategory of ``self``.
657
+ - ``False``, if ``category`` is not a subcategory of ``self``.
658
+ - ``Unknown``, if a quick check was not enough to determine
659
+ whether ``category`` is a subcategory of ``self`` or not.
660
+
661
+ The aim of this method is to offer a framework to add cheap
662
+ tests for subcategories. When doing
663
+ ``category.is_subcategory(self)`` (note the reverse order of
664
+ ``self`` and ``category``), this method is usually called
665
+ first. Only if it returns ``Unknown``, :meth:`is_subcategory`
666
+ will build the list of super categories of ``category``.
667
+
668
+ This method need not to handle the case where ``category`` is
669
+ ``self``; this is the first test that is done in
670
+ :meth:`is_subcategory`.
671
+
672
+ This default implementation tests whether the parent class of
673
+ ``category`` is a subclass of the parent class of ``self``.
674
+ This is most of the time a complete subcategory test.
675
+
676
+ .. WARNING::
677
+
678
+ This test is incomplete for categories in
679
+ :class:`CategoryWithParameters`, as introduced by
680
+ :issue:`11935`. This method is therefore overwritten by
681
+ :meth:`~sage.categories.category.CategoryWithParameters._subcategory_hook_`.
682
+
683
+ EXAMPLES::
684
+
685
+ sage: Rings()._subcategory_hook_(Rings())
686
+ True
687
+ """
688
+ return issubclass(category.parent_class, self.parent_class)
689
+
690
+ def __contains__(self, x):
691
+ """
692
+ Membership testing.
693
+
694
+ Returns whether ``x`` is an object in this category, that is
695
+ if the category of ``x`` is a subcategory of ``self``.
696
+
697
+ EXAMPLES::
698
+
699
+ sage: ZZ in Sets()
700
+ True
701
+ """
702
+ try:
703
+ c = x.category()
704
+ except AttributeError:
705
+ return False
706
+ return c.is_subcategory(self)
707
+
708
+ @staticmethod
709
+ def __classcontains__(cls, x):
710
+ """
711
+ Membership testing, without arguments.
712
+
713
+ INPUT:
714
+
715
+ - ``cls`` -- a category class
716
+ - ``x`` -- any object
717
+
718
+ Returns whether ``x`` is an object of a category which is an instance
719
+ of ``cls``.
720
+
721
+ EXAMPLES:
722
+
723
+ This method makes it easy to test if an object is, say, a
724
+ vector space, without having to specify the base ring::
725
+
726
+ sage: F = FreeModule(QQ, 3) # needs sage.modules
727
+ sage: F in VectorSpaces # needs sage.modules
728
+ True
729
+
730
+ sage: F = FreeModule(ZZ, 3) # needs sage.modules
731
+ sage: F in VectorSpaces # needs sage.modules
732
+ False
733
+
734
+ sage: F in Algebras # needs sage.modules
735
+ False
736
+
737
+ TESTS:
738
+
739
+ Non category objects shall be handled properly::
740
+
741
+ sage: [1,2] in Algebras
742
+ False
743
+ """
744
+ try:
745
+ c = x.categories()
746
+ except AttributeError:
747
+ return False
748
+ return any(isinstance(cat, cls) for cat in c)
749
+
750
+ def is_abelian(self):
751
+ """
752
+ Return whether this category is abelian.
753
+
754
+ An abelian category is a category satisfying:
755
+
756
+ - It has a zero object;
757
+ - It has all pullbacks and pushouts;
758
+ - All monomorphisms and epimorphisms are normal.
759
+
760
+ Equivalently, one can define an increasing sequence of conditions:
761
+
762
+ - A category is pre-additive if it is enriched over abelian groups
763
+ (all homsets are abelian groups and composition is bilinear);
764
+ - A pre-additive category is additive if every finite set of objects
765
+ has a biproduct (we can form direct sums and direct products);
766
+ - An additive category is pre-abelian if every morphism has both a
767
+ kernel and a cokernel;
768
+ - A pre-abelian category is abelian if every monomorphism is the
769
+ kernel of some morphism and every epimorphism is the cokernel of
770
+ some morphism.
771
+
772
+ EXAMPLES::
773
+
774
+ sage: Modules(ZZ).is_abelian()
775
+ True
776
+ sage: FreeModules(ZZ).is_abelian()
777
+ False
778
+ sage: FreeModules(QQ).is_abelian()
779
+ True
780
+ sage: CommutativeAdditiveGroups().is_abelian()
781
+ True
782
+ sage: Semigroups().is_abelian()
783
+ Traceback (most recent call last):
784
+ ...
785
+ NotImplementedError: is_abelian
786
+ """
787
+ raise NotImplementedError("is_abelian")
788
+
789
+ ##########################################################################
790
+ # Methods related to the category hierarchy
791
+ ##########################################################################
792
+
793
+ def category_graph(self):
794
+ r"""
795
+ Return the graph of all super categories of this category.
796
+
797
+ EXAMPLES::
798
+
799
+ sage: C = Algebras(QQ)
800
+ sage: G = C.category_graph() # needs sage.graphs
801
+ sage: G.is_directed_acyclic() # needs sage.graphs
802
+ True
803
+
804
+ The girth of a directed acyclic graph is infinite, however,
805
+ the girth of the underlying undirected graph is 4 in this case::
806
+
807
+ sage: Graph(G).girth() # needs sage.graphs
808
+ 4
809
+ """
810
+ return category_graph([self])
811
+
812
+ @abstract_method
813
+ def super_categories(self):
814
+ """
815
+ Return the *immediate* super categories of ``self``.
816
+
817
+ OUTPUT: a duplicate-free list of categories
818
+
819
+ Every category should implement this method.
820
+
821
+ EXAMPLES::
822
+
823
+ sage: Groups().super_categories()
824
+ [Category of monoids, Category of inverse unital magmas]
825
+ sage: Objects().super_categories()
826
+ []
827
+
828
+ .. NOTE::
829
+
830
+ Since :issue:`10963`, the order of the categories in the
831
+ result is irrelevant. For details, see
832
+ :ref:`category-primer-category-order`.
833
+
834
+ .. NOTE::
835
+
836
+ Whenever speed matters, developers are advised to use the
837
+ lazy attribute :meth:`_super_categories` instead of
838
+ calling this method.
839
+ """
840
+
841
+ @lazy_attribute
842
+ def _all_super_categories(self):
843
+ r"""
844
+ All the super categories of this category, including this category.
845
+
846
+ Since :issue:`11943`, the order of super categories is
847
+ determined by Python's method resolution order C3 algorithm.
848
+
849
+ .. SEEALSO:: :meth:`all_super_categories`
850
+
851
+ .. NOTE:: this attribute is likely to eventually become a tuple.
852
+
853
+ .. NOTE:: this sets :meth:`_super_categories_for_classes` as a side effect
854
+
855
+ EXAMPLES::
856
+
857
+ sage: C = Rings(); C
858
+ Category of rings
859
+ sage: C._all_super_categories
860
+ [Category of rings, Category of rngs, Category of semirings, ...
861
+ Category of monoids, ...
862
+ Category of commutative additive groups, ...
863
+ Category of sets, Category of sets with partial maps,
864
+ Category of objects]
865
+ """
866
+ (result, bases) = C3_sorted_merge([cat._all_super_categories
867
+ for cat in self._super_categories] +
868
+ [self._super_categories],
869
+ category_sort_key)
870
+ if not sorted(result, key=category_sort_key, reverse=True) == result:
871
+ warn("Inconsistent sorting results for all super categories of {}".format(
872
+ self.__class__))
873
+ self._super_categories_for_classes = bases
874
+ return [self] + result
875
+
876
+ @lazy_attribute
877
+ def _all_super_categories_proper(self):
878
+ r"""
879
+ All the proper super categories of this category.
880
+
881
+ Since :issue:`11943`, the order of super categories is
882
+ determined by Python's method resolution order C3 algorithm.
883
+
884
+ .. SEEALSO:: :meth:`all_super_categories`
885
+
886
+ .. NOTE:: this attribute is likely to eventually become a tuple.
887
+
888
+ EXAMPLES::
889
+
890
+ sage: C = Rings(); C
891
+ Category of rings
892
+ sage: C._all_super_categories_proper
893
+ [Category of rngs, Category of semirings, ...
894
+ Category of monoids, ...
895
+ Category of commutative additive groups, ...
896
+ Category of sets, Category of sets with partial maps,
897
+ Category of objects]
898
+ """
899
+ return self._all_super_categories[1:]
900
+
901
+ @lazy_attribute
902
+ def _set_of_super_categories(self):
903
+ """
904
+ The frozen set of all proper super categories of this category.
905
+
906
+ .. NOTE:: this is used for speeding up category containment tests.
907
+
908
+ .. SEEALSO:: :meth:`all_super_categories`
909
+
910
+ EXAMPLES::
911
+
912
+ sage: sorted(Groups()._set_of_super_categories, key=str)
913
+ [Category of inverse unital magmas,
914
+ Category of magmas,
915
+ Category of monoids,
916
+ Category of objects,
917
+ Category of semigroups,
918
+ Category of sets,
919
+ Category of sets with partial maps,
920
+ Category of unital magmas]
921
+ sage: sorted(Groups()._set_of_super_categories, key=str)
922
+ [Category of inverse unital magmas, Category of magmas, Category of monoids,
923
+ Category of objects, Category of semigroups, Category of sets,
924
+ Category of sets with partial maps, Category of unital magmas]
925
+
926
+ TESTS::
927
+
928
+ sage: C = HopfAlgebrasWithBasis(GF(7))
929
+ sage: C._set_of_super_categories == set(C._all_super_categories_proper)
930
+ True
931
+ """
932
+ return frozenset(self._all_super_categories_proper)
933
+
934
+ def all_super_categories(self, proper=False):
935
+ """
936
+ Return the list of all super categories of this category.
937
+
938
+ INPUT:
939
+
940
+ - ``proper`` -- boolean (default: ``False``); whether to exclude this category
941
+
942
+ Since :issue:`11943`, the order of super categories is
943
+ determined by Python's method resolution order C3 algorithm.
944
+
945
+ .. NOTE::
946
+
947
+ Whenever speed matters, the developers are advised to use
948
+ instead the lazy attributes :meth:`_all_super_categories`,
949
+ :meth:`_all_super_categories_proper`, or
950
+ :meth:`_set_of_super_categories`, as
951
+ appropriate. Simply because lazy attributes are much
952
+ faster than any method.
953
+
954
+ .. NOTE::
955
+
956
+ This is not the same as the concept of super category in mathematics.
957
+ In fact, this is not even the opposite relation of :meth:`is_subcategory`::
958
+
959
+ sage: A = VectorSpaces(QQ); A
960
+ Category of vector spaces over Rational Field
961
+ sage: B = VectorSpaces(QQ.category()); B
962
+ Category of vector spaces over (number fields and quotient fields and metric spaces)
963
+ sage: A.is_subcategory(B)
964
+ True
965
+ sage: B in A.all_super_categories()
966
+ False
967
+
968
+ .. SEEALSO:: :meth:`_test_category_graph`
969
+
970
+ EXAMPLES::
971
+
972
+ sage: C = Rings(); C
973
+ Category of rings
974
+ sage: C.all_super_categories()
975
+ [Category of rings, Category of rngs, Category of semirings, ...
976
+ Category of monoids, ...
977
+ Category of commutative additive groups, ...
978
+ Category of sets, Category of sets with partial maps,
979
+ Category of objects]
980
+
981
+ sage: C.all_super_categories(proper = True)
982
+ [Category of rngs, Category of semirings, ...
983
+ Category of monoids, ...
984
+ Category of commutative additive groups, ...
985
+ Category of sets, Category of sets with partial maps,
986
+ Category of objects]
987
+
988
+ sage: Sets().all_super_categories()
989
+ [Category of sets, Category of sets with partial maps, Category of objects]
990
+ sage: Sets().all_super_categories(proper=True)
991
+ [Category of sets with partial maps, Category of objects]
992
+ sage: Sets().all_super_categories() is Sets()._all_super_categories
993
+ True
994
+ sage: Sets().all_super_categories(proper=True) is Sets()._all_super_categories_proper
995
+ True
996
+ """
997
+ if proper:
998
+ return self._all_super_categories_proper
999
+ return self._all_super_categories
1000
+
1001
+ @lazy_attribute
1002
+ def _super_categories(self):
1003
+ """
1004
+ The immediate super categories of this category.
1005
+
1006
+ This lazy attribute caches the result of the mandatory method
1007
+ :meth:`super_categories` for speed. It also does some mangling
1008
+ (flattening join categories, sorting, ...).
1009
+
1010
+ Whenever speed matters, developers are advised to use this
1011
+ lazy attribute rather than calling :meth:`super_categories`.
1012
+
1013
+ .. NOTE::
1014
+
1015
+ This attribute is likely to eventually become a tuple.
1016
+ When this happens, we might as well use :meth:`Category._sort`,
1017
+ if not :meth:`Category._sort_uniq`.
1018
+
1019
+ EXAMPLES::
1020
+
1021
+ sage: Rings()._super_categories
1022
+ [Category of rngs, Category of semirings]
1023
+ """
1024
+ return sorted(_flatten_categories(self.super_categories(), JoinCategory), key=category_sort_key, reverse=True)
1025
+
1026
+ @lazy_attribute
1027
+ def _super_categories_for_classes(self):
1028
+ """
1029
+ The super categories of this category used for building classes.
1030
+
1031
+ This is a close variant of :meth:`_super_categories` used for
1032
+ constructing the list of the bases for :meth:`parent_class`,
1033
+ :meth:`element_class`, and friends. The purpose is ensure that
1034
+ Python will find a proper Method Resolution Order for those
1035
+ classes. For background, see :mod:`sage.misc.c3_controlled`.
1036
+
1037
+ .. SEEALSO:: :meth:`_cmp_key`.
1038
+
1039
+ .. NOTE::
1040
+
1041
+ This attribute is calculated as a by-product of computing
1042
+ :meth:`_all_super_categories`.
1043
+
1044
+ EXAMPLES::
1045
+
1046
+ sage: Rings()._super_categories_for_classes
1047
+ [Category of rngs, Category of semirings]
1048
+ """
1049
+ self._all_super_categories
1050
+ return self._super_categories_for_classes
1051
+
1052
+ ##########################################################################
1053
+ # Methods handling of full subcategories
1054
+ ##########################################################################
1055
+
1056
+ def additional_structure(self) -> Self:
1057
+ """
1058
+ Return whether ``self`` defines additional structure.
1059
+
1060
+ OUTPUT:
1061
+
1062
+ - ``self`` if ``self`` defines additional structure and
1063
+ ``None`` otherwise. This default implementation returns
1064
+ ``self``.
1065
+
1066
+ A category `C` *defines additional structure* if `C`-morphisms
1067
+ shall preserve more structure (e.g. operations) than that
1068
+ specified by the super categories of `C`. For example, the
1069
+ category of magmas defines additional structure, namely the
1070
+ operation `*` that shall be preserved by magma morphisms. On
1071
+ the other hand the category of rings does not define additional
1072
+ structure: a function between two rings that is both a unital
1073
+ magma morphism and a unital additive magma morphism is
1074
+ automatically a ring morphism.
1075
+
1076
+ Formally speaking `C` *defines additional structure*, if `C`
1077
+ is *not* a full subcategory of the join of its super
1078
+ categories: the morphisms need to preserve more structure, and
1079
+ thus the homsets are smaller.
1080
+
1081
+ By default, a category is considered as defining additional
1082
+ structure, unless it is a :ref:`category with axiom
1083
+ <category-primer-axioms>`.
1084
+
1085
+ EXAMPLES:
1086
+
1087
+ Here are some typical structure categories, with the
1088
+ additional structure they define::
1089
+
1090
+ sage: Sets().additional_structure()
1091
+ Category of sets
1092
+ sage: Magmas().additional_structure() # `*`
1093
+ Category of magmas
1094
+ sage: AdditiveMagmas().additional_structure() # `+`
1095
+ Category of additive magmas
1096
+ sage: LeftModules(ZZ).additional_structure() # left multiplication by scalar
1097
+ Category of left modules over Integer Ring
1098
+ sage: Coalgebras(QQ).additional_structure() # coproduct
1099
+ Category of coalgebras over Rational Field
1100
+ sage: Crystals().additional_structure() # crystal operators
1101
+ Category of crystals
1102
+
1103
+ On the other hand, the category of semigroups is not a
1104
+ structure category, since its operation `+` is already defined
1105
+ by the category of magmas::
1106
+
1107
+ sage: Semigroups().additional_structure()
1108
+
1109
+ Most :ref:`categories with axiom <category-primer-axioms>`
1110
+ don't define additional structure::
1111
+
1112
+ sage: Sets().Finite().additional_structure()
1113
+ sage: Rings().Commutative().additional_structure()
1114
+ sage: Modules(QQ).FiniteDimensional().additional_structure()
1115
+ sage: from sage.categories.magmatic_algebras import MagmaticAlgebras
1116
+ sage: MagmaticAlgebras(QQ).Unital().additional_structure()
1117
+
1118
+ As of Sage 6.4, the only exceptions are the category of unital
1119
+ magmas or the category of unital additive magmas (both define
1120
+ a unit which shall be preserved by morphisms)::
1121
+
1122
+ sage: Magmas().Unital().additional_structure()
1123
+ Category of unital magmas
1124
+ sage: AdditiveMagmas().AdditiveUnital().additional_structure()
1125
+ Category of additive unital additive magmas
1126
+
1127
+ Similarly, :ref:`functorial construction categories
1128
+ <category-primer-functorial-constructions>` don't define
1129
+ additional structure, unless the construction is actually
1130
+ defined by their base category. For example, the category of
1131
+ graded modules defines a grading which shall be preserved by
1132
+ morphisms::
1133
+
1134
+ sage: Modules(ZZ).Graded().additional_structure()
1135
+ Category of graded modules over Integer Ring
1136
+
1137
+ On the other hand, the category of graded algebras does not
1138
+ define additional structure; indeed an algebra morphism which
1139
+ is also a module morphism is a graded algebra morphism::
1140
+
1141
+ sage: Algebras(ZZ).Graded().additional_structure()
1142
+
1143
+ Similarly, morphisms are requested to preserve the structure
1144
+ given by the following constructions::
1145
+
1146
+ sage: Sets().Quotients().additional_structure()
1147
+ Category of quotients of sets
1148
+ sage: Sets().CartesianProducts().additional_structure()
1149
+ Category of Cartesian products of sets
1150
+ sage: Modules(QQ).TensorProducts().additional_structure()
1151
+
1152
+ This might change, as we are lacking enough data points to
1153
+ guarantee that this was the correct design decision.
1154
+
1155
+ .. NOTE::
1156
+
1157
+ In some cases a category defines additional structure,
1158
+ where the structure can be useful to manipulate morphisms
1159
+ but where, in most use cases, we don't want the morphisms
1160
+ to necessarily preserve it. For example, in the context of
1161
+ finite dimensional vector spaces, having a distinguished
1162
+ basis allows for representing morphisms by matrices; yet
1163
+ considering only morphisms that preserve that
1164
+ distinguished basis would be boring.
1165
+
1166
+ In such cases, we might want to eventually have two
1167
+ categories, one where the additional structure is
1168
+ preserved, and one where it's not necessarily preserved
1169
+ (we would need to find an idiom for this).
1170
+
1171
+ At this point, a choice is to be made each time, according
1172
+ to the main use cases. Some of those choices are yet to be
1173
+ settled. For example, should by default:
1174
+
1175
+ - an euclidean domain morphism preserve euclidean
1176
+ division? ::
1177
+
1178
+ sage: EuclideanDomains().additional_structure()
1179
+ Category of euclidean domains
1180
+
1181
+ - an enumerated set morphism preserve the distinguished
1182
+ enumeration? ::
1183
+
1184
+ sage: EnumeratedSets().additional_structure()
1185
+
1186
+ - a module with basis morphism preserve the distinguished
1187
+ basis? ::
1188
+
1189
+ sage: Modules(QQ).WithBasis().additional_structure()
1190
+
1191
+ .. SEEALSO::
1192
+
1193
+ This method together with the methods overloading it
1194
+ provide the basic data to determine, for a given category,
1195
+ the super categories that define some structure (see
1196
+ :meth:`structure`), and to test whether a category is a
1197
+ full subcategory of some other category (see
1198
+ :meth:`is_full_subcategory`). For example, the category of
1199
+ Coxeter groups is not full subcategory of the category of
1200
+ groups since morphisms need to preserve the distinguished
1201
+ generators::
1202
+
1203
+ sage: CoxeterGroups().is_full_subcategory(Groups())
1204
+ False
1205
+
1206
+ The support for modeling full subcategories has been
1207
+ introduced in :issue:`16340`.
1208
+ """
1209
+ return self
1210
+
1211
+ @cached_method
1212
+ def structure(self):
1213
+ r"""
1214
+ Return the structure ``self`` is endowed with.
1215
+
1216
+ This method returns the structure that morphisms in this
1217
+ category shall be preserving. For example, it tells that a
1218
+ ring is a set endowed with a structure of both a unital magma
1219
+ and an additive unital magma which satisfies some further
1220
+ axioms. In other words, a ring morphism is a function that
1221
+ preserves the unital magma and additive unital magma
1222
+ structure.
1223
+
1224
+ In practice, this returns the collection of all the super
1225
+ categories of ``self`` that define some additional structure,
1226
+ as a frozen set.
1227
+
1228
+ EXAMPLES::
1229
+
1230
+ sage: Objects().structure()
1231
+ frozenset()
1232
+
1233
+ sage: def structure(C):
1234
+ ....: return Category._sort(C.structure())
1235
+
1236
+ sage: structure(Sets())
1237
+ (Category of sets, Category of sets with partial maps)
1238
+ sage: structure(Magmas())
1239
+ (Category of magmas, Category of sets, Category of sets with partial maps)
1240
+
1241
+ In the following example, we only list the smallest structure
1242
+ categories to get a more readable output::
1243
+
1244
+ sage: def structure(C):
1245
+ ....: return Category._sort_uniq(C.structure())
1246
+
1247
+ sage: structure(Magmas())
1248
+ (Category of magmas,)
1249
+ sage: structure(Rings())
1250
+ (Category of unital magmas, Category of additive unital additive magmas)
1251
+ sage: structure(Fields())
1252
+ (Category of euclidean domains, Category of noetherian rings)
1253
+ sage: structure(Algebras(QQ))
1254
+ (Category of unital magmas,
1255
+ Category of right modules over Rational Field,
1256
+ Category of left modules over Rational Field)
1257
+ sage: structure(HopfAlgebras(QQ).Graded().WithBasis().Connected())
1258
+ (Category of Hopf algebras over Rational Field,
1259
+ Category of graded modules over Rational Field)
1260
+
1261
+ This method is used in :meth:`is_full_subcategory` for
1262
+ deciding whether a category is a full subcategory of some
1263
+ other category, and for documentation purposes. It is computed
1264
+ recursively from the result of :meth:`additional_structure`
1265
+ on the super categories of ``self``.
1266
+ """
1267
+ result = {D for C in self.super_categories() for D in C.structure()}
1268
+ if self.additional_structure() is not None:
1269
+ result.add(self)
1270
+ return frozenset(result)
1271
+
1272
+ def is_full_subcategory(self, other):
1273
+ """
1274
+ Return whether ``self`` is a full subcategory of ``other``.
1275
+
1276
+ A subcategory `B` of a category `A` is a *full subcategory* if
1277
+ any `A`-morphism between two objects of `B` is also a
1278
+ `B`-morphism (the reciprocal always holds: any `B`-morphism
1279
+ between two objects of `B` is an `A`-morphism).
1280
+
1281
+ This is computed by testing whether ``self`` is a subcategory
1282
+ of ``other`` and whether they have the same structure, as
1283
+ determined by :meth:`structure` from the
1284
+ result of :meth:`additional_structure` on the super
1285
+ categories.
1286
+
1287
+ .. WARNING::
1288
+
1289
+ A positive answer is guaranteed to be mathematically
1290
+ correct. A negative answer may mean that Sage has not been
1291
+ taught enough information (or can not yet within the
1292
+ current model) to derive this information. See
1293
+ :meth:`full_super_categories` for a discussion.
1294
+
1295
+ .. SEEALSO::
1296
+
1297
+ - :meth:`is_subcategory`
1298
+ - :meth:`full_super_categories`
1299
+
1300
+ EXAMPLES::
1301
+
1302
+ sage: Magmas().Associative().is_full_subcategory(Magmas())
1303
+ True
1304
+ sage: Magmas().Unital().is_full_subcategory(Magmas())
1305
+ False
1306
+ sage: Rings().is_full_subcategory(Magmas().Unital() & AdditiveMagmas().AdditiveUnital())
1307
+ True
1308
+
1309
+ Here are two typical examples of false negatives::
1310
+
1311
+ sage: Groups().is_full_subcategory(Semigroups())
1312
+ False
1313
+ sage: Groups().is_full_subcategory(Semigroups()) # todo: not implemented
1314
+ True
1315
+ sage: Fields().is_full_subcategory(Rings())
1316
+ False
1317
+ sage: Fields().is_full_subcategory(Rings()) # todo: not implemented
1318
+ True
1319
+
1320
+ .. TODO::
1321
+
1322
+ The latter is a consequence of :class:`EuclideanDomains`
1323
+ currently being a structure category. Is this what we
1324
+ want? ::
1325
+
1326
+ sage: EuclideanDomains().is_full_subcategory(Rings())
1327
+ False
1328
+ """
1329
+ return self.is_subcategory(other) and \
1330
+ len(self.structure()) == len(other.structure())
1331
+
1332
+ @cached_method
1333
+ def full_super_categories(self):
1334
+ r"""
1335
+ Return the *immediate* full super categories of ``self``.
1336
+
1337
+ .. SEEALSO::
1338
+
1339
+ - :meth:`super_categories`
1340
+ - :meth:`is_full_subcategory`
1341
+
1342
+ .. WARNING::
1343
+
1344
+ The current implementation selects the full subcategories
1345
+ among the immediate super categories of ``self``. This
1346
+ assumes that, if `C\subset B\subset A` is a chain of
1347
+ categories and `C` is a full subcategory of `A`, then `C`
1348
+ is a full subcategory of `B` and `B` is a full subcategory
1349
+ of `A`.
1350
+
1351
+ This assumption is guaranteed to hold with the current
1352
+ model and implementation of full subcategories in
1353
+ Sage. However, mathematically speaking, this is too
1354
+ restrictive. This indeed prevents the complete modelling
1355
+ of situations where any `A` morphism between elements of
1356
+ `C` automatically preserves the `B` structure. See below
1357
+ for an example.
1358
+
1359
+ EXAMPLES:
1360
+
1361
+ A semigroup morphism between two finite semigroups is a finite
1362
+ semigroup morphism::
1363
+
1364
+ sage: Semigroups().Finite().full_super_categories()
1365
+ [Category of semigroups]
1366
+
1367
+ On the other hand, a semigroup morphism between two monoids is
1368
+ not necessarily a monoid morphism (which must map the unit to
1369
+ the unit)::
1370
+
1371
+ sage: Monoids().super_categories()
1372
+ [Category of semigroups, Category of unital magmas]
1373
+ sage: Monoids().full_super_categories()
1374
+ [Category of unital magmas]
1375
+
1376
+ Any semigroup morphism between two groups is automatically a
1377
+ monoid morphism (in a group the unit is the unique idempotent,
1378
+ so it has to be mapped to the unit). Yet, due to the
1379
+ limitation of the model advertised above, Sage currently cannot
1380
+ be taught that the category of groups is a full subcategory of
1381
+ the category of semigroups::
1382
+
1383
+ sage: Groups().full_super_categories() # todo: not implemented
1384
+ [Category of monoids, Category of semigroups, Category of inverse unital magmas]
1385
+ sage: Groups().full_super_categories()
1386
+ [Category of monoids, Category of inverse unital magmas]
1387
+ """
1388
+ return [C for C in self.super_categories()
1389
+ if self.is_full_subcategory(C)]
1390
+
1391
+ ##########################################################################
1392
+ # Test methods
1393
+ ##########################################################################
1394
+
1395
+ def _test_category_graph(self, **options):
1396
+ """
1397
+ Check that the category graph matches with Python's method resolution order.
1398
+
1399
+ .. NOTE::
1400
+
1401
+ By :issue:`11943`, the list of categories returned by
1402
+ :meth:`all_super_categories` is supposed to match with the
1403
+ method resolution order of the parent and element
1404
+ classes. This method checks this.
1405
+
1406
+ Note that if
1407
+ :meth:`~sage.structure.category_object.CategoryObject._refine_category_`
1408
+ is called at unexpected times, the invariant might be false. Most
1409
+ commonly, this happens with rings like ``Zmod(n)`` or ``SR``, where
1410
+ a check like ``Zmod(n) in Fields()`` is needed (which checks the primality
1411
+ of `n`) to refine their category to be a subcategory of fields.
1412
+
1413
+ .. SEEALSO::
1414
+
1415
+ :meth:`CategoryWithParameters._make_named_class_key`
1416
+
1417
+ EXAMPLES::
1418
+
1419
+ sage: C = HopfAlgebrasWithBasis(QQ)
1420
+ sage: C.parent_class.mro() == [X.parent_class for X in C._all_super_categories] + [object]
1421
+ True
1422
+ sage: C.element_class.mro() == [X.element_class for X in C._all_super_categories] + [object]
1423
+ True
1424
+ sage: TestSuite(C).run() # indirect doctest
1425
+ """
1426
+ tester = self._tester(**options)
1427
+ tester.assertEqual(self.parent_class.mro(), [C.parent_class for C in self._all_super_categories] + [object])
1428
+ tester.assertEqual(self.element_class.mro(), [C.element_class for C in self._all_super_categories] + [object])
1429
+
1430
+ def _test_category(self, **options):
1431
+ r"""
1432
+ Run generic tests on this category.
1433
+
1434
+ .. SEEALSO:: :class:`TestSuite`.
1435
+
1436
+ EXAMPLES::
1437
+
1438
+ sage: Sets()._test_category()
1439
+
1440
+ Let us now write a couple broken categories::
1441
+
1442
+ sage: class MyObjects(Category):
1443
+ ....: pass
1444
+ sage: MyObjects()._test_category()
1445
+ Traceback (most recent call last):
1446
+ ...
1447
+ NotImplementedError: <abstract method super_categories at ...>
1448
+
1449
+ sage: class MyObjects(Category):
1450
+ ....: def super_categories(self):
1451
+ ....: return tuple()
1452
+ sage: MyObjects()._test_category()
1453
+ Traceback (most recent call last):
1454
+ ...
1455
+ AssertionError: Category of my objects.super_categories() should return a list
1456
+
1457
+ sage: class MyObjects(Category):
1458
+ ....: def super_categories(self):
1459
+ ....: return []
1460
+ sage: MyObjects()._test_category()
1461
+ Traceback (most recent call last):
1462
+ ...
1463
+ AssertionError: Category of my objects is not a subcategory of Objects()
1464
+ """
1465
+ from sage.categories.objects import Objects
1466
+ from sage.categories.sets_cat import Sets
1467
+ tester = self._tester(**options)
1468
+ tester.assertTrue(isinstance(self.super_categories(), list),
1469
+ "%s.super_categories() should return a list" % self)
1470
+ tester.assertTrue(self.is_subcategory(Objects()),
1471
+ "%s is not a subcategory of Objects()" % self)
1472
+ tester.assertTrue(isinstance(self.parent_class, type))
1473
+ tester.assertTrue(all(not isinstance(cat, JoinCategory) for cat in self._super_categories))
1474
+ if not isinstance(self, JoinCategory):
1475
+ tester.assertTrue(all(self._cmp_key > cat._cmp_key for cat in self._super_categories))
1476
+ tester.assertTrue(self.is_subcategory(Category.join(self.super_categories()))) # Not an obviously passing test with axioms
1477
+
1478
+ for category in self._all_super_categories_proper:
1479
+ if self.is_full_subcategory(category):
1480
+ tester.assertTrue(any(cat.is_subcategory(category)
1481
+ for cat in self.full_super_categories()),
1482
+ "Every full super category should be a super category"
1483
+ "of some immediate full super category")
1484
+
1485
+ if self.is_subcategory(Sets()):
1486
+ tester.assertTrue(isinstance(self.parent_class, type))
1487
+ tester.assertTrue(isinstance(self.element_class, type))
1488
+
1489
+ _cmp_key = _cmp_key
1490
+
1491
+ ##########################################################################
1492
+ # Construction of the associated abstract classes for parents, elements, ...
1493
+ ##########################################################################
1494
+
1495
+ def _make_named_class(self, name, method_provider, cache=False, picklable=True):
1496
+ """
1497
+ Construction of the parent/element/... class of ``self``.
1498
+
1499
+ INPUT:
1500
+
1501
+ - ``name`` -- string; the name of the class as an attribute of
1502
+ ``self`` (e.g. "parent_class")
1503
+ - ``method_provider`` -- string; the name of an attribute of
1504
+ ``self`` that provides methods for the new class (in
1505
+ addition to those coming from the super categories,
1506
+ e.g. "ParentMethods")
1507
+ - ``cache`` -- boolean or ``ignore_reduction`` (default: ``False``)
1508
+ (passed down to dynamic_class; for internal use only)
1509
+ - ``picklable`` -- boolean (default: ``True``)
1510
+
1511
+ ASSUMPTION:
1512
+
1513
+ It is assumed that this method is only called from a lazy
1514
+ attribute whose name coincides with the given ``name``.
1515
+
1516
+ OUTPUT:
1517
+
1518
+ A dynamic class with bases given by the corresponding named
1519
+ classes of ``self``'s super_categories, and methods taken from
1520
+ the class ``getattr(self,method_provider)``.
1521
+
1522
+ .. NOTE::
1523
+
1524
+ - In this default implementation, the reduction data of
1525
+ the named class makes it depend on ``self``. Since the
1526
+ result is going to be stored in a lazy attribute of
1527
+ ``self`` anyway, we may as well disable the caching in
1528
+ ``dynamic_class`` (hence the default value
1529
+ ``cache=False``).
1530
+
1531
+ - :class:`CategoryWithParameters` overrides this method so
1532
+ that the same parent/element/... classes can be shared
1533
+ between closely related categories.
1534
+
1535
+ - The bases of the named class may also contain the named
1536
+ classes of some indirect super categories, according to
1537
+ :meth:`_super_categories_for_classes`. This is to
1538
+ guarantee that Python will build consistent method
1539
+ resolution orders. For background, see
1540
+ :mod:`sage.misc.c3_controlled`.
1541
+
1542
+ .. SEEALSO:: :meth:`CategoryWithParameters._make_named_class`
1543
+
1544
+ EXAMPLES::
1545
+
1546
+ sage: PC = Rings()._make_named_class("parent_class", "ParentMethods"); PC
1547
+ <class 'sage.categories.rings.Rings.parent_class'>
1548
+ sage: type(PC)
1549
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
1550
+ sage: PC.__bases__
1551
+ (<class 'sage.categories.rngs.Rngs.parent_class'>,
1552
+ <class 'sage.categories.semirings.Semirings.parent_class'>)
1553
+
1554
+ Note that, by default, the result is not cached::
1555
+
1556
+ sage: PC is Rings()._make_named_class("parent_class", "ParentMethods")
1557
+ False
1558
+
1559
+ Indeed this method is only meant to construct lazy attributes
1560
+ like ``parent_class`` which already handle this caching::
1561
+
1562
+ sage: Rings().parent_class
1563
+ <class 'sage.categories.rings.Rings.parent_class'>
1564
+
1565
+ Reduction for pickling also assumes the existence of this lazy
1566
+ attribute::
1567
+
1568
+ sage: PC._reduction
1569
+ (<built-in function getattr>, (Category of rings, 'parent_class'))
1570
+ sage: loads(dumps(PC)) is Rings().parent_class
1571
+ True
1572
+
1573
+ TESTS::
1574
+
1575
+ sage: class A: pass
1576
+ sage: class BrokenCategory(Category):
1577
+ ....: def super_categories(self): return []
1578
+ ....: ParentMethods = 1
1579
+ ....: class ElementMethods(A):
1580
+ ....: pass
1581
+ ....: class MorphismMethods():
1582
+ ....: pass
1583
+ sage: C = BrokenCategory()
1584
+ sage: C._make_named_class("parent_class", "ParentMethods")
1585
+ Traceback (most recent call last):
1586
+ ...
1587
+ AssertionError: BrokenCategory.ParentMethods should be a class
1588
+ sage: C._make_named_class("element_class", "ElementMethods")
1589
+ doctest:...: UserWarning: BrokenCategory.ElementMethods should not have a super class
1590
+ <class '__main__.BrokenCategory.element_class'>
1591
+ sage: C._make_named_class("morphism_class", "MorphismMethods")
1592
+ <class '__main__.BrokenCategory.morphism_class'>
1593
+ """
1594
+ cls = self.__class__
1595
+ if isinstance(cls, DynamicMetaclass):
1596
+ cls = cls.__base__
1597
+ class_name = "%s.%s" % (cls.__name__, name)
1598
+ method_provider_cls = getattr(self, method_provider, None)
1599
+ if method_provider_cls is None:
1600
+ # If the category provides no XXXMethods class,
1601
+ # point to the documentation of the category itself
1602
+ doccls = cls
1603
+ else:
1604
+ # Otherwise, check XXXMethods
1605
+ assert inspect.isclass(method_provider_cls), \
1606
+ "%s.%s should be a class" % (cls.__name__, method_provider)
1607
+ mro = inspect.getmro(method_provider_cls)
1608
+ if len(mro) > 2 or (len(mro) == 2 and mro[1] is not object):
1609
+ warn("%s.%s should not have a super class" % (cls.__name__, method_provider))
1610
+ # and point the documentation to it
1611
+ doccls = method_provider_cls
1612
+ if picklable:
1613
+ reduction = (getattr, (self, name))
1614
+ else:
1615
+ reduction = None
1616
+ return dynamic_class(class_name,
1617
+ tuple(getattr(cat, name) for cat in self._super_categories_for_classes),
1618
+ method_provider_cls, prepend_cls_bases=False,
1619
+ doccls=doccls, reduction=reduction, cache=cache)
1620
+
1621
+ @lazy_attribute
1622
+ def subcategory_class(self):
1623
+ """
1624
+ A common superclass for all subcategories of this category (including this one).
1625
+
1626
+ This class derives from ``D.subcategory_class`` for each super
1627
+ category `D` of ``self``, and includes all the methods from
1628
+ the nested class ``self.SubcategoryMethods``, if it exists.
1629
+
1630
+ .. SEEALSO::
1631
+
1632
+ - :issue:`12895`
1633
+ - :meth:`parent_class`
1634
+ - :meth:`element_class`
1635
+ - :meth:`_make_named_class`
1636
+
1637
+ EXAMPLES::
1638
+
1639
+ sage: cls = Rings().subcategory_class; cls
1640
+ <class 'sage.categories.rings.Rings.subcategory_class'>
1641
+ sage: type(cls)
1642
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
1643
+
1644
+ ``Rings()`` is an instance of this class, as well as all its subcategories::
1645
+
1646
+ sage: isinstance(Rings(), cls)
1647
+ True
1648
+ sage: isinstance(AlgebrasWithBasis(QQ), cls)
1649
+ True
1650
+
1651
+ .. NOTE::
1652
+
1653
+ See the note about :meth:`_test_category_graph` regarding Python
1654
+ class hierarchy.
1655
+
1656
+ TESTS::
1657
+
1658
+ sage: cls = Algebras(QQ).subcategory_class; cls
1659
+ <class 'sage.categories.algebras.Algebras.subcategory_class'>
1660
+ sage: type(cls)
1661
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
1662
+ """
1663
+ return self._make_named_class('subcategory_class', 'SubcategoryMethods',
1664
+ cache=False, picklable=False)
1665
+
1666
+ @lazy_attribute
1667
+ def parent_class(self):
1668
+ r"""
1669
+ A common super class for all parents in this category (and its
1670
+ subcategories).
1671
+
1672
+ This class contains the methods defined in the nested class
1673
+ ``self.ParentMethods`` (if it exists), and has as bases the
1674
+ parent classes of the super categories of ``self``.
1675
+
1676
+ .. SEEALSO::
1677
+
1678
+ - :meth:`element_class`, :meth:`morphism_class`
1679
+ - :class:`Category` for details
1680
+
1681
+ EXAMPLES::
1682
+
1683
+ sage: C = Algebras(QQ).parent_class; C
1684
+ <class 'sage.categories.algebras.Algebras.parent_class'>
1685
+ sage: type(C)
1686
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
1687
+
1688
+ By :issue:`11935`, some categories share their parent
1689
+ classes. For example, the parent class of an algebra only
1690
+ depends on the category of the base ring. A typical example is
1691
+ the category of algebras over a finite field versus algebras
1692
+ over a non-field::
1693
+
1694
+ sage: Algebras(GF(7)).parent_class is Algebras(GF(5)).parent_class
1695
+ True
1696
+ sage: Algebras(QQ).parent_class is Algebras(ZZ).parent_class
1697
+ False
1698
+ sage: Algebras(ZZ['t']).parent_class is Algebras(ZZ['t','x']).parent_class
1699
+ True
1700
+
1701
+ See :class:`CategoryWithParameters` for an abstract base class for
1702
+ categories that depend on parameters, even though the parent
1703
+ and element classes only depend on the parent or element
1704
+ classes of its super categories. It is used in
1705
+ :class:`~sage.categories.bimodules.Bimodules`,
1706
+ :class:`~sage.categories.category_types.Category_over_base` and
1707
+ :class:`sage.categories.category.JoinCategory`.
1708
+
1709
+ .. NOTE::
1710
+
1711
+ See the note about :meth:`_test_category_graph` regarding Python
1712
+ class hierarchy.
1713
+ """
1714
+ return self._make_named_class('parent_class', 'ParentMethods')
1715
+
1716
+ @lazy_attribute
1717
+ def element_class(self):
1718
+ r"""
1719
+ A common super class for all elements of parents in this category
1720
+ (and its subcategories).
1721
+
1722
+ This class contains the methods defined in the nested class
1723
+ ``self.ElementMethods`` (if it exists), and has as bases the
1724
+ element classes of the super categories of ``self``.
1725
+
1726
+ .. SEEALSO::
1727
+
1728
+ - :meth:`parent_class`, :meth:`morphism_class`
1729
+ - :class:`Category` for details
1730
+
1731
+ EXAMPLES::
1732
+
1733
+ sage: C = Algebras(QQ).element_class; C
1734
+ <class 'sage.categories.algebras.Algebras.element_class'>
1735
+ sage: type(C)
1736
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
1737
+
1738
+ By :issue:`11935`, some categories share their element
1739
+ classes. For example, the element class of an algebra only
1740
+ depends on the category of the base. A typical example is the
1741
+ category of algebras over a field versus algebras over a
1742
+ non-field::
1743
+
1744
+ sage: Algebras(GF(5)).element_class is Algebras(GF(3)).element_class
1745
+ True
1746
+ sage: Algebras(QQ).element_class is Algebras(ZZ).element_class
1747
+ False
1748
+ sage: Algebras(ZZ['t']).element_class is Algebras(ZZ['t','x']).element_class
1749
+ True
1750
+
1751
+ These classes are constructed with ``__slots__ = ()``, so
1752
+ instances may not have a ``__dict__``::
1753
+
1754
+ sage: E = FiniteEnumeratedSets().element_class
1755
+ sage: E.__dictoffset__
1756
+ 0
1757
+
1758
+ .. SEEALSO:: :meth:`parent_class`
1759
+
1760
+ .. NOTE::
1761
+
1762
+ See the note about :meth:`_test_category_graph` regarding Python
1763
+ class hierarchy.
1764
+ """
1765
+ return self._make_named_class('element_class', 'ElementMethods')
1766
+
1767
+ @lazy_attribute
1768
+ def morphism_class(self):
1769
+ r"""
1770
+ A common super class for all morphisms between parents in this
1771
+ category (and its subcategories).
1772
+
1773
+ This class contains the methods defined in the nested class
1774
+ ``self.MorphismMethods`` (if it exists), and has as bases the
1775
+ morphism classes of the super categories of ``self``.
1776
+
1777
+ .. SEEALSO::
1778
+
1779
+ - :meth:`parent_class`, :meth:`element_class`
1780
+ - :class:`Category` for details
1781
+
1782
+ EXAMPLES::
1783
+
1784
+ sage: C = Algebras(QQ).morphism_class; C
1785
+ <class 'sage.categories.algebras.Algebras.morphism_class'>
1786
+ sage: type(C)
1787
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
1788
+ """
1789
+ return self._make_named_class('morphism_class', 'MorphismMethods')
1790
+
1791
+ def required_methods(self):
1792
+ """
1793
+ Return the methods that are required and optional for parents
1794
+ in this category and their elements.
1795
+
1796
+ EXAMPLES::
1797
+
1798
+ sage: Algebras(QQ).required_methods()
1799
+ {'element': {'optional': ['_add_', '_mul_'], 'required': ['__bool__']},
1800
+ 'parent': {'optional': ['algebra_generators'], 'required': ['__contains__']}}
1801
+ """
1802
+ return {"parent": abstract_methods_of_class(self.parent_class),
1803
+ "element": abstract_methods_of_class(self.element_class)}
1804
+
1805
+ # Operations on the lattice of categories
1806
+ def is_subcategory(self, c):
1807
+ """
1808
+ Return ``True`` if there is a natural forgetful functor from ``self`` to `c`.
1809
+
1810
+ EXAMPLES::
1811
+
1812
+ sage: AbGrps = CommutativeAdditiveGroups()
1813
+ sage: Rings().is_subcategory(AbGrps)
1814
+ True
1815
+ sage: AbGrps.is_subcategory(Rings())
1816
+ False
1817
+
1818
+ The ``is_subcategory`` function takes into account the
1819
+ base.
1820
+
1821
+ ::
1822
+
1823
+ sage: M3 = VectorSpaces(FiniteField(3))
1824
+ sage: M9 = VectorSpaces(FiniteField(9, 'a')) # needs sage.rings.finite_rings
1825
+ sage: M3.is_subcategory(M9) # needs sage.rings.finite_rings
1826
+ False
1827
+
1828
+ Join categories are properly handled::
1829
+
1830
+ sage: CatJ = Category.join((CommutativeAdditiveGroups(), Semigroups()))
1831
+ sage: Rings().is_subcategory(CatJ)
1832
+ True
1833
+
1834
+ ::
1835
+
1836
+ sage: V3 = VectorSpaces(FiniteField(3))
1837
+ sage: POSet = PartiallyOrderedSets()
1838
+ sage: PoV3 = Category.join((V3, POSet))
1839
+ sage: A3 = AlgebrasWithBasis(FiniteField(3))
1840
+ sage: PoA3 = Category.join((A3, POSet))
1841
+ sage: PoA3.is_subcategory(PoV3)
1842
+ True
1843
+ sage: PoV3.is_subcategory(PoV3)
1844
+ True
1845
+ sage: PoV3.is_subcategory(PoA3)
1846
+ False
1847
+ """
1848
+ if c is self:
1849
+ return True
1850
+ subcat_hook = c._subcategory_hook_(self)
1851
+ if subcat_hook is Unknown:
1852
+ return c in self._set_of_super_categories
1853
+ return subcat_hook
1854
+
1855
+ def or_subcategory(self, category=None, join=False):
1856
+ """
1857
+ Return ``category`` or ``self`` if ``category`` is ``None``.
1858
+
1859
+ INPUT:
1860
+
1861
+ - ``category`` -- a sub category of ``self``, tuple/list thereof,
1862
+ or ``None``
1863
+ - ``join`` -- boolean (default: ``False``)
1864
+
1865
+ OUTPUT: a category
1866
+
1867
+ EXAMPLES::
1868
+
1869
+ sage: Monoids().or_subcategory(Groups())
1870
+ Category of groups
1871
+ sage: Monoids().or_subcategory(None)
1872
+ Category of monoids
1873
+
1874
+ If category is a list/tuple, then a join category is returned::
1875
+
1876
+ sage: Monoids().or_subcategory((CommutativeAdditiveMonoids(), Groups()))
1877
+ Join of Category of groups and Category of commutative additive monoids
1878
+
1879
+ If ``join`` is ``False``, an error if raised if category is not a
1880
+ subcategory of ``self``::
1881
+
1882
+ sage: Monoids().or_subcategory(EnumeratedSets())
1883
+ Traceback (most recent call last):
1884
+ ...
1885
+ ValueError: Subcategory of `Category of monoids` required;
1886
+ got `Category of enumerated sets`
1887
+
1888
+ Otherwise, the two categories are joined together::
1889
+
1890
+ sage: Monoids().or_subcategory(EnumeratedSets(), join=True)
1891
+ Category of enumerated monoids
1892
+ """
1893
+ if category is None:
1894
+ return self
1895
+ if isinstance(category, (tuple, list)):
1896
+ category = Category.join(category)
1897
+ assert isinstance(category, Category)
1898
+ if join:
1899
+ return Category.join([self, category])
1900
+ else:
1901
+ if not category.is_subcategory(self):
1902
+ raise ValueError("Subcategory of `{}` required; got `{}`".format(self, category))
1903
+ return category
1904
+
1905
+ def _is_subclass(self, c):
1906
+ """
1907
+ Same as is_subcategory, but c may also be the class of a
1908
+ category instead of a category.
1909
+
1910
+ EXAMPLES::
1911
+
1912
+ sage: Fields()._is_subclass(Rings)
1913
+ True
1914
+ sage: Algebras(QQ)._is_subclass(Modules)
1915
+ True
1916
+ sage: Algebras(QQ)._is_subclass(ModulesWithBasis)
1917
+ False
1918
+ """
1919
+ assert (isinstance(c, Category) or (issubclass(c.__class__, type) and issubclass(c, Category)))
1920
+ if isinstance(c, Category):
1921
+ return self.is_subcategory(c)
1922
+ return any(isinstance(cat, c) for cat in self._all_super_categories)
1923
+
1924
+ @cached_method
1925
+ def _meet_(self, other):
1926
+ """
1927
+ Return the largest common subcategory of ``self`` and ``other``.
1928
+
1929
+ EXAMPLES::
1930
+
1931
+ sage: Monoids()._meet_(Monoids())
1932
+ Category of monoids
1933
+ sage: Rings()._meet_(Rings())
1934
+ Category of rings
1935
+ sage: Rings()._meet_(Monoids())
1936
+ Category of monoids
1937
+ sage: Monoids()._meet_(Rings())
1938
+ Category of monoids
1939
+
1940
+ sage: VectorSpaces(QQ)._meet_(Modules(ZZ))
1941
+ Category of commutative additive groups
1942
+ sage: Algebras(ZZ)._meet_(Algebras(QQ))
1943
+ Category of rings
1944
+ sage: Groups()._meet_(Rings())
1945
+ Category of monoids
1946
+ sage: Algebras(QQ)._meet_(Category.join([Fields(), ModulesWithBasis(QQ)]))
1947
+ Join of Category of rings and Category of vector spaces over Rational Field
1948
+
1949
+ Note: abstractly, the category poset is a distributive
1950
+ lattice, so this is well defined; however, the subset of those
1951
+ categories actually implemented is not: we need to also
1952
+ include their join-categories.
1953
+
1954
+ For example, the category of rings is *not* the join of the
1955
+ category of abelian groups and that of semi groups, just a
1956
+ subcategory of their join, since rings further require
1957
+ distributivity.
1958
+
1959
+ For the meet computation, there may be several lowest common
1960
+ sub categories of ``self`` and ``other``, in which case, we need to
1961
+ take the join of them all.
1962
+
1963
+ FIXME:
1964
+
1965
+ - If A is a subcategory of B, A has *more* structure than B,
1966
+ but then *less* objects in there. We should choose an
1967
+ appropriate convention for A<B. Using subcategory calls
1968
+ for A<B, but the current meet and join call for A>B.
1969
+ """
1970
+ if self is other: # useful? fast pathway
1971
+ return self
1972
+ elif self.is_subcategory(other):
1973
+ return other
1974
+ elif other.is_subcategory(self):
1975
+ # Useful fast pathway; try:
1976
+ # %time L = EllipticCurve('960d1').prove_BSD()
1977
+ return self
1978
+ else:
1979
+ return Category.join(self._meet_(sup) for sup in other._super_categories)
1980
+
1981
+ @staticmethod
1982
+ def meet(categories):
1983
+ """
1984
+ Return the meet of a list of categories.
1985
+
1986
+ INPUT:
1987
+
1988
+ - ``categories`` -- a non empty list (or iterable) of categories
1989
+
1990
+ .. SEEALSO:: :meth:`__or__` for a shortcut
1991
+
1992
+ EXAMPLES::
1993
+
1994
+ sage: Category.meet([Algebras(ZZ), Algebras(QQ), Groups()])
1995
+ Category of monoids
1996
+
1997
+ That meet of an empty list should be a category which is a
1998
+ subcategory of all categories, which does not make practical sense::
1999
+
2000
+ sage: Category.meet([])
2001
+ Traceback (most recent call last):
2002
+ ...
2003
+ ValueError: The meet of an empty list of categories is not implemented
2004
+ """
2005
+ categories = tuple(categories)
2006
+ if not categories:
2007
+ raise ValueError("The meet of an empty list of categories is not implemented")
2008
+ result = categories[0]
2009
+ for category in categories[1:]:
2010
+ result = result._meet_(category)
2011
+ return result
2012
+
2013
+ @cached_method
2014
+ def axioms(self):
2015
+ """
2016
+ Return the axioms known to be satisfied by all the objects of ``self``.
2017
+
2018
+ Technically, this is the set of all the axioms ``A`` such that, if
2019
+ ``Cs`` is the category defining ``A``, then ``self`` is a subcategory
2020
+ of ``Cs().A()``. Any additional axiom ``A`` would yield a strict
2021
+ subcategory of ``self``, at the very least ``self & Cs().A()`` where
2022
+ ``Cs`` is the category defining ``A``.
2023
+
2024
+ EXAMPLES::
2025
+
2026
+ sage: Monoids().axioms()
2027
+ frozenset({'Associative', 'Unital'})
2028
+ sage: (EnumeratedSets().Infinite() & Sets().Facade()).axioms()
2029
+ frozenset({'Enumerated', 'Facade', 'Infinite'})
2030
+ """
2031
+ return frozenset(axiom
2032
+ for category in self._super_categories
2033
+ for axiom in category.axioms())
2034
+
2035
+ @cached_method
2036
+ def _with_axiom_as_tuple(self, axiom):
2037
+ """
2038
+ Return a tuple of categories whose join is ``self._with_axiom()``.
2039
+
2040
+ INPUT:
2041
+
2042
+ - ``axiom`` -- string, the name of an axiom
2043
+
2044
+ This is a lazy version of :meth:`_with_axiom` which is used to
2045
+ avoid recursion loops during join calculations.
2046
+
2047
+ .. NOTE:: The order in the result is irrelevant.
2048
+
2049
+ EXAMPLES::
2050
+
2051
+ sage: Sets()._with_axiom_as_tuple('Finite')
2052
+ (Category of finite sets,)
2053
+ sage: Magmas()._with_axiom_as_tuple('Finite')
2054
+ (Category of magmas, Category of finite sets)
2055
+ sage: Rings().Division()._with_axiom_as_tuple('Finite')
2056
+ (Category of division rings,
2057
+ Category of finite monoids,
2058
+ Category of commutative magmas,
2059
+ Category of finite additive groups)
2060
+ sage: HopfAlgebras(QQ)._with_axiom_as_tuple('FiniteDimensional')
2061
+ (Category of Hopf algebras over Rational Field,
2062
+ Category of finite dimensional vector spaces over Rational Field)
2063
+ """
2064
+ if axiom in self.axioms():
2065
+ return (self, )
2066
+ axiom_attribute = getattr(self.__class__, axiom, None)
2067
+ if axiom_attribute is None:
2068
+ # If the axiom is not defined for this category, ignore it
2069
+ # This uses the following invariant: the categories for
2070
+ # which a given axiom is defined form a lower set
2071
+ return (self,)
2072
+ if axiom in self.__class__.__base__.__dict__:
2073
+ # self implements this axiom
2074
+ from .category_with_axiom import CategoryWithAxiom
2075
+ if inspect.isclass(axiom_attribute) and issubclass(axiom_attribute, CategoryWithAxiom):
2076
+ return (axiom_attribute(self),)
2077
+ warn(("Expecting {}.{} to be a subclass of CategoryWithAxiom to"
2078
+ " implement a category with axiom; got {}; ignoring").format(
2079
+ self.__class__.__base__.__name__, axiom, axiom_attribute))
2080
+
2081
+ # self does not implement this axiom
2082
+ result = (self, ) + tuple(cat
2083
+ for category in self._super_categories
2084
+ for cat in category._with_axiom_as_tuple(axiom))
2085
+ hook = getattr(self, axiom + "_extra_super_categories", None)
2086
+ if hook is not None:
2087
+ assert inspect.ismethod(hook)
2088
+ result += tuple(hook())
2089
+ return _sort_uniq(result)
2090
+
2091
+ @cached_method
2092
+ def _with_axiom(self, axiom):
2093
+ """
2094
+ Return the subcategory of the objects of ``self`` satisfying
2095
+ the given ``axiom``.
2096
+
2097
+ Note that this is a private method thus should not be directly
2098
+ used, see below.
2099
+
2100
+ INPUT:
2101
+
2102
+ - ``axiom`` -- string, the name of an axiom
2103
+
2104
+ EXAMPLES::
2105
+
2106
+ sage: Sets()._with_axiom("Finite") # not idiomatic
2107
+ Category of finite sets
2108
+ sage: Sets().Finite() # recommended
2109
+ Category of finite sets
2110
+
2111
+ sage: type(Magmas().Finite().Commutative())
2112
+ <class 'sage.categories.category.JoinCategory_with_category'>
2113
+ sage: Magmas().Finite().Commutative().super_categories()
2114
+ [Category of commutative magmas, Category of finite sets]
2115
+ sage: C = Algebras(QQ).WithBasis().Commutative()
2116
+ sage: C is Algebras(QQ).Commutative().WithBasis()
2117
+ True
2118
+
2119
+ When ``axiom`` is not defined for ``self``, ``self`` is returned::
2120
+
2121
+ sage: Sets()._with_axiom("Associative")
2122
+ Category of sets
2123
+
2124
+ .. WARNING:: This may be changed in the future to raise an error.
2125
+ """
2126
+ return Category.join(self._with_axiom_as_tuple(axiom))
2127
+
2128
+ def _with_axioms(self, axioms):
2129
+ """
2130
+ Return the subcategory of the objects of ``self`` satisfying
2131
+ the given ``axioms``.
2132
+
2133
+ INPUT:
2134
+
2135
+ - ``axioms`` -- list of strings; the names of the axioms
2136
+
2137
+ EXAMPLES::
2138
+
2139
+ sage: Sets()._with_axioms(["Finite"])
2140
+ Category of finite sets
2141
+ sage: Sets()._with_axioms(["Infinite"])
2142
+ Category of infinite sets
2143
+ sage: FiniteSets()._with_axioms(["Finite"])
2144
+ Category of finite sets
2145
+
2146
+ Axioms that are not defined for the ``self`` are ignored::
2147
+
2148
+ sage: Sets()._with_axioms(["FooBar"])
2149
+ Category of sets
2150
+ sage: Magmas()._with_axioms(["FooBar", "Unital"])
2151
+ Category of unital magmas
2152
+
2153
+ Note that adding several axioms at once can do more than
2154
+ adding them one by one. This is because the availability of an
2155
+ axiom may depend on another axiom. For example, for
2156
+ semigroups, the ``Inverse`` axiom is meaningless unless there
2157
+ is a unit::
2158
+
2159
+ sage: Semigroups().Inverse()
2160
+ Traceback (most recent call last):
2161
+ ...
2162
+ AttributeError: 'Semigroups_with_category' object has no attribute 'Inverse'...
2163
+ sage: Semigroups()._with_axioms(["Inverse"])
2164
+ Category of semigroups
2165
+
2166
+ So one needs to first add the ``Unital`` axiom, and then the
2167
+ ``Inverse`` axiom::
2168
+
2169
+ sage: Semigroups().Unital().Inverse()
2170
+ Category of groups
2171
+
2172
+ or to specify all of them at once, in any order::
2173
+
2174
+ sage: Semigroups()._with_axioms(["Inverse", "Unital"])
2175
+ Category of groups
2176
+ sage: Semigroups()._with_axioms(["Unital", "Inverse"])
2177
+ Category of groups
2178
+
2179
+ sage: Magmas()._with_axioms(['Commutative', 'Associative', 'Unital','Inverse'])
2180
+ Category of commutative groups
2181
+ sage: Magmas()._with_axioms(['Inverse', 'Commutative', 'Associative', 'Unital'])
2182
+ Category of commutative groups
2183
+ """
2184
+ # We repeat adding axioms until they have all been
2185
+ # integrated or nothing happens
2186
+ axioms = frozenset(axioms)
2187
+ previous = None
2188
+ result = self
2189
+ while result is not previous:
2190
+ previous = result
2191
+ for axiom in axioms:
2192
+ result = result._with_axiom(axiom)
2193
+ axioms = axioms.difference(result.axioms())
2194
+ return result
2195
+
2196
+ @cached_method
2197
+ def _without_axiom(self, axiom):
2198
+ r"""
2199
+ Return the category with axiom ``axiom`` removed.
2200
+
2201
+ OUTPUT:
2202
+
2203
+ A category ``C`` which does not have axiom ``axiom``
2204
+ and such that either ``C`` is ``self``, or adding back all the
2205
+ axioms of ``self`` gives back ``self``.
2206
+
2207
+ .. WARNING:: This is not guaranteed to be robust.
2208
+
2209
+ EXAMPLES::
2210
+
2211
+ sage: Sets()._without_axiom("Facade")
2212
+ Category of sets
2213
+ sage: Sets().Facade()._without_axiom("Facade")
2214
+ Category of sets
2215
+ sage: Algebras(QQ)._without_axiom("Unital")
2216
+ Category of associative algebras over Rational Field
2217
+ sage: Groups()._without_axiom("Unital") # todo: not implemented
2218
+ Category of semigroups
2219
+ """
2220
+ if axiom not in self.axioms():
2221
+ return self
2222
+ else:
2223
+ raise ValueError("Cannot remove axiom {} from {}".format(axiom, self))
2224
+
2225
+ def _without_axioms(self, named=False) -> Self:
2226
+ r"""
2227
+ Return the category without the axioms that have been added
2228
+ to create it.
2229
+
2230
+ INPUT:
2231
+
2232
+ - ``named`` -- boolean (default: ``False``)
2233
+
2234
+ .. TODO:: Improve this explanation.
2235
+
2236
+ If ``named`` is ``True``, then this stops at the first
2237
+ category that has an explicit name of its own. See
2238
+ :meth:`.category_with_axiom.CategoryWithAxiom._without_axioms`
2239
+
2240
+ EXAMPLES::
2241
+
2242
+ sage: Sets()._without_axioms()
2243
+ Category of sets
2244
+ sage: Semigroups()._without_axioms()
2245
+ Category of magmas
2246
+ sage: Algebras(QQ).Commutative().WithBasis()._without_axioms()
2247
+ Category of magmatic algebras over Rational Field
2248
+ sage: Algebras(QQ).Commutative().WithBasis()._without_axioms(named=True)
2249
+ Category of algebras over Rational Field
2250
+ """
2251
+ return self
2252
+
2253
+ _flatten_categories = staticmethod(_flatten_categories) # a cythonised helper
2254
+
2255
+ @staticmethod
2256
+ def _sort(categories):
2257
+ """
2258
+ Return the categories after sorting them decreasingly according
2259
+ to their comparison key.
2260
+
2261
+ .. SEEALSO:: :meth:`_cmp_key`
2262
+
2263
+ INPUT:
2264
+
2265
+ - ``categories`` -- list (or iterable) of non-join categories
2266
+
2267
+ OUTPUT: a sorted tuple of categories, possibly with repeats
2268
+
2269
+ .. NOTE::
2270
+
2271
+ The auxiliary function ``_flatten_categories`` used in the test
2272
+ below expects a second argument, which is a type such that
2273
+ instances of that type will be replaced by its super
2274
+ categories. Usually, this type is :class:`JoinCategory`.
2275
+
2276
+ EXAMPLES::
2277
+
2278
+ sage: Category._sort([Sets(), Objects(), Coalgebras(QQ), Monoids(), Sets().Finite()])
2279
+ (Category of monoids,
2280
+ Category of coalgebras over Rational Field,
2281
+ Category of finite sets,
2282
+ Category of sets,
2283
+ Category of objects)
2284
+ sage: Category._sort([Sets().Finite(), Semigroups().Finite(), Sets().Facade(),Magmas().Commutative()])
2285
+ (Category of finite semigroups,
2286
+ Category of commutative magmas,
2287
+ Category of finite sets,
2288
+ Category of facade sets)
2289
+ sage: Category._sort(Category._flatten_categories([Sets().Finite(), Algebras(QQ).WithBasis(), Semigroups().Finite(),
2290
+ ....: Sets().Facade(), Algebras(QQ).Commutative(), Algebras(QQ).Graded().WithBasis()],
2291
+ ....: sage.categories.category.JoinCategory))
2292
+ (Category of algebras with basis over Rational Field,
2293
+ Category of algebras with basis over Rational Field,
2294
+ Category of graded algebras over Rational Field,
2295
+ Category of commutative algebras over Rational Field,
2296
+ Category of finite semigroups,
2297
+ Category of finite sets,
2298
+ Category of facade sets)
2299
+ """
2300
+ return tuple(sorted(categories, key=category_sort_key, reverse=True))
2301
+
2302
+ _sort_uniq = staticmethod(_sort_uniq) # a cythonised helper
2303
+
2304
+ def __and__(self, other):
2305
+ """
2306
+ Return the intersection of two categories.
2307
+
2308
+ This is just a shortcut for :meth:`join`.
2309
+
2310
+ EXAMPLES::
2311
+
2312
+ sage: Sets().Finite() & Rings().Commutative()
2313
+ Category of finite commutative rings
2314
+ sage: Monoids() & CommutativeAdditiveMonoids()
2315
+ Join of Category of monoids and Category of commutative additive monoids
2316
+ """
2317
+ return Category.join([self, other])
2318
+
2319
+ def __or__(self, other):
2320
+ """
2321
+ Return the smallest category containing the two categories.
2322
+
2323
+ This is just a shortcut for :meth:`meet`.
2324
+
2325
+ EXAMPLES::
2326
+
2327
+ sage: Algebras(QQ) | Groups()
2328
+ Category of monoids
2329
+ """
2330
+ return Category.meet([self, other])
2331
+
2332
+ _join_cache = _join_cache
2333
+
2334
+ @staticmethod
2335
+ def join(categories, as_list=False, ignore_axioms=(), axioms=()):
2336
+ """
2337
+ Return the join of the input categories in the lattice of categories.
2338
+
2339
+ At the level of objects and morphisms, this operation
2340
+ corresponds to intersection: the objects and morphisms of a
2341
+ join category are those that belong to all its super
2342
+ categories.
2343
+
2344
+ INPUT:
2345
+
2346
+ - ``categories`` -- list (or iterable) of categories
2347
+ - ``as_list`` -- boolean (default: ``False``);
2348
+ whether the result should be returned as a list
2349
+ - ``axioms`` -- tuple of strings; the names of some
2350
+ supplementary axioms
2351
+
2352
+ .. SEEALSO:: :meth:`__and__` for a shortcut
2353
+
2354
+ EXAMPLES::
2355
+
2356
+ sage: J = Category.join((Groups(), CommutativeAdditiveMonoids())); J
2357
+ Join of Category of groups and Category of commutative additive monoids
2358
+ sage: J.super_categories()
2359
+ [Category of groups, Category of commutative additive monoids]
2360
+ sage: J.all_super_categories(proper=True)
2361
+ [Category of groups, ..., Category of magmas,
2362
+ Category of commutative additive monoids, ..., Category of additive magmas,
2363
+ Category of sets, ...]
2364
+
2365
+ As a short hand, one can use::
2366
+
2367
+ sage: Groups() & CommutativeAdditiveMonoids()
2368
+ Join of Category of groups and Category of commutative additive monoids
2369
+
2370
+ This is a commutative and associative operation::
2371
+
2372
+ sage: Groups() & Posets()
2373
+ Join of Category of groups and Category of posets
2374
+ sage: Posets() & Groups()
2375
+ Join of Category of groups and Category of posets
2376
+
2377
+ sage: Groups() & (CommutativeAdditiveMonoids() & Posets())
2378
+ Join of Category of groups
2379
+ and Category of commutative additive monoids
2380
+ and Category of posets
2381
+ sage: (Groups() & CommutativeAdditiveMonoids()) & Posets()
2382
+ Join of Category of groups
2383
+ and Category of commutative additive monoids
2384
+ and Category of posets
2385
+
2386
+ The join of a single category is the category itself::
2387
+
2388
+ sage: Category.join([Monoids()])
2389
+ Category of monoids
2390
+
2391
+ Similarly, the join of several mutually comparable categories is
2392
+ the smallest one::
2393
+
2394
+ sage: Category.join((Sets(), Rings(), Monoids()))
2395
+ Category of rings
2396
+
2397
+ In particular, the unit is the top category :class:`Objects`::
2398
+
2399
+ sage: Groups() & Objects()
2400
+ Category of groups
2401
+
2402
+ If the optional parameter ``as_list`` is ``True``, this
2403
+ returns the super categories of the join as a list, without
2404
+ constructing the join category itself::
2405
+
2406
+ sage: Category.join((Groups(), CommutativeAdditiveMonoids()), as_list=True)
2407
+ [Category of groups, Category of commutative additive monoids]
2408
+ sage: Category.join((Sets(), Rings(), Monoids()), as_list=True)
2409
+ [Category of rings]
2410
+ sage: Category.join((Modules(ZZ), FiniteFields()), as_list=True)
2411
+ [Category of finite enumerated fields, Category of modules over Integer Ring]
2412
+ sage: Category.join([], as_list=True)
2413
+ []
2414
+ sage: Category.join([Groups()], as_list=True)
2415
+ [Category of groups]
2416
+ sage: Category.join([Groups() & Posets()], as_list=True)
2417
+ [Category of groups, Category of posets]
2418
+
2419
+ Support for axiom categories (TODO: put here meaningful examples)::
2420
+
2421
+ sage: Sets().Facade() & Sets().Infinite()
2422
+ Category of facade infinite sets
2423
+ sage: Magmas().Infinite() & Sets().Facade()
2424
+ Category of facade infinite magmas
2425
+
2426
+ sage: FiniteSets() & Monoids()
2427
+ Category of finite monoids
2428
+ sage: Rings().Commutative() & Sets().Finite()
2429
+ Category of finite commutative rings
2430
+
2431
+ Note that several of the above examples are actually join
2432
+ categories; they are just nicely displayed::
2433
+
2434
+ sage: AlgebrasWithBasis(QQ) & FiniteSets().Algebras(QQ)
2435
+ Join of Category of finite dimensional algebras with basis over Rational Field
2436
+ and Category of finite set algebras over Rational Field
2437
+
2438
+ sage: UniqueFactorizationDomains() & Algebras(QQ)
2439
+ Join of Category of unique factorization domains
2440
+ and Category of commutative algebras over Rational Field
2441
+
2442
+ TESTS::
2443
+
2444
+ sage: Magmas().Unital().Commutative().Finite() is Magmas().Finite().Commutative().Unital()
2445
+ True
2446
+ sage: from sage.categories.category_with_axiom import TestObjects
2447
+ sage: T = TestObjects()
2448
+ sage: TCF = T.Commutative().Facade(); TCF
2449
+ Category of facade commutative test objects
2450
+ sage: TCF is T.Facade().Commutative()
2451
+ True
2452
+ sage: TCF is (T.Facade() & T.Commutative())
2453
+ True
2454
+ sage: TCF.axioms()
2455
+ frozenset({'Commutative', 'Facade'})
2456
+ sage: type(TCF)
2457
+ <class 'sage.categories.category_with_axiom.TestObjects.Commutative.Facade_with_category'>
2458
+
2459
+ sage: TCF = T.Commutative().FiniteDimensional()
2460
+ sage: TCF is T.FiniteDimensional().Commutative()
2461
+ True
2462
+ sage: TCF is T.Commutative() & T.FiniteDimensional()
2463
+ True
2464
+ sage: TCF is T.FiniteDimensional() & T.Commutative()
2465
+ True
2466
+ sage: type(TCF)
2467
+ <class 'sage.categories.category_with_axiom.TestObjects.Commutative.FiniteDimensional_with_category'>
2468
+
2469
+ sage: TCU = T.Commutative().Unital()
2470
+ sage: TCU is T.Unital().Commutative()
2471
+ True
2472
+ sage: TCU is T.Commutative() & T.Unital()
2473
+ True
2474
+ sage: TCU is T.Unital() & T.Commutative()
2475
+ True
2476
+
2477
+ sage: TUCF = T.Unital().Commutative().FiniteDimensional(); TUCF
2478
+ Category of finite dimensional commutative unital test objects
2479
+ sage: type(TUCF)
2480
+ <class 'sage.categories.category_with_axiom.TestObjects.FiniteDimensional.Unital.Commutative_with_category'>
2481
+
2482
+ sage: TFFC = T.Facade().FiniteDimensional().Commutative(); TFFC
2483
+ Category of facade finite dimensional commutative test objects
2484
+ sage: type(TFFC)
2485
+ <class 'sage.categories.category.JoinCategory_with_category'>
2486
+ sage: TFFC.super_categories()
2487
+ [Category of facade commutative test objects,
2488
+ Category of finite dimensional commutative test objects]
2489
+ """
2490
+ # Get the list of categories and deal with some trivial cases
2491
+ categories = list(categories)
2492
+ if not categories:
2493
+ if as_list:
2494
+ return []
2495
+ else:
2496
+ # Since Objects() is the top category, it is the neutral element of join
2497
+ from .objects import Objects
2498
+ return Objects()
2499
+ elif len(categories) == 1:
2500
+ category = categories[0]
2501
+ if as_list:
2502
+ if isinstance(category, JoinCategory):
2503
+ return category.super_categories()
2504
+ else:
2505
+ return categories
2506
+ else:
2507
+ return category
2508
+
2509
+ # Get the cache key, and look into the cache
2510
+ # Ensure associativity and commutativity by flattening
2511
+ # TODO:
2512
+ # - Do we want to store the cache after or before the mangling of the categories?
2513
+ # - Caching with ignore_axioms?
2514
+ # JoinCategory's sorting, and removing duplicates
2515
+ cache_key = _sort_uniq(_flatten_categories(categories, JoinCategory))
2516
+ if not ignore_axioms:
2517
+ try:
2518
+ out = _join_cache[cache_key]
2519
+ if as_list:
2520
+ if isinstance(out, JoinCategory):
2521
+ return out._super_categories
2522
+ return [out]
2523
+ return out
2524
+ except KeyError:
2525
+ pass
2526
+
2527
+ # Handle axioms
2528
+ result = join_as_tuple(cache_key, axioms, ignore_axioms)
2529
+ if as_list:
2530
+ return list(result)
2531
+ if len(result) == 1:
2532
+ result = result[0]
2533
+ else:
2534
+ result = JoinCategory(result)
2535
+ if not ignore_axioms:
2536
+ _join_cache[cache_key] = result
2537
+ return result
2538
+
2539
+ def category(self):
2540
+ """
2541
+ Return the category of this category. So far, all categories
2542
+ are in the category of objects.
2543
+
2544
+ EXAMPLES::
2545
+
2546
+ sage: Sets().category()
2547
+ Category of objects
2548
+ sage: VectorSpaces(QQ).category()
2549
+ Category of objects
2550
+ """
2551
+ from .objects import Objects
2552
+ return Objects()
2553
+
2554
+ def example(self, *args, **keywords):
2555
+ """
2556
+ Return an object in this category. Most of the time, this is a parent.
2557
+
2558
+ This serves three purposes:
2559
+
2560
+ - Give a typical example to better explain what the category is all about.
2561
+ (and by the way prove that the category is non empty :-) )
2562
+ - Provide a minimal template for implementing other objects in this category
2563
+ - Provide an object on which to test generic code implemented by the category
2564
+
2565
+ For all those applications, the implementation of the object
2566
+ shall be kept to a strict minimum. The object is therefore not
2567
+ meant to be used for other applications; most of the time a
2568
+ full featured version is available elsewhere in Sage, and
2569
+ should be used instead.
2570
+
2571
+ Technical note: by default ``FooBar(...).example()`` is
2572
+ constructed by looking up
2573
+ ``sage.categories.examples.foo_bar.Example`` and calling it as
2574
+ ``Example()``. Extra positional or named parameters are also
2575
+ passed down. For a category over base ring, the base ring is
2576
+ further passed down as an optional argument.
2577
+
2578
+ Categories are welcome to override this default implementation.
2579
+
2580
+ EXAMPLES::
2581
+
2582
+ sage: Semigroups().example()
2583
+ An example of a semigroup: the left zero semigroup
2584
+
2585
+ sage: Monoids().Subquotients().example()
2586
+ NotImplemented
2587
+ """
2588
+ if '.' in self.__class__.__name__:
2589
+ # this magic should not apply to nested categories like Monoids.Subquotients
2590
+ return NotImplemented
2591
+ module_name = self.__module__.replace("sage.categories", "sage.categories.examples")
2592
+ import sys
2593
+ try:
2594
+ __import__(module_name)
2595
+ module = sys.modules[module_name]
2596
+ except ImportError:
2597
+ return NotImplemented
2598
+ try:
2599
+ cls = module.Example
2600
+ except AttributeError:
2601
+ return NotImplemented
2602
+ # Add the base ring as optional argument if this is a category over base ring
2603
+ if "base_ring" not in keywords:
2604
+ try:
2605
+ keywords["base_ring"] = self.base_ring()
2606
+ except AttributeError:
2607
+ pass
2608
+ return cls(*args, **keywords)
2609
+
2610
+ def __lean_init__(self):
2611
+ r"""
2612
+ Return the category as Lean mathlib input for a typeclass.
2613
+ """
2614
+ raise NotImplementedError
2615
+
2616
+ def _lean_init_(self):
2617
+ r"""
2618
+ Return the category as Lean mathlib input for a typeclass.
2619
+ """
2620
+ return self.__lean_init__()
2621
+
2622
+
2623
+ def is_Category(x):
2624
+ """
2625
+ Return ``True`` if `x` is a category.
2626
+
2627
+ EXAMPLES::
2628
+
2629
+ sage: sage.categories.category.is_Category(CommutativeAdditiveSemigroups())
2630
+ doctest:warning...
2631
+ DeprecationWarning: the function is_Category is deprecated;
2632
+ use 'isinstance(..., Category)' instead
2633
+ See https://github.com/sagemath/sage/issues/37922 for details.
2634
+ True
2635
+ sage: sage.categories.category.is_Category(ZZ)
2636
+ False
2637
+ """
2638
+ from sage.misc.superseded import deprecation
2639
+ deprecation(37922, "the function is_Category is deprecated; use 'isinstance(..., Category)' instead")
2640
+ return isinstance(x, Category)
2641
+
2642
+
2643
+ @cached_function
2644
+ def category_sample():
2645
+ r"""
2646
+ Return a sample of categories.
2647
+
2648
+ It is constructed by looking for all concrete category classes declared in
2649
+ ``sage.categories.all``, calling :meth:`Category.an_instance` on those and
2650
+ taking all their super categories.
2651
+
2652
+ EXAMPLES::
2653
+
2654
+ sage: from sage.categories.category import category_sample
2655
+ sage: sorted(category_sample(), key=str) # needs sage.groups
2656
+ [Category of Coxeter groups,
2657
+ Category of Dedekind domains,
2658
+ Category of G-sets for Symmetric group of order 8! as a permutation group,
2659
+ Category of Hecke modules over Rational Field,
2660
+ Category of Hopf algebras over Rational Field,
2661
+ Category of Hopf algebras with basis over Rational Field,
2662
+ Category of Jacobians over Rational Field,
2663
+ Category of Lie algebras over Rational Field,
2664
+ Category of Weyl groups,
2665
+ Category of abelian varieties over Rational Field,
2666
+ Category of additive magmas, ...,
2667
+ Category of fields, ...,
2668
+ Category of graded Hopf algebras with basis over Rational Field, ...,
2669
+ Category of modular abelian varieties over Rational Field, ...,
2670
+ Category of simplicial complexes, ...,
2671
+ Category of vector spaces over Rational Field, ...
2672
+ """
2673
+ import sage.categories.all
2674
+ abstract_classes_for_categories = [Category]
2675
+ return tuple(cls.an_instance()
2676
+ for cls in sage.categories.all.__dict__.values()
2677
+ if isinstance(cls, type) and issubclass(cls, Category) and cls not in abstract_classes_for_categories)
2678
+
2679
+
2680
+ def category_graph(categories=None):
2681
+ """
2682
+ Return the graph of the categories in Sage.
2683
+
2684
+ INPUT:
2685
+
2686
+ - ``categories`` -- list (or iterable) of categories
2687
+
2688
+ If ``categories`` is specified, then the graph contains the
2689
+ mentioned categories together with all their super
2690
+ categories. Otherwise the graph contains (an instance of) each
2691
+ category in :mod:`sage.categories.all` (e.g. ``Algebras(QQ)`` for
2692
+ algebras).
2693
+
2694
+ For readability, the names of the category are shortened.
2695
+
2696
+ .. TODO:: Further remove the base ring (see also :issue:`15801`).
2697
+
2698
+ EXAMPLES::
2699
+
2700
+ sage: G = sage.categories.category.category_graph(categories=[Groups()]) # needs sage.graphs
2701
+ sage: G.vertices(sort=True) # needs sage.graphs
2702
+ ['groups', 'inverse unital magmas', 'magmas', 'monoids', 'objects',
2703
+ 'semigroups', 'sets', 'sets with partial maps', 'unital magmas']
2704
+ sage: G.plot() # needs sage.graphs sage.plot
2705
+ Graphics object consisting of 20 graphics primitives
2706
+
2707
+ sage: sage.categories.category.category_graph().plot() # needs sage.graphs sage.groups sage.plot
2708
+ Graphics object consisting of ... graphics primitives
2709
+ """
2710
+ from sage import graphs
2711
+ if categories is None:
2712
+ categories = category_sample()
2713
+ # Include all the super categories
2714
+ # Get rid of join categories
2715
+ categories = {cat for category in categories
2716
+ for cat in category.all_super_categories(proper=isinstance(category, JoinCategory))}
2717
+ g = graphs.digraph.DiGraph()
2718
+ for cat in categories:
2719
+ g.add_vertex(cat._repr_object_names())
2720
+ for source in categories:
2721
+ # Don't use super_categories() since it might contain join categories
2722
+ for target in source._super_categories:
2723
+ g.add_edge([source._repr_object_names(), target._repr_object_names()])
2724
+ return g
2725
+
2726
+
2727
+ ##############################################################################
2728
+ # Parametrized categories whose parent/element class depend only on
2729
+ # the super categories
2730
+ ##############################################################################
2731
+
2732
+ class CategoryWithParameters(Category):
2733
+ """
2734
+ A parametrized category whose parent/element classes depend only on
2735
+ its super categories.
2736
+
2737
+ Many categories in Sage are parametrized, like ``C = Algebras(K)``
2738
+ which takes a base ring as parameter. In many cases, however, the
2739
+ operations provided by ``C`` in the parent class and element class
2740
+ depend only on the super categories of ``C``. For example, the
2741
+ vector space operations are provided if and only if ``K`` is a
2742
+ field, since ``VectorSpaces(K)`` is a super category of ``C`` only
2743
+ in that case. In such cases, and as an optimization (see :issue:`11935`),
2744
+ we want to use the same parent and element class for all fields.
2745
+ This is the purpose of this abstract class.
2746
+
2747
+ Currently, :class:`~sage.categories.category.JoinCategory`,
2748
+ :class:`~sage.categories.category_types.Category_over_base` and
2749
+ :class:`~sage.categories.bimodules.Bimodules` inherit from this
2750
+ class.
2751
+
2752
+ EXAMPLES::
2753
+
2754
+ sage: C1 = Algebras(GF(5))
2755
+ sage: C2 = Algebras(GF(3))
2756
+ sage: C3 = Algebras(ZZ)
2757
+ sage: from sage.categories.category import CategoryWithParameters
2758
+ sage: isinstance(C1, CategoryWithParameters)
2759
+ True
2760
+ sage: C1.parent_class is C2.parent_class
2761
+ True
2762
+ sage: C1.parent_class is C3.parent_class
2763
+ False
2764
+
2765
+ .. automethod:: Category._make_named_class
2766
+ """
2767
+
2768
+ def _make_named_class(self, name, method_provider, cache=False, **options):
2769
+ """
2770
+ Return the parent/element/... class of ``self``.
2771
+
2772
+ INPUT:
2773
+
2774
+ - ``name`` -- string; the name of the class as an attribute
2775
+ of ``self``
2776
+ - ``method_provider`` -- string; the name of an attribute of
2777
+ ``self`` that provides methods for the new class (in
2778
+ addition to what comes from the super categories)
2779
+ - ``**options`` -- other named options to pass down to
2780
+ :meth:`Category._make_named_class`
2781
+
2782
+ ASSUMPTION:
2783
+
2784
+ It is assumed that this method is only called from a lazy
2785
+ attribute whose name coincides with the given ``name``.
2786
+ Currently, this means :meth:`Category.subcategory_class`,
2787
+ :meth:`Category.parent_class` or :meth:`element_class`.
2788
+
2789
+ Subclasses need to implement :meth:`_make_named_class_key`.
2790
+
2791
+ OUTPUT:
2792
+
2793
+ A dynamic class that has the corresponding named classes of
2794
+ the super categories of ``self`` as bases and contains the
2795
+ methods provided by ``getattr(self, method_provider)``.
2796
+
2797
+ .. NOTE::
2798
+
2799
+ This method overrides :meth:`Category._make_named_class`
2800
+ so that the returned class *only* depends on the
2801
+ corresponding named classes of the super categories and on
2802
+ the provided methods. This allows for sharing the named
2803
+ classes across closely related categories providing the
2804
+ same code to their parents, elements and so on.
2805
+
2806
+ EXAMPLES:
2807
+
2808
+ The categories of bimodules over the fields ``CC`` or ``RR``
2809
+ provide the same methods to their parents and elements::
2810
+
2811
+ sage: Bimodules(ZZ,RR).parent_class is Bimodules(ZZ,RDF).parent_class # indirect doctest
2812
+ True
2813
+ sage: Bimodules(CC,ZZ).element_class is Bimodules(RR,ZZ).element_class # needs sage.rings.real_mpfr
2814
+ True
2815
+
2816
+ On the other hand, modules over a field have more methods than
2817
+ modules over a ring::
2818
+
2819
+ sage: Modules(GF(3)).parent_class is Modules(ZZ).parent_class
2820
+ False
2821
+ sage: Modules(GF(3)).element_class is Modules(ZZ).element_class
2822
+ False
2823
+
2824
+ For a more subtle example, one could possibly share the classes for
2825
+ ``GF(3)`` and ``GF(2^3, 'x')``, but this is not currently the case::
2826
+
2827
+ sage: Modules(GF(3)).parent_class is Modules(GF(2^3,'x')).parent_class # needs sage.rings.finite_rings
2828
+ False
2829
+
2830
+ This is because those two fields do not have the exact same category::
2831
+
2832
+ sage: GF(3).category()
2833
+ Join of Category of finite enumerated fields
2834
+ and Category of subquotients of monoids
2835
+ and Category of quotients of semigroups
2836
+ sage: GF(2^3,'x').category() # needs sage.rings.finite_rings
2837
+ Category of finite enumerated fields
2838
+
2839
+ Similarly for ``QQ`` and ``RR``::
2840
+
2841
+ sage: QQ.category()
2842
+ Join of Category of number fields
2843
+ and Category of quotient fields
2844
+ and Category of metric spaces
2845
+ sage: RR.category()
2846
+ Join of Category of fields and Category of infinite sets
2847
+ and Category of complete metric spaces
2848
+ sage: Modules(QQ).parent_class is Modules(RR).parent_class
2849
+ False
2850
+
2851
+ Some other cases where one could potentially share those classes::
2852
+
2853
+ sage: MF = Modules(GF(3), dispatch=False)
2854
+ sage: MF.parent_class is Modules(ZZ).parent_class
2855
+ False
2856
+ sage: MF.element_class is Modules(ZZ).element_class
2857
+ False
2858
+
2859
+ TESTS::
2860
+
2861
+ sage: PC = Algebras(QQ).parent_class; PC # indirect doctest
2862
+ <class 'sage.categories.algebras.Algebras.parent_class'>
2863
+ sage: type(PC)
2864
+ <class 'sage.structure.dynamic_class.DynamicMetaclass'>
2865
+ sage: PC.__bases__
2866
+ (<class 'sage.categories.rings.Rings.parent_class'>,
2867
+ <class 'sage.categories.associative_algebras.AssociativeAlgebras.parent_class'>,
2868
+ <class 'sage.categories.unital_algebras.UnitalAlgebras.parent_class'>)
2869
+ sage: loads(dumps(PC)) is PC
2870
+ True
2871
+ """
2872
+ cls = self.__class__
2873
+ if isinstance(cls, DynamicMetaclass):
2874
+ cls = cls.__base__
2875
+ key = (cls, name, self._make_named_class_key(name))
2876
+ try:
2877
+ return self._make_named_class_cache[key]
2878
+ except KeyError:
2879
+ pass
2880
+ result = Category._make_named_class(self, name, method_provider,
2881
+ cache=cache, **options)
2882
+ if key[2] != self._make_named_class_key(name):
2883
+ # the object in the parameter may have had its category refined, which might modify the key
2884
+ # throw result away and recompute
2885
+ return self._make_named_class(name, method_provider, cache=cache, **options)
2886
+ self._make_named_class_cache[key] = result
2887
+ return result
2888
+
2889
+ @abstract_method
2890
+ def _make_named_class_key(self, name):
2891
+ r"""
2892
+ Return what the element/parent/... class depend on.
2893
+
2894
+ This method starts as an optimization to allow different related
2895
+ categories to share the Python types, see :issue:`11935`.
2896
+ However, because of the guarantees stated in :meth:`Category._test_category_graph`,
2897
+ the following rules must be followed.
2898
+
2899
+ - If two categories have different lists of supercategories, they must return
2900
+ different keys::
2901
+
2902
+ sage: Zmod(5) in Fields()
2903
+ True
2904
+ sage: Algebras(Zmod(5)).all_super_categories()
2905
+ [..., Category of vector spaces over Ring of integers modulo 5, ...]
2906
+ sage: Zmod(6) in Fields()
2907
+ False
2908
+ sage: Algebras(Zmod(6)).all_super_categories() # of course don't have category of vector spaces
2909
+ [..., Category of modules over Ring of integers modulo 6, ...]
2910
+ sage: # therefore:
2911
+ sage: Algebras(Zmod(5))._make_named_class_key("parent_class") != Algebras(Zmod(6))._make_named_class_key("parent_class")
2912
+ True
2913
+ sage: Algebras(Zmod(5)).parent_class != Algebras(Zmod(6)).parent_class
2914
+ True
2915
+
2916
+ - If category ``A`` is a supercategory of category ``B``,
2917
+ and category ``B`` uses the optimization, then so must ``A``.
2918
+
2919
+ For example, ``Modules(ZZ)`` is a supercategory of ``Algebras(ZZ)``,
2920
+ and ``Algebras(ZZ)`` implements the optimization::
2921
+
2922
+ sage: from sage.categories.category import CategoryWithParameters
2923
+ sage: isinstance(Algebras(ZZ), CategoryWithParameters)
2924
+ True
2925
+ sage: Algebras(ZZ).parent_class is Algebras(ZZ.category()).parent_class
2926
+ True
2927
+ sage: Modules(ZZ) in Algebras(ZZ).all_super_categories()
2928
+ True
2929
+
2930
+ This forces ``Modules(ZZ)`` to also implement the optimization::
2931
+
2932
+ sage: Modules(ZZ).parent_class is Modules(ZZ.category()).parent_class
2933
+ True
2934
+
2935
+ As a complication, computing the exact category might require some potentially
2936
+ expensive test. See :meth:`Category._test_category_graph` for more details.
2937
+
2938
+ INPUT:
2939
+
2940
+ - ``name`` -- string; the name of the class as an attribute
2941
+ of ``self``
2942
+
2943
+ .. SEEALSO::
2944
+
2945
+ - :meth:`_make_named_class`
2946
+
2947
+ The following can be read for typical implementations of this method.
2948
+
2949
+ - :meth:`sage.categories.category_types.Category_over_base._make_named_class_key`
2950
+ - :meth:`sage.categories.bimodules.Bimodules._make_named_class_key`
2951
+ - :meth:`JoinCategory._make_named_class_key`
2952
+
2953
+ EXAMPLES:
2954
+
2955
+ The parent class of an algebra depends only on the category of the base ring::
2956
+
2957
+ sage: Algebras(ZZ)._make_named_class_key("parent_class")
2958
+ Join of Category of Dedekind domains
2959
+ and Category of euclidean domains
2960
+ and Category of noetherian rings
2961
+ and Category of infinite enumerated sets
2962
+ and Category of metric spaces
2963
+
2964
+ The morphism class of a bimodule depends only on the category
2965
+ of the left and right base rings::
2966
+
2967
+ sage: Bimodules(QQ, ZZ)._make_named_class_key("morphism_class")
2968
+ (Join of Category of number fields
2969
+ and Category of quotient fields
2970
+ and Category of metric spaces,
2971
+ Join of Category of Dedekind domains
2972
+ and Category of euclidean domains
2973
+ and Category of noetherian rings
2974
+ and Category of infinite enumerated sets
2975
+ and Category of metric spaces)
2976
+
2977
+ The element class of a join category depends only on the
2978
+ element class of its super categories::
2979
+
2980
+ sage: Category.join([Groups(), Posets()])._make_named_class_key("element_class")
2981
+ (<class 'sage.categories.groups.Groups.element_class'>,
2982
+ <class 'sage.categories.posets.Posets.element_class'>)
2983
+ """
2984
+
2985
+ _make_named_class_cache = {}
2986
+
2987
+ _cmp_key = _cmp_key_named
2988
+
2989
+ def _subcategory_hook_(self, C):
2990
+ """
2991
+ A quick but partial test whether ``C`` is a subcategory of ``self``.
2992
+
2993
+ INPUT:
2994
+
2995
+ - ``C`` -- a category
2996
+
2997
+ OUTPUT:
2998
+
2999
+ ``False``, if ``C.parent_class`` is not a subclass of
3000
+ ``self.parent_class``, and :obj:`~sage.misc.unknown.Unknown`
3001
+ otherwise.
3002
+
3003
+ EXAMPLES::
3004
+
3005
+ sage: Bimodules(QQ,QQ)._subcategory_hook_(Modules(QQ))
3006
+ Unknown
3007
+ sage: Bimodules(QQ,QQ)._subcategory_hook_(Rings())
3008
+ False
3009
+ """
3010
+ if not issubclass(C.parent_class, self.parent_class):
3011
+ return False
3012
+ return Unknown
3013
+
3014
+
3015
+ #############################################################
3016
+ # Join of several categories
3017
+ #############################################################
3018
+
3019
+ class JoinCategory(CategoryWithParameters):
3020
+ """
3021
+ A class for joins of several categories. Do not use directly;
3022
+ see Category.join instead.
3023
+
3024
+ EXAMPLES::
3025
+
3026
+ sage: from sage.categories.category import JoinCategory
3027
+ sage: J = JoinCategory((Groups(), CommutativeAdditiveMonoids())); J
3028
+ Join of Category of groups and Category of commutative additive monoids
3029
+ sage: J.super_categories()
3030
+ [Category of groups, Category of commutative additive monoids]
3031
+ sage: J.all_super_categories(proper=True)
3032
+ [Category of groups, ..., Category of magmas,
3033
+ Category of commutative additive monoids, ..., Category of additive magmas,
3034
+ Category of sets, Category of sets with partial maps, Category of objects]
3035
+
3036
+ By :issue:`11935`, join categories and categories over base rings
3037
+ inherit from :class:`CategoryWithParameters`. This allows for
3038
+ sharing parent and element classes between similar categories. For
3039
+ example, since group algebras belong to a join category and since
3040
+ the underlying implementation is the same for all finite fields,
3041
+ we have::
3042
+
3043
+ sage: # needs sage.combinat sage.groups sage.rings.finite_rings
3044
+ sage: G = SymmetricGroup(10)
3045
+ sage: A3 = G.algebra(GF(3))
3046
+ sage: A5 = G.algebra(GF(5))
3047
+ sage: type(A3.category())
3048
+ <class 'sage.categories.category.JoinCategory_with_category'>
3049
+ sage: type(A3) is type(A5)
3050
+ True
3051
+
3052
+ .. automethod:: Category._repr_object_names
3053
+ .. automethod:: Category._repr_
3054
+ .. automethod:: Category._without_axioms
3055
+ """
3056
+
3057
+ def __init__(self, super_categories, **kwds):
3058
+ """
3059
+ Initialize this JoinCategory.
3060
+
3061
+ INPUT:
3062
+
3063
+ - ``super_categories`` -- categories to join; this category will
3064
+ consist of objects and morphisms that lie in all of these
3065
+ categories
3066
+
3067
+ - ``name`` -- ignored
3068
+
3069
+ TESTS::
3070
+
3071
+ sage: from sage.categories.category import JoinCategory
3072
+ sage: C = JoinCategory((Groups(), CommutativeAdditiveMonoids())); C
3073
+ Join of Category of groups and Category of commutative additive monoids
3074
+ sage: TestSuite(C).run()
3075
+ """
3076
+ assert len(super_categories) >= 2
3077
+ assert all(not isinstance(category, JoinCategory) for category in super_categories)
3078
+ # Use __super_categories to not overwrite the lazy attribute Category._super_categories
3079
+ # Maybe this would not be needed if the flattening/sorting is does consistently?
3080
+ self.__super_categories = list(super_categories)
3081
+ Category.__init__(self)
3082
+
3083
+ def _make_named_class_key(self, name):
3084
+ r"""
3085
+ Return what the element/parent/... classes depend on.
3086
+
3087
+ Since :issue:`11935`, the element/parent classes of a join
3088
+ category over base only depend on the element/parent class of
3089
+ its super categories.
3090
+
3091
+ .. SEEALSO::
3092
+
3093
+ - :meth:`CategoryWithParameters`
3094
+ - :meth:`CategoryWithParameters._make_named_class_key`
3095
+
3096
+ EXAMPLES::
3097
+
3098
+ sage: Modules(ZZ)._make_named_class_key('element_class')
3099
+ Join of Category of Dedekind domains
3100
+ and Category of euclidean domains
3101
+ and Category of noetherian rings
3102
+ and Category of infinite enumerated sets
3103
+ and Category of metric spaces
3104
+ sage: Modules(QQ)._make_named_class_key('parent_class')
3105
+ Join of Category of number fields
3106
+ and Category of quotient fields
3107
+ and Category of metric spaces
3108
+ sage: Schemes(Spec(ZZ))._make_named_class_key('parent_class')
3109
+ Category of schemes
3110
+ sage: ModularAbelianVarieties(QQ)._make_named_class_key('parent_class')
3111
+ Join of Category of number fields
3112
+ and Category of quotient fields
3113
+ and Category of metric spaces
3114
+ """
3115
+ return tuple(getattr(cat, name) for cat in self._super_categories)
3116
+
3117
+ def super_categories(self):
3118
+ """
3119
+ Return the immediate super categories, as per :meth:`Category.super_categories`.
3120
+
3121
+ EXAMPLES::
3122
+
3123
+ sage: from sage.categories.category import JoinCategory
3124
+ sage: JoinCategory((Semigroups(), FiniteEnumeratedSets())).super_categories()
3125
+ [Category of semigroups, Category of finite enumerated sets]
3126
+ """
3127
+ return self.__super_categories
3128
+
3129
+ def additional_structure(self):
3130
+ r"""
3131
+ Return ``None``.
3132
+
3133
+ Indeed, a join category defines no additional structure.
3134
+
3135
+ .. SEEALSO:: :meth:`Category.additional_structure`
3136
+
3137
+ EXAMPLES::
3138
+
3139
+ sage: Modules(ZZ).additional_structure()
3140
+ """
3141
+ return None
3142
+
3143
+ def _subcategory_hook_(self, category):
3144
+ """
3145
+ Return whether ``category`` is a subcategory of this join category.
3146
+
3147
+ INPUT:
3148
+
3149
+ - ``category`` -- a category
3150
+
3151
+ .. NOTE::
3152
+
3153
+ ``category`` is a sub-category of this join category if
3154
+ and only if it is a sub-category of all super categories
3155
+ of this join category.
3156
+
3157
+ EXAMPLES::
3158
+
3159
+ sage: base_cat = Category.join([NumberFields(), QuotientFields().Metric()])
3160
+ sage: cat = Category.join([Rings(), VectorSpaces(base_cat)])
3161
+ sage: QQ['x'].category().is_subcategory(cat) # indirect doctest
3162
+ True
3163
+ """
3164
+ return all(category.is_subcategory(X) for X in self._super_categories)
3165
+
3166
+ def is_subcategory(self, C):
3167
+ """
3168
+ Check whether this join category is subcategory of another
3169
+ category ``C``.
3170
+
3171
+ EXAMPLES::
3172
+
3173
+ sage: Category.join([Rings(),Modules(QQ)]).is_subcategory(Category.join([Rngs(),Bimodules(QQ,QQ)]))
3174
+ True
3175
+ """
3176
+ if C is self:
3177
+ return True
3178
+ hook = C._subcategory_hook_(self)
3179
+ if hook is Unknown:
3180
+ return any(X.is_subcategory(C) for X in self._super_categories)
3181
+ return hook
3182
+
3183
+ def _with_axiom(self, axiom):
3184
+ """
3185
+ Return the category obtained by adding an axiom to ``self``.
3186
+
3187
+ As mentioned in :meth:`Category._with_axiom`, this method should not be used directly
3188
+ except in internal code.
3189
+
3190
+ .. NOTE::
3191
+
3192
+ This is just an optimization of
3193
+ :meth:`Category._with_axiom`; it's not necessarily
3194
+ actually useful.
3195
+
3196
+ EXAMPLES::
3197
+
3198
+ sage: C = Category.join([Monoids(), Posets()])
3199
+ sage: C._with_axioms(["Finite"]) # not idiomatic
3200
+ Join of Category of finite monoids and Category of finite posets
3201
+ sage: C.Finite() # recommended
3202
+ Join of Category of finite monoids and Category of finite posets
3203
+
3204
+ TESTS:
3205
+
3206
+ Check that axiom categories for a join are reconstructed from
3207
+ the base categories::
3208
+
3209
+ sage: C = Category.join([Monoids(), Magmas().Commutative()])
3210
+ sage: C._with_axioms(["Finite"])
3211
+ Category of finite commutative monoids
3212
+
3213
+ This helps guaranteeing commutativity of taking axioms::
3214
+
3215
+ sage: Monoids().Finite().Commutative() is Monoids().Commutative().Finite()
3216
+ True
3217
+ """
3218
+ return Category.join([cat._with_axiom(axiom) for cat in self._super_categories])
3219
+
3220
+ @cached_method
3221
+ def _without_axiom(self, axiom):
3222
+ """
3223
+ Return this category with axiom ``axiom`` removed.
3224
+
3225
+ OUTPUT:
3226
+
3227
+ A category ``C`` which does not have axiom ``axiom`` and such
3228
+ that either ``C`` is ``self``, or adding back all the
3229
+ axioms of ``self`` gives back ``self``.
3230
+
3231
+ .. SEEALSO:: :meth:`Category._without_axiom`
3232
+
3233
+ .. WARNING:: This is not guaranteed to be robust.
3234
+
3235
+ EXAMPLES::
3236
+
3237
+ sage: C = Posets() & FiniteEnumeratedSets() & Sets().Facade(); C
3238
+ Category of facade finite enumerated posets
3239
+ sage: C._without_axiom("Facade")
3240
+ Category of finite enumerated posets
3241
+
3242
+ sage: C = Sets().Finite().Facade()
3243
+ sage: type(C)
3244
+ <class 'sage.categories.category.JoinCategory_with_category'>
3245
+ sage: C._without_axiom("Facade")
3246
+ Category of finite sets
3247
+ """
3248
+ result = Category.join(C._without_axiom(axiom) for C in self.super_categories())
3249
+ assert axiom not in result.axioms()
3250
+ assert result._with_axioms(self.axioms()) is self
3251
+ return result
3252
+
3253
+ def _without_axioms(self, named=False):
3254
+ """
3255
+ When adjoining axioms to a category, one often gets a join
3256
+ category; this method tries to recover the original
3257
+ category from this join category.
3258
+
3259
+ INPUT:
3260
+
3261
+ - ``named`` -- boolean (default: ``False``)
3262
+
3263
+ See :meth:`Category._without_axioms` for the description
3264
+ of the ``named`` parameter.
3265
+
3266
+ EXAMPLES::
3267
+
3268
+ sage: C = Category.join([Monoids(), Posets()]).Finite()
3269
+ sage: C._repr_(as_join=True)
3270
+ 'Join of Category of finite monoids and Category of finite posets'
3271
+ sage: C._without_axioms()
3272
+ Traceback (most recent call last):
3273
+ ...
3274
+ ValueError: This join category isn't built by adding axioms to a single category
3275
+ sage: C = Monoids().Infinite()
3276
+ sage: C._repr_(as_join=True)
3277
+ 'Join of Category of monoids and Category of infinite sets'
3278
+ sage: C._without_axioms()
3279
+ Category of magmas
3280
+ sage: C._without_axioms(named=True)
3281
+ Category of monoids
3282
+
3283
+ TESTS:
3284
+
3285
+ ``C`` is in fact a join category::
3286
+
3287
+ sage: from sage.categories.category import JoinCategory
3288
+ sage: isinstance(C, JoinCategory)
3289
+ True
3290
+ """
3291
+ axioms = self.axioms()
3292
+ for category in self._super_categories:
3293
+ if category._with_axioms(axioms) is self:
3294
+ return category._without_axioms(named=named)
3295
+ raise ValueError("This join category isn't built by adding axioms"
3296
+ " to a single category")
3297
+
3298
+ def _cmp_key(self):
3299
+ """
3300
+ Return a comparison key for ``self``.
3301
+
3302
+ See :meth:`Category._cmp_key` for the specifications.
3303
+
3304
+ EXAMPLES:
3305
+
3306
+ This raises an error since ``_cmp_key`` should not be called
3307
+ on join categories::
3308
+
3309
+ sage: (Magmas() & CommutativeAdditiveSemigroups())._cmp_key()
3310
+ Traceback (most recent call last):
3311
+ ...
3312
+ ValueError: _cmp_key should not be called on join categories
3313
+ """
3314
+ raise ValueError("_cmp_key should not be called on join categories")
3315
+
3316
+ def _repr_object_names(self):
3317
+ """
3318
+ Return the name of the objects of this category.
3319
+
3320
+ .. SEEALSO:: :meth:`Category._repr_object_names`, :meth:`_repr_`, :meth:`._without_axioms`
3321
+
3322
+ EXAMPLES::
3323
+
3324
+ sage: Groups().Finite().Commutative()._repr_(as_join=True)
3325
+ 'Join of Category of finite groups and Category of commutative groups'
3326
+ sage: Groups().Finite().Commutative()._repr_object_names()
3327
+ 'finite commutative groups'
3328
+
3329
+ This uses :meth:`._without_axioms` which may fail if this
3330
+ category is not obtained by adjoining axioms to some super
3331
+ categories::
3332
+
3333
+ sage: Category.join((Groups(), CommutativeAdditiveMonoids()))._repr_object_names()
3334
+ Traceback (most recent call last):
3335
+ ...
3336
+ ValueError: This join category isn't built by adding axioms to a single category
3337
+ """
3338
+ from sage.categories.category_with_axiom import CategoryWithAxiom
3339
+ return CategoryWithAxiom._repr_object_names_static(self._without_axioms(named=True), self.axioms())
3340
+
3341
+ def _repr_(self, as_join=False):
3342
+ """
3343
+ Print representation.
3344
+
3345
+ INPUT:
3346
+
3347
+ - ``as_join`` -- boolean (default: ``False``)
3348
+
3349
+ EXAMPLES::
3350
+
3351
+ sage: Category.join((Groups(), CommutativeAdditiveMonoids())) #indirect doctest
3352
+ Join of Category of groups and Category of commutative additive monoids
3353
+
3354
+ By default, when a join category is built from category by
3355
+ adjoining axioms, a nice name is printed out::
3356
+
3357
+ sage: Groups().Facade().Finite()
3358
+ Category of facade finite groups
3359
+
3360
+ But this is in fact really a join category::
3361
+
3362
+ sage: Groups().Facade().Finite()._repr_(as_join = True)
3363
+ 'Join of Category of finite groups and Category of facade sets'
3364
+
3365
+ The rationale is to make it more readable, and hide the
3366
+ technical details of how this category is constructed
3367
+ internally, especially since this construction is likely to
3368
+ change over time when new axiom categories are implemented.
3369
+
3370
+ This join category may possibly be obtained by adding axioms
3371
+ to different categories; so the result is not guaranteed to be
3372
+ unique; when this is not the case the first found is used.
3373
+
3374
+ .. SEEALSO:: :meth:`Category._repr_`, :meth:`_repr_object_names`
3375
+
3376
+ TESTS::
3377
+
3378
+ sage: Category.join((Sets().Facade(), Groups()))
3379
+ Category of facade groups
3380
+ """
3381
+ if not as_join:
3382
+ try:
3383
+ return super()._repr_()
3384
+ except ValueError:
3385
+ pass
3386
+ return "Join of " + " and ".join(str(cat) for cat in self._super_categories)
3387
+
3388
+ def __lean_init__(self):
3389
+ r"""
3390
+ Return the category as Lean mathlib input for a typeclass.
3391
+
3392
+ EXAMPLES::
3393
+
3394
+ sage: QQ.category()
3395
+ Join of Category of number fields and Category of quotient fields and Category of metric spaces
3396
+ sage: QQ.category().__lean_init__()
3397
+ Traceback (most recent call last):
3398
+ ...
3399
+ NotImplementedError
3400
+ """
3401
+ return " ".join(cat._lean_init_() for cat in self._super_categories)