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