passagemath-objects 10.6.47__cp311-cp311-macosx_13_0_x86_64.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 (280) hide show
  1. passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_objects/__init__.py +3 -0
  3. passagemath_objects-10.6.47.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.47.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.47.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.47.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_objects.py +37 -0
  8. sage/arith/all__sagemath_objects.py +5 -0
  9. sage/arith/long.pxd +411 -0
  10. sage/arith/numerical_approx.cpython-311-darwin.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-311-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-311-darwin.so +0 -0
  17. sage/categories/action.pxd +29 -0
  18. sage/categories/action.pyx +641 -0
  19. sage/categories/algebra_functor.py +745 -0
  20. sage/categories/all__sagemath_objects.py +33 -0
  21. sage/categories/basic.py +62 -0
  22. sage/categories/cartesian_product.py +295 -0
  23. sage/categories/category.py +3401 -0
  24. sage/categories/category_cy_helper.cpython-311-darwin.so +0 -0
  25. sage/categories/category_cy_helper.pxd +8 -0
  26. sage/categories/category_cy_helper.pyx +322 -0
  27. sage/categories/category_singleton.cpython-311-darwin.so +0 -0
  28. sage/categories/category_singleton.pxd +3 -0
  29. sage/categories/category_singleton.pyx +342 -0
  30. sage/categories/category_types.py +637 -0
  31. sage/categories/category_with_axiom.py +2876 -0
  32. sage/categories/covariant_functorial_construction.py +703 -0
  33. sage/categories/facade_sets.py +228 -0
  34. sage/categories/functor.cpython-311-darwin.so +0 -0
  35. sage/categories/functor.pxd +7 -0
  36. sage/categories/functor.pyx +691 -0
  37. sage/categories/homset.py +1338 -0
  38. sage/categories/homsets.py +364 -0
  39. sage/categories/isomorphic_objects.py +73 -0
  40. sage/categories/map.cpython-311-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-311-darwin.so +0 -0
  44. sage/categories/morphism.pxd +14 -0
  45. sage/categories/morphism.pyx +895 -0
  46. sage/categories/objects.py +167 -0
  47. sage/categories/primer.py +1696 -0
  48. sage/categories/pushout.py +4834 -0
  49. sage/categories/quotients.py +64 -0
  50. sage/categories/realizations.py +200 -0
  51. sage/categories/sets_cat.py +3290 -0
  52. sage/categories/sets_with_partial_maps.py +52 -0
  53. sage/categories/subobjects.py +64 -0
  54. sage/categories/subquotients.py +21 -0
  55. sage/categories/with_realizations.py +311 -0
  56. sage/cpython/__init__.py +19 -0
  57. sage/cpython/_py2_random.py +619 -0
  58. sage/cpython/all.py +3 -0
  59. sage/cpython/atexit.cpython-311-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-311-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-311-darwin.so +0 -0
  64. sage/cpython/cython_metaclass.h +117 -0
  65. sage/cpython/cython_metaclass.pxd +3 -0
  66. sage/cpython/cython_metaclass.pyx +130 -0
  67. sage/cpython/debug.cpython-311-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-311-darwin.so +0 -0
  70. sage/cpython/dict_del_by_value.pxd +9 -0
  71. sage/cpython/dict_del_by_value.pyx +191 -0
  72. sage/cpython/dict_internal.h +245 -0
  73. sage/cpython/getattr.cpython-311-darwin.so +0 -0
  74. sage/cpython/getattr.pxd +9 -0
  75. sage/cpython/getattr.pyx +439 -0
  76. sage/cpython/pycore_long.h +97 -0
  77. sage/cpython/pycore_long.pxd +10 -0
  78. sage/cpython/python_debug.h +44 -0
  79. sage/cpython/python_debug.pxd +47 -0
  80. sage/cpython/pyx_visit.h +13 -0
  81. sage/cpython/string.cpython-311-darwin.so +0 -0
  82. sage/cpython/string.pxd +76 -0
  83. sage/cpython/string.pyx +34 -0
  84. sage/cpython/string_impl.h +60 -0
  85. sage/cpython/type.cpython-311-darwin.so +0 -0
  86. sage/cpython/type.pxd +2 -0
  87. sage/cpython/type.pyx +40 -0
  88. sage/cpython/wrapperdescr.pxd +67 -0
  89. sage/ext/all__sagemath_objects.py +3 -0
  90. sage/ext/ccobject.h +64 -0
  91. sage/ext/cplusplus.pxd +17 -0
  92. sage/ext/mod_int.h +30 -0
  93. sage/ext/mod_int.pxd +24 -0
  94. sage/ext/stdsage.pxd +39 -0
  95. sage/groups/all__sagemath_objects.py +1 -0
  96. sage/groups/group.cpython-311-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-311-darwin.so +0 -0
  100. sage/groups/old.pxd +14 -0
  101. sage/groups/old.pyx +219 -0
  102. sage/libs/all__sagemath_objects.py +3 -0
  103. sage/libs/gmp/__init__.py +1 -0
  104. sage/libs/gmp/all.pxd +6 -0
  105. sage/libs/gmp/binop.pxd +23 -0
  106. sage/libs/gmp/misc.pxd +8 -0
  107. sage/libs/gmp/mpf.pxd +88 -0
  108. sage/libs/gmp/mpn.pxd +57 -0
  109. sage/libs/gmp/mpq.pxd +57 -0
  110. sage/libs/gmp/mpz.pxd +202 -0
  111. sage/libs/gmp/pylong.cpython-311-darwin.so +0 -0
  112. sage/libs/gmp/pylong.pxd +12 -0
  113. sage/libs/gmp/pylong.pyx +150 -0
  114. sage/libs/gmp/random.pxd +25 -0
  115. sage/libs/gmp/randomize.pxd +59 -0
  116. sage/libs/gmp/types.pxd +53 -0
  117. sage/libs/gmpxx.pxd +19 -0
  118. sage/misc/abstract_method.py +276 -0
  119. sage/misc/all__sagemath_objects.py +43 -0
  120. sage/misc/bindable_class.py +253 -0
  121. sage/misc/c3_controlled.cpython-311-darwin.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-311-darwin.so +0 -0
  125. sage/misc/cachefunc.pxd +43 -0
  126. sage/misc/cachefunc.pyx +3781 -0
  127. sage/misc/call.py +188 -0
  128. sage/misc/classcall_metaclass.cpython-311-darwin.so +0 -0
  129. sage/misc/classcall_metaclass.pxd +14 -0
  130. sage/misc/classcall_metaclass.pyx +599 -0
  131. sage/misc/constant_function.cpython-311-darwin.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-311-darwin.so +0 -0
  135. sage/misc/fast_methods.pxd +20 -0
  136. sage/misc/fast_methods.pyx +351 -0
  137. sage/misc/flatten.py +90 -0
  138. sage/misc/fpickle.cpython-311-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-311-darwin.so +0 -0
  141. sage/misc/function_mangling.pxd +11 -0
  142. sage/misc/function_mangling.pyx +308 -0
  143. sage/misc/inherit_comparison.cpython-311-darwin.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-311-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-311-darwin.so +0 -0
  149. sage/misc/lazy_attribute.pyx +607 -0
  150. sage/misc/lazy_format.py +135 -0
  151. sage/misc/lazy_import.cpython-311-darwin.so +0 -0
  152. sage/misc/lazy_import.pyx +1299 -0
  153. sage/misc/lazy_import_cache.py +36 -0
  154. sage/misc/lazy_list.cpython-311-darwin.so +0 -0
  155. sage/misc/lazy_list.pxd +19 -0
  156. sage/misc/lazy_list.pyx +1187 -0
  157. sage/misc/lazy_string.cpython-311-darwin.so +0 -0
  158. sage/misc/lazy_string.pxd +7 -0
  159. sage/misc/lazy_string.pyx +546 -0
  160. sage/misc/misc.py +1066 -0
  161. sage/misc/misc_c.cpython-311-darwin.so +0 -0
  162. sage/misc/misc_c.pxd +3 -0
  163. sage/misc/misc_c.pyx +766 -0
  164. sage/misc/namespace_package.py +37 -0
  165. sage/misc/nested_class.cpython-311-darwin.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-311-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-311-darwin.so +0 -0
  172. sage/misc/randstate.pxd +30 -0
  173. sage/misc/randstate.pyx +1059 -0
  174. sage/misc/repr.py +203 -0
  175. sage/misc/reset.cpython-311-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-311-darwin.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +275 -0
  180. sage/misc/sage_timeit_class.cpython-311-darwin.so +0 -0
  181. sage/misc/sage_timeit_class.pyx +120 -0
  182. sage/misc/sage_unittest.py +637 -0
  183. sage/misc/sageinspect.py +2768 -0
  184. sage/misc/session.cpython-311-darwin.so +0 -0
  185. sage/misc/session.pyx +392 -0
  186. sage/misc/superseded.py +557 -0
  187. sage/misc/test_nested_class.py +228 -0
  188. sage/misc/timing.py +264 -0
  189. sage/misc/unknown.py +222 -0
  190. sage/misc/verbose.py +253 -0
  191. sage/misc/weak_dict.cpython-311-darwin.so +0 -0
  192. sage/misc/weak_dict.pxd +15 -0
  193. sage/misc/weak_dict.pyx +1231 -0
  194. sage/modules/all__sagemath_objects.py +1 -0
  195. sage/modules/module.cpython-311-darwin.so +0 -0
  196. sage/modules/module.pxd +5 -0
  197. sage/modules/module.pyx +329 -0
  198. sage/rings/all__sagemath_objects.py +3 -0
  199. sage/rings/integer_fake.h +22 -0
  200. sage/rings/integer_fake.pxd +55 -0
  201. sage/sets/all__sagemath_objects.py +3 -0
  202. sage/sets/pythonclass.cpython-311-darwin.so +0 -0
  203. sage/sets/pythonclass.pxd +9 -0
  204. sage/sets/pythonclass.pyx +247 -0
  205. sage/structure/__init__.py +4 -0
  206. sage/structure/all.py +30 -0
  207. sage/structure/category_object.cpython-311-darwin.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-311-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-311-darwin.so +0 -0
  214. sage/structure/coerce_actions.pxd +27 -0
  215. sage/structure/coerce_actions.pyx +988 -0
  216. sage/structure/coerce_dict.cpython-311-darwin.so +0 -0
  217. sage/structure/coerce_dict.pxd +51 -0
  218. sage/structure/coerce_dict.pyx +1557 -0
  219. sage/structure/coerce_exceptions.py +23 -0
  220. sage/structure/coerce_maps.cpython-311-darwin.so +0 -0
  221. sage/structure/coerce_maps.pxd +28 -0
  222. sage/structure/coerce_maps.pyx +718 -0
  223. sage/structure/debug_options.cpython-311-darwin.so +0 -0
  224. sage/structure/debug_options.pxd +6 -0
  225. sage/structure/debug_options.pyx +54 -0
  226. sage/structure/dynamic_class.py +541 -0
  227. sage/structure/element.cpython-311-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-311-darwin.so +0 -0
  231. sage/structure/element_wrapper.pxd +12 -0
  232. sage/structure/element_wrapper.pyx +582 -0
  233. sage/structure/factorization.py +1422 -0
  234. sage/structure/factorization_integer.py +105 -0
  235. sage/structure/factory.cpython-311-darwin.so +0 -0
  236. sage/structure/factory.pyx +786 -0
  237. sage/structure/formal_sum.py +489 -0
  238. sage/structure/gens_py.py +73 -0
  239. sage/structure/global_options.py +1743 -0
  240. sage/structure/indexed_generators.py +863 -0
  241. sage/structure/list_clone.cpython-311-darwin.so +0 -0
  242. sage/structure/list_clone.pxd +65 -0
  243. sage/structure/list_clone.pyx +1867 -0
  244. sage/structure/list_clone_demo.cpython-311-darwin.so +0 -0
  245. sage/structure/list_clone_demo.pyx +248 -0
  246. sage/structure/list_clone_timings.py +179 -0
  247. sage/structure/list_clone_timings_cy.cpython-311-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-311-darwin.so +0 -0
  250. sage/structure/mutability.pxd +21 -0
  251. sage/structure/mutability.pyx +348 -0
  252. sage/structure/nonexact.py +69 -0
  253. sage/structure/parent.cpython-311-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-311-darwin.so +0 -0
  257. sage/structure/parent_base.pxd +13 -0
  258. sage/structure/parent_base.pyx +44 -0
  259. sage/structure/parent_gens.cpython-311-darwin.so +0 -0
  260. sage/structure/parent_gens.pxd +22 -0
  261. sage/structure/parent_gens.pyx +377 -0
  262. sage/structure/parent_old.cpython-311-darwin.so +0 -0
  263. sage/structure/parent_old.pxd +25 -0
  264. sage/structure/parent_old.pyx +294 -0
  265. sage/structure/proof/__init__.py +1 -0
  266. sage/structure/proof/all.py +243 -0
  267. sage/structure/proof/proof.py +300 -0
  268. sage/structure/richcmp.cpython-311-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-311-darwin.so +0 -0
  272. sage/structure/sage_object.pxd +3 -0
  273. sage/structure/sage_object.pyx +988 -0
  274. sage/structure/sage_object_test.py +19 -0
  275. sage/structure/sequence.py +937 -0
  276. sage/structure/set_factories.py +1178 -0
  277. sage/structure/set_factories_example.py +527 -0
  278. sage/structure/support_view.py +179 -0
  279. sage/structure/test_factory.py +56 -0
  280. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,1696 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Elements, parents, and categories in Sage: a primer
4
+
5
+ .. contents::
6
+ :depth: 2
7
+ :class: this-will-duplicate-information-and-it-is-still-useful-here
8
+
9
+ Abstract
10
+ ========
11
+
12
+ The purpose of categories in Sage is to translate the mathematical
13
+ concept of categories (category of groups, of vector spaces, ...)
14
+ into a concrete software engineering design pattern for:
15
+
16
+ - organizing and promoting generic code
17
+ - fostering consistency across the Sage library (naming
18
+ conventions, doc, tests)
19
+ - embedding more mathematical knowledge into the system
20
+
21
+ This design pattern is largely inspired from Axiom and its
22
+ followers (Aldor, Fricas, MuPAD, ...). It differs from those by:
23
+
24
+ - blending in the Magma inspired concept of Parent/Element
25
+
26
+ - being built on top of (and not into) the standard Python object
27
+ oriented and class hierarchy mechanism. This did not require
28
+ changing the language, and could in principle be implemented in
29
+ any language supporting the creation of new classes dynamically.
30
+
31
+ The general philosophy is that *Building mathematical information
32
+ into the system yields more expressive, more conceptual and, at
33
+ the end, easier to maintain and faster code* (within a programming
34
+ realm; this would not necessarily apply to specialized libraries
35
+ like gmp!).
36
+
37
+ One line pitch for mathematicians
38
+ ---------------------------------
39
+
40
+ Categories in Sage provide a library of interrelated bookshelves, with
41
+ each bookshelf containing algorithms, tests, documentation, or some
42
+ mathematical facts about the objects of a given category (e.g. groups).
43
+
44
+ One line pitch for programmers
45
+ ------------------------------
46
+
47
+ Categories in Sage provide a large hierarchy of abstract classes for
48
+ mathematical objects. To keep it maintainable, the inheritance
49
+ information between the classes is not hardcoded but instead
50
+ reconstructed dynamically from duplication free semantic information.
51
+
52
+ Introduction: Sage as a library of objects and algorithms
53
+ =========================================================
54
+
55
+ The Sage library, with more than one million lines of code,
56
+ documentation, and tests, implements:
57
+
58
+ - Thousands of different kinds of objects (classes):
59
+
60
+ Integers, polynomials, matrices, groups, number fields, elliptic
61
+ curves, permutations, morphisms, languages, ... and a few raccoons ...
62
+
63
+ - Tens of thousands methods and functions:
64
+
65
+ Arithmetic, integer and polynomial factorization, pattern matching
66
+ on words, ...
67
+
68
+ Some challenges
69
+ ---------------
70
+
71
+ - How to organize this library?
72
+
73
+ One needs some bookshelves to group together related objects and algorithms.
74
+
75
+ - How to ensure consistency?
76
+
77
+ Similar objects should behave similarly::
78
+
79
+ sage: Permutations(5).cardinality()
80
+ 120
81
+
82
+ sage: GL(2,2).cardinality() # needs sage.libs.gap sage.modules
83
+ 6
84
+
85
+ sage: A = random_matrix(ZZ, 6, 3, x=7) # needs sage.modules
86
+ sage: L = LatticePolytope(A.rows()) # needs sage.geometry.polyhedron sage.modules
87
+ sage: L.npoints() # oops! # random # needs palp sage.geometry.polyhedron sage.modules
88
+ 37
89
+
90
+ - How to ensure robustness?
91
+
92
+ - How to reduce duplication?
93
+
94
+ Example: binary powering::
95
+
96
+ sage: m = 3
97
+ sage: m^8 == m*m*m*m*m*m*m*m == ((m^2)^2)^2
98
+ True
99
+
100
+ ::
101
+
102
+ sage: # needs sage.modules, known bug: windows (crash - https://github.com/passagemath/passagemath/issues/1892#issuecomment-3673607183)
103
+ sage: m = random_matrix(QQ, 4, algorithm='echelonizable',
104
+ ....: rank=3, upper_bound=60)
105
+ sage: m^8 == m*m*m*m*m*m*m*m == ((m^2)^2)^2
106
+ True
107
+
108
+ We want to implement binary powering only once, as *generic* code
109
+ that will apply in all cases.
110
+
111
+
112
+ A bit of help from abstract algebra
113
+ ===================================
114
+
115
+ The hierarchy of categories
116
+ ---------------------------
117
+
118
+ What makes binary powering work in the above examples? In both cases,
119
+ we have *a set* endowed with a *multiplicative binary operation* which
120
+ is *associative* and which has a unit element. Such a set is called a
121
+ *monoid*, and binary powering (to a nonnegative power) works generally
122
+ for any monoid.
123
+
124
+ Sage knows about monoids::
125
+
126
+ sage: Monoids()
127
+ Category of monoids
128
+
129
+ and sure enough, binary powering is defined there::
130
+
131
+ sage: m._pow_int.__module__ # needs sage.modules
132
+ 'sage.categories.monoids'
133
+
134
+ That's our bookshelf! And it's used in many places::
135
+
136
+ sage: GL(2, ZZ) in Monoids() # needs sage.modules
137
+ True
138
+ sage: NN in Monoids()
139
+ True
140
+
141
+ For a less trivial bookshelf we can consider euclidean rings: once we
142
+ know how to do euclidean division in some set `R`, we can compute
143
+ gcd's in `R` generically using the Euclidean algorithm.
144
+
145
+ We are in fact very lucky: abstract algebra provides us right away
146
+ with a large and robust set of bookshelves which is the result of
147
+ centuries of work of mathematicians to identify the important
148
+ concepts. This includes for example::
149
+
150
+ sage: Sets()
151
+ Category of sets
152
+
153
+ sage: Groups()
154
+ Category of groups
155
+
156
+ sage: Rings()
157
+ Category of rings
158
+
159
+ sage: Fields()
160
+ Category of fields
161
+
162
+ sage: HopfAlgebras(QQ)
163
+ Category of Hopf algebras over Rational Field
164
+
165
+ Each of the above is called a *category*. It typically specifies what
166
+ are the operations on the elements, as well as the axioms satisfied by
167
+ those operations. For example the category of groups specifies that a
168
+ group is a set endowed with a binary operation (the multiplication)
169
+ which is associative and admits a unit and inverses.
170
+
171
+ Each set in Sage knows which bookshelf of generic algorithms it can
172
+ use, that is to which category it belongs::
173
+
174
+ sage: G = GL(2, ZZ) # needs sage.modules
175
+ sage: G.category() # needs sage.modules
176
+ Category of infinite groups
177
+
178
+ In fact a group is a semigroup, and Sage knows about this::
179
+
180
+ sage: Groups().is_subcategory(Semigroups())
181
+ True
182
+ sage: G in Semigroups() # needs sage.modules
183
+ True
184
+
185
+ Altogether, our group gets algorithms from a bunch of bookshelves::
186
+
187
+ sage: G.categories() # needs sage.modules
188
+ [Category of infinite groups, Category of groups, Category of monoids,
189
+ ...,
190
+ Category of magmas,
191
+ Category of infinite sets, ...]
192
+
193
+ Those can be viewed graphically::
194
+
195
+ sage: g = Groups().category_graph() # needs sage.graphs
196
+ sage: g.set_latex_options(format='dot2tex') # needs sage.graphs sage.modules sage.plot
197
+ sage: view(g) # not tested # needs sage.graphs sage.modules sage.plot
198
+
199
+ In case ``dot2tex`` is not available, you can use instead::
200
+
201
+ sage: g.show(vertex_shape=None, figsize=20) # needs sage.graphs sage.modules sage.plot
202
+
203
+ Here is an overview of all categories in Sage::
204
+
205
+ sage: g = sage.categories.category.category_graph() # needs sage.graphs sage.groups sage.modules
206
+ sage: g.set_latex_options(format='dot2tex') # needs sage.graphs sage.modules sage.plot
207
+ sage: view(g) # not tested # needs sage.graphs sage.modules sage.plot
208
+
209
+ Wrap-up: generic algorithms in Sage are organized in a hierarchy of
210
+ bookshelves modelled upon the usual hierarchy of categories provided
211
+ by abstract algebra.
212
+
213
+ .. _category-primer-parents-elements-categories:
214
+
215
+ Elements, Parents, Categories
216
+ -----------------------------
217
+
218
+ .. RUBRIC:: Parent
219
+
220
+ A *parent* is a Python instance modelling a set of mathematical
221
+ elements together with its additional (algebraic) structure.
222
+
223
+ Examples include the ring of integers, the group `S_3`, the set of
224
+ prime numbers, the set of linear maps between two given vector
225
+ spaces, and a given finite semigroup.
226
+
227
+ These sets are often equipped with additional structure: the set
228
+ of all integers forms a ring. The main way of encoding this
229
+ information is specifying which categories a parent belongs to.
230
+
231
+ It is completely possible to have different Python instances
232
+ modelling the same set of elements. For example, one might want
233
+ to consider the ring of integers, or the poset of integers under
234
+ their standard order, or the poset of integers under divisibility,
235
+ or the semiring of integers under the operations of maximum and
236
+ addition. Each of these would be a different instance, belonging
237
+ to different categories.
238
+
239
+ For a given model, there should be a unique instance in Sage
240
+ representing that parent::
241
+
242
+ sage: IntegerRing() is IntegerRing()
243
+ True
244
+
245
+ .. RUBRIC:: Element
246
+
247
+ An *element* is a Python instance modelling a mathematical element
248
+ of a set.
249
+
250
+ Examples of element include `5` in the integer ring, `x^3 - x` in
251
+ the polynomial ring in `x` over the rationals, `4 + O(3^3)` in the
252
+ 3-adics, the transposition `(1 2)` in `S_3`, and the identity
253
+ morphism in the set of linear maps from `\QQ^3` to `\QQ^3`.
254
+
255
+ Every element in Sage has a parent. The standard idiom in Sage
256
+ for creating elements is to create their parent, and then provide
257
+ enough data to define the element::
258
+
259
+ sage: R = PolynomialRing(ZZ, name='x')
260
+ sage: R([1,2,3])
261
+ 3*x^2 + 2*x + 1
262
+
263
+ One can also create elements using various methods on the parent
264
+ and arithmetic of elements::
265
+
266
+ sage: x = R.gen()
267
+ sage: 1 + 2*x + 3*x^2
268
+ 3*x^2 + 2*x + 1
269
+
270
+ Unlike parents, elements in Sage are not necessarily unique::
271
+
272
+ sage: ZZ(5040) is ZZ(5040)
273
+ False
274
+
275
+ Many parents model algebraic structures, and their elements
276
+ support arithmetic operations. One often further wants to do
277
+ arithmetic by combining elements from different parents: adding
278
+ together integers and rationals for example. Sage supports this
279
+ feature using coercion (see :mod:`sage.structure.coerce` for more
280
+ details).
281
+
282
+ It is possible for a parent to also have simultaneously the
283
+ structure of an element. Consider for example the monoid of all
284
+ finite groups, endowed with the Cartesian product operation.
285
+ Then, every finite group (which is a parent) is also an element of
286
+ this monoid. This is not yet implemented, and the design details
287
+ are not yet fixed but experiments are underway in this direction.
288
+
289
+ .. TODO:: Give a concrete example, typically using :class:`ElementWrapper`.
290
+
291
+ .. RUBRIC:: Category
292
+
293
+ A *category* is a Python instance modelling a mathematical category.
294
+
295
+ Examples of categories include the category of finite semigroups,
296
+ the category of all (Python) objects, the category of
297
+ `\ZZ`-algebras, and the category of Cartesian products of
298
+ `\ZZ`-algebras::
299
+
300
+ sage: FiniteSemigroups()
301
+ Category of finite semigroups
302
+ sage: Objects()
303
+ Category of objects
304
+ sage: Algebras(ZZ)
305
+ Category of algebras over Integer Ring
306
+ sage: Algebras(ZZ).CartesianProducts()
307
+ Category of Cartesian products of algebras over Integer Ring
308
+
309
+ Mind the 's' in the names of the categories above;
310
+ ``GroupAlgebra`` and ``GroupAlgebras`` are distinct things.
311
+
312
+ Every parent belongs to a collection of categories. Moreover,
313
+ categories are interrelated by the *super categories*
314
+ relation. For example, the category of rings is a super category
315
+ of the category of fields, because every field is also a ring.
316
+
317
+ A category serves two roles:
318
+
319
+ - to provide a model for the mathematical concept of a category
320
+ and the associated structures: homsets, morphisms, functorial
321
+ constructions, axioms.
322
+
323
+ - to organize and promote generic code, naming conventions,
324
+ documentation, and tests across similar mathematical structures.
325
+
326
+ .. RUBRIC:: CategoryObject
327
+
328
+ Objects of a mathematical category are not necessarily parents.
329
+ Parent has a superclass that provides a means of modeling such.
330
+
331
+ For example, the category of schemes does not have a faithful
332
+ forgetful functor to the category of sets, so it does not make
333
+ sense to talk about schemes as parents.
334
+
335
+ .. RUBRIC:: Morphisms, Homsets
336
+
337
+ As category theorists will expect, *Morphisms* and *Homsets* will
338
+ play an ever more important role, as support for them will
339
+ improve.
340
+
341
+ ----
342
+
343
+ Much of the mathematical information in Sage is encoded as relations
344
+ between elements and their parents, parents and their categories, and
345
+ categories and their super categories::
346
+
347
+ sage: 1.parent()
348
+ Integer Ring
349
+
350
+ sage: ZZ
351
+ Integer Ring
352
+
353
+ sage: ZZ.category()
354
+ Join of Category of Dedekind domains
355
+ and Category of euclidean domains
356
+ and Category of noetherian rings
357
+ and Category of infinite enumerated sets
358
+ and Category of metric spaces
359
+
360
+ sage: ZZ.categories()
361
+ [Join of Category of Dedekind domains
362
+ and Category of euclidean domains
363
+ and Category of noetherian rings
364
+ and Category of infinite enumerated sets
365
+ and Category of metric spaces,
366
+ Category of Dedekind domains,
367
+ Category of euclidean domains, Category of principal ideal domains,
368
+ Category of unique factorization domains, Category of gcd domains,
369
+ Category of integral domains, Category of domains, ...
370
+ Category of commutative rings, Category of rings, ...
371
+ Category of magmas and additive magmas, ...
372
+ Category of monoids, Category of semigroups,
373
+ Category of commutative magmas, Category of unital magmas, Category of magmas,
374
+ Category of commutative additive groups, ..., Category of additive magmas,
375
+ Category of infinite enumerated sets, Category of enumerated sets,
376
+ Category of infinite sets, Category of metric spaces,
377
+ Category of topological spaces, Category of sets,
378
+ Category of sets with partial maps,
379
+ Category of objects]
380
+
381
+ sage: g = EuclideanDomains().category_graph() # needs sage.graphs
382
+ sage: g.set_latex_options(format='dot2tex') # needs sage.graphs sage.plot
383
+ sage: view(g) # not tested # needs sage.graphs sage.plot
384
+
385
+ A bit of help from computer science
386
+ ===================================
387
+
388
+ Hierarchy of classes
389
+ --------------------
390
+
391
+ How are the bookshelves implemented in practice?
392
+
393
+ Sage uses the classical design paradigm of Object Oriented Programming
394
+ (OOP). Its fundamental principle is that any object that a program is
395
+ to manipulate should be modelled by an *instance* of a *class*. The
396
+ class implements:
397
+
398
+ - a *data structure*: which describes how the object is stored,
399
+ - *methods*: which describe the operations on the object.
400
+
401
+ The instance itself contains the data for the given object, according
402
+ to the specified data structure.
403
+
404
+ Hence, all the objects mentioned above should be instances of some
405
+ classes. For example, an integer in Sage is an instance of the class
406
+ :class:`Integer` (and it knows about it!)::
407
+
408
+ sage: i = 12
409
+ sage: type(i)
410
+ <class 'sage.rings.integer.Integer'>
411
+
412
+ Applying an operation is generally done by *calling a method*::
413
+
414
+ sage: i.factor()
415
+ 2^2 * 3
416
+
417
+ sage: # needs sage.symbolic
418
+ sage: x = var('x')
419
+ sage: p = 6*x^2 + 12*x + 6
420
+ sage: type(p)
421
+ <class 'sage.symbolic.expression.Expression'>
422
+ sage: p.factor()
423
+ 6*(x + 1)^2
424
+
425
+ sage: # needs sage.symbolic
426
+ sage: R.<x> = PolynomialRing(QQ, sparse=True)
427
+ sage: pQ = R(p)
428
+ sage: type(pQ)
429
+ <class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category.element_class'>
430
+ sage: pQ.factor()
431
+ (6) * (x + 1)^2
432
+
433
+ sage: # needs sage.symbolic
434
+ sage: pZ = ZZ['x'](p)
435
+ sage: type(pZ)
436
+ <class 'sage.rings.polynomial.polynomial_integer_dense_flint.Polynomial_integer_dense_flint'>
437
+ sage: pZ.factor()
438
+ 2 * 3 * (x + 1)^2
439
+
440
+ Factoring integers, expressions, or polynomials are distinct tasks,
441
+ with completely different algorithms. Yet, from a user (or caller)
442
+ point of view, all those objects can be manipulated alike. This
443
+ illustrates the OOP concepts of *polymorphism*, *data abstraction*,
444
+ and *encapsulation*.
445
+
446
+ Let us be curious, and see where some methods are defined. This can be
447
+ done by introspection::
448
+
449
+ sage: i._mul_?? # not tested
450
+
451
+ For plain Python methods, one can also just ask in which module they
452
+ are implemented::
453
+
454
+ sage: i._pow_.__module__ # not tested (Issue #24275)
455
+ 'sage.categories.semigroups'
456
+
457
+ sage: pQ._mul_.__module__ # needs sage.symbolic
458
+ 'sage.rings.polynomial.polynomial_element_generic'
459
+ sage: pQ._pow_.__module__ # not tested (Issue #24275) # needs sage.symbolic
460
+ 'sage.categories.semigroups'
461
+
462
+ We see that integers and polynomials have each their own
463
+ multiplication method: the multiplication algorithms are indeed
464
+ unrelated and deeply tied to their respective datastructures. On the
465
+ other hand, as we have seen above, they share the same powering method
466
+ because the set `\ZZ` of integers, and the set `\QQ[x]` of
467
+ polynomials are both semigroups. Namely, the class for integers and
468
+ the class for polynomials both derive from an *abstract class* for
469
+ semigroup elements, which factors out the *generic* methods like
470
+ ``_pow_``. This illustrates the use of *hierarchy of classes* to share
471
+ common code between classes having common behaviour.
472
+
473
+ OOP design is all about isolating the objects that one wants to model
474
+ together with their operations, and designing an appropriate hierarchy
475
+ of classes for organizing the code. As we have seen above, the design
476
+ of the class hierarchy is easy since it can be modelled upon the
477
+ hierarchy of categories (bookshelves). Here is for example a piece of
478
+ the hierarchy of classes for an element of a group of permutations::
479
+
480
+ sage: P = Permutations(4)
481
+ sage: m = P.an_element()
482
+ sage: for cls in m.__class__.mro(): print(cls)
483
+ <class 'sage.combinat.permutation.StandardPermutations_n_with_category.element_class'>
484
+ <class 'sage.combinat.permutation.StandardPermutations_n.Element'>
485
+ <class 'sage.combinat.permutation.Permutation'>
486
+ ...
487
+ <class 'sage.categories.groups.Groups.element_class'>
488
+ <class 'sage.categories.monoids.Monoids.element_class'>
489
+ ...
490
+ <class 'sage.categories.semigroups.Semigroups.element_class'>
491
+ ...
492
+
493
+ On the top, we see concrete classes that describe the data structure
494
+ for matrices and provide the operations that are tied to this data
495
+ structure. Then follow abstract classes that are attached to the
496
+ hierarchy of categories and provide generic algorithms.
497
+
498
+ The full hierarchy is best viewed graphically::
499
+
500
+ sage: g = class_graph(m.__class__) # needs sage.combinat sage.graphs
501
+ sage: g.set_latex_options(format='dot2tex') # needs sage.combinat sage.graphs sage.plot
502
+ sage: view(g) # not tested # needs sage.combinat sage.graphs sage.plot
503
+
504
+ Parallel hierarchy of classes for parents
505
+ -----------------------------------------
506
+
507
+ Let us recall that we do not just want to compute with elements of
508
+ mathematical sets, but with the sets themselves::
509
+
510
+ sage: ZZ.one()
511
+ 1
512
+
513
+ sage: R = QQ['x,y']
514
+ sage: R.krull_dimension()
515
+ 2
516
+ sage: A = R.quotient( R.ideal(x^2 - 2) )
517
+ sage: A.krull_dimension() # todo: not implemented
518
+
519
+ Here are some typical operations that one may want to carry on various
520
+ kinds of sets:
521
+
522
+ - The set of permutations of 5, the set of rational points of an
523
+ elliptic curve: counting, listing, random generation
524
+
525
+ - A language (set of words): rationality testing, counting elements,
526
+ generating series
527
+
528
+ - A finite semigroup: left/right ideals, center, representation theory
529
+
530
+ - A vector space, an algebra: Cartesian product, tensor product, quotient
531
+
532
+ Hence, following the OOP fundamental principle, parents should also be
533
+ modelled by instances of some (hierarchy of) classes. For example, our
534
+ group `G` is an instance of the following class::
535
+
536
+ sage: G = GL(2, ZZ) # needs sage.modules
537
+ sage: type(G) # needs sage.libs.gap sage.modules
538
+ <class 'sage.groups.matrix_gps.linear_gap.LinearMatrixGroup_gap_with_category'>
539
+
540
+ Here is a piece of the hierarchy of classes above it::
541
+
542
+ sage: for cls in G.__class__.mro(): print(cls) # needs sage.libs.gap sage.modules
543
+ <class 'sage.groups.matrix_gps.linear_gap.LinearMatrixGroup_gap_with_category'>
544
+ ...
545
+ <class 'sage.categories.groups.Groups.parent_class'>
546
+ <class 'sage.categories.monoids.Monoids.parent_class'>
547
+ <class 'sage.categories.semigroups.Semigroups.parent_class'>
548
+ ...
549
+
550
+ Note that the hierarchy of abstract classes is again attached to
551
+ categories and parallel to that we had seen for the elements. This is
552
+ best viewed graphically::
553
+
554
+ sage: # needs sage.combinat sage.graphs sage.modules sage.plot
555
+ sage: g = class_graph(m.__class__)
556
+ sage: g.relabel(lambda x: x.replace("_",r"\_"))
557
+ sage: g.set_latex_options(format='dot2tex')
558
+ sage: view(g) # not tested
559
+
560
+ .. NOTE::
561
+
562
+ This is a progress upon systems like Axiom or MuPAD where a parent
563
+ is modelled by the class of its elements; this oversimplification
564
+ leads to confusion between methods on parents and elements, and
565
+ makes parents special; in particular it prevents potentially
566
+ interesting constructions like "groups of groups".
567
+
568
+ Sage categories
569
+ ===============
570
+
571
+ Why this business of categories? And to start with, why don't we just
572
+ have a good old hierarchy of classes ``Group``, ``Semigroup``,
573
+ ``Magma``, ... ?
574
+
575
+ Dynamic hierarchy of classes
576
+ ----------------------------
577
+
578
+ As we have just seen, when we manipulate groups, we actually
579
+ manipulate several kinds of objects:
580
+
581
+ - groups
582
+ - group elements
583
+ - morphisms between groups
584
+ - and even the category of groups itself!
585
+
586
+ Thus, on the group bookshelf, we want to put generic code for each of
587
+ the above. We therefore need three, parallel hierarchies of abstract
588
+ classes:
589
+
590
+ - Group, Monoid, Semigroup, Magma, ...
591
+ - GroupElement, MonoidElement, SemigroupElement, MagmaElement, ...
592
+ - GroupMorphism, MonoidMorphism, SemigroupMorphism, MagmaMorphism, ...
593
+
594
+ (and in fact many more as we will see).
595
+
596
+ We could implement the above hierarchies as usual::
597
+
598
+ class Group(Monoid):
599
+ # generic methods that apply to all groups
600
+
601
+ class GroupElement(MonoidElement):
602
+ # generic methods that apply to all group elements
603
+
604
+ class GroupMorphism(MonoidMorphism):
605
+ # generic methods that apply to all group morphisms
606
+
607
+ And indeed that's how it was done in Sage before 2009, and there are
608
+ still many traces of this. The drawback of this approach is
609
+ duplication: the fact that a group is a monoid is repeated three times
610
+ above!
611
+
612
+ Instead, Sage now uses the following syntax, where the :class:`Groups`
613
+ bookshelf is structured into units with *nested classes*::
614
+
615
+ class Groups(Category):
616
+
617
+ def super_categories(self):
618
+ return [Monoids(), ...]
619
+
620
+ class ParentMethods:
621
+ # generic methods that apply to all groups
622
+
623
+ class ElementMethods:
624
+ # generic methods that apply to all group elements
625
+
626
+ class MorphismMethods:
627
+ # generic methods that apply to all group morphisms (not yet implemented)
628
+
629
+ class SubcategoryMethods:
630
+ # generic methods that apply to all subcategories of Groups()
631
+
632
+ With this syntax, the information that a group is a monoid is
633
+ specified only once, in the :meth:`Category.super_categories`
634
+ method. And indeed, when the category of inverse unital magmas was
635
+ introduced, there was a *single point of truth* to update in order to
636
+ reflect the fact that a group is an inverse unital magma::
637
+
638
+ sage: Groups().super_categories()
639
+ [Category of monoids, Category of inverse unital magmas]
640
+
641
+ The price to pay (there is no free lunch) is that some magic is
642
+ required to construct the actual hierarchy of classes for parents,
643
+ elements, and morphisms. Namely, ``Groups.ElementMethods`` should be
644
+ seen as just a bag of methods, and the actual class
645
+ ``Groups().element_class`` is constructed from it by adding the
646
+ appropriate super classes according to
647
+ ``Groups().super_categories()``::
648
+
649
+ sage: Groups().element_class
650
+ <class 'sage.categories.groups.Groups.element_class'>
651
+
652
+ sage: Groups().element_class.__bases__
653
+ (<class 'sage.categories.monoids.Monoids.element_class'>,
654
+ <class 'sage.categories.magmas.Magmas.Unital.Inverse.element_class'>)
655
+
656
+ We now see that the hierarchy of classes for parents and elements is
657
+ parallel to the hierarchy of categories::
658
+
659
+ sage: Groups().all_super_categories()
660
+ [Category of groups,
661
+ Category of monoids,
662
+ Category of semigroups,
663
+ ...
664
+ Category of magmas,
665
+ Category of sets,
666
+ ...]
667
+
668
+ sage: for cls in Groups().element_class.mro(): print(cls)
669
+ <class 'sage.categories.groups.Groups.element_class'>
670
+ <class 'sage.categories.monoids.Monoids.element_class'>
671
+ <class 'sage.categories.semigroups.Semigroups.element_class'>
672
+ ...
673
+ <class 'sage.categories.magmas.Magmas.element_class'>
674
+ ...
675
+ sage: for cls in Groups().parent_class.mro(): print(cls)
676
+ <class 'sage.categories.groups.Groups.parent_class'>
677
+ <class 'sage.categories.monoids.Monoids.parent_class'>
678
+ <class 'sage.categories.semigroups.Semigroups.parent_class'>
679
+ ...
680
+ <class 'sage.categories.magmas.Magmas.parent_class'>
681
+ ...
682
+
683
+ Another advantage of building the hierarchy of classes dynamically is
684
+ that, for parametrized categories, the hierarchy may depend on the
685
+ parameters. For example an algebra over `\QQ` is a `\QQ`-vector space,
686
+ but an algebra over `\ZZ` is not (it is just a `\ZZ`-module)!
687
+
688
+ .. NOTE::
689
+
690
+ At this point this whole infrastructure may feel like
691
+ overdesigning, right? We felt like this too! But we will see later
692
+ that, once one gets used to it, this approach scales very
693
+ naturally.
694
+
695
+ From a computer science point of view, this infrastructure
696
+ implements, on top of standard multiple inheritance, a dynamic
697
+ composition mechanism of mixin classes (:wikipedia:`Mixin`),
698
+ governed by mathematical properties.
699
+
700
+ For implementation details on how the hierarchy of classes for
701
+ parents and elements is constructed, see :class:`Category`.
702
+
703
+
704
+ .. _category-primer-subcategory:
705
+
706
+ On the category hierarchy: subcategories and super categories
707
+ -------------------------------------------------------------
708
+
709
+ We have seen above that, for example, the category of sets is a super
710
+ category of the category of groups. This models the fact that a group
711
+ can be unambiguously considered as a set by forgetting its group
712
+ operation. In object-oriented parlance, we want the relation "a group
713
+ *is a* set", so that groups can directly inherit code implemented on
714
+ sets.
715
+
716
+ Formally, a category ``Cs()`` is a *super category* of a category
717
+ ``Ds()`` if Sage considers any object of ``Ds()`` to be an object of
718
+ ``Cs()``, up to an implicit application of a canonical functor from
719
+ ``Ds()`` to ``Cs()``. This functor is normally an inclusion of
720
+ categories or a forgetful functor. Reciprocally, ``Ds()`` is said to
721
+ be a *subcategory* of ``Cs()``.
722
+
723
+ .. WARNING::
724
+
725
+ This terminology deviates from the usual mathematical definition
726
+ of *subcategory* and is subject to change. Indeed, the forgetful
727
+ functor from the category of groups to the category of sets is not
728
+ an inclusion of categories, as it is not injective: a given set
729
+ may admit more than one group structure. See :issue:`16183` for
730
+ more details. The name *supercategory* is also used with a
731
+ different meaning in certain areas of mathematics.
732
+
733
+ Categories are instances and have operations
734
+ --------------------------------------------
735
+
736
+ Note that categories themselves are naturally modelled by instances
737
+ because they can have operations of their own. An important one is::
738
+
739
+ sage: Groups().example() # needs sage.modules
740
+ General Linear Group of degree 4 over Rational Field
741
+
742
+ which gives an example of object of the category. Besides illustrating
743
+ the category, the example provides a minimal template for implementing
744
+ a new object in the category::
745
+
746
+ sage: S = Semigroups().example(); S
747
+ An example of a semigroup: the left zero semigroup
748
+
749
+ Its source code can be obtained by introspection::
750
+
751
+ sage: S?? # not tested
752
+
753
+ This example is also typically used for testing generic methods. See
754
+ :meth:`Category.example` for more.
755
+
756
+ Other operations on categories include querying the super categories
757
+ or the axioms satisfied by the operations of a category::
758
+
759
+ sage: Groups().super_categories()
760
+ [Category of monoids, Category of inverse unital magmas]
761
+ sage: Groups().axioms()
762
+ frozenset({'Associative', 'Inverse', 'Unital'})
763
+
764
+ or constructing the intersection of two categories, or the smallest
765
+ category containing them::
766
+
767
+ sage: Groups() & FiniteSets()
768
+ Category of finite groups
769
+ sage: Algebras(QQ) | Groups()
770
+ Category of monoids
771
+
772
+ Specifications and generic documentation
773
+ ----------------------------------------
774
+
775
+ Categories do not only contain code but also the specifications of the
776
+ operations. In particular a list of mandatory and optional methods to
777
+ be implemented can be found by introspection with::
778
+
779
+ sage: Groups().required_methods()
780
+ {'element': {'optional': ['_mul_'], 'required': []},
781
+ 'parent': {'optional': [], 'required': ['__contains__']}}
782
+
783
+ Documentation about those methods can be obtained with::
784
+
785
+ sage: G = Groups()
786
+ sage: G.element_class._mul_? # not tested
787
+ sage: G.parent_class.one? # not tested
788
+
789
+ See also the :func:`abstract_method` decorator.
790
+
791
+ .. WARNING::
792
+
793
+ Well, more precisely, that's how things should be, but there is
794
+ still some work to do in this direction. For example, the inverse
795
+ operation is not specified above. Also, we are still missing a
796
+ good programmatic syntax to specify the input and output types of
797
+ the methods. Finally, in many cases the implementer must provide
798
+ at least one of two methods, each having a default implementation
799
+ using the other one (e.g. listing or iterating for a finite
800
+ enumerated set); there is currently no good programmatic way to
801
+ specify this.
802
+
803
+ Generic tests
804
+ -------------
805
+
806
+ Another feature that parents and elements receive from categories is
807
+ generic tests; their purpose is to check (at least to some extent)
808
+ that the parent satisfies the required mathematical properties (is my
809
+ semigroup indeed associative?) and is implemented according to the
810
+ specifications (does the method ``an_element`` indeed return an
811
+ element of the parent?)::
812
+
813
+ sage: S = FiniteSemigroups().example(alphabet=('a', 'b'))
814
+ sage: TestSuite(S).run(verbose = True)
815
+ running ._test_an_element() . . . pass
816
+ running ._test_associativity() . . . pass
817
+ running ._test_cardinality() . . . pass
818
+ running ._test_category() . . . pass
819
+ running ._test_construction() . . . pass
820
+ running ._test_elements() . . .
821
+ Running the test suite of self.an_element()
822
+ running ._test_category() . . . pass
823
+ running ._test_eq() . . . pass
824
+ running ._test_new() . . . pass
825
+ running ._test_not_implemented_methods() . . . pass
826
+ running ._test_pickling() . . . pass
827
+ pass
828
+ running ._test_elements_eq_reflexive() . . . pass
829
+ running ._test_elements_eq_symmetric() . . . pass
830
+ running ._test_elements_eq_transitive() . . . pass
831
+ running ._test_elements_neq() . . . pass
832
+ running ._test_enumerated_set_contains() . . . pass
833
+ running ._test_enumerated_set_iter_cardinality() . . . pass
834
+ running ._test_enumerated_set_iter_list() . . . pass
835
+ running ._test_eq() . . . pass
836
+ running ._test_new() . . . pass
837
+ running ._test_not_implemented_methods() . . . pass
838
+ running ._test_pickling() . . . pass
839
+ running ._test_some_elements() . . . pass
840
+
841
+ Tests can be run individually::
842
+
843
+ sage: S._test_associativity()
844
+
845
+ Here is how to access the code of this test::
846
+
847
+ sage: S._test_associativity?? # not tested
848
+
849
+ Here is how to run the test on all elements::
850
+
851
+ sage: L = S.list()
852
+ sage: S._test_associativity(elements=L)
853
+
854
+ See :class:`TestSuite` for more information.
855
+
856
+ Let us see what happens when a test fails. Here we redefine the
857
+ product of `S` to something definitely not associative::
858
+
859
+ sage: S.product = lambda x, y: S("("+x.value +y.value+")")
860
+
861
+ And rerun the test::
862
+
863
+ sage: S._test_associativity(elements=L)
864
+ Traceback (most recent call last):
865
+ ...
866
+ File ".../sage/categories/semigroups.py", line ..., in _test_associativity
867
+ tester.assertTrue((x * y) * z == x * (y * z))
868
+ ...
869
+ AssertionError: '((aa)a)' != '(a(aa))'
870
+
871
+ We can recover instantly the actual values of ``x``, ``y``, ``z``, that is,
872
+ a counterexample to the associativity of our broken semigroup, using post
873
+ mortem introspection with the Python debugger ``pdb`` (this does not
874
+ work yet in the notebook)::
875
+
876
+ sage: import pdb
877
+ sage: pdb.pm() # not tested
878
+ > /opt/sage-5.11.rc1/local/lib/python/unittest/case.py(424)assertTrue()
879
+ -> raise self.failureException(msg)
880
+ (Pdb) u
881
+ > /opt/sage-5.11.rc1/local/lib/python2.7/site-packages/sage/categories/semigroups.py(145)_test_associativity()
882
+ -> tester.assertTrue((x * y) * z == x * (y * z))
883
+ (Pdb) p x, y, z
884
+ ('a', 'a', 'a')
885
+ (Pdb) p (x * y) * z
886
+ '((aa)a)'
887
+ (Pdb) p x * (y * z)
888
+ '(a(aa))'
889
+
890
+ Wrap-up
891
+ -------
892
+
893
+ - Categories provide a natural hierarchy of bookshelves to organize
894
+ not only code, but also specifications and testing tools.
895
+
896
+ - Everything about, say, algebras with a distinguished basis is
897
+ gathered in :class:`AlgebrasWithBasis` or its super categories.
898
+ This includes properties and algorithms for elements, parents,
899
+ morphisms, but also, as we will see, for constructions like
900
+ Cartesian products or quotients.
901
+
902
+ - The mathematical relations between elements, parents, and categories
903
+ translate dynamically into a traditional hierarchy of classes.
904
+
905
+ - This design enforces robustness and consistency, which is
906
+ particularly welcome given that Python is an interpreted language
907
+ without static type checking.
908
+
909
+ Case study
910
+ ==========
911
+
912
+ In this section, we study an existing parent in detail; a good followup is to
913
+ go through the :mod:`sage.categories.tutorial` or the thematic tutorial on
914
+ coercion and categories ("How to implement new algebraic structures in Sage")
915
+ to learn how to implement a new one!
916
+
917
+ We consider the example of finite semigroup provided by the category::
918
+
919
+ sage: S = FiniteSemigroups().example(); S
920
+ An example of a finite semigroup: the left regular band generated by ('a', 'b', 'c', 'd')
921
+ sage: S? # not tested
922
+
923
+ Where do all the operations on ``S`` and its elements come from?
924
+
925
+ ::
926
+
927
+ sage: x = S('a')
928
+
929
+ ``_repr_`` is a technical method which comes with the data structure
930
+ (:class:`ElementWrapper`); since it's implemented in Cython, we need
931
+ to use Sage's introspection tools to recover where it's implemented::
932
+
933
+ sage: x._repr_.__module__
934
+ sage: sage.misc.sageinspect.sage_getfile(x._repr_)
935
+ '.../sage/structure/element_wrapper.pyx'
936
+
937
+ ``_pow_int`` is a generic method for all finite semigroups::
938
+
939
+ sage: x._pow_int.__module__
940
+ 'sage.categories.semigroups'
941
+
942
+ ``__mul__`` is a generic method provided by the :class:`Magmas`
943
+ category (a *magma* is a set with an inner law `*`, not necessarily
944
+ associative). If the two arguments are in the same parent, it will
945
+ call the method ``_mul_``, and otherwise let the :mod:`coercion model
946
+ <sage.structure.coerce>` try to discover how to do the
947
+ multiplication::
948
+
949
+ sage: x.__mul__?? # not tested
950
+
951
+ Since it is a speed critical method, it is implemented in Cython
952
+ in a separate file::
953
+
954
+ sage: x._mul_.__module__
955
+ 'sage.categories.coercion_methods'
956
+
957
+ ``_mul_`` is a default implementation, also provided by the
958
+ :class:`Magmas` category, that delegates the work to the method
959
+ ``product`` of the parent (following the advice: if you do not know
960
+ what to do, ask your parent); it's also a speed critical method::
961
+
962
+ sage: x._mul_?? # not tested
963
+ sage: x._mul_.__module__
964
+ 'sage.categories.coercion_methods'
965
+ sage: x._mul_.__func__ is Magmas.ElementMethods._mul_parent
966
+ True
967
+
968
+ ``product`` is a mathematical method implemented by the parent::
969
+
970
+ sage: S.product.__module__
971
+ 'sage.categories.examples.finite_semigroups'
972
+
973
+ ``cayley_graph`` is a generic method on the parent, provided by the
974
+ :class:`FiniteSemigroups` category::
975
+
976
+ sage: S.cayley_graph.__module__
977
+ 'sage.categories.semigroups'
978
+
979
+ ``multiplication_table`` is a generic method on the parent, provided
980
+ by the :class:`Magmas` category (it does not require associativity)::
981
+
982
+ sage: S.multiplication_table.__module__
983
+ 'sage.categories.magmas'
984
+
985
+ Consider now the implementation of the semigroup::
986
+
987
+ sage: S?? # not tested
988
+
989
+ This implementation specifies a data structure for the parents and the
990
+ elements, and makes a promise: the implemented parent is a finite
991
+ semigroup. Then it fulfills the promise by implementing the basic
992
+ operation ``product``. It also implements the optional method
993
+ ``semigroup_generators``. In exchange, `S` and its elements receive
994
+ generic implementations of all the other operations. `S` may override
995
+ any of those by more efficient ones. It may typically implement the
996
+ element method ``is_idempotent`` to always return ``True``.
997
+
998
+ A (not yet complete) list of mandatory and optional methods to be
999
+ implemented can be found by introspection with::
1000
+
1001
+ sage: FiniteSemigroups().required_methods()
1002
+ {'element': {'optional': ['_mul_'], 'required': []},
1003
+ 'parent': {'optional': ['semigroup_generators'],
1004
+ 'required': ['__contains__']}}
1005
+
1006
+ ``product`` does not appear in the list because a default implementation
1007
+ is provided in term of the method ``_mul_`` on elements. Of course, at
1008
+ least one of them should be implemented. On the other hand, a default
1009
+ implementation for ``__contains__`` is provided by :class:`Parent`.
1010
+
1011
+ Documentation about those methods can be obtained with::
1012
+
1013
+ sage: C = FiniteSemigroups().element_class
1014
+ sage: C._mul_? # not tested
1015
+
1016
+ See also the :func:`~sage.misc.abstract_method.abstract_method` decorator.
1017
+
1018
+ Here is the code for the finite semigroups category::
1019
+
1020
+ sage: FiniteSemigroups?? # not tested
1021
+
1022
+
1023
+ Specifying the category of a parent
1024
+ ===================================
1025
+
1026
+ Some parent constructors (not enough!) allow to specify the desired
1027
+ category for the parent. This can typically be used to specify
1028
+ additional properties of the parent that we know to hold a priori. For
1029
+ example, permutation groups are by default in the category of finite
1030
+ permutation groups (no surprise)::
1031
+
1032
+ sage: P = PermutationGroup([[(1,2,3)]]); P # needs sage.groups
1033
+ Permutation Group with generators [(1,2,3)]
1034
+ sage: P.category() # needs sage.groups
1035
+ Category of finite enumerated permutation groups
1036
+
1037
+ In this case, the group is commutative, so we can specify this::
1038
+
1039
+ sage: P = PermutationGroup([[(1,2,3)]], # needs sage.groups
1040
+ ....: category=PermutationGroups().Finite().Commutative()); P
1041
+ Permutation Group with generators [(1,2,3)]
1042
+ sage: P.category() # needs sage.groups
1043
+ Category of finite enumerated commutative permutation groups
1044
+
1045
+ This feature can even be used, typically in experimental code, to add
1046
+ more structure to existing parents, and in particular to add methods
1047
+ for the parents or the elements, without touching the code base::
1048
+
1049
+ sage: class Foos(Category):
1050
+ ....: def super_categories(self):
1051
+ ....: return [PermutationGroups().Finite().Commutative()]
1052
+ ....: class ParentMethods:
1053
+ ....: def foo(self): print("foo")
1054
+ ....: class ElementMethods:
1055
+ ....: def bar(self): print("bar")
1056
+
1057
+ sage: # needs sage.groups
1058
+ sage: P = PermutationGroup([[(1,2,3)]], category=Foos())
1059
+ sage: P.foo()
1060
+ foo
1061
+ sage: p = P.an_element()
1062
+ sage: p.bar()
1063
+ bar
1064
+
1065
+ In the long run, it would be thinkable to use this idiom to implement
1066
+ forgetful functors; for example the above group could be constructed
1067
+ as a plain set with::
1068
+
1069
+ sage: P = PermutationGroup([[(1,2,3)]], category=Sets()) # not implemented, needs sage.groups
1070
+
1071
+ At this stage though, this is still to be explored for robustness
1072
+ and practicality. For now, most parents that accept a category argument
1073
+ only accept a subcategory of the default one.
1074
+
1075
+ Scaling further: functorial constructions, axioms, ...
1076
+ ======================================================
1077
+
1078
+ In this section, we explore more advanced features of categories.
1079
+ Along the way, we illustrate that a large hierarchy of categories is
1080
+ desirable to model complicated mathematics, and that scaling to
1081
+ support such a large hierarchy is the driving motivation for the
1082
+ design of the category infrastructure.
1083
+
1084
+ .. _category-primer-functorial-constructions:
1085
+
1086
+ Functorial constructions
1087
+ ------------------------
1088
+
1089
+ Sage has support for a certain number of so-called *covariant
1090
+ functorial constructions* which can be used to construct new parents
1091
+ from existing ones while carrying over as much as possible of their
1092
+ algebraic structure. This includes:
1093
+
1094
+ - Cartesian products:
1095
+ See :const:`~sage.categories.cartesian_product.cartesian_product`.
1096
+
1097
+ - Tensor products:
1098
+ See :const:`~sage.categories.tensor.tensor`.
1099
+
1100
+ - Subquotients / quotients / subobjects / isomorphic objects:
1101
+ See:
1102
+
1103
+ - :meth:`Sets().Subquotients <Sets.SubcategoryMethods.Subquotients>`,
1104
+ - :meth:`Sets().Quotients <Sets.SubcategoryMethods.Quotients>`,
1105
+ - :meth:`Sets().Subobjects <Sets.SubcategoryMethods.Subobjects>`,
1106
+ - :meth:`Sets().IsomorphicObjects <Sets.SubcategoryMethods.IsomorphicObjects>`
1107
+
1108
+ - Dual objects:
1109
+ See :meth:`Modules().DualObjects <Modules.SubcategoryMethods.DualObjects>`.
1110
+
1111
+ - Algebras, as in group algebras, monoid algebras, ...:
1112
+ See: :meth:`Sets.ParentMethods.algebra`.
1113
+
1114
+ Let for example `A` and `B` be two parents, and let us construct the
1115
+ Cartesian product `A \times B \times B`::
1116
+
1117
+ sage: A = AlgebrasWithBasis(QQ).example(); A.rename('A') # needs sage.combinat sage.modules
1118
+ sage: B = HopfAlgebrasWithBasis(QQ).example(); B.rename('B') # needs sage.groups sage.modules
1119
+ sage: C = cartesian_product([A, B, B]); C # needs sage.combinat sage.groups sage.modules
1120
+ A (+) B (+) B
1121
+
1122
+ In which category should this new parent be? Since `A` and `B` are
1123
+ vector spaces, the result is, as a vector space, the direct sum
1124
+ `A \oplus B \oplus B`, hence the notation. Also, since both `A` and `B`
1125
+ are monoids, `A \times B \times B` is naturally endowed with a monoid
1126
+ structure for pointwise multiplication::
1127
+
1128
+ sage: C in Monoids() # needs sage.combinat sage.groups sage.modules
1129
+ True
1130
+
1131
+ the unit being the Cartesian product of the units of the operands::
1132
+
1133
+ sage: C.one() # needs sage.combinat sage.groups sage.modules
1134
+ B[(0, word: )] + B[(1, ())] + B[(2, ())]
1135
+ sage: cartesian_product([A.one(), B.one(), B.one()]) # needs sage.combinat sage.groups sage.modules
1136
+ B[(0, word: )] + B[(1, ())] + B[(2, ())]
1137
+
1138
+ The pointwise product can be implemented generically for all magmas
1139
+ (i.e. sets endowed with a multiplicative operation) that are
1140
+ constructed as Cartesian products. It's thus implemented in the
1141
+ :class:`Magmas` category::
1142
+
1143
+ sage: C.product.__module__ # needs sage.combinat sage.groups sage.modules
1144
+ 'sage.categories.magmas'
1145
+
1146
+ More specifically, keeping on using nested classes to structure the
1147
+ code, the product method is put in the nested class
1148
+ :class:`Magmas.CartesianProducts.ParentMethods`::
1149
+
1150
+ class Magmas(Category):
1151
+ class ParentMethods:
1152
+ # methods for magmas
1153
+ class ElementMethods:
1154
+ # methods for elements of magmas
1155
+ class CartesianProduct(CartesianProductCategory):
1156
+ class ParentMethods:
1157
+ # methods for magmas that are constructed as Cartesian products
1158
+ def product(self, x, y):
1159
+ # ...
1160
+ class ElementMethods:
1161
+ # ...
1162
+
1163
+ .. NOTE::
1164
+
1165
+ The support for nested classes in Python is relatively
1166
+ recent. Their intensive use for the category infrastructure did
1167
+ reveal some glitches in their implementation, in particular around
1168
+ class naming and introspection. Sage currently works around the
1169
+ more annoying ones but some remain visible. See
1170
+ e.g. :mod:`sage.misc.test_nested_class`.
1171
+
1172
+
1173
+ Let us now look at the categories of ``C``::
1174
+
1175
+ sage: C.categories() # needs sage.combinat sage.groups sage.modules
1176
+ [Category of finite dimensional Cartesian products of algebras with basis over Rational Field, ...
1177
+ Category of Cartesian products of algebras over Rational Field, ...
1178
+ Category of Cartesian products of semigroups, Category of semigroups, ...
1179
+ Category of Cartesian products of magmas, ..., Category of magmas, ...
1180
+ Category of Cartesian products of additive magmas, ..., Category of additive magmas,
1181
+ Category of Cartesian products of sets, Category of sets, ...]
1182
+
1183
+ This reveals the parallel hierarchy of categories for Cartesian
1184
+ products of semigroups magmas, ... We are thus glad that Sage uses
1185
+ its knowledge that a monoid is a semigroup to automatically deduce
1186
+ that a Cartesian product of monoids is a Cartesian product of
1187
+ semigroups, and build the hierarchy of classes for parents and
1188
+ elements accordingly.
1189
+
1190
+ In general, the Cartesian product of `A` and `B` can potentially be an
1191
+ algebra, a coalgebra, a differential module, and be finite
1192
+ dimensional, or graded, or .... This can only be decided at runtime,
1193
+ by introspection into the properties of `A` and `B`; furthermore, the
1194
+ number of possible combinations (e.g. finite dimensional differential
1195
+ algebra) grows exponentially with the number of properties.
1196
+
1197
+ .. _category-primer-axioms:
1198
+
1199
+ Axioms
1200
+ ------
1201
+
1202
+ First examples
1203
+ ^^^^^^^^^^^^^^
1204
+
1205
+ We have seen that Sage is aware of the axioms satisfied by, for
1206
+ example, groups::
1207
+
1208
+ sage: Groups().axioms()
1209
+ frozenset({'Associative', 'Inverse', 'Unital'})
1210
+
1211
+ In fact, the category of groups can be *defined* by stating that a
1212
+ group is a magma, that is a set endowed with an internal binary
1213
+ multiplication, which satisfies the above axioms. Accordingly, we can
1214
+ construct the category of groups from the category of magmas::
1215
+
1216
+ sage: Magmas().Associative().Unital().Inverse()
1217
+ Category of groups
1218
+
1219
+ In general, we can construct new categories in Sage by specifying the
1220
+ axioms that are satisfied by the operations of the super
1221
+ categories. For example, starting from the category of magmas, we can
1222
+ construct all the following categories just by specifying the axioms
1223
+ satisfied by the multiplication::
1224
+
1225
+ sage: Magmas()
1226
+ Category of magmas
1227
+ sage: Magmas().Unital()
1228
+ Category of unital magmas
1229
+
1230
+ ::
1231
+
1232
+ sage: Magmas().Commutative().Unital()
1233
+ Category of commutative unital magmas
1234
+ sage: Magmas().Unital().Commutative()
1235
+ Category of commutative unital magmas
1236
+
1237
+ ::
1238
+
1239
+ sage: Magmas().Associative()
1240
+ Category of semigroups
1241
+
1242
+ ::
1243
+
1244
+ sage: Magmas().Associative().Unital()
1245
+ Category of monoids
1246
+
1247
+ ::
1248
+
1249
+ sage: Magmas().Associative().Unital().Commutative()
1250
+ Category of commutative monoids
1251
+
1252
+ ::
1253
+
1254
+ sage: Magmas().Associative().Unital().Inverse()
1255
+ Category of groups
1256
+
1257
+
1258
+ Axioms and categories with axioms
1259
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1260
+
1261
+ Here, ``Associative``, ``Unital``, ``Commutative`` are axioms. In
1262
+ general, any category ``Cs`` in Sage can declare a new axiom
1263
+ ``A``. Then, the *category with axiom* ``Cs.A()`` models the
1264
+ subcategory of the objects of ``Cs`` satisfying the axiom
1265
+ ``A``. Similarly, for any subcategory ``Ds`` of ``Cs``, ``Ds.A()``
1266
+ models the subcategory of the objects of ``Ds`` satisfying the axiom
1267
+ ``A``. In most cases, it's a *full subcategory* (see
1268
+ :wikipedia:`Subcategory`).
1269
+
1270
+ For example, the category of sets defines the ``Finite`` axiom, and
1271
+ this axiom is available in the subcategory of groups::
1272
+
1273
+ sage: Sets().Finite()
1274
+ Category of finite sets
1275
+ sage: Groups().Finite()
1276
+ Category of finite groups
1277
+
1278
+ The meaning of each axiom is described in the documentation of the
1279
+ corresponding method, which can be obtained as usual by
1280
+ introspection::
1281
+
1282
+ sage: C = Groups()
1283
+ sage: C.Finite? # not tested
1284
+
1285
+ The purpose of categories with axioms is no different from other
1286
+ categories: to provide bookshelves of code, documentation,
1287
+ mathematical knowledge, tests, for their objects. The extra feature is
1288
+ that, when intersecting categories, axioms are automatically combined
1289
+ together::
1290
+
1291
+ sage: C = Magmas().Associative() & Magmas().Unital().Inverse() & Sets().Finite(); C
1292
+ Category of finite groups
1293
+ sage: sorted(C.axioms())
1294
+ ['Associative', 'Finite', 'Inverse', 'Unital']
1295
+
1296
+ For a more advanced example, Sage knows that a ring is a set `C`
1297
+ endowed with a multiplication which distributes over addition, such
1298
+ that `(C, +)` is a commutative additive group and `(C, *)` is a monoid::
1299
+
1300
+ sage: C = (CommutativeAdditiveGroups() & Monoids()).Distributive(); C
1301
+ Category of rings
1302
+
1303
+ sage: sorted(C.axioms())
1304
+ ['AdditiveAssociative', 'AdditiveCommutative', 'AdditiveInverse',
1305
+ 'AdditiveUnital', 'Associative', 'Distributive', 'Unital']
1306
+
1307
+ The infrastructure allows for specifying further deduction rules, in
1308
+ order to encode mathematical facts like Wedderburn's theorem::
1309
+
1310
+ sage: DivisionRings() & Sets().Finite()
1311
+ Category of finite enumerated fields
1312
+
1313
+ .. NOTE::
1314
+
1315
+ When an axiom specifies the properties of some operations in Sage,
1316
+ the notations for those operations are tied to this axiom. For
1317
+ example, as we have seen above, we need two distinct axioms for
1318
+ associativity: the axiom "AdditiveAssociative" is about the
1319
+ properties of the addition `+`, whereas the axiom "Associative" is
1320
+ about the properties of the multiplication `*`.
1321
+
1322
+ We are touching here an inherent limitation of the current
1323
+ infrastructure. There is indeed no support for providing generic
1324
+ code that is independent of the notations. In particular, the
1325
+ category hierarchy about additive structures (additive monoids,
1326
+ additive groups, ...) is completely duplicated by that for
1327
+ multiplicative structures (monoids, groups, ...).
1328
+
1329
+ As far as we know, none of the existing computer algebra systems
1330
+ has a good solution for this problem. The difficulty is that this
1331
+ is not only about a single notation but a bunch of operators and
1332
+ methods: ``+, -, zero, summation, sum, ...`` in one case, ``*, /,
1333
+ one, product, prod, factor, ...`` in the other. Sharing something
1334
+ between the two hierarchies of categories would only be useful if
1335
+ one could write generic code that applies in both cases; for that
1336
+ one needs to somehow automatically substitute the right operations
1337
+ in the right spots in the code. That's kind of what we are doing
1338
+ manually between
1339
+ e.g. :meth:`AdditiveMagmas.ParentMethods.addition_table` and
1340
+ :meth:`Magmas.ParentMethods.multiplication_table`, but doing this
1341
+ systematically is a different beast from what we have been doing
1342
+ so far with just usual inheritance.
1343
+
1344
+ .. _category-primer-axioms-single-entry-point:
1345
+
1346
+ Single entry point and name space usage
1347
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1348
+
1349
+ A nice feature of the notation ``Cs.A()`` is that, from a single entry
1350
+ point (say the category :class:`Magmas` as above), one can explore a
1351
+ whole range of related categories, typically with the help of
1352
+ introspection to discover which axioms are available, and without
1353
+ having to import new Python modules. This feature will be used in
1354
+ :issue:`15741` to unclutter the global name space from, for example,
1355
+ the many variants of the category of algebras like::
1356
+
1357
+ sage: FiniteDimensionalAlgebrasWithBasis(QQ)
1358
+ Category of finite dimensional algebras with basis over Rational Field
1359
+
1360
+ There will of course be a deprecation step, but it's recommended to
1361
+ prefer right away the more flexible notation::
1362
+
1363
+ sage: Algebras(QQ).WithBasis().FiniteDimensional()
1364
+ Category of finite dimensional algebras with basis over Rational Field
1365
+
1366
+ .. TOPIC:: Design discussion
1367
+
1368
+ How far should this be pushed? :class:`Fields` should definitely
1369
+ stay, but should :class:`FiniteGroups` or :class:`DivisionRings`
1370
+ be removed from the global namespace? Do we want to further
1371
+ completely deprecate the notation ``FiniteGroups()`` in favor of
1372
+ ``Groups().Finite()``?
1373
+
1374
+ .. _category-primer-axioms-explosion:
1375
+
1376
+ On the potential combinatorial explosion of categories with axioms
1377
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1378
+
1379
+ Even for a very simple category like ``Magmas``, there are about `2^5`
1380
+ potential combinations of the axioms! Think about what this becomes
1381
+ for a category with two operations `+` and `*`::
1382
+
1383
+ sage: C = (Magmas() & AdditiveMagmas()).Distributive(); C
1384
+ Category of distributive magmas and additive magmas
1385
+
1386
+ sage: CAA = C.Associative().AdditiveAssociative()
1387
+ sage: CAA.AdditiveCommutative().AdditiveUnital().AdditiveInverse()
1388
+ Category of rngs
1389
+
1390
+ sage: CAA.AdditiveCommutative().AdditiveUnital().Unital()
1391
+ Category of semirings
1392
+
1393
+ sage: CAA.AdditiveCommutative().AdditiveUnital().AdditiveInverse().Unital()
1394
+ Category of rings
1395
+
1396
+ sage: Rings().Division()
1397
+ Category of division rings
1398
+
1399
+ sage: Rings().Division().Commutative()
1400
+ Category of fields
1401
+
1402
+ sage: Rings().Division().Finite()
1403
+ Category of finite enumerated fields
1404
+
1405
+ or for more advanced categories::
1406
+
1407
+ sage: g = HopfAlgebras(QQ).WithBasis().Graded().Connected().category_graph() # needs sage.graphs
1408
+ sage: g.set_latex_options(format='dot2tex') # needs sage.graphs sage.plot
1409
+ sage: view(g) # not tested # needs sage.graphs sage.plot
1410
+
1411
+ Difference between axioms and regressive covariant functorial constructions
1412
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1413
+
1414
+ Our running examples here will be the axiom ``FiniteDimensional`` and
1415
+ the regressive covariant functorial construction ``Graded``. Let
1416
+ ``Cs`` be some subcategory of ``Modules``, say the category of modules
1417
+ itself::
1418
+
1419
+ sage: Cs = Modules(QQ)
1420
+
1421
+ Then, ``Cs.FiniteDimensional()`` (respectively ``Cs.Graded()``) is the
1422
+ subcategory of the objects ``O`` of ``Cs`` which are finite
1423
+ dimensional (respectively graded).
1424
+
1425
+ Let also ``Ds`` be a subcategory of ``Cs``, say::
1426
+
1427
+ sage: Ds = Algebras(QQ)
1428
+
1429
+ A finite dimensional algebra is also a finite dimensional module::
1430
+
1431
+ sage: Algebras(QQ).FiniteDimensional().is_subcategory(Modules(QQ).FiniteDimensional())
1432
+ True
1433
+
1434
+ Similarly a graded algebra is also a graded module::
1435
+
1436
+ sage: Algebras(QQ).Graded().is_subcategory( Modules(QQ).Graded() )
1437
+ True
1438
+
1439
+ This is the *covariance* property: for ``A`` an axiom or a covariant
1440
+ functorial construction, if ``Ds`` is a subcategory of ``Cs``, then
1441
+ ``Ds.A()`` is a subcategory of ``Cs.A()``.
1442
+
1443
+ What happens if we consider reciprocally an object of ``Cs.A()`` which
1444
+ is also in ``Ds``? A finite dimensional module which is also an
1445
+ algebra is a finite dimensional algebra::
1446
+
1447
+ sage: Modules(QQ).FiniteDimensional() & Algebras(QQ)
1448
+ Category of finite dimensional algebras over Rational Field
1449
+
1450
+ On the other hand, a graded module `O` which is also an algebra is not
1451
+ necessarily a graded algebra! Indeed, the grading on `O` may not be
1452
+ compatible with the product on `O`::
1453
+
1454
+ sage: Modules(QQ).Graded() & Algebras(QQ)
1455
+ Join of Category of algebras over Rational Field
1456
+ and Category of graded vector spaces over Rational Field
1457
+
1458
+ The relevant difference between ``FiniteDimensional`` and ``Graded``
1459
+ is that ``FiniteDimensional`` is a statement about the properties of
1460
+ ``O`` seen as a module (and thus does not depend on the given
1461
+ category), whereas ``Graded`` is a statement about the properties of
1462
+ ``O`` and all its operations in the given category.
1463
+
1464
+ In general, if a category satisfies a given axiom, any subcategory
1465
+ also satisfies that axiom. Another formulation is that, for an axiom
1466
+ ``A`` defined in a super category ``Cs`` of ``Ds``, ``Ds.A()`` is the
1467
+ intersection of the categories ``Ds`` and ``Cs.A()``::
1468
+
1469
+ sage: As = Algebras(QQ).FiniteDimensional(); As
1470
+ Category of finite dimensional algebras over Rational Field
1471
+ sage: Bs = Algebras(QQ) & Modules(QQ).FiniteDimensional(); As
1472
+ Category of finite dimensional algebras over Rational Field
1473
+ sage: As is Bs
1474
+ True
1475
+
1476
+ An immediate consequence is that, as we have already noticed, axioms
1477
+ commute::
1478
+
1479
+ sage: As = Algebras(QQ).FiniteDimensional().WithBasis(); As
1480
+ Category of finite dimensional algebras with basis over Rational Field
1481
+ sage: Bs = Algebras(QQ).WithBasis().FiniteDimensional(); Bs
1482
+ Category of finite dimensional algebras with basis over Rational Field
1483
+ sage: As is Bs
1484
+ True
1485
+
1486
+ On the other hand, axioms do not necessarily commute with functorial
1487
+ constructions, even if the current printout may missuggest so::
1488
+
1489
+ sage: As = Algebras(QQ).Graded().WithBasis(); As
1490
+ Category of graded algebras with basis over Rational Field
1491
+ sage: Bs = Algebras(QQ).WithBasis().Graded(); Bs
1492
+ Category of graded algebras with basis over Rational Field
1493
+ sage: As is Bs
1494
+ False
1495
+
1496
+ This is because ``Bs`` is the category of algebras endowed with basis,
1497
+ which are further graded; in particular the basis must respect the
1498
+ grading (i.e. be made of homogeneous elements). On the other hand,
1499
+ ``As`` is the category of graded algebras, which are further endowed
1500
+ with some basis; that basis need not respect the grading. In fact
1501
+ ``As`` is really a join category::
1502
+
1503
+ sage: type(As)
1504
+ <class 'sage.categories.category.JoinCategory_with_category'>
1505
+ sage: As._repr_(as_join=True)
1506
+ 'Join of Category of algebras with basis over Rational Field and Category of graded algebras over Rational Field'
1507
+
1508
+ .. TODO::
1509
+
1510
+ Improve the printing of functorial constructions and joins to
1511
+ raise this potentially dangerous ambiguity.
1512
+
1513
+
1514
+ Further reading on axioms
1515
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
1516
+
1517
+ We refer to :mod:`sage.categories.category_with_axiom` for how to
1518
+ implement axioms.
1519
+
1520
+ Wrap-up
1521
+ -------
1522
+
1523
+ As we have seen, there is a combinatorial explosion of possible
1524
+ classes. Constructing by hand the full class hierarchy would not scale
1525
+ unless one would restrict to a very rigid subset. Even if it was
1526
+ possible to construct automatically the full hierarchy, this would not
1527
+ scale with respect to system resources.
1528
+
1529
+ When designing software systems with large hierarchies of abstract
1530
+ classes for business objects, the difficulty is usually to identify a
1531
+ proper set of key concepts. Here we are lucky, as the key concepts
1532
+ have been long identified and are relatively few:
1533
+
1534
+ - Operations (`+`, `*`, ...)
1535
+ - Axioms on those operations (associativity, ...)
1536
+ - Constructions (Cartesian products, ...)
1537
+
1538
+ Better, those concepts are sufficiently well known so that a user can
1539
+ reasonably be expected to be familiar with the concepts that are
1540
+ involved for his own needs.
1541
+
1542
+ Instead, the difficulty is concentrated in the huge number of possible
1543
+ combinations, an unpredictable large subset of which being potentially
1544
+ of interest; at the same time, only a small -- but moving -- subset
1545
+ has code naturally attached to it.
1546
+
1547
+ This has led to the current design, where one focuses on writing the
1548
+ relatively few classes for which there is actual code or mathematical
1549
+ information, and lets Sage *compose dynamically and lazily* those
1550
+ building blocks to construct the minimal hierarchy of classes needed
1551
+ for the computation at hand. This allows for the infrastructure to
1552
+ scale smoothly as bookshelves are added, extended, or reorganized.
1553
+
1554
+
1555
+ Writing a new category
1556
+ ======================
1557
+
1558
+ Each category `C` **must** be provided with a method
1559
+ ``C.super_categories()`` and *can* be provided with a method
1560
+ ``C._subcategory_hook_(D)``. Also, it may be needed to insert `C` into
1561
+ the output of the ``super_categories()`` method of some other
1562
+ category. This determines the position of `C` in the category graph.
1563
+
1564
+ A category *may* provide methods that can be used by all its objects,
1565
+ respectively by all elements of its objects.
1566
+
1567
+ Each category *should* come with a good example, in
1568
+ :mod:`sage.categories.examples`.
1569
+
1570
+ Inserting the new category into the category graph
1571
+ --------------------------------------------------
1572
+
1573
+ ``C.super_categories()`` *must* return a list of categories, namely
1574
+ the *immediate* super categories of `C`. Of course, if you know that
1575
+ your new category `C` is an immediate super category of some existing
1576
+ category `D`, then you should also update the method
1577
+ ``D.super_categories`` to include `C`.
1578
+
1579
+ The immediate super categories of `C` *should not* be :class:`join
1580
+ categories <.category.JoinCategory>`. Furthermore, one always should have::
1581
+
1582
+ Cs().is_subcategory( Category.join(Cs().super_categories()) )
1583
+
1584
+ Cs()._cmp_key > other._cmp_key for other in Cs().super_categories()
1585
+
1586
+ This is checked by :meth:`~sage.categories.category.Category._test_category`.
1587
+
1588
+ In several cases, the category `C` is directly provided with a generic
1589
+ implementation of ``super_categories``; a typical example is when `C`
1590
+ implements an axiom or a functorial construction; in such a case, `C`
1591
+ may implement ``C.extra_super_categories()`` to complement the super
1592
+ categories discovered by the generic implementation. This method needs
1593
+ not return immediate super categories; instead it's usually best to
1594
+ specify the largest super category providing the desired mathematical
1595
+ information. For example, the category
1596
+ :class:`Magmas.Commutative.Algebras` just states that the algebra of a
1597
+ commutative magma is a commutative magma. This is sufficient to let
1598
+ Sage deduce that it's in fact a commutative algebra.
1599
+
1600
+ Methods for objects and elements
1601
+ --------------------------------
1602
+
1603
+ Different objects of the same category share some algebraic features, and
1604
+ very often these features can be encoded in a method, in a generic way.
1605
+ For example, for every commutative additive monoid, it makes sense to ask
1606
+ for the sum of a list of elements. Sage's category framework allows to
1607
+ provide a generic implementation for all objects of a category.
1608
+
1609
+ If you want to provide your new category with generic methods for
1610
+ objects (or elements of objects), then you simply add a nested class
1611
+ called ``ParentMethods`` (or ``ElementMethods``). The methods of that
1612
+ class will automatically become methods of the objects (or the
1613
+ elements). For instance::
1614
+
1615
+ sage: P.<x,y> = ZZ[]
1616
+ sage: P.prod([x,y,2])
1617
+ 2*x*y
1618
+ sage: P.prod.__module__
1619
+ 'sage.categories.monoids'
1620
+ sage: P.prod.__func__ is raw_getattr(Monoids().ParentMethods, "prod")
1621
+ True
1622
+
1623
+ We recommend to study the code of one example::
1624
+
1625
+ sage: C = CommutativeAdditiveMonoids()
1626
+ sage: C?? # not tested
1627
+
1628
+ .. _category-primer-category-order:
1629
+
1630
+ On the order of super categories
1631
+ --------------------------------
1632
+
1633
+ The generic method ``C.all_super_categories()`` determines recursively
1634
+ the list of *all* super categories of `C`.
1635
+
1636
+ The order of the categories in this list does influence the
1637
+ inheritance of methods for parents and elements. Namely, if `P` is an
1638
+ object in the category `C` and if `C_1` and `C_2` are both super
1639
+ categories of `C` defining some method ``foo`` in ``ParentMethods``,
1640
+ then `P` will use `C_1`'s version of ``foo`` if and only if `C_1`
1641
+ appears in ``C.all_super_categories()`` before `C_2`.
1642
+
1643
+ However this must be considered as an *implementation detail*: if
1644
+ `C_1` and `C_2` are incomparable categories, then the order in which
1645
+ they appear must be mathematically irrelevant: in particular, the
1646
+ methods ``foo`` in `C_1` and `C_2` must have the same semantic. Code
1647
+ should not rely on any specific order, as it is subject to later
1648
+ change. Whenever one of the implementations is preferred in some common
1649
+ subcategory of `C_1` and `C_2`, for example for efficiency reasons,
1650
+ the ambiguity should be resolved explicitly by defining a
1651
+ method ``foo`` in this category. See the method ``some_elements`` in
1652
+ the code of the category :class:`FiniteCoxeterGroups` for an example.
1653
+
1654
+ Since :issue:`11943`, ``C.all_super_categories()`` is computed by the
1655
+ so-called ``C3`` algorithm used by Python to compute Method Resolution
1656
+ Order of new-style classes. Thus the order in
1657
+ ``C.all_super_categories()``, ``C.parent_class.mro()`` and
1658
+ ``C.element_class.mro()`` are guaranteed to be consistent.
1659
+
1660
+ Since :issue:`13589`, the ``C3`` algorithm is put under control of some
1661
+ total order on categories. This order is not necessarily meaningful,
1662
+ but it guarantees that ``C3`` always finds a consistent Method
1663
+ Resolution Order. For background, see
1664
+ :mod:`sage.misc.c3_controlled`. A visible effect is that the order in
1665
+ which categories are specified in ``C.super_categories()``, or in a
1666
+ join category, no longer influences the result of
1667
+ ``C.all_super_categories()``.
1668
+
1669
+ Subcategory hook (advanced optimization feature)
1670
+ ------------------------------------------------
1671
+
1672
+ The default implementation of the method ``C.is_subcategory(D)`` is to
1673
+ look up whether `D` appears in ``C.all_super_categories()``. However,
1674
+ building the list of all the super categories of `C` is an expensive
1675
+ operation that is sometimes best avoided. For example, if both `C` and
1676
+ `D` are categories defined over a base, but the bases differ, then one
1677
+ knows right away that they can not be subcategories of each other.
1678
+
1679
+ When such a short-path is known, one can implement a method
1680
+ ``_subcategory_hook_``. Then, ``C.is_subcategory(D)`` first calls
1681
+ ``D._subcategory_hook_(C)``. If this returns ``Unknown``, then
1682
+ ``C.is_subcategory(D)`` tries to find ``D`` in
1683
+ ``C.all_super_categories()``. Otherwise, ``C.is_subcategory(D)``
1684
+ returns the result of ``D._subcategory_hook_(C)``.
1685
+
1686
+ By default, ``D._subcategory_hook_(C)`` tests whether
1687
+ ``issubclass(C.parent_class,D.parent_class)``, which is very often
1688
+ giving the right answer::
1689
+
1690
+ sage: Rings()._subcategory_hook_(Algebras(QQ))
1691
+ True
1692
+ sage: HopfAlgebras(QQ)._subcategory_hook_(Algebras(QQ))
1693
+ False
1694
+ sage: Algebras(QQ)._subcategory_hook_(HopfAlgebras(QQ))
1695
+ True
1696
+ """