passagemath-objects 10.6.41__cp314-cp314t-macosx_13_0_arm64.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.

Potentially problematic release.


This version of passagemath-objects might be problematic. Click here for more details.

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.41.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.41.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.41.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.41.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-314t-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-314t-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2112 -0
  43. sage/categories/morphism.cpython-314t-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 +3228 -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-314t-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-314t-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-314t-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-314t-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-314t-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-314t-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-314t-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-314t-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +276 -0
  180. sage/misc/sage_timeit_class.cpython-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-314t-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-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-314t-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-314t-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-314t-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-314t-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-314t-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-314t-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-314t-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,1338 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Homsets
4
+
5
+ The class :class:`Hom` is the base class used to represent sets of morphisms
6
+ between objects of a given category.
7
+ :class:`Hom` objects are usually "weakly" cached upon creation so that they
8
+ don't have to be generated over and over but can be garbage collected together
9
+ with the corresponding objects when these are not strongly ref'ed anymore.
10
+
11
+ EXAMPLES:
12
+
13
+ In the following, the :class:`Hom` object is indeed cached::
14
+
15
+ sage: K = GF(17)
16
+ sage: H = Hom(ZZ, K)
17
+ sage: H
18
+ Set of Homomorphisms from Integer Ring to Finite Field of size 17
19
+ sage: H is Hom(ZZ, K)
20
+ True
21
+
22
+ Nonetheless, garbage collection occurs when the original references are
23
+ overwritten::
24
+
25
+ sage: # needs sage.libs.pari
26
+ sage: for p in prime_range(200):
27
+ ....: K = GF(p)
28
+ ....: H = Hom(ZZ, K)
29
+ sage: import gc
30
+ sage: _ = gc.collect()
31
+ sage: from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn as FF
32
+ sage: L = [x for x in gc.get_objects() if isinstance(x, FF)]
33
+ sage: len(L)
34
+ 1
35
+ sage: L
36
+ [Finite Field of size 199]
37
+
38
+ AUTHORS:
39
+
40
+ - David Kohel and William Stein
41
+
42
+ - David Joyner (2005-12-17): added examples
43
+
44
+ - William Stein (2006-01-14): Changed from Homspace to Homset.
45
+
46
+ - Nicolas M. Thiery (2008-12-): Updated for the new category framework
47
+
48
+ - Simon King (2011-12): Use a weak cache for homsets
49
+
50
+ - Simon King (2013-02): added examples
51
+ """
52
+
53
+ # ****************************************************************************
54
+ # Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu>,
55
+ # William Stein <wstein@gmail.com>
56
+ #
57
+ # Distributed under the terms of the GNU General Public License (GPL)
58
+ #
59
+ # This code is distributed in the hope that it will be useful,
60
+ # but WITHOUT ANY WARRANTY; without even the implied warranty
61
+ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
62
+ #
63
+ # See the GNU General Public License for more details; the full text
64
+ # is available at:
65
+ #
66
+ # https://www.gnu.org/licenses/
67
+ # ****************************************************************************
68
+
69
+ from sage.categories import morphism
70
+ from sage.categories.category import Category, JoinCategory
71
+ from sage.misc.fast_methods import WithEqualityById
72
+ from sage.misc.lazy_attribute import lazy_attribute
73
+
74
+ ###################################
75
+ # Use the weak "triple" dictionary
76
+ # introduced in github issue #715
77
+ # with weak values, as introduced in
78
+ # github issue #14159
79
+ from sage.structure.coerce_dict import TripleDict
80
+ from sage.structure.dynamic_class import dynamic_class
81
+ from sage.structure.parent import Parent, Set_generic
82
+ from sage.structure.unique_representation import UniqueRepresentation
83
+
84
+ _cache = TripleDict(weak_values=True)
85
+
86
+
87
+ def Hom(X, Y, category=None, check=True):
88
+ """
89
+ Create the space of homomorphisms from X to Y in the category ``category``.
90
+
91
+ INPUT:
92
+
93
+ - ``X`` -- an object of a category
94
+
95
+ - ``Y`` -- an object of a category
96
+
97
+ - ``category`` -- a category in which the morphisms must be
98
+ (default: the meet of the categories of ``X`` and ``Y``);
99
+ both ``X`` and ``Y`` must belong to that category
100
+
101
+ - ``check`` -- boolean (default: ``True``); whether to check the
102
+ input, and in particular that ``X`` and ``Y`` belong to
103
+ ``category``.
104
+
105
+ OUTPUT: a homset in category
106
+
107
+ EXAMPLES::
108
+
109
+ sage: V = VectorSpace(QQ, 3) # needs sage.modules
110
+ sage: Hom(V, V) # needs sage.modules
111
+ Set of Morphisms (Linear Transformations) from
112
+ Vector space of dimension 3 over Rational Field to
113
+ Vector space of dimension 3 over Rational Field
114
+ sage: G = AlternatingGroup(3) # needs sage.groups
115
+ sage: Hom(G, G) # needs sage.groups
116
+ Set of Morphisms
117
+ from Alternating group of order 3!/2 as a permutation group
118
+ to Alternating group of order 3!/2 as a permutation group
119
+ in Category of finite enumerated permutation groups
120
+ sage: Hom(ZZ, QQ, Sets())
121
+ Set of Morphisms from Integer Ring to Rational Field in Category of sets
122
+
123
+ sage: Hom(FreeModule(ZZ, 1), FreeModule(QQ, 1)) # needs sage.modules
124
+ Set of Morphisms
125
+ from Ambient free module of rank 1 over the principal ideal domain Integer Ring
126
+ to Vector space of dimension 1 over Rational Field
127
+ in Category of commutative additive groups
128
+ sage: Hom(FreeModule(QQ, 1), FreeModule(ZZ, 1)) # needs sage.modules
129
+ Set of Morphisms
130
+ from Vector space of dimension 1 over Rational Field
131
+ to Ambient free module of rank 1 over the principal ideal domain Integer Ring
132
+ in Category of commutative additive groups
133
+
134
+ Here, we test against a memory leak that has been fixed at :issue:`11521` by
135
+ using a weak cache::
136
+
137
+ sage: # needs sage.libs.pari
138
+ sage: for p in prime_range(10^3):
139
+ ....: K = GF(p)
140
+ ....: a = K(0)
141
+ sage: import gc
142
+ sage: gc.collect() # random
143
+ 624
144
+ sage: from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn as FF
145
+ sage: L = [x for x in gc.get_objects() if isinstance(x, FF)]
146
+ sage: len(L), L[0]
147
+ (1, Finite Field of size 997)
148
+
149
+ To illustrate the choice of the category, we consider the
150
+ following parents as running examples::
151
+
152
+ sage: X = ZZ; X
153
+ Integer Ring
154
+ sage: Y = SymmetricGroup(3); Y # needs sage.groups
155
+ Symmetric group of order 3! as a permutation group
156
+
157
+ By default, the smallest category containing both ``X`` and ``Y``,
158
+ is used::
159
+
160
+ sage: Hom(X, Y) # needs sage.groups
161
+ Set of Morphisms from Integer Ring
162
+ to Symmetric group of order 3! as a permutation group
163
+ in Category of enumerated monoids
164
+
165
+ Otherwise, if ``category`` is specified, then ``category`` is used,
166
+ after checking that ``X`` and ``Y`` are indeed in ``category``::
167
+
168
+ sage: Hom(X, Y, Magmas()) # needs sage.groups
169
+ Set of Morphisms
170
+ from Integer Ring
171
+ to Symmetric group of order 3! as a permutation group
172
+ in Category of magmas
173
+
174
+ sage: Hom(X, Y, Groups()) # needs sage.groups
175
+ Traceback (most recent call last):
176
+ ...
177
+ ValueError: Integer Ring is not in Category of groups
178
+
179
+ A parent (or a parent class of a category) may specify how to
180
+ construct certain homsets by implementing a method ``_Hom_(self,
181
+ codomain, category)``. This method should either construct the
182
+ requested homset or raise a :exc:`TypeError`. This hook is currently
183
+ mostly used to create homsets in some specific subclass of
184
+ :class:`Homset` (e.g. :class:`sage.rings.homset.RingHomset`)::
185
+
186
+ sage: Hom(QQ,QQ).__class__
187
+ <class 'sage.rings.homset.RingHomset_generic_with_category'>
188
+
189
+ Do not call this hook directly to create homsets, as it does not
190
+ handle unique representation::
191
+
192
+ sage: Hom(QQ,QQ) == QQ._Hom_(QQ, category=QQ.category())
193
+ True
194
+ sage: Hom(QQ,QQ) is QQ._Hom_(QQ, category=QQ.category())
195
+ False
196
+
197
+ TESTS:
198
+
199
+ Homset are unique parents::
200
+
201
+ sage: k = GF(5)
202
+ sage: H1 = Hom(k, k)
203
+ sage: H2 = Hom(k, k)
204
+ sage: H1 is H2
205
+ True
206
+
207
+ Moreover, if no category is provided, then the result is identical
208
+ with the result for the meet of the categories of the domain and
209
+ the codomain::
210
+
211
+ sage: Hom(QQ, ZZ) is Hom(QQ,ZZ, Category.meet([QQ.category(), ZZ.category()]))
212
+ True
213
+
214
+ Some doc tests in :mod:`sage.rings` (need to) break the unique
215
+ parent assumption. But if domain or codomain are not unique
216
+ parents, then the homset will not fit. That is to say, the hom set
217
+ found in the cache will have a (co)domain that is equal to, but
218
+ not identical with, the given (co)domain.
219
+
220
+ By :issue:`9138`, we abandon the uniqueness of homsets, if the
221
+ domain or codomain break uniqueness::
222
+
223
+ sage: from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict_domain
224
+ sage: P.<x,y,z>=MPolynomialRing_polydict_domain(QQ, 3, order='degrevlex')
225
+ sage: Q.<x,y,z>=MPolynomialRing_polydict_domain(QQ, 3, order='degrevlex')
226
+ sage: P == Q
227
+ True
228
+ sage: P is Q
229
+ False
230
+
231
+ Hence, ``P`` and ``Q`` are not unique parents. By consequence, the
232
+ following homsets aren't either::
233
+
234
+ sage: H1 = Hom(QQ,P)
235
+ sage: H2 = Hom(QQ,Q)
236
+ sage: H1 == H2
237
+ True
238
+ sage: H1 is H2
239
+ False
240
+
241
+ It is always the most recently constructed homset that remains in
242
+ the cache::
243
+
244
+ sage: H2 is Hom(QQ,Q)
245
+ True
246
+
247
+ Variation on the theme::
248
+
249
+ sage: # needs sage.modules
250
+ sage: U1 = FreeModule(ZZ, 2)
251
+ sage: U2 = FreeModule(ZZ, 2, inner_product_matrix=matrix([[1,0], [0,-1]]))
252
+ sage: U1 == U2, U1 is U2
253
+ (False, False)
254
+ sage: V = ZZ^3
255
+ sage: H1 = Hom(U1, V); H2 = Hom(U2, V)
256
+ sage: H1 == H2, H1 is H2
257
+ (False, False)
258
+ sage: H1 = Hom(V, U1); H2 = Hom(V, U2)
259
+ sage: H1 == H2, H1 is H2
260
+ (False, False)
261
+
262
+ Since :issue:`11900`, the meet of the categories of the given arguments is
263
+ used to determine the default category of the homset. This can also be a
264
+ join category, as in the following example::
265
+
266
+ sage: PA = Parent(category=Algebras(QQ))
267
+ sage: PJ = Parent(category=Rings() & Modules(QQ))
268
+ sage: Hom(PA, PJ)
269
+ Set of Homomorphisms
270
+ from <sage.structure.parent.Parent object at ...>
271
+ to <sage.structure.parent.Parent object at ...>
272
+ sage: Hom(PA, PJ).category()
273
+ Category of homsets of
274
+ unital magmas and right modules over Rational Field
275
+ and left modules over Rational Field
276
+ sage: Hom(PA, PJ, Rngs())
277
+ Set of Morphisms
278
+ from <sage.structure.parent.Parent object at ...>
279
+ to <sage.structure.parent.Parent object at ...> in Category of rngs
280
+
281
+ .. TODO::
282
+
283
+ - Design decision: how much of the homset comes from the
284
+ category of ``X`` and ``Y``, and how much from the specific
285
+ ``X`` and ``Y``. In particular, do we need several parent
286
+ classes depending on ``X`` and ``Y``, or does the difference
287
+ only lie in the elements (i.e. the morphism), and of course
288
+ how the parent calls their constructors.
289
+ - Specify the protocol for the ``_Hom_`` hook in case of ambiguity
290
+ (e.g. if both a parent and some category thereof provide one).
291
+
292
+ TESTS:
293
+
294
+ Facade parents over plain Python types are supported::
295
+
296
+ sage: from sage.sets.pythonclass import Set_PythonType
297
+ sage: R = Set_PythonType(int)
298
+ sage: S = Set_PythonType(float)
299
+ sage: Hom(R, S)
300
+ Set of Morphisms from Set of Python objects of class 'int'
301
+ to Set of Python objects of class 'float' in Category of infinite sets
302
+
303
+ Checks that the domain and codomain are in the specified
304
+ category. Case of a non parent::
305
+
306
+ sage: # needs sage.graphs
307
+ sage: S = SimplicialComplex([[1,2], [1,4]]); S.rename('S')
308
+ sage: Hom(S, S, SimplicialComplexes())
309
+ Set of Morphisms from S to S in Category of finite simplicial complexes
310
+ sage: Hom(Set(), S, Sets())
311
+ Set of Morphisms from {} to S in Category of sets
312
+ sage: Hom(S, Set(), Sets())
313
+ Set of Morphisms from S to {} in Category of sets
314
+ sage: H = Hom(S, S, ChainComplexes(QQ))
315
+ Traceback (most recent call last):
316
+ ...
317
+ ValueError: S is not in Category of chain complexes over Rational Field
318
+
319
+ Those checks are done with the natural idiom ``X in category``,
320
+ and not ``X.category().is_subcategory(category)`` as it used to be
321
+ before :issue:`16275` (see :issue:`15801` for a real use case)::
322
+
323
+ sage: # needs sage.graphs
324
+ sage: class PermissiveCategory(Category):
325
+ ....: def super_categories(self): return [Objects()]
326
+ ....: def __contains__(self, X): return True
327
+ sage: C = PermissiveCategory(); C.rename('Permissive category')
328
+ sage: S.category().is_subcategory(C)
329
+ False
330
+ sage: S in C
331
+ True
332
+ sage: Hom(S, S, C)
333
+ Set of Morphisms from S to S in Permissive category
334
+
335
+ With ``check=False``, uninitialized parents, as can appear upon
336
+ unpickling, are supported. Case of a parent::
337
+
338
+ sage: cls = type(Set())
339
+ sage: S = unpickle_newobj(cls, ()) # A non parent
340
+ sage: H = Hom(S, S, SimplicialComplexes(), check=False)
341
+ sage: H = Hom(S, S, Sets(), check=False)
342
+ sage: H = Hom(S, S, ChainComplexes(QQ), check=False)
343
+
344
+ Case of a non parent::
345
+
346
+ sage: # needs sage.graphs
347
+ sage: cls = type(SimplicialComplex([[1,2], [1,4]]))
348
+ sage: S = unpickle_newobj(cls, ())
349
+ sage: H = Hom(S, S, Sets(), check=False)
350
+ sage: H = Hom(S, S, Groups(), check=False)
351
+ sage: H = Hom(S, S, SimplicialComplexes(), check=False)
352
+
353
+ Typical example where unpickling involves calling Hom on an
354
+ uninitialized parent::
355
+
356
+ sage: P.<x,y> = QQ['x,y']
357
+ sage: Q = P.quotient([x^2 - 1, y^2 - 1])
358
+ sage: q = Q.an_element() # needs sage.libs.singular
359
+ sage: explain_pickle(dumps(Q)) # needs sage.libs.singular
360
+ pg_...
361
+ ... = pg_dynamic_class('QuotientRing_generic_with_category', (pg_QuotientRing_generic, pg_getattr(..., 'parent_class')), None, None, pg_QuotientRing_generic)
362
+ si... = unpickle_newobj(..., ())
363
+ ...
364
+ si... = pg_unpickle_MPolynomialRing_libsingular(..., ('x', 'y'), ...)
365
+ si... = ... pg_Hom(si..., si..., ...) ...
366
+ sage: Q == loads(dumps(Q))
367
+ True
368
+
369
+ Check that the ``_Hom_`` method of the ``category`` input is used::
370
+
371
+ sage: from sage.categories.category_types import Category_over_base_ring
372
+ sage: class ModulesWithHom(Category_over_base_ring):
373
+ ....: def super_categories(self):
374
+ ....: return [Modules(self.base_ring())]
375
+ ....: class ParentMethods:
376
+ ....: def _Hom_(self, Y, category=None):
377
+ ....: print("Modules")
378
+ ....: raise TypeError
379
+ sage: class AlgebrasWithHom(Category_over_base_ring):
380
+ ....: def super_categories(self):
381
+ ....: return [Algebras(self.base_ring()), ModulesWithHom(self.base_ring())]
382
+ ....: class ParentMethods:
383
+ ....: def _Hom_(self, Y, category=None):
384
+ ....: R = self.base_ring()
385
+ ....: if category is not None and category.is_subcategory(Algebras(R)):
386
+ ....: print("Algebras")
387
+ ....: raise TypeError
388
+ sage: from sage.structure.element import Element
389
+ sage: class Foo(Parent):
390
+ ....: def _coerce_map_from_base_ring(self):
391
+ ....: return self._generic_coerce_map(self.base_ring())
392
+ ....: class Element(Element):
393
+ ....: pass
394
+ sage: X = Foo(base=QQ, category=AlgebrasWithHom(QQ))
395
+ sage: H = Hom(X, X, ModulesWithHom(QQ))
396
+ Modules
397
+ """
398
+ # This should use cache_function instead
399
+ # However some special handling is currently needed for
400
+ # domains/codomains that break the unique parent condition. Also,
401
+ # at some point, it somehow broke the coercion (see e.g. sage -t
402
+ # sage.rings.real_mpfr). To be investigated.
403
+ global _cache
404
+ key = (X,Y,category)
405
+ try:
406
+ H = _cache[key]
407
+ except KeyError:
408
+ H = None
409
+ if H is not None:
410
+ # Return H unless the domain or codomain breaks the unique parent condition
411
+ if H.domain() is X and H.codomain() is Y:
412
+ return H
413
+
414
+ # Determines the category
415
+ if category is None:
416
+ category = X.category()._meet_(Y.category())
417
+ # Recurse to make sure that Hom(X, Y) and Hom(X, Y, category) are identical
418
+ # No need to check the input again
419
+ H = Hom(X, Y, category, check=False)
420
+ else:
421
+ if check:
422
+ if not isinstance(category, Category):
423
+ raise TypeError("Argument category (= {}) must be a category.".format(category))
424
+ for O in [X, Y]:
425
+ try:
426
+ category_mismatch = O not in category
427
+ except Exception:
428
+ # An error should not happen, this here is just to be on
429
+ # the safe side.
430
+ category_mismatch = True
431
+ # A category mismatch does not necessarily mean that an error
432
+ # should be raised. Instead, it could be the case that we are
433
+ # unpickling an old pickle (that doesn't set the "check"
434
+ # argument to False). In this case, it could be that the
435
+ # (co)domain is not properly initialised, which we are
436
+ # checking now. See trac #16275 and #14793.
437
+ if category_mismatch and O._is_category_initialized():
438
+ # At this point, we can be rather sure that O is properly
439
+ # initialised, and thus its string representation is
440
+ # available for the following error message. It simply
441
+ # belongs to the wrong category.
442
+ raise ValueError("{} is not in {}".format(O, category))
443
+
444
+ # Construct H
445
+ try: # _Hom_ hook from the parent
446
+ H = X._Hom_(Y, category)
447
+ except (AttributeError, TypeError):
448
+ # Workaround in case the above fails, but the category
449
+ # also provides a _Hom_ hook.
450
+ # FIXME:
451
+ # - If X._Hom_ actually comes from category and fails, it
452
+ # will be called twice.
453
+ # - This is bound to fail if X is an extension type and
454
+ # does not actually inherit from category.parent_class
455
+ # For join categories, we check all of the direct super
456
+ # categories as the parent_class of the join category is
457
+ # not (necessarily) inherited and join categories do not
458
+ # implement a _Hom_ (see trac #23418).
459
+ if not isinstance(category, JoinCategory):
460
+ cats = [category]
461
+ else:
462
+ cats = category.super_categories()
463
+ H = None
464
+ for C in cats:
465
+ try:
466
+ H = C.parent_class._Hom_(X, Y, category=category)
467
+ break
468
+ except (AttributeError, TypeError):
469
+ pass
470
+ if H is None:
471
+ # By default, construct a plain homset.
472
+ H = Homset(X, Y, category=category, check=check)
473
+ _cache[key] = H
474
+ if isinstance(X, UniqueRepresentation) and isinstance(Y, UniqueRepresentation):
475
+ if not isinstance(H, WithEqualityById):
476
+ try:
477
+ H.__class__ = dynamic_class(H.__class__.__name__+"_with_equality_by_id", (WithEqualityById, H.__class__), doccls=H.__class__)
478
+ except Exception:
479
+ pass
480
+ return H
481
+
482
+
483
+ def hom(X, Y, f):
484
+ """
485
+ Return ``Hom(X,Y)(f)``, where ``f`` is data that defines an element of
486
+ ``Hom(X,Y)``.
487
+
488
+ EXAMPLES::
489
+
490
+ sage: R.<x> = QQ[]
491
+ sage: phi = hom(R, QQ, [2])
492
+ sage: phi(x^2 + 3)
493
+ 7
494
+ """
495
+ return Hom(X,Y)(f)
496
+
497
+
498
+ def End(X, category=None):
499
+ r"""
500
+ Create the set of endomorphisms of ``X`` in the category category.
501
+
502
+ INPUT:
503
+
504
+ - ``X`` -- anything
505
+
506
+ - ``category`` -- (optional) category in which to coerce ``X``
507
+
508
+ OUTPUT: a set of endomorphisms in category
509
+
510
+ EXAMPLES::
511
+
512
+ sage: V = VectorSpace(QQ, 3) # needs sage.modules
513
+ sage: End(V) # needs sage.modules
514
+ Set of Morphisms (Linear Transformations)
515
+ from Vector space of dimension 3 over Rational Field
516
+ to Vector space of dimension 3 over Rational Field
517
+
518
+ ::
519
+
520
+ sage: # needs sage.groups
521
+ sage: G = AlternatingGroup(3)
522
+ sage: S = End(G); S
523
+ Set of Morphisms
524
+ from Alternating group of order 3!/2 as a permutation group
525
+ to Alternating group of order 3!/2 as a permutation group
526
+ in Category of finite enumerated permutation groups
527
+ sage: S.domain()
528
+ Alternating group of order 3!/2 as a permutation group
529
+
530
+ To avoid creating superfluous categories, a homset in a category
531
+ ``Cs()`` is in the homset category of the lowest full super category
532
+ ``Bs()`` of ``Cs()`` that implements ``Bs.Homsets`` (or the join
533
+ thereof if there are several). For example, finite groups form a
534
+ full subcategory of unital magmas: any unital magma morphism
535
+ between two finite groups is a finite group morphism. Since finite
536
+ groups currently implement nothing more than unital magmas about
537
+ their homsets, we have::
538
+
539
+ sage: # needs sage.groups sage.modules
540
+ sage: G = GL(3, 3)
541
+ sage: G.category()
542
+ Category of finite groups
543
+ sage: H = Hom(G, G)
544
+ sage: H.homset_category()
545
+ Category of finite groups
546
+ sage: H.category()
547
+ Category of endsets of unital magmas
548
+
549
+ Similarly, a ring morphism just needs to preserve addition,
550
+ multiplication, zero, and one. Accordingly, and since the category
551
+ of rings implements nothing specific about its homsets, a ring
552
+ homset is currently constructed in the category of homsets of
553
+ unital magmas and unital additive magmas::
554
+
555
+ sage: H = Hom(ZZ,ZZ,Rings())
556
+ sage: H.category()
557
+ Category of endsets of unital magmas and additive unital additive magmas
558
+ """
559
+ return Hom(X,X, category)
560
+
561
+
562
+ def end(X, f):
563
+ """
564
+ Return ``End(X)(f)``, where ``f`` is data that defines an element of
565
+ ``End(X)``.
566
+
567
+ EXAMPLES::
568
+
569
+ sage: R.<x> = QQ[]
570
+ sage: phi = end(R, [x + 1])
571
+ sage: phi
572
+ Ring endomorphism of Univariate Polynomial Ring in x over Rational Field
573
+ Defn: x |--> x + 1
574
+ sage: phi(x^2 + 5)
575
+ x^2 + 2*x + 6
576
+ """
577
+ return End(X)(f)
578
+
579
+
580
+ class Homset(Set_generic):
581
+ """
582
+ The class for collections of morphisms in a category.
583
+
584
+ EXAMPLES::
585
+
586
+ sage: H = Hom(QQ^2, QQ^3) # needs sage.modules
587
+ sage: loads(H.dumps()) is H # needs sage.modules
588
+ True
589
+
590
+ Homsets of unique parents are unique as well::
591
+
592
+ sage: H = End(AffineSpace(2, names='x,y'))
593
+ sage: loads(dumps(AffineSpace(2, names='x,y'))) is AffineSpace(2, names='x,y')
594
+ True
595
+ sage: loads(dumps(H)) is H
596
+ True
597
+
598
+ Conversely, homsets of non-unique parents are non-unique::
599
+
600
+ sage: P11 = ProductProjectiveSpaces(QQ, [1, 1])
601
+ sage: H = End(P11)
602
+ sage: loads(dumps(P11)) is ProductProjectiveSpaces(QQ, [1, 1])
603
+ False
604
+ sage: loads(dumps(P11)) == ProductProjectiveSpaces(QQ, [1, 1])
605
+ True
606
+ sage: loads(dumps(H)) is H
607
+ False
608
+ sage: loads(dumps(H)) == H
609
+ True
610
+ """
611
+ def __init__(self, X, Y, category=None, base=None, check=True):
612
+ r"""
613
+ TESTS::
614
+
615
+ sage: X = ZZ['x']; X.rename('X')
616
+ sage: Y = ZZ['y']; Y.rename('Y')
617
+ sage: f = X.hom([0], Y)
618
+ sage: class MyHomset(Homset):
619
+ ....: def _an_element_(self):
620
+ ....: return sage.categories.morphism.SetMorphism(self, f)
621
+ sage: import __main__; __main__.MyHomset = MyHomset # fakes MyHomset being defined in a Python module
622
+ sage: H = MyHomset(X, Y, category=Monoids(), base = ZZ)
623
+ sage: H
624
+ Set of Morphisms from X to Y in Category of monoids
625
+ sage: TestSuite(H).run()
626
+
627
+ sage: H = MyHomset(X, Y, category=1, base = ZZ)
628
+ Traceback (most recent call last):
629
+ ...
630
+ TypeError: category (=1) must be a category
631
+
632
+ sage: H = MyHomset(X, Y, category=1, base = ZZ, check = False)
633
+ Traceback (most recent call last):
634
+ ...
635
+ AttributeError: 'sage.rings.integer.Integer' object has no attribute 'Homsets'...
636
+ sage: P.<t> = ZZ[]
637
+ sage: f = P.hom([1/2*t])
638
+ sage: f.parent().domain()
639
+ Univariate Polynomial Ring in t over Integer Ring
640
+ sage: f.domain() is f.parent().domain()
641
+ True
642
+
643
+ Test that ``base_ring`` is initialized properly::
644
+
645
+ sage: R = QQ['x']
646
+ sage: Hom(R, R).base_ring()
647
+ Rational Field
648
+ sage: Hom(R, R, category=Sets()).base_ring()
649
+ sage: Hom(R, R, category=Modules(QQ)).base_ring()
650
+ Rational Field
651
+ sage: Hom(QQ^3, QQ^3, category=Modules(QQ)).base_ring() # needs sage.modules
652
+ Rational Field
653
+
654
+ For whatever it's worth, the ``base`` arguments takes precedence::
655
+
656
+ sage: MyHomset(ZZ^3, ZZ^3, base=QQ).base_ring() # needs sage.modules
657
+ Rational Field
658
+ """
659
+ self._domain = X
660
+ self._codomain = Y
661
+ if category is None:
662
+ category = X.category()
663
+ self.__category = category
664
+ if check:
665
+ if not isinstance(category, Category):
666
+ raise TypeError("category (=%s) must be a category" % category)
667
+ # if not X in category:
668
+ # raise TypeError("X (=%s) must be in category (=%s)" % (X, category))
669
+ # if not Y in category:
670
+ # raise TypeError("Y (=%s) must be in category (=%s)" % (Y, category))
671
+
672
+ if base is None and hasattr(category, "WithBasis"):
673
+ # The above is a lame but fast check that category is a
674
+ # subcategory of Modules(...). That will do until
675
+ # CategoryObject.base_ring will be gone and not prevent
676
+ # anymore from implementing base_ring in Modules.Homsets.ParentMethods.
677
+ # See also #15801.
678
+ base = X.base_ring()
679
+
680
+ Parent.__init__(self, base=base,
681
+ category=category.Endsets() if X is Y else category.Homsets())
682
+
683
+ def __reduce__(self):
684
+ """
685
+ Implement pickling by construction for Homsets.
686
+
687
+ Homsets are unpickled using the function
688
+ :func:`~sage.categories.homset.Hom` which is cached:
689
+ ``Hom(domain, codomain, category, check=False)``.
690
+
691
+ .. NOTE::
692
+
693
+ It can happen, that ``Hom(X,X)`` is called during
694
+ unpickling with an uninitialized instance ``X`` of a Python
695
+ class. In some of these cases, testing that ``X in
696
+ category`` can trigger ``X.category()``. This in turn can
697
+ raise a error, or return a too large category (``Sets()``,
698
+ for example) and (worse!) assign this larger category to
699
+ the ``X._category`` cdef attribute, so that it would
700
+ subsequently seem that ``X``'s category was initialised.
701
+
702
+ Beside speed considerations, this is the main rationale
703
+ for disabling checks upon unpickling.
704
+
705
+ .. SEEALSO:: :issue:`14793`, :issue:`16275`
706
+
707
+ EXAMPLES::
708
+
709
+ sage: H = Hom(QQ^2, QQ^3) # needs sage.modules
710
+ sage: H.__reduce__() # needs sage.modules
711
+ (<function Hom at ...>,
712
+ (Vector space of dimension 2 over Rational Field,
713
+ Vector space of dimension 3 over Rational Field,
714
+ Category of finite dimensional vector spaces with basis over
715
+ (number fields and quotient fields and metric spaces),
716
+ False))
717
+
718
+ TESTS::
719
+
720
+ sage: loads(H.dumps()) is H # needs sage.modules
721
+ True
722
+
723
+ Homsets of non-unique parents are non-unique as well::
724
+
725
+ sage: # needs sage.groups
726
+ sage: G = PermutationGroup([[(1, 2, 3), (4, 5)], [(3, 4)]])
727
+ sage: G is loads(dumps(G))
728
+ False
729
+ sage: H = Hom(G, G)
730
+ sage: H is loads(dumps(H))
731
+ False
732
+ sage: H == loads(dumps(H))
733
+ True
734
+ """
735
+ return Hom, (self._domain, self._codomain, self.__category, False)
736
+
737
+ def _repr_(self):
738
+ """
739
+ TESTS::
740
+
741
+ sage: Hom(ZZ^2, QQ, category=Sets())._repr_() # needs sage.modules
742
+ 'Set of Morphisms from Ambient free module of rank 2 over the principal ideal domain Integer Ring to Rational Field in Category of sets'
743
+ """
744
+ return "Set of Morphisms from {} to {} in {}".format(self._domain,
745
+ self._codomain, self.__category)
746
+
747
+ def __hash__(self):
748
+ """
749
+ The hash is obtained from domain, codomain and base.
750
+
751
+ TESTS::
752
+
753
+ sage: hash(Hom(ZZ, QQ)) == hash((ZZ, QQ, ZZ))
754
+ True
755
+ sage: hash(Hom(QQ, ZZ)) == hash((QQ, ZZ, QQ))
756
+ True
757
+
758
+ sage: # needs database_cremona_mini_ellcurve sage.schemes
759
+ sage: E = EllipticCurve('37a')
760
+ sage: H = E(0).parent(); H
761
+ Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
762
+ sage: hash(H) == hash((H.domain(), H.codomain(), H.base()))
763
+ True
764
+ """
765
+ return hash((self._domain, self._codomain, self.base()))
766
+
767
+ def __bool__(self) -> bool:
768
+ """
769
+ TESTS::
770
+
771
+ sage: bool(Hom(ZZ, QQ))
772
+ True
773
+ """
774
+ return True
775
+
776
+ def homset_category(self):
777
+ """
778
+ Return the category that this is a Hom in, i.e., this is typically
779
+ the category of the domain or codomain object.
780
+
781
+ EXAMPLES::
782
+
783
+ sage: H = Hom(AlternatingGroup(4), AlternatingGroup(7)) # needs sage.groups
784
+ sage: H.homset_category() # needs sage.groups
785
+ Category of finite enumerated permutation groups
786
+ """
787
+ return self.__category
788
+
789
+ def _element_constructor_(self, x, check=None, **options):
790
+ r"""
791
+ Construct a morphism in this homset from ``x`` if possible.
792
+
793
+ EXAMPLES::
794
+
795
+ sage: H = Hom(SymmetricGroup(4), SymmetricGroup(7)) # needs sage.groups
796
+ sage: phi = Hom(SymmetricGroup(5), SymmetricGroup(6)).natural_map() # needs sage.groups
797
+ sage: phi # needs sage.groups
798
+ Coercion morphism:
799
+ From: Symmetric group of order 5! as a permutation group
800
+ To: Symmetric group of order 6! as a permutation group
801
+
802
+ When converting `\phi` into `H`, some coerce maps are applied. Note
803
+ that (in contrast to what is stated in the following string
804
+ representation) it is safe to use the resulting map, since a composite
805
+ map prevents the codomains of all constituent maps from garbage
806
+ collection, if there is a strong reference to its domain (which is the
807
+ case here)::
808
+
809
+ sage: H(phi) # needs sage.groups
810
+ Composite map:
811
+ From: Symmetric group of order 4! as a permutation group
812
+ To: Symmetric group of order 7! as a permutation group
813
+ Defn: (map internal to coercion system -- copy before use)
814
+ Coercion map:
815
+ From: Symmetric group of order 4! as a permutation group
816
+ To: Symmetric group of order 5! as a permutation group
817
+ then
818
+ Coercion morphism:
819
+ From: Symmetric group of order 5! as a permutation group
820
+ To: Symmetric group of order 6! as a permutation group
821
+ then
822
+ (map internal to coercion system -- copy before use)
823
+ Coercion map:
824
+ From: Symmetric group of order 6! as a permutation group
825
+ To: Symmetric group of order 7! as a permutation group
826
+
827
+ Also note that making a copy of the resulting map will automatically
828
+ make strengthened copies of the composed maps::
829
+
830
+ sage: copy(H(phi)) # needs sage.groups
831
+ Composite map:
832
+ From: Symmetric group of order 4! as a permutation group
833
+ To: Symmetric group of order 7! as a permutation group
834
+ Defn: Coercion map:
835
+ From: Symmetric group of order 4! as a permutation group
836
+ To: Symmetric group of order 5! as a permutation group
837
+ then
838
+ Coercion morphism:
839
+ From: Symmetric group of order 5! as a permutation group
840
+ To: Symmetric group of order 6! as a permutation group
841
+ then
842
+ Coercion map:
843
+ From: Symmetric group of order 6! as a permutation group
844
+ To: Symmetric group of order 7! as a permutation group
845
+ sage: H = Hom(ZZ, ZZ, Sets())
846
+ sage: f = H( lambda x: x + 1 )
847
+ sage: f.parent()
848
+ Set of Morphisms from Integer Ring to Integer Ring in Category of sets
849
+ sage: f.domain()
850
+ Integer Ring
851
+ sage: f.codomain()
852
+ Integer Ring
853
+ sage: f(1), f(2), f(3)
854
+ (2, 3, 4)
855
+
856
+ sage: H = Hom(Set([1,2,3]), Set([1,2,3]))
857
+ sage: f = H(lambda x: 4 - x)
858
+ sage: f.parent()
859
+ Set of Morphisms from {1, 2, 3} to {1, 2, 3} in Category of finite enumerated sets
860
+ sage: f(1), f(2), f(3) # todo: not implemented
861
+
862
+ sage: H = Hom(ZZ, QQ, Sets())
863
+ sage: f = H( ConstantFunction(2/3) )
864
+ sage: f.parent()
865
+ Set of Morphisms from Integer Ring to Rational Field in Category of sets
866
+ sage: f(1), f(2), f(3)
867
+ (2/3, 2/3, 2/3)
868
+
869
+ By :issue:`14711`, conversion and coerce maps should be copied
870
+ before using them outside of the coercion system::
871
+
872
+ sage: H = Hom(ZZ,QQ['t'], CommutativeAdditiveGroups())
873
+ sage: P.<t> = ZZ[]
874
+ sage: f = P.hom([2*t])
875
+ sage: phi = H._generic_convert_map(f.parent()); phi
876
+ Conversion map:
877
+ From: Set of Homomorphisms from Univariate Polynomial Ring in t over Integer Ring to Univariate Polynomial Ring in t over Integer Ring
878
+ To: Set of Morphisms from Integer Ring to Univariate Polynomial Ring in t over Rational Field in Category of commutative additive groups
879
+ sage: H._generic_convert_map(f.parent())(f)
880
+ Composite map:
881
+ From: Integer Ring
882
+ To: Univariate Polynomial Ring in t over Rational Field
883
+ Defn: (map internal to coercion system -- copy before use)
884
+ Polynomial base injection morphism:
885
+ From: Integer Ring
886
+ To: Univariate Polynomial Ring in t over Integer Ring
887
+ then
888
+ Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring
889
+ Defn: t |--> 2*t
890
+ then
891
+ (map internal to coercion system -- copy before use)
892
+ Ring morphism:
893
+ From: Univariate Polynomial Ring in t over Integer Ring
894
+ To: Univariate Polynomial Ring in t over Rational Field
895
+ sage: copy(H._generic_convert_map(f.parent())(f))
896
+ Composite map:
897
+ From: Integer Ring
898
+ To: Univariate Polynomial Ring in t over Rational Field
899
+ Defn: Polynomial base injection morphism:
900
+ From: Integer Ring
901
+ To: Univariate Polynomial Ring in t over Integer Ring
902
+ then
903
+ Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring
904
+ Defn: t |--> 2*t
905
+ then
906
+ Ring morphism:
907
+ From: Univariate Polynomial Ring in t over Integer Ring
908
+ To: Univariate Polynomial Ring in t over Rational Field
909
+ Defn: Induced from base ring by
910
+ Natural morphism:
911
+ From: Integer Ring
912
+ To: Rational Field
913
+
914
+ TESTS::
915
+
916
+ sage: # needs sage.combinat sage.groups
917
+ sage: G.<x,y,z> = FreeGroup()
918
+ sage: H = Hom(G, G)
919
+ sage: H(H.identity())
920
+ Identity endomorphism of Free Group on generators {x, y, z}
921
+ sage: H()
922
+ Traceback (most recent call last):
923
+ ...
924
+ TypeError: unable to convert 0 to an element of
925
+ Set of Morphisms from Free Group on generators {x, y, z}
926
+ to Free Group on generators {x, y, z} in Category of infinite groups
927
+ sage: H("whatever")
928
+ Traceback (most recent call last):
929
+ ...
930
+ TypeError: unable to convert 'whatever' to an element of
931
+ Set of Morphisms from Free Group on generators {x, y, z}
932
+ to Free Group on generators {x, y, z} in Category of infinite groups
933
+ sage: HH = Hom(H, H)
934
+ sage: HH(HH.identity(), foo='bar')
935
+ Traceback (most recent call last):
936
+ ...
937
+ NotImplementedError: no keywords are implemented for
938
+ constructing elements of ...
939
+
940
+ AUTHORS:
941
+
942
+ - Robert Bradshaw, with changes by Nicolas M. Thiery
943
+ """
944
+ if options:
945
+ # TODO: this is specific for ModulesWithBasis; generalize
946
+ # this to allow homsets and categories to provide more
947
+ # morphism constructors (on_algebra_generators, ...)
948
+ try:
949
+ call_with_keywords = self.__call_on_basis__
950
+ except AttributeError:
951
+ if 'base_map' in options:
952
+ raise NotImplementedError("base_map not supported for this Homset; you may need to specify a category")
953
+ raise NotImplementedError("no keywords are implemented for constructing elements of {}".format(self))
954
+ options.setdefault("category", self.homset_category())
955
+ return call_with_keywords(**options)
956
+
957
+ if isinstance(x, morphism.Morphism):
958
+ if x.domain() != self.domain():
959
+ mor = x.domain()._internal_coerce_map_from(self.domain())
960
+ if mor is None:
961
+ raise TypeError("Incompatible domains: x (=%s) cannot be an element of %s" % (x,self))
962
+ x = x * mor
963
+ if x.codomain() != self.codomain():
964
+ mor = self.codomain()._internal_coerce_map_from(x.codomain())
965
+ if mor is None:
966
+ raise TypeError("Incompatible codomains: x (=%s) cannot be an element of %s" % (x,self))
967
+ x = mor * x
968
+ return x
969
+
970
+ if callable(x):
971
+ return self.element_class_set_morphism(self, x)
972
+
973
+ raise TypeError("unable to convert {!r} to an element of {}".format(x, self))
974
+
975
+ @lazy_attribute
976
+ def _abstract_element_class(self):
977
+ """
978
+ An abstract class for the elements of this homset.
979
+
980
+ This class is built from the element class of the homset
981
+ category and the morphism class of the category. This makes
982
+ it possible for a category to provide code for its morphisms
983
+ and for morphisms of all its subcategories, full or not.
984
+
985
+ .. NOTE::
986
+
987
+ The element class of ``C.Homsets()`` will be inherited by
988
+ morphisms in *full* subcategories of ``C``, while the morphism
989
+ class of ``C`` will be inherited by *all* subcategories of
990
+ ``C``. Hence, if some feature of a morphism depends on the
991
+ algebraic properties of the homsets, it should be implemented by
992
+ ``C.Homsets.ElementMethods``, but if it depends only on the
993
+ algebraic properties of domain and codomain, it should be
994
+ implemented in ``C.MorphismMethods``.
995
+
996
+ At this point, the homset element classes take precedence over the
997
+ morphism classes. But this may be subject to change.
998
+
999
+
1000
+ .. TODO::
1001
+
1002
+ - Make sure this class is shared whenever possible.
1003
+ - Flatten join category classes
1004
+
1005
+ .. SEEALSO::
1006
+
1007
+ - :meth:`Parent._abstract_element_class`
1008
+
1009
+ EXAMPLES:
1010
+
1011
+ Let's take a homset of finite commutative groups as example; at
1012
+ this point this is the simplest one to create (gosh)::
1013
+
1014
+ sage: # needs sage.groups
1015
+ sage: cat = Groups().Finite().Commutative()
1016
+ sage: C3 = PermutationGroup([(1,2,3)])
1017
+ sage: C3._refine_category_(cat)
1018
+ sage: C2 = PermutationGroup([(1,2)])
1019
+ sage: C2._refine_category_(cat)
1020
+ sage: H = Hom(C3, C2, cat)
1021
+ sage: H.homset_category()
1022
+ Category of finite commutative groups
1023
+ sage: H.category()
1024
+ Category of homsets of unital magmas
1025
+ sage: cls = H._abstract_element_class; cls
1026
+ <class 'sage.categories.homsets.GroupHomset_libgap_with_category._abstract_element_class'>
1027
+ sage: cls.__bases__ == (H.category().element_class, H.homset_category().morphism_class)
1028
+ True
1029
+
1030
+ A morphism of finite commutative semigroups is also a morphism
1031
+ of semigroups, of magmas, ...; it thus inherits code from all
1032
+ those categories::
1033
+
1034
+ sage: # needs sage.groups
1035
+ sage: issubclass(cls, Semigroups().Finite().morphism_class)
1036
+ True
1037
+ sage: issubclass(cls, Semigroups().morphism_class)
1038
+ True
1039
+ sage: issubclass(cls, Magmas().Commutative().morphism_class)
1040
+ True
1041
+ sage: issubclass(cls, Magmas().morphism_class)
1042
+ True
1043
+ sage: issubclass(cls, Sets().morphism_class)
1044
+ True
1045
+
1046
+ Recall that FiniteMonoids() is a full subcategory of
1047
+ ``Monoids()``, but not of ``FiniteSemigroups()``. Thus::
1048
+
1049
+ sage: issubclass(cls, Monoids().Finite().Homsets().element_class) # needs sage.groups
1050
+ True
1051
+ sage: issubclass(cls, Semigroups().Finite().Homsets().element_class) # needs sage.groups
1052
+ False
1053
+ """
1054
+ class_name = "%s._abstract_element_class" % self.__class__.__name__
1055
+ return dynamic_class(class_name, (self.category().element_class, self.homset_category().morphism_class))
1056
+
1057
+ @lazy_attribute
1058
+ def element_class_set_morphism(self):
1059
+ """
1060
+ A base class for elements of this homset which are
1061
+ also ``SetMorphism``, i.e. implemented by mean of a
1062
+ Python function.
1063
+
1064
+ This is currently plain ``SetMorphism``, without inheritance
1065
+ from categories.
1066
+
1067
+ .. TODO::
1068
+
1069
+ Refactor during the upcoming homset cleanup.
1070
+
1071
+ EXAMPLES::
1072
+
1073
+ sage: H = Hom(ZZ, ZZ)
1074
+ sage: H.element_class_set_morphism
1075
+ <class 'sage.categories.morphism.SetMorphism'>
1076
+ """
1077
+ return self.__make_element_class__(morphism.SetMorphism)
1078
+
1079
+ def __eq__(self, other):
1080
+ """
1081
+ For two homsets, it is tested whether the domain, the codomain and
1082
+ the category coincide.
1083
+
1084
+ EXAMPLES::
1085
+
1086
+ sage: H1 = Hom(ZZ,QQ, CommutativeAdditiveGroups())
1087
+ sage: H2 = Hom(ZZ,QQ)
1088
+ sage: H1 == H2
1089
+ False
1090
+ sage: H1 == loads(dumps(H1))
1091
+ True
1092
+ """
1093
+ if not isinstance(other, Homset):
1094
+ return False
1095
+ return (self._domain == other._domain
1096
+ and self._codomain == other._codomain
1097
+ and self.__category == other.__category)
1098
+
1099
+ def __ne__(self, other):
1100
+ """
1101
+ Check for not-equality of ``self`` and ``other``.
1102
+
1103
+ EXAMPLES::
1104
+
1105
+ sage: H1 = Hom(ZZ,QQ, CommutativeAdditiveGroups())
1106
+ sage: H2 = Hom(ZZ,QQ)
1107
+ sage: H3 = Hom(ZZ['t'],QQ, CommutativeAdditiveGroups())
1108
+ sage: H4 = Hom(ZZ,QQ['t'], CommutativeAdditiveGroups())
1109
+ sage: H1 != H2
1110
+ True
1111
+ sage: H1 != loads(dumps(H1))
1112
+ False
1113
+ sage: H1 != H3 != H4 != H1
1114
+ True
1115
+ """
1116
+ return not (self == other)
1117
+
1118
+ def __contains__(self, x):
1119
+ """
1120
+ Test whether the parent of the argument is ``self``.
1121
+
1122
+ TESTS::
1123
+
1124
+ sage: P.<t> = ZZ[]
1125
+ sage: f = P.hom([1/2*t])
1126
+ sage: f in Hom(ZZ['t'],QQ['t']) # indirect doctest
1127
+ True
1128
+ sage: f in Hom(ZZ['t'],QQ['t'], CommutativeAdditiveGroups()) # indirect doctest
1129
+ False
1130
+ """
1131
+ try:
1132
+ return x.parent() == self
1133
+ except AttributeError:
1134
+ pass
1135
+ return False
1136
+
1137
+ def natural_map(self):
1138
+ """
1139
+ Return the "natural map" of this homset.
1140
+
1141
+ .. NOTE::
1142
+
1143
+ By default, a formal coercion morphism is returned.
1144
+
1145
+ EXAMPLES::
1146
+
1147
+ sage: H = Hom(ZZ['t'],QQ['t'], CommutativeAdditiveGroups())
1148
+ sage: H.natural_map()
1149
+ Coercion morphism:
1150
+ From: Univariate Polynomial Ring in t over Integer Ring
1151
+ To: Univariate Polynomial Ring in t over Rational Field
1152
+ sage: H = Hom(QQ['t'], GF(3)['t'])
1153
+ sage: H.natural_map()
1154
+ Traceback (most recent call last):
1155
+ ...
1156
+ TypeError: natural coercion morphism
1157
+ from Univariate Polynomial Ring in t over Rational Field
1158
+ to Univariate Polynomial Ring in t over Finite Field of size 3 not defined
1159
+ """
1160
+ return morphism.FormalCoercionMorphism(self) # good default in many cases
1161
+
1162
+ def identity(self):
1163
+ """
1164
+ The identity map of this homset.
1165
+
1166
+ .. NOTE::
1167
+
1168
+ Of course, this only exists for sets of endomorphisms.
1169
+
1170
+ EXAMPLES::
1171
+
1172
+ sage: H = Hom(QQ,QQ)
1173
+ sage: H.identity()
1174
+ Identity endomorphism of Rational Field
1175
+ sage: H = Hom(ZZ,QQ)
1176
+ sage: H.identity()
1177
+ Traceback (most recent call last):
1178
+ ...
1179
+ TypeError: identity map only defined for endomorphisms; try natural_map() instead
1180
+ sage: H.natural_map()
1181
+ Natural morphism:
1182
+ From: Integer Ring
1183
+ To: Rational Field
1184
+ """
1185
+ if self.is_endomorphism_set():
1186
+ return morphism.IdentityMorphism(self)
1187
+ raise TypeError("identity map only defined for endomorphisms; try natural_map() instead")
1188
+
1189
+ def one(self):
1190
+ """
1191
+ The identity map of this homset.
1192
+
1193
+ .. NOTE::
1194
+
1195
+ Of course, this only exists for sets of endomorphisms.
1196
+
1197
+ EXAMPLES::
1198
+
1199
+ sage: K = GaussianIntegers() # needs sage.rings.number_field
1200
+ sage: End(K).one() # needs sage.rings.number_field
1201
+ Identity endomorphism of Gaussian Integers generated by I
1202
+ in Number Field in I with defining polynomial x^2 + 1 with I = 1*I
1203
+ """
1204
+ return self.identity()
1205
+
1206
+ def domain(self):
1207
+ """
1208
+ Return the domain of this homset.
1209
+
1210
+ EXAMPLES::
1211
+
1212
+ sage: P.<t> = ZZ[]
1213
+ sage: f = P.hom([1/2*t])
1214
+ sage: f.parent().domain()
1215
+ Univariate Polynomial Ring in t over Integer Ring
1216
+ sage: f.domain() is f.parent().domain()
1217
+ True
1218
+ """
1219
+ return self._domain
1220
+
1221
+ def codomain(self):
1222
+ """
1223
+ Return the codomain of this homset.
1224
+
1225
+ EXAMPLES::
1226
+
1227
+ sage: P.<t> = ZZ[]
1228
+ sage: f = P.hom([1/2*t])
1229
+ sage: f.parent().codomain()
1230
+ Univariate Polynomial Ring in t over Rational Field
1231
+ sage: f.codomain() is f.parent().codomain()
1232
+ True
1233
+ """
1234
+ return self._codomain
1235
+
1236
+ def reversed(self):
1237
+ """
1238
+ Return the corresponding homset, but with the domain and codomain
1239
+ reversed.
1240
+
1241
+ EXAMPLES::
1242
+
1243
+ sage: # needs sage.modules
1244
+ sage: H = Hom(ZZ^2, ZZ^3); H
1245
+ Set of Morphisms from Ambient free module of rank 2 over
1246
+ the principal ideal domain Integer Ring to Ambient free module
1247
+ of rank 3 over the principal ideal domain Integer Ring in
1248
+ Category of finite dimensional modules with basis over (Dedekind
1249
+ domains and euclidean domains and noetherian rings
1250
+ and infinite enumerated sets and metric spaces)
1251
+ sage: type(H)
1252
+ <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
1253
+ sage: H.reversed()
1254
+ Set of Morphisms from Ambient free module of rank 3 over
1255
+ the principal ideal domain Integer Ring to Ambient free module
1256
+ of rank 2 over the principal ideal domain Integer Ring in
1257
+ Category of finite dimensional modules with basis over (Dedekind
1258
+ domains and euclidean domains and noetherian rings
1259
+ and infinite enumerated sets and metric spaces)
1260
+ sage: type(H.reversed())
1261
+ <class 'sage.modules.free_module_homspace.FreeModuleHomspace_with_category'>
1262
+ """
1263
+ return Hom(self.codomain(), self.domain(),
1264
+ category=self.homset_category())
1265
+
1266
+
1267
+ # Really needed???
1268
+ class HomsetWithBase(Homset):
1269
+ def __init__(self, X, Y, category=None, check=True, base=None):
1270
+ r"""
1271
+ TESTS::
1272
+
1273
+ sage: X = ZZ['x']; X.rename('X')
1274
+ sage: Y = ZZ['y']; Y.rename('Y')
1275
+ sage: f = X.hom([0], Y)
1276
+ sage: class MyHomset(HomsetWithBase):
1277
+ ....: def _an_element_(self):
1278
+ ....: return sage.categories.morphism.SetMorphism(self, f)
1279
+ sage: import __main__; __main__.MyHomset = MyHomset # fakes MyHomset being defined in a Python module
1280
+ sage: H = MyHomset(X, Y, category=Monoids())
1281
+ sage: H
1282
+ Set of Morphisms from X to Y in Category of monoids
1283
+ sage: H.base()
1284
+ Integer Ring
1285
+ sage: TestSuite(H).run()
1286
+ """
1287
+ if base is None:
1288
+ base = X.base_ring()
1289
+ Homset.__init__(self, X, Y, check=check, category=category, base=base)
1290
+
1291
+
1292
+ def is_Homset(x):
1293
+ """
1294
+ Return ``True`` if ``x`` is a set of homomorphisms in a category.
1295
+
1296
+ EXAMPLES::
1297
+
1298
+ sage: from sage.categories.homset import is_Homset
1299
+ sage: P.<t> = ZZ[]
1300
+ sage: f = P.hom([1/2*t])
1301
+ sage: is_Homset(f)
1302
+ doctest:warning...
1303
+ DeprecationWarning: the function is_Homset is deprecated;
1304
+ use 'isinstance(..., Homset)' instead
1305
+ See https://github.com/sagemath/sage/issues/37922 for details.
1306
+ False
1307
+ sage: is_Homset(f.category())
1308
+ False
1309
+ sage: is_Homset(f.parent())
1310
+ True
1311
+ """
1312
+ from sage.misc.superseded import deprecation
1313
+ deprecation(37922, "the function is_Homset is deprecated; use 'isinstance(..., Homset)' instead")
1314
+ return isinstance(x, Homset)
1315
+
1316
+
1317
+ def is_Endset(x):
1318
+ """
1319
+ Return ``True`` if ``x`` is a set of endomorphisms in a category.
1320
+
1321
+ EXAMPLES::
1322
+
1323
+ sage: from sage.categories.homset import is_Endset
1324
+ sage: P.<t> = ZZ[]
1325
+ sage: f = P.hom([1/2*t])
1326
+ sage: is_Endset(f.parent())
1327
+ doctest:warning...
1328
+ DeprecationWarning: the function is_Endset is deprecated;
1329
+ use 'isinstance(..., Homset) and ....is_endomorphism_set()' instead
1330
+ See https://github.com/sagemath/sage/issues/37922 for details.
1331
+ False
1332
+ sage: g = P.hom([2*t])
1333
+ sage: is_Endset(g.parent())
1334
+ True
1335
+ """
1336
+ from sage.misc.superseded import deprecation
1337
+ deprecation(37922, "the function is_Endset is deprecated; use 'isinstance(..., Homset) and ....is_endomorphism_set()' instead")
1338
+ return isinstance(x, Homset) and x.is_endomorphism_set()