passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.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 (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,3299 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ r"""
3
+ Homomorphisms of rings
4
+
5
+ We give a large number of examples of ring homomorphisms.
6
+
7
+ EXAMPLES:
8
+
9
+ Natural inclusion `\ZZ \hookrightarrow \QQ`::
10
+
11
+ sage: H = Hom(ZZ, QQ)
12
+ sage: phi = H([1])
13
+ sage: phi(10)
14
+ 10
15
+ sage: phi(3/1)
16
+ 3
17
+ sage: phi(2/3)
18
+ Traceback (most recent call last):
19
+ ...
20
+ TypeError: 2/3 fails to convert into the map's domain Integer Ring,
21
+ but a `pushforward` method is not properly implemented
22
+
23
+ There is no homomorphism in the other direction::
24
+
25
+ sage: H = Hom(QQ, ZZ)
26
+ sage: H([1])
27
+ Traceback (most recent call last):
28
+ ...
29
+ ValueError: relations do not all (canonically) map to 0
30
+ under map determined by images of generators
31
+
32
+ EXAMPLES:
33
+
34
+ Reduction to finite field::
35
+
36
+ sage: # needs sage.rings.finite_rings
37
+ sage: H = Hom(ZZ, GF(9, 'a'))
38
+ sage: phi = H([1])
39
+ sage: phi(5)
40
+ 2
41
+ sage: psi = H([4])
42
+ sage: psi(5)
43
+ 2
44
+
45
+ Map from single variable polynomial ring::
46
+
47
+ sage: R.<x> = ZZ[]
48
+ sage: phi = R.hom([2], GF(5)); phi
49
+ Ring morphism:
50
+ From: Univariate Polynomial Ring in x over Integer Ring
51
+ To: Finite Field of size 5
52
+ Defn: x |--> 2
53
+ sage: phi(x + 12)
54
+ 4
55
+
56
+ Identity map on the real numbers::
57
+
58
+ sage: # needs sage.rings.real_mpfr
59
+ sage: f = RR.hom([RR(1)]); f
60
+ Ring endomorphism of Real Field with 53 bits of precision
61
+ Defn: 1.00000000000000 |--> 1.00000000000000
62
+ sage: f(2.5)
63
+ 2.50000000000000
64
+ sage: f = RR.hom([2.0])
65
+ Traceback (most recent call last):
66
+ ...
67
+ ValueError: relations do not all (canonically) map to 0
68
+ under map determined by images of generators
69
+
70
+ Homomorphism from one precision of field to another.
71
+
72
+ From smaller to bigger doesn't make sense::
73
+
74
+ sage: R200 = RealField(200) # needs sage.rings.real_mpfr
75
+ sage: f = RR.hom( R200 ) # needs sage.rings.real_mpfr
76
+ Traceback (most recent call last):
77
+ ...
78
+ TypeError: natural coercion morphism from Real Field with 53 bits of precision
79
+ to Real Field with 200 bits of precision not defined
80
+
81
+ From bigger to small does::
82
+
83
+ sage: f = RR.hom(RealField(15)) # needs sage.rings.real_mpfr
84
+ sage: f(2.5) # needs sage.rings.real_mpfr
85
+ 2.500
86
+ sage: f(RR.pi()) # needs sage.rings.real_mpfr
87
+ 3.142
88
+
89
+ Inclusion map from the reals to the complexes::
90
+
91
+ sage: # needs sage.rings.real_mpfr
92
+ sage: i = RR.hom([CC(1)]); i
93
+ Ring morphism:
94
+ From: Real Field with 53 bits of precision
95
+ To: Complex Field with 53 bits of precision
96
+ Defn: 1.00000000000000 |--> 1.00000000000000
97
+ sage: i(RR('3.1'))
98
+ 3.10000000000000
99
+
100
+ A map from a multivariate polynomial ring to itself::
101
+
102
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
103
+ sage: phi = R.hom([y, z, x^2]); phi
104
+ Ring endomorphism of Multivariate Polynomial Ring in x, y, z over Rational Field
105
+ Defn: x |--> y
106
+ y |--> z
107
+ z |--> x^2
108
+ sage: phi(x + y + z)
109
+ x^2 + y + z
110
+
111
+ An endomorphism of a quotient of a multi-variate polynomial ring::
112
+
113
+ sage: # needs sage.libs.singular
114
+ sage: R.<x,y> = PolynomialRing(QQ)
115
+ sage: S.<a,b> = quo(R, ideal(1 + y^2))
116
+ sage: phi = S.hom([a^2, -b]); phi
117
+ Ring endomorphism of Quotient of Multivariate Polynomial Ring in x, y
118
+ over Rational Field by the ideal (y^2 + 1)
119
+ Defn: a |--> a^2
120
+ b |--> -b
121
+ sage: phi(b)
122
+ -b
123
+ sage: phi(a^2 + b^2)
124
+ a^4 - 1
125
+
126
+ The reduction map from the integers to the integers modulo 8, viewed as
127
+ a quotient ring::
128
+
129
+ sage: R = ZZ.quo(8*ZZ)
130
+ sage: pi = R.cover(); pi
131
+ Ring morphism:
132
+ From: Integer Ring
133
+ To: Ring of integers modulo 8
134
+ Defn: Natural quotient map
135
+ sage: pi.domain()
136
+ Integer Ring
137
+ sage: pi.codomain()
138
+ Ring of integers modulo 8
139
+ sage: pi(10)
140
+ 2
141
+ sage: pi.lift()
142
+ Set-theoretic ring morphism:
143
+ From: Ring of integers modulo 8
144
+ To: Integer Ring
145
+ Defn: Choice of lifting map
146
+ sage: pi.lift(13)
147
+ 5
148
+
149
+ Inclusion of ``GF(2)`` into ``GF(4,'a')``::
150
+
151
+ sage: # needs sage.rings.finite_rings
152
+ sage: k = GF(2)
153
+ sage: i = k.hom(GF(4, 'a'))
154
+ sage: i
155
+ Ring morphism:
156
+ From: Finite Field of size 2
157
+ To: Finite Field in a of size 2^2
158
+ Defn: 1 |--> 1
159
+ sage: i(0)
160
+ 0
161
+ sage: a = i(1); a.parent()
162
+ Finite Field in a of size 2^2
163
+
164
+ We next compose the inclusion with reduction from the integers to
165
+ ``GF(2)``::
166
+
167
+ sage: # needs sage.rings.finite_rings
168
+ sage: pi = ZZ.hom(k); pi
169
+ Natural morphism:
170
+ From: Integer Ring
171
+ To: Finite Field of size 2
172
+ sage: f = i * pi; f
173
+ Composite map:
174
+ From: Integer Ring
175
+ To: Finite Field in a of size 2^2
176
+ Defn: Natural morphism:
177
+ From: Integer Ring
178
+ To: Finite Field of size 2
179
+ then
180
+ Ring morphism:
181
+ From: Finite Field of size 2
182
+ To: Finite Field in a of size 2^2
183
+ Defn: 1 |--> 1
184
+ sage: a = f(5); a
185
+ 1
186
+ sage: a.parent()
187
+ Finite Field in a of size 2^2
188
+
189
+ Inclusion from `\QQ` to the 3-adic field::
190
+
191
+ sage: # needs sage.rings.padics
192
+ sage: phi = QQ.hom(Qp(3, print_mode='series'))
193
+ sage: phi
194
+ Ring morphism:
195
+ From: Rational Field
196
+ To: 3-adic Field with capped relative precision 20
197
+ sage: phi.codomain()
198
+ 3-adic Field with capped relative precision 20
199
+ sage: phi(394)
200
+ 1 + 2*3 + 3^2 + 2*3^3 + 3^4 + 3^5 + O(3^20)
201
+
202
+ An automorphism of a quotient of a univariate polynomial ring::
203
+
204
+ sage: # needs sage.libs.pari
205
+ sage: R.<x> = PolynomialRing(QQ)
206
+ sage: S.<sqrt2> = R.quo(x^2 - 2)
207
+ sage: sqrt2^2
208
+ 2
209
+ sage: (3+sqrt2)^10
210
+ 993054*sqrt2 + 1404491
211
+ sage: c = S.hom([-sqrt2])
212
+ sage: c(1+sqrt2)
213
+ -sqrt2 + 1
214
+
215
+ Note that Sage verifies that the morphism is valid::
216
+
217
+ sage: (1 - sqrt2)^2 # needs sage.libs.pari
218
+ -2*sqrt2 + 3
219
+ sage: c = S.hom([1 - sqrt2]) # this is not valid # needs sage.libs.pari
220
+ Traceback (most recent call last):
221
+ ...
222
+ ValueError: relations do not all (canonically) map to 0
223
+ under map determined by images of generators
224
+
225
+ Endomorphism of power series ring::
226
+
227
+ sage: R.<t> = PowerSeriesRing(QQ, default_prec=10); R
228
+ Power Series Ring in t over Rational Field
229
+ sage: f = R.hom([t^2]); f
230
+ Ring endomorphism of Power Series Ring in t over Rational Field
231
+ Defn: t |--> t^2
232
+ sage: s = 1/(1 + t); s
233
+ 1 - t + t^2 - t^3 + t^4 - t^5 + t^6 - t^7 + t^8 - t^9 + O(t^10)
234
+ sage: f(s)
235
+ 1 - t^2 + t^4 - t^6 + t^8 - t^10 + t^12 - t^14 + t^16 - t^18 + O(t^20)
236
+
237
+ Frobenius on a power series ring over a finite field::
238
+
239
+ sage: R.<t> = PowerSeriesRing(GF(5))
240
+ sage: f = R.hom([t^5]); f
241
+ Ring endomorphism of Power Series Ring in t over Finite Field of size 5
242
+ Defn: t |--> t^5
243
+ sage: a = 2 + t + 3*t^2 + 4*t^3 + O(t^4)
244
+ sage: b = 1 + t + 2*t^2 + t^3 + O(t^5)
245
+ sage: f(a)
246
+ 2 + t^5 + 3*t^10 + 4*t^15 + O(t^20)
247
+ sage: f(b)
248
+ 1 + t^5 + 2*t^10 + t^15 + O(t^25)
249
+ sage: f(a*b)
250
+ 2 + 3*t^5 + 3*t^10 + t^15 + O(t^20)
251
+ sage: f(a)*f(b)
252
+ 2 + 3*t^5 + 3*t^10 + t^15 + O(t^20)
253
+
254
+ Homomorphism of Laurent series ring::
255
+
256
+ sage: R.<t> = LaurentSeriesRing(QQ, 10)
257
+ sage: f = R.hom([t^3 + t]); f
258
+ Ring endomorphism of Laurent Series Ring in t over Rational Field
259
+ Defn: t |--> t + t^3
260
+ sage: s = 2/t^2 + 1/(1 + t); s
261
+ 2*t^-2 + 1 - t + t^2 - t^3 + t^4 - t^5 + t^6 - t^7 + t^8 - t^9 + O(t^10)
262
+ sage: f(s)
263
+ 2*t^-2 - 3 - t + 7*t^2 - 2*t^3 - 5*t^4 - 4*t^5 + 16*t^6 - 9*t^7 + O(t^8)
264
+ sage: f = R.hom([t^3]); f
265
+ Ring endomorphism of Laurent Series Ring in t over Rational Field
266
+ Defn: t |--> t^3
267
+ sage: f(s)
268
+ 2*t^-6 + 1 - t^3 + t^6 - t^9 + t^12 - t^15 + t^18 - t^21 + t^24 - t^27 + O(t^30)
269
+
270
+ Note that the homomorphism must result in a converging Laurent
271
+ series, so the valuation of the image of the generator must be
272
+ positive::
273
+
274
+ sage: R.hom([1/t])
275
+ Traceback (most recent call last):
276
+ ...
277
+ ValueError: relations do not all (canonically) map to 0
278
+ under map determined by images of generators
279
+ sage: R.hom([1])
280
+ Traceback (most recent call last):
281
+ ...
282
+ ValueError: relations do not all (canonically) map to 0
283
+ under map determined by images of generators
284
+
285
+ Complex conjugation on cyclotomic fields::
286
+
287
+ sage: # needs sage.rings.number_field
288
+ sage: K.<zeta7> = CyclotomicField(7)
289
+ sage: c = K.hom([1/zeta7]); c
290
+ Ring endomorphism of Cyclotomic Field of order 7 and degree 6
291
+ Defn: zeta7 |--> -zeta7^5 - zeta7^4 - zeta7^3 - zeta7^2 - zeta7 - 1
292
+ sage: a = (1+zeta7)^5; a
293
+ zeta7^5 + 5*zeta7^4 + 10*zeta7^3 + 10*zeta7^2 + 5*zeta7 + 1
294
+ sage: c(a)
295
+ 5*zeta7^5 + 5*zeta7^4 - 4*zeta7^2 - 5*zeta7 - 4
296
+ sage: c(zeta7 + 1/zeta7) # this element is obviously fixed by inversion
297
+ -zeta7^5 - zeta7^4 - zeta7^3 - zeta7^2 - 1
298
+ sage: zeta7 + 1/zeta7
299
+ -zeta7^5 - zeta7^4 - zeta7^3 - zeta7^2 - 1
300
+
301
+ Embedding a number field into the reals::
302
+
303
+ sage: # needs sage.rings.number_field
304
+ sage: R.<x> = PolynomialRing(QQ)
305
+ sage: K.<beta> = NumberField(x^3 - 2)
306
+ sage: alpha = RR(2)^(1/3); alpha
307
+ 1.25992104989487
308
+ sage: i = K.hom([alpha],check=False); i
309
+ Ring morphism:
310
+ From: Number Field in beta with defining polynomial x^3 - 2
311
+ To: Real Field with 53 bits of precision
312
+ Defn: beta |--> 1.25992104989487
313
+ sage: i(beta)
314
+ 1.25992104989487
315
+ sage: i(beta^3)
316
+ 2.00000000000000
317
+ sage: i(beta^2 + 1)
318
+ 2.58740105196820
319
+
320
+ An example from Jim Carlson::
321
+
322
+ sage: K = QQ # by the way :-)
323
+ sage: R.<a,b,c,d> = K[]; R
324
+ Multivariate Polynomial Ring in a, b, c, d over Rational Field
325
+ sage: S.<u> = K[]; S
326
+ Univariate Polynomial Ring in u over Rational Field
327
+ sage: f = R.hom([0,0,0,u], S); f
328
+ Ring morphism:
329
+ From: Multivariate Polynomial Ring in a, b, c, d over Rational Field
330
+ To: Univariate Polynomial Ring in u over Rational Field
331
+ Defn: a |--> 0
332
+ b |--> 0
333
+ c |--> 0
334
+ d |--> u
335
+ sage: f(a + b + c + d)
336
+ u
337
+ sage: f((a+b+c+d)^2)
338
+ u^2
339
+
340
+ TESTS::
341
+
342
+ sage: H = Hom(ZZ, QQ)
343
+ sage: H == loads(dumps(H))
344
+ True
345
+
346
+ ::
347
+
348
+ sage: # needs sage.rings.number_field
349
+ sage: K.<zeta7> = CyclotomicField(7)
350
+ sage: c = K.hom([1/zeta7])
351
+ sage: c == loads(dumps(c))
352
+ True
353
+
354
+ ::
355
+
356
+ sage: R.<t> = PowerSeriesRing(GF(5))
357
+ sage: f = R.hom([t^5])
358
+ sage: f == loads(dumps(f))
359
+ True
360
+
361
+ We define the identity map in many possible ways. These should all
362
+ compare equal::
363
+
364
+ sage: # needs sage.rings.finite_rings
365
+ sage: k = GF(2)
366
+ sage: R.<x> = k[]
367
+ sage: F4.<a> = R.quo(x^2 + x + 1)
368
+ sage: H = End(F4)
369
+ sage: from sage.rings.morphism import *
370
+ sage: phi1 = H.identity(); phi1
371
+ Identity endomorphism of Univariate Quotient Polynomial Ring in a
372
+ over Finite Field of size 2 with modulus x^2 + x + 1
373
+ sage: phi2 = H([a]); phi2
374
+ Ring endomorphism of Univariate Quotient Polynomial Ring in a
375
+ over Finite Field of size 2 with modulus x^2 + x + 1
376
+ Defn: a |--> a
377
+ sage: phi3 = RingHomomorphism_from_base(H, R.hom([x])); phi3 # needs sage.libs.ntl
378
+ Ring endomorphism of Univariate Quotient Polynomial Ring in a
379
+ over Finite Field of size 2 with modulus x^2 + x + 1
380
+ Defn: Induced from base ring by
381
+ Ring endomorphism of Univariate Polynomial Ring in x
382
+ over Finite Field of size 2 (using GF2X)
383
+ Defn: x |--> x
384
+ sage: phi4 = RingHomomorphism_cover(H); phi4
385
+ Ring endomorphism of Univariate Quotient Polynomial Ring in a
386
+ over Finite Field of size 2 with modulus x^2 + x + 1
387
+ Defn: Natural quotient map
388
+ sage: phi5 = F4.frobenius_endomorphism() ^ 2; phi5
389
+ Frobenius endomorphism x |--> x^(2^2) of
390
+ Univariate Quotient Polynomial Ring in a
391
+ over Finite Field of size 2 with modulus x^2 + x + 1
392
+ sage: maps = [phi1, phi2, phi3, phi4, phi5] # needs sage.libs.ntl
393
+ sage: for f in maps: # needs sage.libs.ntl
394
+ ....: for g in maps:
395
+ ....: if f != g:
396
+ ....: print("{} != {}".format(f, g))
397
+ """
398
+
399
+ # ****************************************************************************
400
+ # Copyright (C) 2006 William Stein <wstein@gmail.com>
401
+ #
402
+ # This program is free software: you can redistribute it and/or modify
403
+ # it under the terms of the GNU General Public License as published by
404
+ # the Free Software Foundation, either version 2 of the License, or
405
+ # (at your option) any later version.
406
+ # https://www.gnu.org/licenses/
407
+ # ****************************************************************************
408
+
409
+ from sage.rings import ideal
410
+ import sage.structure.all
411
+ from sage.structure.richcmp cimport (richcmp, rich_to_bool)
412
+ from sage.misc.cachefunc import cached_method
413
+ from sage.categories.rings import Rings
414
+ from sage.categories.facade_sets import FacadeSets
415
+
416
+
417
+ cdef class RingMap(Morphism):
418
+ """
419
+ Set-theoretic map between rings.
420
+
421
+ TESTS:
422
+
423
+ This is an abstract base class that is not directly instantiated,
424
+ but we will do so anyway as a test::
425
+
426
+ sage: f = sage.rings.morphism.RingMap(ZZ.Hom(ZZ))
427
+ sage: parent(f)
428
+ Set of Homomorphisms from Integer Ring to Integer Ring
429
+ sage: type(f)
430
+ <class 'sage.rings.morphism.RingMap'>
431
+ """
432
+ def _repr_type(self):
433
+ """
434
+ TESTS::
435
+
436
+ sage: f = sage.rings.morphism.RingMap(ZZ.Hom(ZZ))
437
+ sage: type(f)
438
+ <class 'sage.rings.morphism.RingMap'>
439
+ sage: f._repr_type()
440
+ 'Set-theoretic ring'
441
+ sage: f
442
+ Set-theoretic ring endomorphism of Integer Ring
443
+ """
444
+ return "Set-theoretic ring"
445
+
446
+
447
+ cdef class RingMap_lift(RingMap):
448
+ r"""
449
+ Given rings `R` and `S` such that for any
450
+ `x \in R` the function ``x.lift()`` is an
451
+ element that naturally coerces to `S`, this returns the
452
+ set-theoretic ring map `R \to S` sending `x` to
453
+ ``x.lift()``.
454
+
455
+ EXAMPLES::
456
+
457
+ sage: R.<x,y> = QQ[]
458
+ sage: S.<xbar,ybar> = R.quo( (x^2 + y^2, y) ) # needs sage.libs.singular
459
+ sage: S.lift() # needs sage.libs.singular
460
+ Set-theoretic ring morphism:
461
+ From: Quotient of Multivariate Polynomial Ring in x, y
462
+ over Rational Field by the ideal (x^2 + y^2, y)
463
+ To: Multivariate Polynomial Ring in x, y over Rational Field
464
+ Defn: Choice of lifting map
465
+ sage: S.lift() == 0 # needs sage.libs.singular
466
+ False
467
+
468
+ Since :issue:`11068`, it is possible to create
469
+ quotient rings of non-commutative rings by two-sided
470
+ ideals. It was needed to modify :class:`RingMap_lift`
471
+ so that rings can be accepted that are no instances
472
+ of :class:`sage.rings.ring.Ring`, as in the following
473
+ example::
474
+
475
+ sage: # needs sage.modules sage.rings.finite_rings
476
+ sage: MS = MatrixSpace(GF(5), 2, 2)
477
+ sage: I = MS * [MS.0*MS.1, MS.2+MS.3] * MS
478
+ sage: Q = MS.quo(I)
479
+ sage: Q.0*Q.1 # indirect doctest
480
+ [0 1]
481
+ [0 0]
482
+ """
483
+ def __init__(self, R, S):
484
+ """
485
+ Create a lifting ring map.
486
+
487
+ EXAMPLES::
488
+
489
+ sage: f = Zmod(8).lift() # indirect doctest
490
+ sage: f(3)
491
+ 3
492
+ sage: type(f(3))
493
+ <class 'sage.rings.integer.Integer'>
494
+ sage: type(f)
495
+ <class 'sage.rings.morphism.RingMap_lift'>
496
+
497
+ An invalid example::
498
+
499
+ sage: GF9.<one, a> = GaussianIntegers().quotient(3) # needs sage.rings.number_field
500
+ sage: from sage.rings.morphism import RingMap_lift
501
+ sage: RingMap_lift(GF9, ZZ) # needs sage.rings.number_field
502
+ Traceback (most recent call last):
503
+ ...
504
+ TypeError: no canonical coercion from Number Field in I
505
+ with defining polynomial x^2 + 1 with I = 1*I to Integer Ring
506
+ """
507
+ self.S = <Parent?>S
508
+ x = <Element?>R(0).lift()
509
+ f = self.S.coerce_map_from(x._parent)
510
+ if f is None:
511
+ raise TypeError(f"no canonical coercion from {x._parent} to {S}")
512
+ self.to_S = f
513
+
514
+ from sage.categories.sets_cat import Sets
515
+ H = R.Hom(S, Sets())
516
+ RingMap.__init__(self, H)
517
+
518
+ cdef _update_slots(self, dict _slots):
519
+ """
520
+ Helper for copying and pickling.
521
+
522
+ EXAMPLES::
523
+
524
+ sage: f = Zmod(8).lift()
525
+ sage: g = copy(f) # indirect doctest
526
+ sage: g(3) == f(3)
527
+ True
528
+ sage: f == g
529
+ True
530
+ sage: f is g
531
+ False
532
+ """
533
+ self.S = _slots['S']
534
+ self.to_S = _slots['to_S']
535
+ Morphism._update_slots(self, _slots)
536
+
537
+ cdef dict _extra_slots(self):
538
+ """
539
+ Helper for copying and pickling.
540
+
541
+ EXAMPLES::
542
+
543
+ sage: f = Zmod(8).lift()
544
+ sage: g = copy(f) # indirect doctest
545
+ sage: g(3) == f(3)
546
+ True
547
+ """
548
+ slots = Morphism._extra_slots(self)
549
+ slots['S'] = self.S
550
+ slots['to_S'] = self.to_S
551
+ return slots
552
+
553
+ cpdef _richcmp_(self, other, int op):
554
+ """
555
+ Compare a ring lifting maps ``self`` to ``other``.
556
+
557
+ Ring lifting maps never compare equal to any other data type.
558
+ If ``other`` is a ring lifting maps, the parents of ``self`` and
559
+ ``other`` are compared.
560
+
561
+ EXAMPLES::
562
+
563
+ sage: f = Zmod(8).lift()
564
+ sage: g = Zmod(10).lift()
565
+ sage: f == f
566
+ True
567
+ sage: f == g
568
+ False
569
+
570
+ Verify that :issue:`5758` has been fixed::
571
+
572
+ sage: Zmod(8).lift() == 1
573
+ False
574
+ """
575
+ if not isinstance(other, RingMap_lift):
576
+ # Generic comparison
577
+ return RingMap._richcmp_(self, other, op)
578
+ # Two lifting maps with the same parent must be equal
579
+ return rich_to_bool(op, 0)
580
+
581
+ def __hash__(self):
582
+ """
583
+ Return the hash of this morphism.
584
+
585
+ TESTS::
586
+
587
+ sage: f = Zmod(8).lift()
588
+ sage: type(f)
589
+ <class 'sage.rings.morphism.RingMap_lift'>
590
+ sage: hash(f) == hash(f)
591
+ True
592
+ sage: {f: 1}[f]
593
+ 1
594
+ sage: g = Zmod(10).lift()
595
+ sage: hash(f) == hash(g)
596
+ False
597
+ """
598
+ return hash((self.domain(), self.codomain()))
599
+
600
+ def _repr_defn(self):
601
+ """
602
+ Used in printing out lifting maps.
603
+
604
+ EXAMPLES::
605
+
606
+ sage: f = Zmod(8).lift()
607
+ sage: f._repr_defn()
608
+ 'Choice of lifting map'
609
+ sage: f
610
+ Set-theoretic ring morphism:
611
+ From: Ring of integers modulo 8
612
+ To: Integer Ring
613
+ Defn: Choice of lifting map
614
+ """
615
+ return "Choice of lifting map"
616
+
617
+ cpdef Element _call_(self, x):
618
+ """
619
+ Evaluate this function at ``x``.
620
+
621
+ EXAMPLES::
622
+
623
+ sage: f = Zmod(8).lift()
624
+ sage: type(f)
625
+ <class 'sage.rings.morphism.RingMap_lift'>
626
+ sage: f(-1) # indirect doctest
627
+ 7
628
+ sage: type(f(-1))
629
+ <class 'sage.rings.integer.Integer'>
630
+ """
631
+ return self.to_S(x.lift())
632
+
633
+
634
+ cdef class RingHomomorphism(RingMap):
635
+ """
636
+ Homomorphism of rings.
637
+ """
638
+ def __init__(self, parent):
639
+ """
640
+ Initialize ``self``.
641
+
642
+ EXAMPLES::
643
+
644
+ sage: f = ZZ.hom(Zp(3)); f # needs sage.rings.padics
645
+ Ring morphism:
646
+ From: Integer Ring
647
+ To: 3-adic Ring with capped relative precision 20
648
+
649
+ TESTS::
650
+
651
+ sage: isinstance(f, sage.rings.morphism.RingHomomorphism) # needs sage.rings.padics
652
+ True
653
+ """
654
+ from sage.rings.homset import RingHomset_generic
655
+ if not isinstance(parent, RingHomset_generic):
656
+ raise TypeError("parent must be a ring homset")
657
+ RingMap.__init__(self, parent)
658
+
659
+ def _repr_type(self):
660
+ """
661
+ Used internally in printing this morphism.
662
+
663
+ TESTS::
664
+
665
+ sage: ZZ.hom(Zp(3))._repr_type() # needs sage.rings.padics
666
+ 'Ring'
667
+ """
668
+ return "Ring"
669
+
670
+ def _set_lift(self, lift):
671
+ r"""
672
+ Used internally to define a lifting map associated to
673
+ this homomorphism, which goes in the other direction. I.e.,
674
+ if ``self`` is from `R` to `S`, then the lift must be a set-theoretic
675
+ map from `S` to `R` such that ``self(lift(x)) == x``.
676
+
677
+ INPUT:
678
+
679
+ - ``lift`` -- a ring map
680
+
681
+ OUTPUT: changes the state of ``self``
682
+
683
+ EXAMPLES::
684
+
685
+ sage: R = ZZ.quo(3*ZZ)
686
+ sage: pi = R.cover() # indirect doctest
687
+ sage: pi.lift()
688
+ Set-theoretic ring morphism:
689
+ From: Ring of integers modulo 3
690
+ To: Integer Ring
691
+ Defn: Choice of lifting map
692
+ """
693
+ if lift.domain() != self.codomain():
694
+ raise TypeError("lift must have correct domain")
695
+ if lift.codomain() != self.domain():
696
+ raise TypeError("lift must have correct codomain")
697
+ self._lift = lift
698
+
699
+ cdef _update_slots(self, dict _slots):
700
+ """
701
+ Helper for copying and pickling.
702
+
703
+ EXAMPLES::
704
+
705
+ sage: f = ZZ.hom(Zmod(6))
706
+ sage: g = copy(f) # indirect doctest
707
+ sage: g == f
708
+ True
709
+ sage: g is f
710
+ False
711
+ sage: g(7)
712
+ 1
713
+ """
714
+ if '_lift' in _slots:
715
+ self._lift = _slots['_lift']
716
+ Morphism._update_slots(self, _slots)
717
+
718
+ cdef dict _extra_slots(self):
719
+ """
720
+ Helper for copying and pickling.
721
+
722
+ EXAMPLES::
723
+
724
+ sage: f = ZZ.hom(Zmod(6))
725
+ sage: g = copy(f) # indirect doctest
726
+ sage: g == f
727
+ True
728
+ sage: g is f
729
+ False
730
+ sage: g(7)
731
+ 1
732
+ """
733
+ slots = Morphism._extra_slots(self)
734
+ try:
735
+ slots['_lift'] = self._lift
736
+ except AttributeError:
737
+ pass
738
+ return slots
739
+
740
+ def _composition_(self, right, homset):
741
+ """
742
+ If ``homset`` is a homset of rings and ``right`` is a
743
+ ring homomorphism given by the images of generators,
744
+ (indirectly in the case of homomorphisms from relative
745
+ number fields), the composition with ``self`` will be
746
+ of the appropriate type.
747
+
748
+ Otherwise, a formal composite map is returned.
749
+
750
+ EXAMPLES::
751
+
752
+ sage: R.<x,y> = QQ[]
753
+ sage: S.<a,b> = QQ[]
754
+ sage: f = R.hom([a+b,a-b])
755
+ sage: g = S.hom(Frac(S))
756
+ sage: g*f # indirect doctest
757
+ Composite map:
758
+ From: Multivariate Polynomial Ring in x, y over Rational Field
759
+ To: Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field
760
+ Defn: Ring morphism:
761
+ From: Multivariate Polynomial Ring in x, y over Rational Field
762
+ To: Multivariate Polynomial Ring in a, b over Rational Field
763
+ Defn: x |--> a + b
764
+ y |--> a - b
765
+ then
766
+ Coercion map:
767
+ From: Multivariate Polynomial Ring in a, b over Rational Field
768
+ To: Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field
769
+
770
+ When ``right`` is defined by the images of generators, the
771
+ result has the type of a homomorphism between its domain and
772
+ codomain::
773
+
774
+ sage: C = CyclotomicField(24) # needs sage.rings.number_field
775
+ sage: f = End(C)[1] # needs sage.rings.number_field
776
+ sage: type(f*f) == type(f) # needs sage.rings.number_field
777
+ True
778
+
779
+ An example where the domain of ``right`` is a relative number field::
780
+
781
+ sage: PQ.<X> = QQ[]
782
+ sage: K.<a, b> = NumberField([X^2 - 2, X^2 - 3]) # needs sage.rings.number_field
783
+ sage: e, u, v, w = End(K) # needs sage.rings.number_field
784
+ sage: u*v # needs sage.rings.number_field
785
+ Relative number field endomorphism of
786
+ Number Field in a with defining polynomial X^2 - 2 over its base field
787
+ Defn: a |--> -a
788
+ b |--> b
789
+
790
+ An example where ``right`` is not a ring homomorphism::
791
+
792
+ sage: from sage.categories.morphism import SetMorphism
793
+ sage: h = SetMorphism(Hom(R,S,Rings()), lambda p: p[0])
794
+ sage: g*h
795
+ Composite map:
796
+ From: Multivariate Polynomial Ring in x, y over Rational Field
797
+ To: Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field
798
+ Defn: Generic morphism:
799
+ From: Multivariate Polynomial Ring in x, y over Rational Field
800
+ To: Multivariate Polynomial Ring in a, b over Rational Field
801
+ then
802
+ Coercion map:
803
+ From: Multivariate Polynomial Ring in a, b over Rational Field
804
+ To: Fraction Field of
805
+ Multivariate Polynomial Ring in a, b over Rational Field
806
+
807
+ We check that composition works when there is a base map::
808
+
809
+ sage: # needs sage.rings.finite_rings
810
+ sage: R.<x> = ZZ[]
811
+ sage: K.<a> = GF(7^2)
812
+ sage: L.<u> = K.extension(x^3 - 3)
813
+ sage: phi = L.hom([u^7], base_map=K.frobenius_endomorphism())
814
+ sage: phi
815
+ Ring endomorphism of Univariate Quotient Polynomial Ring in u
816
+ over Finite Field in a of size 7^2 with modulus u^3 + 4
817
+ Defn: u |--> 2*u
818
+ with map of base ring
819
+ sage: psi = phi^3; psi
820
+ Ring endomorphism of Univariate Quotient Polynomial Ring in u
821
+ over Finite Field in a of size 7^2 with modulus u^3 + 4
822
+ Defn: u |--> u
823
+ with map of base ring
824
+ sage: psi(a) == phi(phi(phi(a)))
825
+ True
826
+
827
+ It also works when the image of the base map is not contained within the base ring of the codomain::
828
+
829
+ sage: S.<x> = QQ[]
830
+ sage: T.<y> = S[]
831
+ sage: cc = S.hom([x + y])
832
+ sage: f = T.hom([x - y], base_map=cc)
833
+ sage: f*f
834
+ Ring endomorphism of Univariate Polynomial Ring in y
835
+ over Univariate Polynomial Ring in x over Rational Field
836
+ Defn: y |--> 2*y
837
+ with map of base ring
838
+ sage: (f*f).base_map()
839
+ Ring morphism:
840
+ From: Univariate Polynomial Ring in x over Rational Field
841
+ To: Univariate Polynomial Ring in y over
842
+ Univariate Polynomial Ring in x over Rational Field
843
+ Defn: x |--> 2*x
844
+ with map of base ring
845
+
846
+ sage: S.<x> = QQ[]
847
+ sage: T.<y> = S[]
848
+ sage: cc = S.hom([x+y])
849
+ sage: f = T.hom([x-y], base_map=cc)
850
+ sage: g = T.hom([x-y])
851
+ sage: (f*g)(x)
852
+ y + x
853
+ sage: f(g(x))
854
+ y + x
855
+
856
+ AUTHORS:
857
+
858
+ - Simon King (2010-05)
859
+ - Francis Clarke (2011-02)
860
+ - David Roe (2019-10)
861
+ """
862
+ from sage.categories.morphism import IdentityMorphism
863
+ from sage.categories.rings import Rings
864
+ if isinstance(right, IdentityMorphism):
865
+ return self
866
+ if homset.homset_category().is_subcategory(Rings()):
867
+ if isinstance(right, RingHomomorphism_im_gens):
868
+ rbm = right.base_map()
869
+ kwds = {'check': False}
870
+ if rbm is None and isinstance(self, RingHomomorphism_im_gens) and self.base_map() is not None:
871
+ rbm = right.codomain().coerce_map_from(right.domain().base_ring())
872
+ if rbm is not None:
873
+ kwds['base_map'] = self * rbm
874
+ try:
875
+ return homset([self(g) for g in right.im_gens()], **kwds)
876
+ except ValueError:
877
+ pass
878
+ try:
879
+ from sage.rings.number_field.morphism import RelativeNumberFieldHomomorphism_from_abs
880
+ except ImportError:
881
+ pass
882
+ else:
883
+ if isinstance(right, RelativeNumberFieldHomomorphism_from_abs):
884
+ try:
885
+ return homset(self*right.abs_hom())
886
+ except ValueError:
887
+ pass
888
+ return sage.categories.map.Map._composition_(self, right, homset)
889
+
890
+ def pushforward(self, I):
891
+ """
892
+ Return the pushforward of the ideal `I` under this ring
893
+ homomorphism.
894
+
895
+ EXAMPLES::
896
+
897
+ sage: R.<x,y> = QQ[]; S.<xx,yy> = R.quo([x^2, y^2]); f = S.cover() # needs sage.libs.singular
898
+ sage: f.pushforward(R.ideal([x, 3*x + x*y + y^2])) # needs sage.libs.singular
899
+ Ideal (xx, xx*yy + 3*xx) of Quotient of Multivariate Polynomial Ring
900
+ in x, y over Rational Field by the ideal (x^2, y^2)
901
+ """
902
+ if not isinstance(I, ideal.Ideal_generic):
903
+ raise TypeError("I must be an ideal")
904
+ R = self.codomain()
905
+ return R.ideal([self(y) for y in I.gens()])
906
+
907
+ def inverse_image(self, I):
908
+ """
909
+ Return the inverse image of an ideal or an element in the codomain
910
+ of this ring homomorphism.
911
+
912
+ INPUT:
913
+
914
+ - ``I`` -- an ideal or element in the codomain
915
+
916
+ OUTPUT:
917
+
918
+ For an ideal `I` in the codomain, this returns the largest ideal in the
919
+ domain whose image is contained in `I`.
920
+
921
+ Given an element `b` in the codomain, this returns an arbitrary element
922
+ `a` in the domain such that ``self(a) = b`` if one such exists.
923
+ The element `a` is unique if this ring homomorphism is injective.
924
+
925
+ EXAMPLES::
926
+
927
+ sage: R.<x,y,z> = QQ[]
928
+ sage: S.<u,v> = QQ[]
929
+ sage: f = R.hom([u^2, u*v, v^2], S)
930
+ sage: I = S.ideal([u^6, u^5*v, u^4*v^2, u^3*v^3])
931
+ sage: J = f.inverse_image(I); J # needs sage.libs.singular
932
+ Ideal (y^2 - x*z, x*y*z, x^2*z, x^2*y, x^3)
933
+ of Multivariate Polynomial Ring in x, y, z over Rational Field
934
+ sage: f(J) == I # needs sage.libs.singular
935
+ True
936
+
937
+ Under the above homomorphism, there exists an inverse image for
938
+ every element that only involves monomials of even degree::
939
+
940
+ sage: [f.inverse_image(p) for p in [u^2, u^4, u*v + u^3*v^3]] # needs sage.libs.singular
941
+ [x, x^2, x*y*z + y]
942
+ sage: f.inverse_image(u*v^2) # needs sage.libs.singular
943
+ Traceback (most recent call last):
944
+ ...
945
+ ValueError: element u*v^2 does not have preimage
946
+
947
+ The image of the inverse image ideal can be strictly smaller than the
948
+ original ideal::
949
+
950
+ sage: # needs sage.libs.singular sage.rings.number_field
951
+ sage: S.<u,v> = QQ['u,v'].quotient('v^2 - 2')
952
+ sage: f = QuadraticField(2).hom([v], S)
953
+ sage: I = S.ideal(u + v)
954
+ sage: J = f.inverse_image(I)
955
+ sage: J.is_zero()
956
+ True
957
+ sage: f(J) < I
958
+ True
959
+
960
+ Fractional ideals are not yet fully supported::
961
+
962
+ sage: # needs sage.rings.number_field
963
+ sage: K.<a> = NumberField(QQ['x']('x^2+2'))
964
+ sage: f = K.hom([-a], K)
965
+ sage: I = K.ideal([a + 1])
966
+ sage: f.inverse_image(I) # needs sage.libs.singular
967
+ Traceback (most recent call last):
968
+ ...
969
+ NotImplementedError: inverse image not implemented...
970
+ sage: f.inverse_image(K.ideal(0)).is_zero() # needs sage.libs.singular
971
+ True
972
+ sage: f.inverse()(I) # needs sage.libs.singular sage.rings.padics
973
+ Fractional ideal (-a + 1)
974
+
975
+ ALGORITHM:
976
+
977
+ By default, this computes a Gröbner basis of an ideal related to the
978
+ graph of the ring homomorphism.
979
+
980
+ REFERENCES:
981
+
982
+ - Proposition 2.5.12 [DS2009]_
983
+
984
+ TESTS::
985
+
986
+ sage: ZZ.hom(Zp(2)).inverse_image(ZZ.ideal(2)) # needs sage.rings.padics
987
+ Traceback (most recent call last):
988
+ ...
989
+ ValueError: not an ideal or element in codomain 2-adic Ring
990
+ with capped relative precision 20
991
+
992
+ ::
993
+
994
+ sage: ZZ.hom(Zp(2)).inverse_image(Zp(2).ideal(2)) # needs sage.rings.padics
995
+ Traceback (most recent call last):
996
+ ...
997
+ NotImplementedError: base rings must be equal
998
+ """
999
+ from sage.categories.ring_ideals import RingIdeals
1000
+ B = self.codomain()
1001
+ if I in RingIdeals(B):
1002
+ return self._inverse_image_ideal(I)
1003
+ elif I in B:
1004
+ return self._inverse_image_element(I)
1005
+ else:
1006
+ raise ValueError("not an ideal or element in codomain %s" % B)
1007
+
1008
+ def _inverse_image_ideal(self, I):
1009
+ """
1010
+ Return the inverse image of an ideal under this ring homomorphism.
1011
+
1012
+ EXAMPLES::
1013
+
1014
+ sage: # needs sage.rings.number_field sage.symbolic
1015
+ sage: R.<x,y> = QQbar[]
1016
+ sage: f = R.hom([x, QQbar(i) * x + y^2], R)
1017
+ sage: I = R.ideal(y^3)
1018
+ sage: J = f._inverse_image_ideal(I); J
1019
+ Ideal (x^2 + 2*I*x*y - y^2)
1020
+ of Multivariate Polynomial Ring in x, y over Algebraic Field
1021
+ sage: f(J) <= I
1022
+ True
1023
+
1024
+ TESTS:
1025
+
1026
+ Check that :issue:`31367` is fixed::
1027
+
1028
+ sage: A.<t> = QQ[]
1029
+ sage: B.<x,y> = QQ['x,y'].quotient('y') # needs sage.libs.singular
1030
+ sage: f = A.hom([x], B) # needs sage.libs.singular
1031
+ sage: f.kernel() # needs sage.libs.singular
1032
+ Principal ideal (0) of Univariate Polynomial Ring in t over Rational Field
1033
+
1034
+ ::
1035
+
1036
+ sage: A.<t,u> = QQ[]
1037
+ sage: B.<x,y,z> = QQ['x,y,z'].quotient('z') # needs sage.libs.singular
1038
+ sage: f = A.hom([x, y], B) # needs sage.libs.singular
1039
+ sage: f.kernel() # needs sage.libs.singular
1040
+ Ideal (0) of Multivariate Polynomial Ring in t, u over Rational Field
1041
+ """
1042
+ from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_generic
1043
+ from sage.rings.quotient_ring import QuotientRing_nc
1044
+ from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_base
1045
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
1046
+ B = self.codomain()
1047
+ graph, from_B, to_A = self._graph_ideal()
1048
+ Q = graph.ring()
1049
+ gens_B = Q.gens()[:B.ngens()]
1050
+ if I.is_zero():
1051
+ # avoid adding the 0-ideal to the graph ideal in order to benefit
1052
+ # from a cached Gröbner basis
1053
+ graph_I = graph
1054
+ elif isinstance(B, (MPolynomialRing_base,
1055
+ PolynomialRing_generic,
1056
+ QuotientRing_nc,
1057
+ PolynomialQuotientRing_generic)):
1058
+ graph_I = graph + from_B(I)
1059
+ else:
1060
+ # nonzero fractional ideals of number fields not yet supported
1061
+ raise NotImplementedError("inverse image not implemented "
1062
+ "for ideals in %s" % B)
1063
+ if isinstance(Q, QuotientRing_nc):
1064
+ # elimination_ideal does not work with quotient rings, so
1065
+ # switch to the cover ring
1066
+ gens_B_lifted = Q.cover_ring().gens()[:B.ngens()]
1067
+ graph_I_lifted = Q.cover()._inverse_image_ideal(graph_I)
1068
+ preimage = graph_I_lifted.elimination_ideal(gens_B_lifted)
1069
+ _, ambient_to_A = to_A
1070
+ return ambient_to_A(preimage)
1071
+ else:
1072
+ preimage = graph_I.elimination_ideal(gens_B)
1073
+ return to_A(preimage)
1074
+
1075
+ def _inverse_image_element(self, b):
1076
+ """
1077
+ Return an element `a` such that ``self(a) = b`` if one such exists.
1078
+
1079
+ TESTS:
1080
+
1081
+ A degenerate case::
1082
+
1083
+ sage: R.<x,y> = QQ['x,y'].quotient(1) # needs sage.libs.singular
1084
+ sage: f = R.hom([y, x], R) # needs sage.libs.singular
1085
+ sage: f.inverse_image(x), f.inverse_image(y) # indirect doctest # needs sage.libs.singular
1086
+ (0, 0)
1087
+
1088
+ Check cases involving quotient rings in which a generator is constant
1089
+ (:issue:`31178`)::
1090
+
1091
+ sage: # needs sage.libs.singular
1092
+ sage: R.<x,y> = QQ[]
1093
+ sage: B.<c,d> = R.quotient(R.ideal(x))
1094
+ sage: g = R.hom([d^2, d^3], B)
1095
+ sage: g.inverse_image(d)
1096
+ Traceback (most recent call last):
1097
+ ...
1098
+ ValueError: element d does not have preimage
1099
+ sage: g.inverse_image(d^2)
1100
+ x
1101
+ sage: g.inverse_image(d^3)
1102
+ y
1103
+ sage: A.<a,b> = R.quotient(R.ideal(y^2 - x^3))
1104
+ sage: h = A.hom([d^2, d^3], B)
1105
+ sage: h.inverse_image(d^2)
1106
+ a
1107
+
1108
+ Check that quotient rings are handled correctly (:issue:`33217`)::
1109
+
1110
+ sage: # needs sage.libs.singular
1111
+ sage: A.<x,y,z> = QQ['X,Y,Z'].quotient('X^2+Y^2+Z^2-1')
1112
+ sage: B.<t,u,v,w> = QQ['T,U,V,W'].quotient(['T^2+U^2-1', 'V^2+W^2-1'])
1113
+ sage: psi = A.hom([v*u, w*u, t], B)
1114
+ sage: psi.inverse_image(t^2) == z^2
1115
+ True
1116
+
1117
+ Check that the case in which the domain is a quotient ring
1118
+ and codomain a finite field of same characteristic is handled correctly::
1119
+
1120
+ sage: # needs sage.rings.finite_rings
1121
+ sage: F8.<a> = GF(2^3)
1122
+ sage: PR.<y> = PolynomialRing(F8)
1123
+ sage: IP = y^4 + a*y^3 + (a^2 + 1)*y + a^2 + 1
1124
+ sage: assert IP.is_irreducible()
1125
+ sage: Q.<w> = PR.quotient(IP)
1126
+ sage: SF.<z> = IP.splitting_field()
1127
+ sage: r = z^9 + z^7 + z^3 + z + 1
1128
+ sage: assert IP.change_ring(SF)(r) == 0
1129
+ sage: f = Q.hom([r,], SF)
1130
+ sage: f.inverse_image(z) # indirect doctest # needs sage.modules
1131
+ w^3 + (a^2 + a + 1)*w^2 + (a^2 + 1)*w + a^2 + 1
1132
+ """
1133
+ from sage.rings.finite_rings.finite_field_base import FiniteField
1134
+ from sage.rings.quotient_ring import QuotientRing_nc
1135
+ if isinstance(self.domain(), QuotientRing_nc) and isinstance(self.codomain(), FiniteField):
1136
+ if self.domain().characteristic() == self.codomain().characteristic():
1137
+ return self._preimage_from_linear_dependence(b)
1138
+ graph, from_B, to_A = self._graph_ideal()
1139
+ gens_A = graph.ring().gens()[-self.domain().ngens():]
1140
+ a = graph.reduce(from_B(b))
1141
+ if not all(x in gens_A for x in a.lm().variables()):
1142
+ raise ValueError(f"element {b} does not have preimage")
1143
+ return to_A(a)
1144
+
1145
+ @cached_method
1146
+ def _preimage_from_linear_dependence(self, b):
1147
+ r"""
1148
+ Return an element `a` in self's domain such that ``self(a) = b``.
1149
+
1150
+ Return the preimage of ``b`` by solving a linear system
1151
+ in the common prime subfield. This yields the unique
1152
+ element in the domain that maps to ``b`` in the codomain.
1153
+
1154
+ An error is raised when the domain and codomain are not isomorphic.
1155
+
1156
+ INPUT:
1157
+
1158
+ - ``b`` -- an element in the codomain of this morphism
1159
+
1160
+ OUTPUT: an element `a` in the domain of this morphism such that ``self(a) = b``.
1161
+
1162
+ EXAMPLES::
1163
+
1164
+ This example illustrates the error message we get if the domain and codomain have different cardinality.
1165
+ In that case, we certainly know the morphism is not an isomorphism::
1166
+
1167
+ sage: # needs sage.rings.finite_rings
1168
+ sage: F4.<a> = GF(2^2, modulus=[1,1,1])
1169
+ sage: PR.<y> = PolynomialRing(F4)
1170
+ sage: IP = y^5 + y + 1
1171
+ sage: assert not IP.is_irreducible()
1172
+ sage: Q.<w> = PR.quotient(IP)
1173
+ sage: SF.<z> = IP.splitting_field()
1174
+ sage: r = IP.change_ring(SF).roots()[0][0]
1175
+ sage: f = Q.hom([r,], SF)
1176
+ sage: f._preimage_from_linear_dependence(z)
1177
+ Traceback (most recent call last):
1178
+ ...
1179
+ ValueError: the cardinalities of the domain (=1024) and codomain (=64) should be equal
1180
+ """
1181
+ D = self.domain()
1182
+ C = self.codomain()
1183
+ if D.characteristic() != C.characteristic():
1184
+ raise ValueError("the domain's and codomain's characteristic should be equal")
1185
+ if (d_card := D.cardinality()) != (c_card := C.cardinality()):
1186
+ raise ValueError(f"the cardinalities of the domain (={d_card}) and codomain (={c_card}) should be equal")
1187
+ if C != b.parent():
1188
+ raise TypeError(f"{b} fails to convert into the morphism's codomain {C}")
1189
+ F1 = D.base_ring()
1190
+ im_gen = self.im_gens()[0]
1191
+ target = im_gen.parent().gen()
1192
+ g = F1.gen()
1193
+ ncoeffs = F1.degree()
1194
+ from sage.modules.free_module_element import vector
1195
+ A = [vector(g**j * im_gen**i) for i in range(D.degree()) for j in range(ncoeffs)]
1196
+ from sage.matrix.constructor import Matrix
1197
+ M = Matrix(A).T
1198
+ T = vector(target)
1199
+ s = M.solve_right(T)
1200
+ P = D([F1(s[i:i+ncoeffs]) for i in range(0, len(s), ncoeffs)])
1201
+ return self.parent().reversed()(P)(b)
1202
+
1203
+ @cached_method
1204
+ def kernel(self):
1205
+ """
1206
+ Return the kernel ideal of this ring homomorphism.
1207
+
1208
+ EXAMPLES::
1209
+
1210
+ sage: A.<x,y> = QQ[]
1211
+ sage: B.<t> = QQ[]
1212
+ sage: f = A.hom([t^4, t^3 - t^2], B)
1213
+ sage: f.kernel() # needs sage.libs.singular
1214
+ Ideal (y^4 - x^3 + 4*x^2*y - 2*x*y^2 + x^2)
1215
+ of Multivariate Polynomial Ring in x, y over Rational Field
1216
+
1217
+ We express a Veronese subring of a polynomial ring as a quotient ring::
1218
+
1219
+ sage: A.<a,b,c,d> = QQ[]
1220
+ sage: B.<u,v> = QQ[]
1221
+ sage: f = A.hom([u^3, u^2*v, u*v^2, v^3], B)
1222
+ sage: f.kernel() == A.ideal(matrix.hankel([a, b, c], [d]).minors(2)) # needs sage.libs.singular
1223
+ True
1224
+ sage: Q = A.quotient(f.kernel()) # needs sage.libs.singular
1225
+ sage: Q.hom(f.im_gens(), B).is_injective() # needs sage.libs.singular
1226
+ True
1227
+
1228
+ The Steiner-Roman surface::
1229
+
1230
+ sage: R.<x,y,z> = QQ[]
1231
+ sage: S = R.quotient(x^2 + y^2 + z^2 - 1)
1232
+ sage: f = R.hom([x*y, x*z, y*z], S) # needs sage.libs.singular
1233
+ sage: f.kernel() # needs sage.libs.singular
1234
+ Ideal (x^2*y^2 + x^2*z^2 + y^2*z^2 - x*y*z)
1235
+ of Multivariate Polynomial Ring in x, y, z over Rational Field
1236
+
1237
+ TESTS:
1238
+
1239
+ The results are cached::
1240
+
1241
+ sage: f.kernel() is f.kernel() # needs sage.libs.singular
1242
+ True
1243
+
1244
+ A degenerate case::
1245
+
1246
+ sage: R.<x,y> = QQ[]
1247
+ sage: f = R.hom([0, 0], R.quotient(1)) # needs sage.libs.singular
1248
+ sage: f.kernel().is_one() # needs sage.libs.singular
1249
+ True
1250
+
1251
+ ::
1252
+
1253
+ sage: K.<sqrt2> = QuadraticField(2) # needs sage.rings.number_field
1254
+ sage: K.hom([-sqrt2], K).kernel().is_zero() # needs sage.libs.singular sage.rings.number_field
1255
+ True
1256
+
1257
+ ::
1258
+
1259
+ sage: # needs sage.rings.number_field
1260
+ sage: A.<a> = QuadraticField(2)
1261
+ sage: B.<b> = A.extension(A['b']('b^2-3'))
1262
+ sage: C.<c> = B.absolute_field()
1263
+ sage: A.hom([B(a)], C).kernel().is_zero() # needs sage.libs.singular
1264
+ True
1265
+ sage: A.hom([a], B).kernel()
1266
+ Traceback (most recent call last):
1267
+ ...
1268
+ NotImplementedError: base rings must be equal
1269
+ """
1270
+ return self._inverse_image_ideal(self.codomain().zero_ideal())
1271
+
1272
+ def lift(self, x=None):
1273
+ """
1274
+ Return a lifting map associated to this homomorphism, if
1275
+ it has been defined.
1276
+
1277
+ If ``x`` is not ``None``, return the value of the lift morphism on
1278
+ ``x``.
1279
+
1280
+ EXAMPLES::
1281
+
1282
+ sage: R.<x,y> = QQ[]
1283
+ sage: f = R.hom([x,x])
1284
+ sage: f(x+y)
1285
+ 2*x
1286
+ sage: f.lift()
1287
+ Traceback (most recent call last):
1288
+ ...
1289
+ ValueError: no lift map defined
1290
+ sage: g = R.hom(R)
1291
+ sage: f._set_lift(g)
1292
+ sage: f.lift() == g
1293
+ True
1294
+ sage: f.lift(x)
1295
+ x
1296
+ """
1297
+ if self._lift is None:
1298
+ raise ValueError("no lift map defined")
1299
+ if x is None:
1300
+ return self._lift
1301
+ return self._lift(x)
1302
+
1303
+ @cached_method
1304
+ def _graph_ideal(self):
1305
+ """
1306
+ Return the ideal corresponding to the graph of this ring homomorphism.
1307
+
1308
+ OUTPUT:
1309
+
1310
+ - the graph as an ideal in the tensor product of codomain and domain
1311
+ - a map from the codomain to the ring of the graph ideal
1312
+ - a map from the ring of the graph ideal to the domain
1313
+
1314
+ The second map is only meaningful for those elements that involve only
1315
+ variables of the domain of ``self``.
1316
+
1317
+ EXAMPLES::
1318
+
1319
+ sage: R.<x,y> = QQ[]
1320
+ sage: QQ['t'].hom([x*y^2], R)._graph_ideal()
1321
+ (Ideal (x*y^2 - t) of Multivariate Polynomial Ring in x, y, t over
1322
+ Rational Field,
1323
+ Ring morphism:
1324
+ From: Multivariate Polynomial Ring in x, y over Rational Field
1325
+ To: Multivariate Polynomial Ring in x, y, t over Rational Field
1326
+ Defn: x |--> x
1327
+ y |--> y,
1328
+ Ring morphism:
1329
+ From: Multivariate Polynomial Ring in x, y, t over Rational Field
1330
+ To: Univariate Polynomial Ring in t over Rational Field
1331
+ Defn: x |--> 0
1332
+ y |--> 0
1333
+ t |--> t)
1334
+
1335
+ TESTS:
1336
+
1337
+ Ideals in quotient rings over ``QQbar`` do not support reduction yet,
1338
+ so the graph is constructed in the ambient ring instead::
1339
+
1340
+ sage: # needs sage.libs.singular sage.rings.number_field
1341
+ sage: A.<z,w> = QQbar['z,w'].quotient('z*w - 1')
1342
+ sage: B.<x,y> = QQbar['x,y'].quotient('2*x^2 + y^2 - 1')
1343
+ sage: f = A.hom([QQbar(2).sqrt()*x + QQbar(I)*y,
1344
+ ....: QQbar(2).sqrt()*x - QQbar(I)*y], B)
1345
+ sage: f._graph_ideal()[0]
1346
+ Ideal (z*w - 1, 2*x^2 + y^2 - 1,
1347
+ 1.414213562373095?*x + I*y - z,
1348
+ 1.414213562373095?*x + (-I)*y - w)
1349
+ of Multivariate Polynomial Ring in x, y, z, w over Algebraic Field
1350
+ sage: f.inverse()(f(z)), f.inverse()(f(w))
1351
+ (z, w)
1352
+
1353
+ Non-trivial base maps are not supported::
1354
+
1355
+ sage: # needs sage.rings.number_field
1356
+ sage: K.<a> = QuadraticField(2)
1357
+ sage: R.<x,y> = K[]
1358
+ sage: f = R.hom([x, a*x + y], R, base_map=K.hom([-a], K))
1359
+ sage: f._graph_ideal()
1360
+ Traceback (most recent call last):
1361
+ ...
1362
+ NotImplementedError: base map must be trivial
1363
+
1364
+ Non-commutative rings are not supported (:issue:`32824`)::
1365
+
1366
+ sage: A = GradedCommutativeAlgebra(QQ, 'x,y,z') # needs sage.combinat sage.modules
1367
+ sage: A.hom(A.gens(), A).kernel() # needs sage.combinat sage.modules
1368
+ Traceback (most recent call last):
1369
+ ...
1370
+ NotImplementedError: rings are not commutative
1371
+ """
1372
+ from sage.rings.quotient_ring import QuotientRing_nc
1373
+ from sage.rings.ideal import Ideal_generic
1374
+ A = self.domain()
1375
+ B = self.codomain()
1376
+ Comm = Rings().Commutative()
1377
+ if not (A in Comm and B in Comm):
1378
+ raise NotImplementedError("rings are not commutative")
1379
+ if A.base_ring() != B.base_ring():
1380
+ raise NotImplementedError("base rings must be equal")
1381
+ try:
1382
+ base_map = self.base_map()
1383
+ except AttributeError:
1384
+ pass
1385
+ else:
1386
+ if base_map is not None:
1387
+ raise NotImplementedError("base map must be trivial")
1388
+ Q = _tensor_product_ring(B, A)
1389
+ A_to_Q = A.hom(Q.gens()[B.ngens():], Q, check=False)
1390
+ B_to_Q = B.hom(Q.gens()[:B.ngens()], Q, check=False)
1391
+ graph = Q.ideal([B_to_Q(self(x)) - A_to_Q(x) for x in A.gens()])
1392
+ R = Q.cover_ring() if isinstance(Q, QuotientRing_nc) else Q
1393
+ R_to_A = R.hom(tuple([0] * B.ngens()) + A.gens(), A, check=False)
1394
+ Q_to_A = R_to_A if R is Q else R_to_A * Q.lifting_map()
1395
+
1396
+ # Since we compute normal forms modulo the graph ideal, check that
1397
+ # the default `reduce` method has been overwritten
1398
+ if graph.reduce.__func__ is Ideal_generic.reduce:
1399
+ if Q is not R:
1400
+ # Although the graph naturally lives in the quotient Q, we try
1401
+ # to lift it to the ambient R as a workaround, since in some
1402
+ # cases (e.g. over QQbar) reduction is supported in R
1403
+ graph_R = Q.cover()._inverse_image_ideal(graph)
1404
+ if graph_R.reduce.__func__ is not Ideal_generic.reduce:
1405
+ return graph_R, (Q.lifting_map() * B_to_Q), R_to_A
1406
+ raise NotImplementedError('"reduce" not implemented for %s' % Q)
1407
+ return graph, B_to_Q, Q_to_A
1408
+
1409
+ @cached_method
1410
+ def inverse(self):
1411
+ """
1412
+ Return the inverse of this ring homomorphism if it exists.
1413
+
1414
+ Raises a :exc:`ZeroDivisionError` if the inverse does not exist.
1415
+
1416
+ ALGORITHM:
1417
+
1418
+ By default, this computes a Gröbner basis of the ideal corresponding to
1419
+ the graph of the ring homomorphism.
1420
+
1421
+ EXAMPLES::
1422
+
1423
+ sage: R.<t> = QQ[]
1424
+ sage: f = R.hom([2*t - 1], R)
1425
+ sage: f.inverse() # needs sage.libs.singular
1426
+ Ring endomorphism of Univariate Polynomial Ring in t over Rational Field
1427
+ Defn: t |--> 1/2*t + 1/2
1428
+
1429
+ The following non-linear homomorphism is not invertible, but it induces
1430
+ an isomorphism on a quotient ring::
1431
+
1432
+ sage: # needs sage.libs.singular
1433
+ sage: R.<x,y,z> = QQ[]
1434
+ sage: f = R.hom([y*z, x*z, x*y], R)
1435
+ sage: f.inverse()
1436
+ Traceback (most recent call last):
1437
+ ...
1438
+ ZeroDivisionError: ring homomorphism not surjective
1439
+ sage: f.is_injective()
1440
+ True
1441
+ sage: Q.<x,y,z> = R.quotient(x*y*z - 1)
1442
+ sage: g = Q.hom([y*z, x*z, x*y], Q)
1443
+ sage: g.inverse()
1444
+ Ring endomorphism of Quotient of Multivariate Polynomial Ring
1445
+ in x, y, z over Rational Field by the ideal (x*y*z - 1)
1446
+ Defn: x |--> y*z
1447
+ y |--> x*z
1448
+ z |--> x*y
1449
+
1450
+ Homomorphisms over the integers are supported::
1451
+
1452
+ sage: S.<x,y> = ZZ[]
1453
+ sage: f = S.hom([x + 2*y, x + 3*y], S)
1454
+ sage: f.inverse() # needs sage.libs.singular
1455
+ Ring endomorphism of Multivariate Polynomial Ring in x, y over Integer Ring
1456
+ Defn: x |--> 3*x - 2*y
1457
+ y |--> -x + y
1458
+ sage: (f.inverse() * f).is_identity() # needs sage.libs.singular
1459
+ True
1460
+
1461
+ The following homomorphism is invertible over the rationals, but not
1462
+ over the integers::
1463
+
1464
+ sage: g = S.hom([x + y, x - y - 2], S)
1465
+ sage: g.inverse() # needs sage.libs.singular
1466
+ Traceback (most recent call last):
1467
+ ...
1468
+ ZeroDivisionError: ring homomorphism not surjective
1469
+ sage: R.<x,y> = QQ[x,y]
1470
+ sage: h = R.hom([x + y, x - y - 2], R)
1471
+ sage: (h.inverse() * h).is_identity() # needs sage.libs.singular
1472
+ True
1473
+
1474
+ This example by M. Nagata is a wild automorphism::
1475
+
1476
+ sage: R.<x,y,z> = QQ[]
1477
+ sage: sigma = R.hom([x - 2*y*(z*x+y^2) - z*(z*x+y^2)^2,
1478
+ ....: y + z*(z*x+y^2), z], R)
1479
+ sage: tau = sigma.inverse(); tau # needs sage.libs.singular
1480
+ Ring endomorphism of Multivariate Polynomial Ring in x, y, z over
1481
+ Rational Field
1482
+ Defn: x |--> -y^4*z - 2*x*y^2*z^2 - x^2*z^3 + 2*y^3 + 2*x*y*z + x
1483
+ y |--> -y^2*z - x*z^2 + y
1484
+ z |--> z
1485
+ sage: (tau * sigma).is_identity() # needs sage.libs.singular
1486
+ True
1487
+
1488
+ We compute the triangular automorphism that converts moments to
1489
+ cumulants, as well as its inverse, using the moment generating
1490
+ function. The choice of a term ordering can have a great impact on the
1491
+ computation time of a Gröbner basis, so here we choose a weighted
1492
+ ordering such that the images of the generators are homogeneous
1493
+ polynomials. ::
1494
+
1495
+ sage: d = 12
1496
+ sage: T = TermOrder('wdegrevlex', [1..d])
1497
+ sage: R = PolynomialRing(QQ, ['x%s' % j for j in (1..d)], order=T)
1498
+ sage: S.<t> = PowerSeriesRing(R)
1499
+ sage: egf = S([0] + list(R.gens())).ogf_to_egf().exp(prec=d+1)
1500
+ sage: phi = R.hom(egf.egf_to_ogf().list()[1:], R)
1501
+ sage: phi.im_gens()[:5]
1502
+ [x1,
1503
+ x1^2 + x2,
1504
+ x1^3 + 3*x1*x2 + x3,
1505
+ x1^4 + 6*x1^2*x2 + 3*x2^2 + 4*x1*x3 + x4,
1506
+ x1^5 + 10*x1^3*x2 + 15*x1*x2^2 + 10*x1^2*x3 + 10*x2*x3 + 5*x1*x4 + x5]
1507
+ sage: all(p.is_homogeneous() for p in phi.im_gens()) # needs sage.libs.singular
1508
+ True
1509
+ sage: phi.inverse().im_gens()[:5] # needs sage.libs.singular
1510
+ [x1,
1511
+ -x1^2 + x2,
1512
+ 2*x1^3 - 3*x1*x2 + x3,
1513
+ -6*x1^4 + 12*x1^2*x2 - 3*x2^2 - 4*x1*x3 + x4,
1514
+ 24*x1^5 - 60*x1^3*x2 + 30*x1*x2^2 + 20*x1^2*x3 - 10*x2*x3 - 5*x1*x4 + x5]
1515
+ sage: (phi.inverse() * phi).is_identity() # needs sage.libs.singular
1516
+ True
1517
+
1518
+ Automorphisms of number fields as well as Galois fields are supported::
1519
+
1520
+ sage: K.<zeta7> = CyclotomicField(7) # needs sage.rings.number_field
1521
+ sage: c = K.hom([1/zeta7]) # needs sage.rings.number_field
1522
+ sage: (c.inverse() * c).is_identity() # needs sage.libs.singular sage.rings.number_field
1523
+ True
1524
+
1525
+ sage: F.<t> = GF(7^3) # needs sage.rings.finite_rings
1526
+ sage: f = F.hom(t^7, F) # needs sage.rings.finite_rings
1527
+ sage: (f.inverse() * f).is_identity() # needs sage.libs.singular sage.rings.finite_rings
1528
+ True
1529
+
1530
+ An isomorphism between the algebraic torus and the circle over a number
1531
+ field::
1532
+
1533
+ sage: # needs sage.libs.singular sage.rings.number_field
1534
+ sage: K.<i> = QuadraticField(-1)
1535
+ sage: A.<z,w> = K['z,w'].quotient('z*w - 1')
1536
+ sage: B.<x,y> = K['x,y'].quotient('x^2 + y^2 - 1')
1537
+ sage: f = A.hom([x + i*y, x - i*y], B)
1538
+ sage: g = f.inverse()
1539
+ sage: g.morphism_from_cover().im_gens()
1540
+ [1/2*z + 1/2*w, (-1/2*i)*z + (1/2*i)*w]
1541
+ sage: all(g(f(z)) == z for z in A.gens())
1542
+ True
1543
+
1544
+ TESTS:
1545
+
1546
+ Morphisms involving quotient rings::
1547
+
1548
+ sage: # needs sage.libs.singular
1549
+ sage: R.<x,y> = QQ[]
1550
+ sage: S.<s,u,t> = QQ['s,u,t'].quotient('u-t^2')
1551
+ sage: f = R.hom([s, -t], S)
1552
+ sage: (f.inverse() * f).is_identity()
1553
+ True
1554
+ sage: Q.<v,w> = R.quotient(x - y^2)
1555
+ sage: g = Q.hom([v, -w], Q)
1556
+ sage: g.inverse()(g(v)) == v and g.inverse()(g(w)) == w
1557
+ True
1558
+ sage: S.<z> = QQ[]
1559
+ sage: h = Q.hom([z^2, -z], S)
1560
+ sage: h.inverse()(h(v)) == v and h.inverse()(h(w)) == w
1561
+ True
1562
+
1563
+ Morphisms between number fields and quotient rings::
1564
+
1565
+ sage: # needs sage.rings.number_field
1566
+ sage: K.<sqrt2> = QuadraticField(2)
1567
+ sage: f = K.hom([-sqrt2], K.polynomial_quotient_ring())
1568
+ sage: (f.inverse() * f).is_identity() # needs sage.libs.singular
1569
+ True
1570
+ sage: g = K.polynomial_quotient_ring().hom([-sqrt2], K)
1571
+ sage: (g.inverse() * g).is_identity() # needs sage.libs.singular
1572
+ True
1573
+
1574
+ Morphisms involving Galois fields::
1575
+
1576
+ sage: # needs sage.rings.finite_rings
1577
+ sage: A.<t> = GF(7^3)
1578
+ sage: R = A.polynomial_ring().quotient(A.polynomial())
1579
+ sage: g = A.hom(R.gens(), R)
1580
+ sage: (g.inverse() * g).is_identity() # needs sage.libs.singular
1581
+ True
1582
+ sage: B.<T>, f = A.extension(3, map=True)
1583
+ sage: f.inverse()
1584
+ Traceback (most recent call last):
1585
+ ...
1586
+ ZeroDivisionError: ring homomorphism not surjective
1587
+ sage: B.<T>, f = A.extension(1, map=True)
1588
+ sage: f.inverse()
1589
+ Ring morphism:
1590
+ From: Finite Field in T of size 7^3
1591
+ To: Finite Field in t of size 7^3
1592
+ Defn: T |--> t
1593
+
1594
+ Non-injective homomorphisms::
1595
+
1596
+ sage: # needs sage.libs.singular
1597
+ sage: R.<x,y> = QQ[]
1598
+ sage: S.<a,b,c> = QQ[]
1599
+ sage: S.hom([x, y, 0], R).inverse()
1600
+ Traceback (most recent call last):
1601
+ ...
1602
+ ZeroDivisionError: ring homomorphism not injective
1603
+ sage: T.<z> = QQ[]
1604
+ sage: R.hom([2*z, 3*z], T).inverse()
1605
+ Traceback (most recent call last):
1606
+ ...
1607
+ ZeroDivisionError: ring homomorphism not injective
1608
+ sage: Q.<u,v> = R.quotient([x^5, y^4])
1609
+ sage: R.hom([u, v], Q).inverse()
1610
+ Traceback (most recent call last):
1611
+ ...
1612
+ ZeroDivisionError: ring homomorphism not injective
1613
+ sage: Q.cover().inverse()
1614
+ Traceback (most recent call last):
1615
+ ...
1616
+ ZeroDivisionError: ring homomorphism not injective
1617
+
1618
+ Univariate quotient rings::
1619
+
1620
+ sage: R.<t> = QQ['t'].quotient('t^5') # needs sage.libs.pari
1621
+ sage: f = R.hom([2*t], R)
1622
+ sage: (f.inverse() * f).is_identity() # needs sage.libs.singular
1623
+ True
1624
+
1625
+ A homomorphism over ``QQbar``::
1626
+
1627
+ sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
1628
+ sage: f = R.hom([x + QQbar(I)*y^2, -y], R) # needs sage.rings.number_field
1629
+ sage: (f.inverse() * f).is_identity() # needs sage.libs.singular sage.rings.number_field
1630
+ True
1631
+
1632
+ Check that results are cached::
1633
+
1634
+ sage: R.<x,y> = GF(823)[]
1635
+ sage: f = R.hom([x, y + x^2], R)
1636
+ sage: f.inverse() is f.inverse() # needs sage.libs.singular
1637
+ True
1638
+
1639
+ Some subclasses of ring homomorphisms are not supported::
1640
+
1641
+ sage: from sage.rings.morphism import FrobeniusEndomorphism_generic
1642
+ sage: K.<u> = PowerSeriesRing(GF(5))
1643
+ sage: FrobeniusEndomorphism_generic(K).inverse()
1644
+ Traceback (most recent call last):
1645
+ ...
1646
+ NotImplementedError
1647
+
1648
+ ::
1649
+
1650
+ sage: R.<x,y> = LaurentPolynomialRing(QQ) # needs sage.modules
1651
+ sage: R.hom([y, x], R).inverse() # needs sage.libs.singular sage.modules
1652
+ Traceback (most recent call last):
1653
+ ...
1654
+ NotImplementedError
1655
+
1656
+ ::
1657
+
1658
+ sage: K.<x> = FunctionField(QQ)
1659
+ sage: K.hom(1/x).inverse()
1660
+ Traceback (most recent call last):
1661
+ ...
1662
+ NotImplementedError: inverse not implemented...
1663
+
1664
+ The implementation performs several computations that require a Gröbner
1665
+ basis of the graph ideal, so we check that the Gröbner basis is cached
1666
+ after the first such computation::
1667
+
1668
+ sage: R.<x,y> = QQ[]
1669
+ sage: f = R.hom([x + 123*y^2, y], R)
1670
+ sage: f._graph_ideal()[0].groebner_basis.is_in_cache()
1671
+ False
1672
+ sage: f.is_injective() # needs sage.libs.singular
1673
+ True
1674
+ sage: f._graph_ideal()[0].groebner_basis.is_in_cache() # needs sage.libs.singular
1675
+ True
1676
+
1677
+ Check case where domain is quotient ring and codomain a finite field of same characteristic. Fixes (:issue:`39690`)::
1678
+
1679
+ sage: # needs sage.rings.finite_rings
1680
+ sage: F4.<a> = GF(2^2, modulus=[1,1,1])
1681
+ sage: PR.<y> = PolynomialRing(F4)
1682
+ sage: IP = y^3 + y + 1
1683
+ sage: assert IP.is_irreducible()
1684
+ sage: Q.<w> = PR.quotient(IP)
1685
+ sage: SF.<z> = IP.splitting_field()
1686
+ sage: SF
1687
+ Finite Field in z of size 2^6
1688
+ sage: r = z^4 + z^2 + z + 1
1689
+ sage: assert IP.change_ring(SF)(r) == 0
1690
+ sage: f = Q.hom([r,], SF)
1691
+ sage: f
1692
+ Ring morphism:
1693
+ From: Univariate Quotient Polynomial Ring in w over Finite Field in a of size 2^2 with modulus y^3 + y + 1
1694
+ To: Finite Field in z of size 2^6
1695
+ Defn: w |--> z^4 + z^2 + z + 1
1696
+ sage: f.inverse() # indirect doctest # needs sage.modules
1697
+ Ring morphism:
1698
+ From: Finite Field in z of size 2^6
1699
+ To: Univariate Quotient Polynomial Ring in w over Finite Field in a of size 2^2 with modulus y^3 + y + 1
1700
+ Defn: z |--> (a + 1)*w^2 + a*w + 1
1701
+ """
1702
+ if not self.is_injective():
1703
+ raise ZeroDivisionError("ring homomorphism not injective")
1704
+ ys = self.codomain().gens()
1705
+ try:
1706
+ preimages = [self._inverse_image_element(y) for y in ys]
1707
+ except ValueError:
1708
+ raise ZeroDivisionError("ring homomorphism not surjective")
1709
+ return self.parent().reversed()(preimages, check=False)
1710
+
1711
+ def __invert__(self):
1712
+ """
1713
+ Return the inverse of this ring homomorphism if it exists.
1714
+
1715
+ This simply calls :meth:`inverse`.
1716
+
1717
+ EXAMPLES::
1718
+
1719
+ sage: R.<x,y> = GF(17)[]
1720
+ sage: f = R.hom([3*x, y + x^2 + x^3], R)
1721
+ sage: (f * ~f).is_identity() # needs sage.libs.singular
1722
+ True
1723
+ """
1724
+ return self.inverse()
1725
+
1726
+ def is_surjective(self):
1727
+ """
1728
+ Return whether this ring homomorphism is surjective.
1729
+
1730
+ EXAMPLES::
1731
+
1732
+ sage: R.<x,y,z> = QQ[]
1733
+ sage: R.hom([y*z, x*z, x*y], R).is_surjective() # needs sage.libs.singular
1734
+ False
1735
+ sage: Q.<x,y,z> = R.quotient(x*y*z - 1) # needs sage.libs.singular
1736
+ sage: R.hom([y*z, x*z, x*y], Q).is_surjective() # needs sage.libs.singular
1737
+ True
1738
+
1739
+ ALGORITHM:
1740
+
1741
+ By default, this requires the computation of a Gröbner basis.
1742
+ """
1743
+ for y in self.codomain().gens():
1744
+ try:
1745
+ self._inverse_image_element(y)
1746
+ except ValueError:
1747
+ return False
1748
+ return True
1749
+
1750
+ def is_invertible(self):
1751
+ """
1752
+ Return whether this ring homomorphism is bijective.
1753
+
1754
+ EXAMPLES::
1755
+
1756
+ sage: R.<x,y,z> = QQ[]
1757
+ sage: R.hom([y*z, x*z, x*y], R).is_invertible() # needs sage.libs.singular
1758
+ False
1759
+ sage: Q.<x,y,z> = R.quotient(x*y*z - 1) # needs sage.libs.singular
1760
+ sage: Q.hom([y*z, x*z, x*y], Q).is_invertible() # needs sage.libs.singular
1761
+ True
1762
+
1763
+ ALGORITHM:
1764
+
1765
+ By default, this requires the computation of a Gröbner basis.
1766
+ """
1767
+ return self.is_injective() and self.is_surjective()
1768
+
1769
+
1770
+ cdef class RingHomomorphism_im_gens(RingHomomorphism):
1771
+ """
1772
+ A ring homomorphism determined by the images of generators.
1773
+ """
1774
+ def __init__(self, parent, im_gens, check=True, base_map=None):
1775
+ """
1776
+ EXAMPLES::
1777
+
1778
+ sage: R.<x,y> = QQ[]
1779
+ sage: phi = R.hom([x, x + y]); phi
1780
+ Ring endomorphism of Multivariate Polynomial Ring in x, y over Rational Field
1781
+ Defn: x |--> x
1782
+ y |--> x + y
1783
+ sage: type(phi)
1784
+ <class 'sage.rings.morphism.RingHomomorphism_im_gens'>
1785
+
1786
+ Here's another example where the domain isn't free::
1787
+
1788
+ sage: S.<xx,yy> = R.quotient(x - y) # needs sage.libs.singular
1789
+ sage: phi = S.hom([xx + 1, xx + 1]) # needs sage.libs.singular
1790
+
1791
+ Note that one has to specify valid images::
1792
+
1793
+ sage: phi = S.hom([xx + 1, xx - 1]) # needs sage.libs.singular
1794
+ Traceback (most recent call last):
1795
+ ...
1796
+ ValueError: relations do not all (canonically) map to 0
1797
+ under map determined by images of generators
1798
+
1799
+ You can give a map of the base ring::
1800
+
1801
+ sage: # needs sage.rings.number_field
1802
+ sage: Zx.<x> = ZZ[]
1803
+ sage: K.<i> = NumberField(x^2 + 1)
1804
+ sage: cc = K.hom([-i])
1805
+ sage: R.<t> = K[]
1806
+ sage: z = 1 + i*t + (3+4*i)*t^2
1807
+ sage: z._im_gens_(R, [t^2], base_map=cc)
1808
+ (-4*i + 3)*t^4 - i*t^2 + 1
1809
+
1810
+ The base map's codomain is extended to the whole codomain::
1811
+
1812
+ sage: S.<x> = QQ[]
1813
+ sage: T.<y> = S[]
1814
+ sage: cc = S.hom([x + 1])
1815
+ sage: f = T.hom([x - y], base_map=cc)
1816
+ sage: g = T.hom([x - y], base_map=cc.extend_codomain(T))
1817
+ sage: f == g
1818
+ True
1819
+ sage: f.base_map() == cc.extend_codomain(T)
1820
+ True
1821
+
1822
+ There is a check option, but it may be ignored in some cases
1823
+ -- it's purpose isn't so you can lie to Sage, but to sometimes
1824
+ speed up creation of a homomorphism::
1825
+
1826
+ sage: R.<x,y> = QQ[]
1827
+ sage: S.<xx,yy> = R.quotient(x - y) # needs sage.libs.singular
1828
+ sage: phi = S.hom([xx + 1, xx - 1], check=False) # needs sage.libs.singular
1829
+ Traceback (most recent call last):
1830
+ ...
1831
+ ValueError: relations do not all (canonically) map to 0
1832
+ under map determined by images of generators
1833
+ """
1834
+ RingHomomorphism.__init__(self, parent)
1835
+ if not isinstance(im_gens, sage.structure.sequence.Sequence_generic):
1836
+ if not isinstance(im_gens, (tuple, list)):
1837
+ im_gens = [im_gens]
1838
+ im_gens = sage.structure.all.Sequence(im_gens, parent.codomain(),
1839
+ check=check, immutable=True)
1840
+ if check:
1841
+ if len(im_gens) != parent.domain().ngens():
1842
+ raise ValueError("number of images must equal number of generators")
1843
+ if base_map is None:
1844
+ tkwds = {}
1845
+ else:
1846
+ if base_map.codomain() is not self.codomain():
1847
+ base_map = base_map.extend_codomain(self.codomain())
1848
+ tkwds = {'base_map': base_map}
1849
+ t = parent.domain()._is_valid_homomorphism_(parent.codomain(), im_gens, **tkwds)
1850
+ if not t:
1851
+ raise ValueError("relations do not all (canonically) map to 0 under map determined by images of generators")
1852
+ if not im_gens.is_immutable():
1853
+ import copy
1854
+ im_gens = copy.copy(im_gens)
1855
+ im_gens.set_immutable()
1856
+ self._im_gens = im_gens
1857
+ self._base_map = base_map
1858
+
1859
+ def im_gens(self):
1860
+ """
1861
+ Return the images of the generators of the domain.
1862
+
1863
+ OUTPUT:
1864
+
1865
+ - ``list`` -- a copy of the list of gens (it is safe to change this)
1866
+
1867
+ EXAMPLES::
1868
+
1869
+ sage: R.<x,y> = QQ[]
1870
+ sage: f = R.hom([x, x + y])
1871
+ sage: f.im_gens()
1872
+ [x, x + y]
1873
+
1874
+ We verify that the returned list of images of gens is a copy,
1875
+ so changing it doesn't change ``f``::
1876
+
1877
+ sage: f.im_gens()[0] = 5
1878
+ sage: f.im_gens()
1879
+ [x, x + y]
1880
+ """
1881
+ return list(self._im_gens)
1882
+
1883
+ def base_map(self):
1884
+ """
1885
+ Return the map on the base ring that is part of the defining
1886
+ data for this morphism. May return ``None`` if a coercion is used.
1887
+
1888
+ EXAMPLES::
1889
+
1890
+ sage: # needs sage.rings.number_field
1891
+ sage: R.<x> = ZZ[]
1892
+ sage: K.<i> = NumberField(x^2 + 1)
1893
+ sage: cc = K.hom([-i])
1894
+ sage: S.<y> = K[]
1895
+ sage: phi = S.hom([y^2], base_map=cc)
1896
+ sage: phi
1897
+ Ring endomorphism of Univariate Polynomial Ring in y
1898
+ over Number Field in i with defining polynomial x^2 + 1
1899
+ Defn: y |--> y^2
1900
+ with map of base ring
1901
+ sage: phi(y)
1902
+ y^2
1903
+ sage: phi(i*y)
1904
+ -i*y^2
1905
+ sage: phi.base_map()
1906
+ Composite map:
1907
+ From: Number Field in i with defining polynomial x^2 + 1
1908
+ To: Univariate Polynomial Ring in y over Number Field in i
1909
+ with defining polynomial x^2 + 1
1910
+ Defn: Ring endomorphism of Number Field in i with defining polynomial x^2 + 1
1911
+ Defn: i |--> -i
1912
+ then
1913
+ Polynomial base injection morphism:
1914
+ From: Number Field in i with defining polynomial x^2 + 1
1915
+ To: Univariate Polynomial Ring in y over Number Field in i
1916
+ with defining polynomial x^2 + 1
1917
+ """
1918
+ return self._base_map
1919
+
1920
+ cdef _update_slots(self, dict _slots):
1921
+ """
1922
+ Helper for copying and pickling.
1923
+
1924
+ EXAMPLES::
1925
+
1926
+ sage: R.<x,y> = QQ[]
1927
+ sage: f = R.hom([x, x + y])
1928
+ sage: g = copy(f) # indirect doctest
1929
+ sage: g == f
1930
+ True
1931
+ sage: g is f
1932
+ False
1933
+ sage: g(y)
1934
+ x + y
1935
+ """
1936
+ self._im_gens = _slots['__im_gens'] # double underscores for legacy pickles
1937
+ self._base_map = _slots.get('_base_map')
1938
+ RingHomomorphism._update_slots(self, _slots)
1939
+
1940
+ cdef dict _extra_slots(self):
1941
+ """
1942
+ Helper for copying and pickling.
1943
+
1944
+ EXAMPLES::
1945
+
1946
+ sage: R.<x,y> = QQ[]
1947
+ sage: f = R.hom([x, x + y])
1948
+ sage: g = copy(f) # indirect doctest
1949
+ sage: g == f
1950
+ True
1951
+ sage: g is f
1952
+ False
1953
+ sage: g(y)
1954
+ x + y
1955
+ """
1956
+ slots = RingHomomorphism._extra_slots(self)
1957
+ slots['__im_gens'] = self._im_gens
1958
+ slots['_base_map'] = self._base_map
1959
+ return slots
1960
+
1961
+ cpdef _richcmp_(self, other, int op):
1962
+ r"""
1963
+ EXAMPLES:
1964
+
1965
+ A single variate quotient over `\QQ`::
1966
+
1967
+ sage: # needs sage.libs.pari
1968
+ sage: R.<x> = QQ[]
1969
+ sage: Q.<a> = R.quotient(x^2 + x + 1)
1970
+ sage: f1 = R.hom([a])
1971
+ sage: f2 = R.hom([a + a^2 + a + 1])
1972
+ sage: f1 == f2
1973
+ True
1974
+ sage: f1 == R.hom([a^2])
1975
+ False
1976
+ sage: f1(x^3 + x)
1977
+ a + 1
1978
+ sage: f2(x^3 + x)
1979
+ a + 1
1980
+
1981
+ TESTS::
1982
+
1983
+ sage: loads(dumps(f2)) == f2 # needs sage.libs.pari
1984
+ True
1985
+
1986
+ ::
1987
+
1988
+ sage: R.<x,y> = QQ[]; f = R.hom([x, x + y]); g = R.hom([y, x])
1989
+ sage: f == g # indirect doctest
1990
+ False
1991
+
1992
+ EXAMPLES:
1993
+
1994
+ A multivariate quotient over a finite field::
1995
+
1996
+ sage: # needs sage.libs.singular
1997
+ sage: R.<x,y> = GF(7)[]
1998
+ sage: Q.<a,b> = R.quotient([x^2 + x + 1, y^2 + y + 1])
1999
+ sage: f1 = R.hom([a, b])
2000
+ sage: f2 = R.hom([a + a^2 + a + 1, b + b^2 + b + 1])
2001
+ sage: f1 == f2
2002
+ True
2003
+ sage: f1 == R.hom([b, a])
2004
+ False
2005
+ sage: x^3 + x + y^2
2006
+ x^3 + y^2 + x
2007
+ sage: f1(x^3 + x + y^2)
2008
+ a - b
2009
+ sage: f2(x^3 + x + y^2)
2010
+ a - b
2011
+
2012
+ TESTS::
2013
+
2014
+ sage: loads(dumps(f2)) == f2 # needs sage.libs.pari
2015
+ True
2016
+
2017
+ This was fixed in :issue:`24277`::
2018
+
2019
+ sage: H = End(QQ)
2020
+ sage: H(1) == H.identity()
2021
+ True
2022
+ """
2023
+ if not isinstance(other, RingHomomorphism_im_gens):
2024
+ # Generic comparison
2025
+ return RingMap._richcmp_(self, other, op)
2026
+ # Check equality using the images of the generators.
2027
+ self_im = self._im_gens
2028
+ other_im = (<RingHomomorphism_im_gens>other)._im_gens
2029
+ self_hom = self._base_map
2030
+ other_hom = (<RingHomomorphism_im_gens>other)._base_map
2031
+ return richcmp((self_im, self_hom), (other_im, other_hom), op)
2032
+
2033
+ def __hash__(self):
2034
+ """
2035
+ Return the hash of this morphism.
2036
+
2037
+ EXAMPLES::
2038
+
2039
+ sage: R.<x> = ZZ[]
2040
+ sage: s = R.hom([x+1])
2041
+ sage: type(s)
2042
+ <class 'sage.rings.morphism.RingHomomorphism_im_gens'>
2043
+ sage: hash(s) == hash(s)
2044
+ True
2045
+ sage: {s: 1}[s]
2046
+ 1
2047
+ """
2048
+ return hash((self._im_gens, self._base_map))
2049
+
2050
+ def _repr_defn(self):
2051
+ """
2052
+ Used in constructing string representation of ``self``.
2053
+
2054
+ EXAMPLES::
2055
+
2056
+ sage: R.<x,y> = QQ[]; f = R.hom([x^2,x+y])
2057
+ sage: print(f._repr_defn())
2058
+ x |--> x^2
2059
+ y |--> x + y
2060
+ """
2061
+ D = self.domain()
2062
+ if D in FacadeSets():
2063
+ D, = D.facade_for()
2064
+ ig = self._im_gens
2065
+ s = '\n'.join('{} |--> {}'.format(D.gen(i), ig[i])
2066
+ for i in range(D.ngens()))
2067
+ if s and self._base_map is not None:
2068
+ s += '\nwith map of base ring'
2069
+ return s
2070
+
2071
+ cpdef Element _call_(self, x):
2072
+ """
2073
+ Evaluate this homomorphism at ``x``.
2074
+
2075
+ EXAMPLES::
2076
+
2077
+ sage: R.<x,y,z> = ZZ[]; f = R.hom([2*x,z,y])
2078
+ sage: f(x+2*y+3*z) # indirect doctest
2079
+ 2*x + 3*y + 2*z
2080
+ """
2081
+ return x._im_gens_(self.codomain(), self.im_gens(), base_map=self.base_map())
2082
+
2083
+
2084
+ cdef class RingHomomorphism_from_base(RingHomomorphism):
2085
+ """
2086
+ A ring homomorphism determined by a ring homomorphism of the base ring.
2087
+
2088
+ AUTHOR:
2089
+
2090
+ - Simon King (initial version, 2010-04-30)
2091
+
2092
+ EXAMPLES:
2093
+
2094
+ We define two polynomial rings and a ring homomorphism::
2095
+
2096
+ sage: R.<x,y> = QQ[]
2097
+ sage: S.<z> = QQ[]
2098
+ sage: f = R.hom([2*z,3*z],S)
2099
+
2100
+ Now we construct polynomial rings based on ``R`` and ``S``, and let
2101
+ ``f`` act on the coefficients::
2102
+
2103
+ sage: PR.<t> = R[]
2104
+ sage: PS = S['t']
2105
+ sage: Pf = PR.hom(f,PS)
2106
+ sage: Pf
2107
+ Ring morphism:
2108
+ From: Univariate Polynomial Ring in t
2109
+ over Multivariate Polynomial Ring in x, y over Rational Field
2110
+ To: Univariate Polynomial Ring in t
2111
+ over Univariate Polynomial Ring in z over Rational Field
2112
+ Defn: Induced from base ring by
2113
+ Ring morphism:
2114
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2115
+ To: Univariate Polynomial Ring in z over Rational Field
2116
+ Defn: x |--> 2*z
2117
+ y |--> 3*z
2118
+ sage: p = (x - 4*y + 1/13)*t^2 + (1/2*x^2 - 1/3*y^2)*t + 2*y^2 + x
2119
+ sage: Pf(p)
2120
+ (-10*z + 1/13)*t^2 - z^2*t + 18*z^2 + 2*z
2121
+
2122
+ Similarly, we can construct the induced homomorphism on a matrix ring over
2123
+ our polynomial rings::
2124
+
2125
+ sage: # needs sage.modules
2126
+ sage: MR = MatrixSpace(R, 2, 2)
2127
+ sage: MS = MatrixSpace(S, 2, 2)
2128
+ sage: M = MR([x^2 + 1/7*x*y - y^2, -1/2*y^2 + 2*y + 1/6,
2129
+ ....: 4*x^2 - 14*x, 1/2*y^2 + 13/4*x - 2/11*y])
2130
+ sage: Mf = MR.hom(f, MS)
2131
+ sage: Mf
2132
+ Ring morphism:
2133
+ From: Full MatrixSpace of 2 by 2 dense matrices
2134
+ over Multivariate Polynomial Ring in x, y over Rational Field
2135
+ To: Full MatrixSpace of 2 by 2 dense matrices
2136
+ over Univariate Polynomial Ring in z over Rational Field
2137
+ Defn: Induced from base ring by
2138
+ Ring morphism:
2139
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2140
+ To: Univariate Polynomial Ring in z over Rational Field
2141
+ Defn: x |--> 2*z
2142
+ y |--> 3*z
2143
+ sage: Mf(M)
2144
+ [ -29/7*z^2 -9/2*z^2 + 6*z + 1/6]
2145
+ [ 16*z^2 - 28*z 9/2*z^2 + 131/22*z]
2146
+
2147
+ The construction of induced homomorphisms is recursive, and so we have::
2148
+
2149
+ sage: # needs sage.modules
2150
+ sage: MPR = MatrixSpace(PR, 2)
2151
+ sage: MPS = MatrixSpace(PS, 2)
2152
+ sage: M = MPR([(-x + y)*t^2 + 58*t - 3*x^2 + x*y,
2153
+ ....: (- 1/7*x*y - 1/40*x)*t^2 + (5*x^2 + y^2)*t + 2*y,
2154
+ ....: (- 1/3*y + 1)*t^2 + 1/3*x*y + y^2 + 5/2*y + 1/4,
2155
+ ....: (x + 6*y + 1)*t^2])
2156
+ sage: MPf = MPR.hom(f, MPS); MPf
2157
+ Ring morphism:
2158
+ From: Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial
2159
+ Ring in t over Multivariate Polynomial Ring in x, y over Rational Field
2160
+ To: Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial
2161
+ Ring in t over Univariate Polynomial Ring in z over Rational Field
2162
+ Defn: Induced from base ring by
2163
+ Ring morphism:
2164
+ From: Univariate Polynomial Ring in t
2165
+ over Multivariate Polynomial Ring in x, y over Rational Field
2166
+ To: Univariate Polynomial Ring in t
2167
+ over Univariate Polynomial Ring in z over Rational Field
2168
+ Defn: Induced from base ring by
2169
+ Ring morphism:
2170
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2171
+ To: Univariate Polynomial Ring in z over Rational Field
2172
+ Defn: x |--> 2*z
2173
+ y |--> 3*z
2174
+ sage: MPf(M)
2175
+ [ z*t^2 + 58*t - 6*z^2 (-6/7*z^2 - 1/20*z)*t^2 + 29*z^2*t + 6*z]
2176
+ [ (-z + 1)*t^2 + 11*z^2 + 15/2*z + 1/4 (20*z + 1)*t^2]
2177
+ """
2178
+ def __init__(self, parent, underlying):
2179
+ """
2180
+ Initialize ``self``.
2181
+
2182
+ TESTS::
2183
+
2184
+ sage: from sage.rings.morphism import RingHomomorphism_from_base
2185
+ sage: R.<x> = ZZ[]
2186
+ sage: f = R.hom([2*x], R)
2187
+ sage: P = MatrixSpace(R, 2).Hom(MatrixSpace(R, 2)) # needs sage.modules
2188
+ sage: g = RingHomomorphism_from_base(P, f) # needs sage.modules
2189
+ sage: g # needs sage.modules
2190
+ Ring endomorphism of Full MatrixSpace of 2 by 2 dense matrices
2191
+ over Univariate Polynomial Ring in x over Integer Ring
2192
+ Defn: Induced from base ring by
2193
+ Ring endomorphism of Univariate Polynomial Ring in x over Integer Ring
2194
+ Defn: x |--> 2*x
2195
+
2196
+ Note that an induced homomorphism only makes sense if domain and
2197
+ codomain are constructed in a compatible way. So, the following
2198
+ results in an error::
2199
+
2200
+ sage: P = MatrixSpace(R, 2).Hom(R['t']) # needs sage.modules
2201
+ sage: g = RingHomomorphism_from_base(P, f) # needs sage.modules
2202
+ Traceback (most recent call last):
2203
+ ...
2204
+ ValueError: domain (Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring)
2205
+ and codomain (Univariate Polynomial Ring in t over Univariate Polynomial Ring in x over Integer Ring)
2206
+ must have the same functorial construction over their base rings
2207
+ """
2208
+ RingHomomorphism.__init__(self, parent)
2209
+ if underlying.domain() != parent.domain().base():
2210
+ raise ValueError("The given homomorphism has to have the domain %s" % parent.domain().base())
2211
+ if underlying.codomain() != parent.codomain().base():
2212
+ raise ValueError("The given homomorphism has to have the codomain %s" % parent.codomain().base())
2213
+ if parent.domain().construction()[0] != parent.codomain().construction()[0]:
2214
+ raise ValueError(f"domain ({parent.domain()}) and codomain ({parent.codomain()}) must have the same functorial construction over their base rings")
2215
+ self._underlying = underlying
2216
+
2217
+ def underlying_map(self):
2218
+ """
2219
+ Return the underlying homomorphism of the base ring.
2220
+
2221
+ EXAMPLES::
2222
+
2223
+ sage: # needs sage.modules
2224
+ sage: R.<x,y> = QQ[]
2225
+ sage: S.<z> = QQ[]
2226
+ sage: f = R.hom([2*z, 3*z], S)
2227
+ sage: MR = MatrixSpace(R, 2)
2228
+ sage: MS = MatrixSpace(S, 2)
2229
+ sage: g = MR.hom(f, MS)
2230
+ sage: g.underlying_map() == f
2231
+ True
2232
+ """
2233
+ return self._underlying
2234
+
2235
+ cdef _update_slots(self, dict _slots):
2236
+ """
2237
+ Helper for copying and pickling.
2238
+
2239
+ EXAMPLES::
2240
+
2241
+ sage: R.<x,y> = QQ[]
2242
+ sage: S.<z> = QQ[]
2243
+ sage: f = R.hom([2*z, 3*z],S)
2244
+ sage: PR.<t> = R[]
2245
+ sage: PS = S['t']
2246
+ sage: phi = PR.hom(f, PS)
2247
+ sage: type(phi)
2248
+ <class 'sage.rings.morphism.RingHomomorphism_from_base'>
2249
+ sage: psi = copy(phi); psi # indirect doctest
2250
+ Ring morphism:
2251
+ From: Univariate Polynomial Ring in t over Multivariate Polynomial Ring in x, y over Rational Field
2252
+ To: Univariate Polynomial Ring in t over Univariate Polynomial Ring in z over Rational Field
2253
+ Defn: Induced from base ring by
2254
+ Ring morphism:
2255
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2256
+ To: Univariate Polynomial Ring in z over Rational Field
2257
+ Defn: x |--> 2*z
2258
+ y |--> 3*z
2259
+ sage: psi(x*t)
2260
+ 2*z*t
2261
+ """
2262
+ self._underlying = _slots['__underlying'] # double underscore for legacy pickles
2263
+ RingHomomorphism._update_slots(self, _slots)
2264
+
2265
+ cdef dict _extra_slots(self):
2266
+ """
2267
+ Helper for copying and pickling.
2268
+
2269
+ EXAMPLES::
2270
+
2271
+ sage: R.<x,y> = QQ[]
2272
+ sage: S.<z> = QQ[]
2273
+ sage: f = R.hom([2*z,3*z],S)
2274
+ sage: PR.<t> = R[]
2275
+ sage: PS = S['t']
2276
+ sage: phi = PR.hom(f,PS)
2277
+ sage: type(phi)
2278
+ <class 'sage.rings.morphism.RingHomomorphism_from_base'>
2279
+ sage: psi = copy(phi); psi # indirect doctest
2280
+ Ring morphism:
2281
+ From: Univariate Polynomial Ring in t over Multivariate Polynomial Ring in x, y over Rational Field
2282
+ To: Univariate Polynomial Ring in t over Univariate Polynomial Ring in z over Rational Field
2283
+ Defn: Induced from base ring by
2284
+ Ring morphism:
2285
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2286
+ To: Univariate Polynomial Ring in z over Rational Field
2287
+ Defn: x |--> 2*z
2288
+ y |--> 3*z
2289
+ sage: psi(x*t)
2290
+ 2*z*t
2291
+ """
2292
+ slots = RingHomomorphism._extra_slots(self)
2293
+ slots['__underlying'] = self._underlying
2294
+ return slots
2295
+
2296
+ cpdef _richcmp_(self, other, int op):
2297
+ r"""
2298
+ EXAMPLES:
2299
+
2300
+ A multivariate polynomial ring over a single variate quotient over
2301
+ `\QQ`::
2302
+
2303
+ sage: # needs sage.libs.pari sage.libs.singular sage.modules
2304
+ sage: R.<x> = QQ[]
2305
+ sage: Q.<a> = R.quotient(x^2 + x + 1)
2306
+ sage: f1 = R.hom([a])
2307
+ sage: f2 = R.hom([a + a^2 + a + 1])
2308
+ sage: PR.<s,t> = R[]
2309
+ sage: PQ = Q['s','t']
2310
+ sage: f1P = PR.hom(f1,PQ)
2311
+ sage: f2P = PR.hom(f2,PQ)
2312
+ sage: f1P == f2P
2313
+ True
2314
+
2315
+ TESTS::
2316
+
2317
+ sage: f1P == loads(dumps(f1P)) # needs sage.libs.pari sage.libs.singular sage.modules
2318
+ True
2319
+
2320
+ sage: R.<x,y> = QQ[]; f = R.hom([x, x + y]); g = R.hom([y, x])
2321
+ sage: S.<z> = R[]
2322
+ sage: fS = S.hom(f, S); gS = S.hom(g, S)
2323
+ sage: fS != gS # indirect doctest
2324
+ True
2325
+
2326
+ EXAMPLES:
2327
+
2328
+ A matrix ring over a multivariate quotient over a finite field::
2329
+
2330
+ sage: # needs sage.libs.singular sage.modules
2331
+ sage: R.<x,y> = GF(7)[]
2332
+ sage: Q.<a,b> = R.quotient([x^2 + x + 1, y^2 + y + 1])
2333
+ sage: f1 = R.hom([a, b])
2334
+ sage: f2 = R.hom([a + a^2 + a + 1, b + b^2 + b + 1])
2335
+ sage: MR = MatrixSpace(R, 2)
2336
+ sage: MQ = MatrixSpace(Q, 2)
2337
+ sage: f1M = MR.hom(f1, MQ)
2338
+ sage: f2M = MR.hom(f2, MQ)
2339
+ sage: f1M == f2M
2340
+ True
2341
+
2342
+ TESTS::
2343
+
2344
+ sage: f1M == loads(dumps(f1M)) # needs sage.libs.singular sage.modules
2345
+ True
2346
+ """
2347
+ if not isinstance(other, RingHomomorphism_from_base):
2348
+ # Generic comparison
2349
+ return RingMap._richcmp_(self, other, op)
2350
+ self_underlying = self._underlying
2351
+ other_underlying = (<RingHomomorphism_from_base>other)._underlying
2352
+ return richcmp(self_underlying, other_underlying, op)
2353
+
2354
+ def _repr_defn(self):
2355
+ """
2356
+ Used in constructing string representation of ``self``.
2357
+
2358
+ EXAMPLES:
2359
+
2360
+ We use a matrix ring over univariate polynomial ring over the fraction field
2361
+ over a multivariate polynomial ring::
2362
+
2363
+ sage: R1.<x,y> = ZZ[]
2364
+ sage: f = R1.hom([x + y, x - y])
2365
+ sage: R2 = MatrixSpace(FractionField(R1)['t'], 2) # needs sage.modules
2366
+ sage: g = R2.hom(f, R2) # needs sage.modules
2367
+ sage: g # indirect doctest # needs sage.modules
2368
+ Ring endomorphism of Full MatrixSpace of 2 by 2 dense matrices
2369
+ over Univariate Polynomial Ring in t over Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring
2370
+ Defn: Induced from base ring by
2371
+ Ring endomorphism of Univariate Polynomial Ring in t over Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring
2372
+ Defn: Induced from base ring by
2373
+ Ring endomorphism of Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring
2374
+ Defn: x |--> x + y
2375
+ y |--> x - y
2376
+ """
2377
+ U = repr(self._underlying).split('\n')
2378
+ return 'Induced from base ring by\n'+'\n'.join(U)
2379
+
2380
+ cpdef Element _call_(self, x):
2381
+ """
2382
+ Evaluate this homomorphism at ``x``.
2383
+
2384
+ EXAMPLES::
2385
+
2386
+ sage: R1.<x,y> = ZZ[]
2387
+ sage: f = R1.hom([x+y,x-y])
2388
+ sage: f(2*x + y + 2) # indirect doctest
2389
+ 3*x + y + 2
2390
+ """
2391
+ P = self.codomain()
2392
+ try:
2393
+ return P({a: self._underlying(b) for a, b in x.monomial_coefficients().items()})
2394
+ except Exception:
2395
+ pass
2396
+ try:
2397
+ return P([self._underlying(b) for b in x])
2398
+ except Exception:
2399
+ pass
2400
+ try:
2401
+ return P(self._underlying(x.numerator()))/P(self._underlying(x.denominator()))
2402
+ except Exception:
2403
+ raise TypeError("invalid argument %s" % repr(x))
2404
+
2405
+ @cached_method
2406
+ def inverse(self):
2407
+ """
2408
+ Return the inverse of this ring homomorphism if the underlying
2409
+ homomorphism of the base ring is invertible.
2410
+
2411
+ EXAMPLES::
2412
+
2413
+ sage: R.<x,y> = QQ[]
2414
+ sage: S.<a,b> = QQ[]
2415
+ sage: f = R.hom([a + b, a - b], S)
2416
+ sage: PR.<t> = R[]
2417
+ sage: PS = S['t']
2418
+ sage: Pf = PR.hom(f, PS)
2419
+ sage: Pf.inverse() # needs sage.libs.singular
2420
+ Ring morphism:
2421
+ From: Univariate Polynomial Ring in t over Multivariate
2422
+ Polynomial Ring in a, b over Rational Field
2423
+ To: Univariate Polynomial Ring in t over Multivariate
2424
+ Polynomial Ring in x, y over Rational Field
2425
+ Defn: Induced from base ring by
2426
+ Ring morphism:
2427
+ From: Multivariate Polynomial Ring in a, b over Rational Field
2428
+ To: Multivariate Polynomial Ring in x, y over Rational Field
2429
+ Defn: a |--> 1/2*x + 1/2*y
2430
+ b |--> 1/2*x - 1/2*y
2431
+ sage: Pf.inverse()(Pf(x*t^2 + y*t)) # needs sage.libs.singular
2432
+ x*t^2 + y*t
2433
+ """
2434
+ return self.parent().reversed()(self._underlying.inverse())
2435
+
2436
+
2437
+ cdef class RingHomomorphism_from_fraction_field(RingHomomorphism):
2438
+ r"""
2439
+ Morphisms between fraction fields.
2440
+
2441
+ TESTS::
2442
+
2443
+ sage: S.<x> = QQ[]
2444
+ sage: f = S.hom([x^2])
2445
+ sage: g = f.extend_to_fraction_field() # needs sage.libs.singular
2446
+ sage: type(g) # needs sage.libs.singular
2447
+ <class 'sage.rings.morphism.RingHomomorphism_from_fraction_field'>
2448
+ """
2449
+ def __init__(self, parent, morphism):
2450
+ r"""
2451
+ Initialize this morphism.
2452
+
2453
+ TESTS::
2454
+
2455
+ sage: # needs sage.rings.number_field
2456
+ sage: x = polygen(ZZ, 'x')
2457
+ sage: A.<a> = ZZ.extension(x^2 - 2)
2458
+ sage: f = A.coerce_map_from(ZZ)
2459
+ sage: g = f.extend_to_fraction_field() # indirect doctest
2460
+ sage: g
2461
+ Ring morphism:
2462
+ From: Rational Field
2463
+ To: Number Field in a with defining polynomial x^2 - 2
2464
+ """
2465
+ RingHomomorphism.__init__(self, parent)
2466
+ self._morphism = morphism
2467
+
2468
+ def _repr_defn(self):
2469
+ r"""
2470
+ Return a string definition of this morphism.
2471
+
2472
+ EXAMPLES::
2473
+
2474
+ sage: S.<x> = QQ[]
2475
+ sage: f = S.hom([x^2]).extend_to_fraction_field() # needs sage.libs.singular
2476
+ sage: f # needs sage.libs.singular
2477
+ Ring endomorphism of Fraction Field of Univariate Polynomial Ring in x over Rational Field
2478
+ Defn: x |--> x^2
2479
+ sage: f._repr_defn() # needs sage.libs.singular
2480
+ 'x |--> x^2'
2481
+ """
2482
+ return self._morphism._repr_defn()
2483
+
2484
+ cpdef Element _call_(self, x):
2485
+ r"""
2486
+ Return the value of this morphism at ``x``.
2487
+
2488
+ INPUT:
2489
+
2490
+ - ``x`` -- an element in the domain of this morphism
2491
+
2492
+ EXAMPLES::
2493
+
2494
+ sage: S.<x> = QQ[]
2495
+ sage: f = S.hom([x + 1]).extend_to_fraction_field() # needs sage.libs.singular
2496
+ sage: f(1/x) # needs sage.libs.singular
2497
+ 1/(x + 1)
2498
+ sage: f(1/(x-1)) # needs sage.libs.singular
2499
+ 1/x
2500
+ """
2501
+ return self._morphism(x.numerator()) / self._morphism(x.denominator())
2502
+
2503
+ cdef _update_slots(self, dict _slots):
2504
+ """
2505
+ Helper function for copying and pickling.
2506
+
2507
+ TESTS::
2508
+
2509
+ sage: # needs sage.libs.singular
2510
+ sage: S.<x> = QQ[]
2511
+ sage: f = S.hom([x + 1]).extend_to_fraction_field()
2512
+
2513
+ sage: g = copy(f) # indirect doctest # needs sage.libs.singular
2514
+ sage: f == g # needs sage.libs.singular
2515
+ True
2516
+ sage: f is g # needs sage.libs.singular
2517
+ False
2518
+ """
2519
+ self._morphism = _slots['_morphism']
2520
+ RingHomomorphism._update_slots(self, _slots)
2521
+
2522
+ cdef dict _extra_slots(self):
2523
+ """
2524
+ Helper function for copying and pickling.
2525
+
2526
+ TESTS::
2527
+
2528
+ sage: S.<x> = QQ[]
2529
+ sage: f = S.hom([x + 1]).extend_to_fraction_field() # needs sage.libs.singular
2530
+ sage: loads(dumps(f)) == f # needs sage.libs.singular
2531
+ True
2532
+ """
2533
+ slots = RingHomomorphism._extra_slots(self)
2534
+ slots['_morphism'] = self._morphism
2535
+ return slots
2536
+
2537
+ @cached_method
2538
+ def inverse(self):
2539
+ """
2540
+ Return the inverse of this ring homomorphism if it exists.
2541
+
2542
+ EXAMPLES::
2543
+
2544
+ sage: S.<x> = QQ[]
2545
+ sage: f = S.hom([2*x - 1])
2546
+ sage: g = f.extend_to_fraction_field() # needs sage.libs.singular
2547
+ sage: g.inverse() # needs sage.libs.singular
2548
+ Ring endomorphism of Fraction Field of Univariate Polynomial Ring
2549
+ in x over Rational Field
2550
+ Defn: x |--> 1/2*x + 1/2
2551
+ """
2552
+ return self.parent().reversed()(self._morphism.inverse())
2553
+
2554
+
2555
+ cdef class RingHomomorphism_cover(RingHomomorphism):
2556
+ r"""
2557
+ A homomorphism induced by quotienting a ring out by an ideal.
2558
+
2559
+ EXAMPLES::
2560
+
2561
+ sage: R.<x,y> = PolynomialRing(QQ, 2)
2562
+ sage: S.<a,b> = R.quo(x^2 + y^2) # needs sage.libs.singular
2563
+ sage: phi = S.cover(); phi # needs sage.libs.singular
2564
+ Ring morphism:
2565
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2566
+ To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field
2567
+ by the ideal (x^2 + y^2)
2568
+ Defn: Natural quotient map
2569
+ sage: phi(x + y) # needs sage.libs.singular
2570
+ a + b
2571
+ """
2572
+ def __init__(self, parent):
2573
+ """
2574
+ Create a covering ring homomorphism, induced by quotienting out by an
2575
+ ideal.
2576
+
2577
+ EXAMPLES::
2578
+
2579
+ sage: f = Zmod(6).cover(); f # implicit test
2580
+ Ring morphism:
2581
+ From: Integer Ring
2582
+ To: Ring of integers modulo 6
2583
+ Defn: Natural quotient map
2584
+ sage: type(f)
2585
+ <class 'sage.rings.morphism.RingHomomorphism_cover'>
2586
+ """
2587
+ RingHomomorphism.__init__(self, parent)
2588
+
2589
+ cpdef Element _call_(self, x):
2590
+ """
2591
+ Evaluate this covering homomorphism at ``x``, which just involves
2592
+ coercing ``x`` into the domain, then codomain.
2593
+
2594
+ EXAMPLES::
2595
+
2596
+ sage: f = Zmod(6).cover()
2597
+ sage: type(f)
2598
+ <class 'sage.rings.morphism.RingHomomorphism_cover'>
2599
+ sage: f(-5) # indirect doctest
2600
+ 1
2601
+
2602
+ TESTS:
2603
+
2604
+ We verify that calling directly raises the expected error
2605
+ (just coercing into the codomain), but calling with __call__
2606
+ (the second call below) gives a :exc:`TypeError` since 1/2 cannot be
2607
+ coerced into the domain. ::
2608
+
2609
+ sage: f._call_(1/2)
2610
+ Traceback (most recent call last):
2611
+ ...
2612
+ ZeroDivisionError: inverse of Mod(2, 6) does not exist
2613
+ sage: f(1/2)
2614
+ Traceback (most recent call last):
2615
+ ...
2616
+ TypeError: 1/2 fails to convert into the map's domain Integer Ring,
2617
+ but a `pushforward` method is not properly implemented
2618
+ """
2619
+ return self.codomain()(x)
2620
+
2621
+ def _repr_defn(self):
2622
+ """
2623
+ Used internally for printing covering morphisms.
2624
+
2625
+ EXAMPLES::
2626
+
2627
+ sage: f = Zmod(6).cover()
2628
+ sage: f._repr_defn()
2629
+ 'Natural quotient map'
2630
+ sage: type(f)
2631
+ <class 'sage.rings.morphism.RingHomomorphism_cover'>
2632
+ """
2633
+ return "Natural quotient map"
2634
+
2635
+ def kernel(self):
2636
+ """
2637
+ Return the kernel of this covering morphism, which is the ideal that
2638
+ was quotiented out by.
2639
+
2640
+ EXAMPLES::
2641
+
2642
+ sage: f = Zmod(6).cover()
2643
+ sage: f.kernel()
2644
+ Principal ideal (6) of Integer Ring
2645
+ """
2646
+ return self.codomain().defining_ideal()
2647
+
2648
+ cpdef _richcmp_(self, other, int op):
2649
+ """
2650
+ Compare ``self`` to ``other``.
2651
+
2652
+ EXAMPLES::
2653
+
2654
+ sage: # needs sage.libs.singular
2655
+ sage: R.<x,y> = PolynomialRing(QQ, 2)
2656
+ sage: S.<a,b> = R.quo(x^2 + y^2)
2657
+ sage: phi = S.cover()
2658
+ sage: phi == loads(dumps(phi))
2659
+ True
2660
+ sage: phi == R.quo(x^2 + y^3).cover()
2661
+ False
2662
+ """
2663
+ if not isinstance(other, RingHomomorphism_cover):
2664
+ # Generic comparison
2665
+ return RingMap._richcmp_(self, other, op)
2666
+ # Two cover maps with the same parent must be equal
2667
+ return rich_to_bool(op, 0)
2668
+
2669
+ def __hash__(self):
2670
+ """
2671
+ Return the hash of this morphism.
2672
+
2673
+ TESTS::
2674
+
2675
+ sage: # needs sage.libs.singular
2676
+ sage: R.<x,y> = PolynomialRing(QQ, 2)
2677
+ sage: S.<a,b> = R.quo(x^2 + y^2)
2678
+ sage: phi = S.cover()
2679
+ sage: type(phi)
2680
+ <class 'sage.rings.morphism.RingHomomorphism_cover'>
2681
+ sage: hash(phi) == hash(phi)
2682
+ True
2683
+ sage: {phi: 1}[phi]
2684
+ 1
2685
+ """
2686
+ return hash((self.domain(), self.codomain()))
2687
+
2688
+ def _inverse_image_ideal(self, I):
2689
+ """
2690
+ Return the inverse image of the ideal `I` under this covering morphism.
2691
+
2692
+ INPUT:
2693
+
2694
+ - ``I`` -- an ideal in the quotient ring
2695
+
2696
+ EXAMPLES::
2697
+
2698
+ sage: # needs sage.libs.singular
2699
+ sage: R.<x,y> = QQ['x,y'].quotient('x^2 * y^2')
2700
+ sage: R.cover().inverse_image(R.ideal(x^3, y^3 + 1))
2701
+ Ideal (x^2*y^2, x^3, y^3 + 1) of Multivariate Polynomial Ring
2702
+ in x, y over Rational Field
2703
+ sage: S.<u,v> = QQbar['u,v'].quotient('u^4 - 1')
2704
+ sage: S.cover().inverse_image(S.ideal(u^2 - 1))
2705
+ Ideal (u^4 - 1, u^2 - 1) of Multivariate Polynomial Ring in u, v
2706
+ over Algebraic Field
2707
+ """
2708
+ if I.is_zero():
2709
+ return self.kernel()
2710
+ return self.kernel() + [f.lift() for f in I.gens()]
2711
+
2712
+ def _inverse_image_element(self, b):
2713
+ """
2714
+ Lift an element from the quotient to the cover ring of this ring
2715
+ homomorphism.
2716
+
2717
+ EXAMPLES::
2718
+
2719
+ sage: Q.<u,v> = QQ['x,y'].quotient('x + y') # needs sage.libs.singular
2720
+ sage: Q.cover().inverse_image(u) # needs sage.libs.singular
2721
+ -y
2722
+ """
2723
+ return b.lift()
2724
+
2725
+
2726
+ cdef class RingHomomorphism_from_quotient(RingHomomorphism):
2727
+ r"""
2728
+ A ring homomorphism with domain a generic quotient ring.
2729
+
2730
+ INPUT:
2731
+
2732
+ - ``parent`` -- a ring homset ``Hom(R,S)``
2733
+
2734
+ - ``phi`` -- a ring homomorphism ``C --> S``, where ``C`` is the
2735
+ domain of ``R.cover()``
2736
+
2737
+ OUTPUT: a ring homomorphism
2738
+
2739
+ The domain `R` is a quotient object `C \to R`, and
2740
+ ``R.cover()`` is the ring homomorphism
2741
+ `\varphi: C \to R`. The condition on the elements
2742
+ ``im_gens`` of `S` is that they define a
2743
+ homomorphism `C \to S` such that each generator of the
2744
+ kernel of `\varphi` maps to `0`.
2745
+
2746
+ EXAMPLES::
2747
+
2748
+ sage: # needs sage.libs.singular
2749
+ sage: R.<x, y, z> = PolynomialRing(QQ, 3)
2750
+ sage: S.<a, b, c> = R.quo(x^3 + y^3 + z^3)
2751
+ sage: phi = S.hom([b, c, a]); phi
2752
+ Ring endomorphism of Quotient of Multivariate Polynomial Ring in x, y, z
2753
+ over Rational Field by the ideal (x^3 + y^3 + z^3)
2754
+ Defn: a |--> b
2755
+ b |--> c
2756
+ c |--> a
2757
+ sage: phi(a + b + c)
2758
+ a + b + c
2759
+ sage: loads(dumps(phi)) == phi
2760
+ True
2761
+
2762
+ Validity of the homomorphism is determined, when possible, and a
2763
+ :exc:`TypeError` is raised if there is no homomorphism sending the
2764
+ generators to the given images::
2765
+
2766
+ sage: S.hom([b^2, c^2, a^2]) # needs sage.libs.singular
2767
+ Traceback (most recent call last):
2768
+ ...
2769
+ ValueError: relations do not all (canonically) map to 0
2770
+ under map determined by images of generators
2771
+ """
2772
+ def __init__(self, parent, phi):
2773
+ """
2774
+ Initialize ``self``.
2775
+
2776
+ EXAMPLES::
2777
+
2778
+ sage: R.<x,y> = QQ[]; S.<xx,yy> = R.quo([x^2,y^2]); S.hom([yy,xx]) # needs sage.libs.singular
2779
+ Ring endomorphism of Quotient of Multivariate Polynomial Ring in x, y
2780
+ over Rational Field by the ideal (x^2, y^2)
2781
+ Defn: xx |--> yy
2782
+ yy |--> xx
2783
+ """
2784
+ RingHomomorphism.__init__(self, parent)
2785
+ R = parent.domain()
2786
+ pi = R.cover() # the covering map, which should be a RingHomomorphism
2787
+ if not isinstance(pi, RingHomomorphism):
2788
+ raise TypeError("pi should be a ring homomorphism")
2789
+ if not isinstance(phi, RingHomomorphism):
2790
+ raise TypeError("phi should be a ring homomorphism")
2791
+ if pi.domain() != phi.domain():
2792
+ raise ValueError("Domain of phi must equal domain of covering (%s != %s)." % (pi.domain(), phi.domain()))
2793
+ for x in pi.kernel().gens():
2794
+ if phi(x) != 0:
2795
+ raise ValueError("relations do not all (canonically) map to 0 under map determined by images of generators")
2796
+ self._lift = pi.lift()
2797
+ self.phi = phi
2798
+
2799
+ cdef _update_slots(self, dict _slots):
2800
+ """
2801
+ Helper for copying and pickling.
2802
+
2803
+ EXAMPLES::
2804
+
2805
+ sage: # needs sage.libs.singular
2806
+ sage: R.<x, y, z> = PolynomialRing(QQ, 3)
2807
+ sage: S.<a, b, c> = R.quo(x^3 + y^3 + z^3)
2808
+ sage: phi = S.hom([b, c, a]); phi
2809
+ Ring endomorphism of Quotient of Multivariate Polynomial Ring in x, y, z
2810
+ over Rational Field by the ideal (x^3 + y^3 + z^3)
2811
+ Defn: a |--> b
2812
+ b |--> c
2813
+ c |--> a
2814
+ sage: phi(a + b + c)
2815
+ a + b + c
2816
+ sage: psi = copy(phi) # indirect doctest
2817
+ sage: psi == phi
2818
+ True
2819
+ sage: psi is phi
2820
+ False
2821
+ sage: psi(a) == phi(a)
2822
+ True
2823
+ """
2824
+ self.phi = _slots['phi']
2825
+ RingHomomorphism._update_slots(self, _slots)
2826
+
2827
+ cdef dict _extra_slots(self):
2828
+ """
2829
+ Helper for copying and pickling.
2830
+
2831
+ EXAMPLES::
2832
+
2833
+ sage: # needs sage.libs.singular
2834
+ sage: R.<x, y, z> = PolynomialRing(QQ, 3)
2835
+ sage: S.<a, b, c> = R.quo(x^3 + y^3 + z^3)
2836
+ sage: phi = S.hom([b, c, a]); phi
2837
+ Ring endomorphism of Quotient of Multivariate Polynomial Ring in x, y, z
2838
+ over Rational Field by the ideal (x^3 + y^3 + z^3)
2839
+ Defn: a |--> b
2840
+ b |--> c
2841
+ c |--> a
2842
+ sage: phi(a + b + c)
2843
+ a + b + c
2844
+ sage: psi = copy(phi) # indirect doctest
2845
+ sage: psi == phi
2846
+ True
2847
+ sage: psi is phi
2848
+ False
2849
+ sage: psi(a) == phi(a)
2850
+ True
2851
+ """
2852
+ slots = RingHomomorphism._extra_slots(self)
2853
+ slots['phi'] = self.phi
2854
+ return slots
2855
+
2856
+ def _phi(self):
2857
+ """
2858
+ Underlying morphism used to define this quotient map, i.e.,
2859
+ morphism from the cover of the domain.
2860
+
2861
+ EXAMPLES::
2862
+
2863
+ sage: R.<x,y> = QQ[]; S.<xx,yy> = R.quo([x^2, y^2]); f = S.hom([yy,xx]) # needs sage.libs.singular
2864
+ sage: f._phi() # needs sage.libs.singular
2865
+ Ring morphism:
2866
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2867
+ To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2, y^2)
2868
+ Defn: x |--> yy
2869
+ y |--> xx
2870
+ """
2871
+ return self.phi
2872
+
2873
+ def morphism_from_cover(self):
2874
+ """
2875
+ Underlying morphism used to define this quotient map, i.e.,
2876
+ the morphism from the cover of the domain.
2877
+
2878
+ EXAMPLES::
2879
+
2880
+ sage: R.<x,y> = QQ[]; S.<xx,yy> = R.quo([x^2, y^2]) # needs sage.libs.singular
2881
+ sage: S.hom([yy,xx]).morphism_from_cover() # needs sage.libs.singular
2882
+ Ring morphism:
2883
+ From: Multivariate Polynomial Ring in x, y over Rational Field
2884
+ To: Quotient of Multivariate Polynomial Ring in x, y
2885
+ over Rational Field by the ideal (x^2, y^2)
2886
+ Defn: x |--> yy
2887
+ y |--> xx
2888
+ """
2889
+ return self.phi
2890
+
2891
+ cpdef _richcmp_(self, other, int op):
2892
+ """
2893
+ Compare ``self`` to ``other``.
2894
+
2895
+ EXAMPLES::
2896
+
2897
+ sage: # needs sage.libs.singular
2898
+ sage: R.<x, y, z> = PolynomialRing(GF(19), 3)
2899
+ sage: S.<a, b, c> = R.quo(x^3 + y^3 + z^3)
2900
+ sage: phi = S.hom([b, c, a])
2901
+ sage: psi = S.hom([c, b, a])
2902
+ sage: f = S.hom([b, c, a + a^3 + b^3 + c^3])
2903
+ sage: phi == psi
2904
+ False
2905
+ sage: phi == f
2906
+ True
2907
+ """
2908
+ if not isinstance(other, RingHomomorphism_from_quotient):
2909
+ # Generic comparison
2910
+ return RingMap._richcmp_(self, other, op)
2911
+ # Generic comparison
2912
+ self_phi = self.phi
2913
+ other_phi = (<RingHomomorphism_from_quotient>other).phi
2914
+ return richcmp(self_phi, other_phi, op)
2915
+
2916
+ def __hash__(self):
2917
+ """
2918
+ Return the hash of this morphism.
2919
+
2920
+ EXAMPLES::
2921
+
2922
+ sage: # needs sage.libs.singular
2923
+ sage: R.<x, y, z> = PolynomialRing(GF(19), 3)
2924
+ sage: S.<a, b, c> = R.quo(x^3 + y^3 + z^3)
2925
+ sage: phi = S.hom([b, c, a])
2926
+ sage: type(phi)
2927
+ <class 'sage.rings.morphism.RingHomomorphism_from_quotient'>
2928
+ sage: hash(phi) == hash(phi)
2929
+ True
2930
+ sage: {phi: 1}[phi]
2931
+ 1
2932
+ """
2933
+ return hash(self.phi)
2934
+
2935
+ def _repr_defn(self) -> str:
2936
+ """
2937
+ Used internally for printing this function.
2938
+
2939
+ EXAMPLES::
2940
+
2941
+ sage: R.<x,y> = QQ[]; S.<xx,yy> = R.quo([x^2,y^2]) # needs sage.libs.singular
2942
+ sage: f = S.hom([yy, xx]) # needs sage.libs.singular
2943
+ sage: print(f._repr_defn()) # needs sage.libs.singular
2944
+ xx |--> yy
2945
+ yy |--> xx
2946
+ """
2947
+ D = self.domain()
2948
+ ig = self.phi.im_gens()
2949
+ return '\n'.join('{} |--> {}'.format(D.gen(i), ig[i])
2950
+ for i in range(D.ngens()))
2951
+
2952
+ cpdef Element _call_(self, x):
2953
+ """
2954
+ Evaluate this function at ``x``.
2955
+
2956
+ EXAMPLES::
2957
+
2958
+ sage: R.<x,y> = QQ[]; S.<xx,yy> = R.quo([x^2, y^2]); f = S.hom([yy, xx]) # needs sage.libs.singular
2959
+ sage: f(3*x + (1/2)*y) # indirect doctest # needs sage.libs.singular
2960
+ 1/2*xx + 3*yy
2961
+ """
2962
+ return self.phi(self.lift(x))
2963
+
2964
+
2965
+ cdef class FrobeniusEndomorphism_generic(RingHomomorphism):
2966
+ """
2967
+ A class implementing Frobenius endomorphisms on rings of prime
2968
+ characteristic.
2969
+ """
2970
+ def __init__(self, domain, n=1):
2971
+ """
2972
+ INPUT:
2973
+
2974
+ - ``domain`` -- a ring
2975
+
2976
+ - ``n`` -- nonnegative integer (default: 1)
2977
+
2978
+ OUTPUT:
2979
+
2980
+ The `n`-th power of the absolute (arithmetic) Frobenius
2981
+ endomorphism on ``domain``
2982
+
2983
+ TESTS::
2984
+
2985
+ sage: from sage.rings.morphism import FrobeniusEndomorphism_generic
2986
+ sage: K.<u> = PowerSeriesRing(GF(5))
2987
+ sage: FrobeniusEndomorphism_generic(K)
2988
+ Frobenius endomorphism x |--> x^5 of Power Series Ring in u
2989
+ over Finite Field of size 5
2990
+ sage: FrobeniusEndomorphism_generic(K, 2)
2991
+ Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u
2992
+ over Finite Field of size 5
2993
+ """
2994
+ from sage.rings.ring import CommutativeRing
2995
+ from sage.categories.commutative_rings import CommutativeRings
2996
+ from sage.categories.homset import Hom
2997
+ if not (domain in CommutativeRings() or
2998
+ isinstance(domain, CommutativeRing)): # TODO: remove this line
2999
+ raise TypeError("The base ring must be a commutative ring")
3000
+ self._p = domain.characteristic()
3001
+ if not self._p.is_prime():
3002
+ raise TypeError("the characteristic of the base ring must be prime")
3003
+ try:
3004
+ n = Integer(n)
3005
+ except TypeError:
3006
+ raise TypeError("n (=%s) is not a nonnegative integer" % n)
3007
+ if n < 0:
3008
+ raise TypeError("n (=%s) is not a nonnegative integer" % n)
3009
+ self._power = n
3010
+ self._q = self._p ** self._power
3011
+ RingHomomorphism.__init__(self, Hom(domain, domain))
3012
+
3013
+ cdef _update_slots(self, dict _slots):
3014
+ """
3015
+ Update information with the given slots.
3016
+
3017
+ Helper function for copying or pickling.
3018
+
3019
+ EXAMPLES::
3020
+
3021
+ sage: # needs sage.rings.finite_rings
3022
+ sage: K = Frac(GF(5)['T'])
3023
+ sage: phi = K.frobenius_endomorphism()
3024
+ sage: psi = copy(phi)
3025
+ sage: phi == psi
3026
+ True
3027
+ """
3028
+ self._p = _slots['_domain'].characteristic()
3029
+ self._power = _slots['_power']
3030
+ self._q = self._p ** self._power
3031
+ RingHomomorphism._update_slots(self, _slots)
3032
+
3033
+ cdef dict _extra_slots(self):
3034
+ """
3035
+ Return additional information about this morphism
3036
+ as a dictionary.
3037
+
3038
+ Helper function for copying or pickling.
3039
+
3040
+ EXAMPLES::
3041
+
3042
+ sage: # needs sage.rings.finite_rings
3043
+ sage: K = Frac(GF(25)['T'])
3044
+ sage: phi = K.frobenius_endomorphism(2)
3045
+ sage: phi
3046
+ Frobenius endomorphism x |--> x^(5^2) of Fraction Field of
3047
+ Univariate Polynomial Ring in T over Finite Field in z2 of size 5^2
3048
+ sage: psi = loads(dumps(phi)); psi
3049
+ Frobenius endomorphism x |--> x^(5^2) of Fraction Field of
3050
+ Univariate Polynomial Ring in T over Finite Field in z2 of size 5^2
3051
+ sage: phi == psi
3052
+ True
3053
+ """
3054
+ slots = RingHomomorphism._extra_slots(self)
3055
+ slots['_power'] = self._power
3056
+ return slots
3057
+
3058
+ def _repr_(self):
3059
+ """
3060
+ Return a string representation of this endomorphism.
3061
+
3062
+ EXAMPLES::
3063
+
3064
+ sage: K.<u> = PowerSeriesRing(GF(5))
3065
+ sage: Frob = K.frobenius_endomorphism(); Frob
3066
+ Frobenius endomorphism x |--> x^5 of Power Series Ring in u
3067
+ over Finite Field of size 5
3068
+
3069
+ sage: Frob._repr_()
3070
+ 'Frobenius endomorphism x |--> x^5 of Power Series Ring in u
3071
+ over Finite Field of size 5'
3072
+ """
3073
+ if self._power == 0:
3074
+ s = "Identity endomorphism"
3075
+ elif self._power == 1:
3076
+ s = "Frobenius endomorphism x |--> x^%s" % self._p
3077
+ else:
3078
+ s = "Frobenius endomorphism x |--> x^(%s^%s)" % (self._p, self._power)
3079
+ s += " of %s" % self.domain()
3080
+ return s
3081
+
3082
+ def _repr_short(self):
3083
+ """
3084
+ Return a short string representation of this endomorphism.
3085
+
3086
+ EXAMPLES::
3087
+
3088
+ sage: # needs sage.rings.finite_rings
3089
+ sage: K.<u> = PowerSeriesRing(GF(5))
3090
+ sage: Frob = K.frobenius_endomorphism()
3091
+ sage: Frob._repr_short()
3092
+ 'Frob'
3093
+ sage: (Frob^2)._repr_short()
3094
+ 'Frob^2'
3095
+ """
3096
+ if self._power == 0:
3097
+ s = "Identity"
3098
+ elif self._power == 1:
3099
+ s = "Frob"
3100
+ else:
3101
+ s = "Frob^%s" % self._power
3102
+ return s
3103
+
3104
+ def _latex_(self):
3105
+ r"""
3106
+ Return a latex representation of this endomorphism.
3107
+
3108
+ EXAMPLES::
3109
+
3110
+ sage: K.<u> = PowerSeriesRing(GF(5))
3111
+ sage: Frob = K.frobenius_endomorphism(2)
3112
+ sage: Frob._latex_()
3113
+ '\\verb"Frob"^{2}'
3114
+ """
3115
+ if self._power == 0:
3116
+ s = '\\verb"id"'
3117
+ elif self._power == 1:
3118
+ s = '\\verb"Frob"'
3119
+ else:
3120
+ s = '\\verb"Frob"^{%s}' % self._power
3121
+ return s
3122
+
3123
+ cpdef Element _call_ (self, x):
3124
+ """
3125
+ TESTS::
3126
+
3127
+ sage: # needs sage.rings.finite_rings
3128
+ sage: K.<u> = PowerSeriesRing(GF(5))
3129
+ sage: Frob = K.frobenius_endomorphism()
3130
+ sage: Frob(u)
3131
+ u^5
3132
+ sage: (Frob^2)(1 + u)
3133
+ 1 + u^25
3134
+ """
3135
+ return x ** self._q
3136
+
3137
+ def power(self):
3138
+ """
3139
+ Return an integer `n` such that this endomorphism
3140
+ is the `n`-th power of the absolute (arithmetic)
3141
+ Frobenius.
3142
+
3143
+ EXAMPLES::
3144
+
3145
+ sage: # needs sage.rings.finite_rings
3146
+ sage: K.<u> = PowerSeriesRing(GF(5))
3147
+ sage: Frob = K.frobenius_endomorphism()
3148
+ sage: Frob.power()
3149
+ 1
3150
+ sage: (Frob^9).power()
3151
+ 9
3152
+ """
3153
+ return self._power
3154
+
3155
+ def __pow__(self, n, ignored):
3156
+ """
3157
+ Return the `n`-th iterate of this endomorphism.
3158
+
3159
+ EXAMPLES::
3160
+
3161
+ sage: K.<u> = PowerSeriesRing(GF(5))
3162
+ sage: Frob = K.frobenius_endomorphism(); Frob
3163
+ Frobenius endomorphism x |--> x^5 of Power Series Ring in u
3164
+ over Finite Field of size 5
3165
+ sage: Frob^2
3166
+ Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u
3167
+ over Finite Field of size 5
3168
+ """
3169
+ return self.__class__(self.domain(), self.power()*n)
3170
+
3171
+ def _composition(self, right):
3172
+ """
3173
+ Return ``self`` o ``right``.
3174
+
3175
+ EXAMPLES::
3176
+
3177
+ sage: # needs sage.rings.finite_rings
3178
+ sage: K.<u> = PowerSeriesRing(GF(5))
3179
+ sage: f = K.frobenius_endomorphism(); f
3180
+ Frobenius endomorphism x |--> x^5 of Power Series Ring in u
3181
+ over Finite Field of size 5
3182
+ sage: g = K.frobenius_endomorphism(2); g
3183
+ Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u
3184
+ over Finite Field of size 5
3185
+ sage: f * g
3186
+ Frobenius endomorphism x |--> x^(5^3) of Power Series Ring in u
3187
+ over Finite Field of size 5
3188
+ """
3189
+ if isinstance(right, FrobeniusEndomorphism_generic):
3190
+ return self.__class__(self.domain(), self._power + right.power())
3191
+ else:
3192
+ return RingHomomorphism._composition(self, right)
3193
+
3194
+ def __hash__(self):
3195
+ """
3196
+ Return a hash of this morphism.
3197
+
3198
+ It is the hash of the triple (domain, codomain, definition)
3199
+ where ``definition`` is:
3200
+
3201
+ - a tuple consisting of the images of the generators
3202
+ of the domain if domain has generators
3203
+
3204
+ - the string representation of this morphism otherwise
3205
+
3206
+ AUTHOR:
3207
+
3208
+ - Xavier Caruso (2012-07-09)
3209
+ """
3210
+ domain = self.domain()
3211
+ codomain = self.codomain()
3212
+ return hash((domain, codomain, ('Frob', self._power)))
3213
+
3214
+
3215
+ def _tensor_product_ring(B, A):
3216
+ """
3217
+ Construct a quotient ring representing the tensor product of two rings
3218
+ over a common base ring.
3219
+
3220
+ Allowed arguments are polynomial rings, quotient rings, number fields and
3221
+ finite fields.
3222
+
3223
+ EXAMPLES::
3224
+
3225
+ sage: # needs sage.libs.singular
3226
+ sage: from sage.rings.morphism import _tensor_product_ring
3227
+ sage: R.<x,y> = QQ[]
3228
+ sage: S.<u,v> = R.quotient(x^2 + y^2)
3229
+ sage: Q = _tensor_product_ring(S, R); Q
3230
+ Quotient of Multivariate Polynomial Ring in u, v, x, y over
3231
+ Rational Field by the ideal (u^2 + v^2)
3232
+ sage: Q.term_order()
3233
+ Block term order with blocks:
3234
+ (Degree reverse lexicographic term order of length 2,
3235
+ Degree reverse lexicographic term order of length 2)
3236
+ sage: _tensor_product_ring(R, R)
3237
+ Multivariate Polynomial Ring in y0, y1, x0, x1 over Rational Field
3238
+
3239
+ TESTS:
3240
+
3241
+ Local orderings are not supported::
3242
+
3243
+ sage: R = PolynomialRing(QQ, 'x,y', order='negdeglex')
3244
+ sage: _tensor_product_ring(R, R) # needs sage.libs.singular
3245
+ Traceback (most recent call last):
3246
+ ...
3247
+ ValueError: term ordering must be global
3248
+ """
3249
+ from sage.rings.finite_rings.finite_field_base import FiniteField
3250
+ from sage.rings.number_field.number_field_base import NumberField
3251
+ from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_base
3252
+ from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_generic
3253
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
3254
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
3255
+ from sage.rings.polynomial.term_order import TermOrder
3256
+ from sage.rings.quotient_ring import QuotientRing_nc
3257
+
3258
+ if set(B.variable_names()).isdisjoint(A.variable_names()):
3259
+ names = B.variable_names() + A.variable_names()
3260
+ else:
3261
+ names = (['y%d' % d for d in range(B.ngens())] +
3262
+ ['x%d' % d for d in range(A.ngens())])
3263
+
3264
+ def term_order(A):
3265
+ # univariate rings do not have a term order
3266
+ if (isinstance(A, (PolynomialRing_generic, PolynomialQuotientRing_generic))
3267
+ or (isinstance(A, (NumberField, FiniteField))
3268
+ and not A.is_prime_field())):
3269
+ return TermOrder('lex', 1)
3270
+ try:
3271
+ t = A.term_order()
3272
+ except AttributeError:
3273
+ raise NotImplementedError("inverse not implemented for "
3274
+ "morphisms of %s" % A)
3275
+ if not t.is_global():
3276
+ raise ValueError("term ordering must be global")
3277
+ return t
3278
+ R = PolynomialRing(A.base_ring(), names=names,
3279
+ order=term_order(B) + term_order(A))
3280
+
3281
+ def relations(A, R_gens_A):
3282
+ if isinstance(A, (MPolynomialRing_base, PolynomialRing_generic)):
3283
+ return []
3284
+ elif isinstance(A, PolynomialQuotientRing_generic):
3285
+ to_R = A.ambient().hom(R_gens_A, R, check=False)
3286
+ return [to_R(A.modulus())]
3287
+ elif isinstance(A, QuotientRing_nc):
3288
+ to_R = A.ambient().hom(R_gens_A, R, check=False)
3289
+ return list(to_R(A.defining_ideal()).gens())
3290
+ elif (isinstance(A, (NumberField, FiniteField))
3291
+ and not A.is_prime_field()):
3292
+ to_R = A.polynomial_ring().hom(R_gens_A, R, check=False)
3293
+ return [to_R(A.polynomial())]
3294
+ else:
3295
+ raise NotImplementedError("inverse not implemented for "
3296
+ "morphisms of %s" % A)
3297
+ rels_A = relations(A, R.gens()[B.ngens():])
3298
+ rels_B = relations(B, R.gens()[:B.ngens()])
3299
+ return R.quotient(rels_A + rels_B, names=R.variable_names())