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,3082 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ r"""
3
+ Base class for elements of multivariate polynomial rings
4
+ """
5
+
6
+ # ********************************************************************
7
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
8
+ #
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ # https://www.gnu.org/licenses/
14
+ # ********************************************************************
15
+ from itertools import chain
16
+
17
+ from sage.rings.integer cimport Integer
18
+ from sage.rings.integer_ring import ZZ
19
+ from sage.structure.coerce cimport coercion_model
20
+ from sage.misc.derivative import multi_derivative
21
+ from sage.misc.misc_c import prod
22
+ from sage.misc.superseded import deprecated_function_alias
23
+
24
+
25
+ def is_MPolynomial(x):
26
+ from sage.misc.superseded import deprecation
27
+ deprecation(32709, "the function is_MPolynomial is deprecated; use isinstance(x, sage.rings.polynomial.multi_polynomial.MPolynomial) instead")
28
+
29
+ return isinstance(x, MPolynomial)
30
+
31
+
32
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
33
+ from sage.categories.map cimport Map
34
+ from sage.rings.rational_field import QQ
35
+
36
+ from sage.rings.polynomial.polydict cimport ETuple
37
+ from sage.rings.polynomial.polynomial_element cimport Polynomial
38
+
39
+ cdef class MPolynomial(CommutativePolynomial):
40
+
41
+ # -------------------------
42
+ # Some standard conversions
43
+ # -------------------------
44
+ def _scalar_conversion(self, R):
45
+ r"""
46
+ TESTS::
47
+
48
+ sage: # needs sage.rings.real_mpfr
49
+ sage: ZZ(RR['x,y'](0)) # indirect doctest
50
+ 0
51
+ sage: ZZ(RR['x,y'](0.5))
52
+ Traceback (most recent call last):
53
+ ...
54
+ TypeError: Attempt to coerce non-integral RealNumber to Integer
55
+ sage: ZZ(RR['x,y'].gen(0))
56
+ Traceback (most recent call last):
57
+ ...
58
+ TypeError: unable to convert non-constant polynomial x to Integer Ring
59
+
60
+ sage: # needs sage.rings.real_mpfr
61
+ sage: RR(RR['x,y'](0)) # indirect doctest
62
+ 0.000000000000000
63
+ sage: RR(ZZ['x,y'].gen(0))
64
+ Traceback (most recent call last):
65
+ ...
66
+ TypeError: unable to convert non-constant polynomial x to Real Field with 53 bits of precision
67
+
68
+ sage: # needs sage.rings.real_mpfr
69
+ sage: CC(RR['x,y'](0)) # indirect doctest
70
+ 0.000000000000000
71
+ sage: CC(ZZ['x,y'].gen(0))
72
+ Traceback (most recent call last):
73
+ ...
74
+ TypeError: unable to convert non-constant polynomial x to Complex Field with 53 bits of precision
75
+
76
+ sage: # needs sage.rings.real_mpfr
77
+ sage: RDF(RR['x,y'](0))
78
+ 0.0
79
+ sage: RDF(ZZ['x,y'].gen(0))
80
+ Traceback (most recent call last):
81
+ ...
82
+ TypeError: unable to convert non-constant polynomial x to Real Double Field
83
+
84
+ sage: # needs sage.rings.real_mpfr
85
+ sage: CDF(RR['x,y'](0)) # indirect doctest
86
+ 0.0
87
+ sage: CDF(ZZ['x,y'].gen(0))
88
+ Traceback (most recent call last):
89
+ ...
90
+ TypeError: unable to convert non-constant polynomial x to Complex Double Field
91
+
92
+ sage: # needs sage.libs.flint sage.rings.real_mpfr
93
+ sage: a = RR['x,y'](1)
94
+ sage: RBF(a)
95
+ 1.000000000000000
96
+ sage: RIF(a)
97
+ 1
98
+ sage: CBF(a)
99
+ 1.000000000000000
100
+ sage: CIF(a)
101
+ 1
102
+ sage: CBF(RR['x,y'](1)) # indirect doctest
103
+ 1.000000000000000
104
+ sage: CBF(ZZ['x,y'].gen(0))
105
+ Traceback (most recent call last):
106
+ ...
107
+ TypeError: unable to convert non-constant polynomial x to Complex ball field with 53 bits of precision
108
+
109
+ sage: x = polygen(QQ)
110
+ sage: A.<u> = NumberField(x^3 - 2) # needs sage.rings.number_field
111
+ sage: A(A['x,y'](u)) # needs sage.rings.number_field
112
+ u
113
+ """
114
+ if self.degree() <= 0:
115
+ return R(self.constant_coefficient())
116
+ raise TypeError(f"unable to convert non-constant polynomial {self} to {R}")
117
+
118
+ _real_double_ = _scalar_conversion
119
+ _complex_double_ = _scalar_conversion
120
+ _mpfr_ = _scalar_conversion
121
+ _complex_mpfr_ = _scalar_conversion
122
+ _real_mpfi_ = _scalar_conversion
123
+ _complex_mpfi_ = _scalar_conversion
124
+ _arb_ = _scalar_conversion
125
+ _acb_ = _scalar_conversion
126
+ _integer_ = _scalar_conversion
127
+ _algebraic_ = _scalar_conversion
128
+ _number_field_ = _scalar_conversion
129
+
130
+ def __int__(self):
131
+ r"""
132
+ TESTS::
133
+
134
+ sage: type(RR['x,y'])
135
+ <class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_domain_with_category'>
136
+ sage: type(RR['x, y'](0))
137
+ <class 'sage.rings.polynomial.multi_polynomial_element.MPolynomial_polydict'>
138
+
139
+ sage: int(RR['x,y'](0)) # indirect doctest
140
+ 0
141
+ sage: int(RR['x,y'](10))
142
+ 10
143
+ sage: int(ZZ['x,y'].gen(0))
144
+ Traceback (most recent call last):
145
+ ...
146
+ TypeError: unable to convert non-constant polynomial x to <class 'int'>
147
+
148
+ sage: ZZ(RR['x,y'](0)) # indirect doctest
149
+ 0
150
+ sage: ZZ(RR['x,y'](0.5)) # needs sage.rings.real_mpfr
151
+ Traceback (most recent call last):
152
+ ...
153
+ TypeError: Attempt to coerce non-integral RealNumber to Integer
154
+ sage: ZZ(RR['x,y'].gen(0))
155
+ Traceback (most recent call last):
156
+ ...
157
+ TypeError: unable to convert non-constant polynomial x to Integer Ring
158
+ """
159
+ return self._scalar_conversion(int)
160
+
161
+ def __float__(self):
162
+ r"""
163
+ TESTS::
164
+
165
+ sage: float(RR['x,y'](0)) # indirect doctest
166
+ 0.0
167
+ sage: float(ZZ['x,y'].gen(0))
168
+ Traceback (most recent call last):
169
+ ...
170
+ TypeError: unable to convert non-constant polynomial x to <class 'float'>
171
+ """
172
+ return self._scalar_conversion(float)
173
+
174
+ def _rational_(self):
175
+ r"""
176
+ TESTS::
177
+
178
+ sage: QQ(RR['x,y'](0.5)) # indirect doctest
179
+ 1/2
180
+ sage: QQ(RR['x,y'].gen(0))
181
+ Traceback (most recent call last):
182
+ ...
183
+ TypeError: unable to convert non-constant polynomial x to Rational Field
184
+ """
185
+ from sage.rings.rational_field import QQ
186
+ return self._scalar_conversion(QQ)
187
+
188
+ def _symbolic_(self, R):
189
+ r"""
190
+ EXAMPLES::
191
+
192
+ sage: # needs sage.symbolic
193
+ sage: R.<x,y> = QQ[]
194
+ sage: f = x^3 + y
195
+ sage: g = f._symbolic_(SR); g
196
+ x^3 + y
197
+ sage: g(x=2, y=2)
198
+ 10
199
+ sage: g = SR(f)
200
+ sage: g(x=2, y=2)
201
+ 10
202
+ """
203
+ d = dict([(repr(g), R.var(g)) for g in self.parent().gens()])
204
+ return self.subs(**d)
205
+
206
+ def _polynomial_(self, R):
207
+ var = R.variable_name()
208
+ if var in self._parent.variable_names():
209
+ return R(self.polynomial(self._parent(var)))
210
+ return R([self])
211
+
212
+ def leading_support(self, *args, **kwds):
213
+ r"""
214
+ Return the maximal element of the support of ``self``,
215
+ according to the term order.
216
+
217
+ If the term ordering of the basis elements is not what is
218
+ desired, a comparison key, ``key(x)``, can be provided.
219
+
220
+ EXAMPLES::
221
+
222
+ sage: R.<x,y,z> = PolynomialRing(QQ)
223
+ sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_support()
224
+ (0, 4, 0)
225
+ sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
226
+ sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_support()
227
+ (1, 2, 0)
228
+ sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
229
+ sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_support()
230
+ (0, 1, 3)
231
+ """
232
+ if 'key' in kwds:
233
+ return max(self.support(), *args, **kwds)
234
+ kwds['key'] = self._parent.term_order().sortkey
235
+ return max(self.support(), *args, **kwds)
236
+
237
+ def trailing_support(self, *args, **kwds):
238
+ r"""
239
+ Return the minimal element of the support of ``self``,
240
+ according to the term order.
241
+
242
+ If the term ordering of the basis elements is not what is
243
+ desired, a comparison key, ``key(x)``, can be provided.
244
+
245
+ EXAMPLES::
246
+
247
+ sage: R.<x,y,z> = PolynomialRing(QQ)
248
+ sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_support()
249
+ (1, 1, 1)
250
+ sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
251
+ sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_support()
252
+ (0, 1, 3)
253
+ sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
254
+ sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_support()
255
+ (1, 2, 0)
256
+ """
257
+ if 'key' in kwds:
258
+ return min(self.support(), *args, **kwds)
259
+ kwds['key'] = self._parent.term_order().sortkey
260
+ return min(self.support(), *args, **kwds)
261
+
262
+ def coefficients(self):
263
+ r"""
264
+ Return the nonzero coefficients of this polynomial in a list.
265
+
266
+ The returned list is decreasingly ordered by the term ordering
267
+ of ``self.parent()``, i.e. the list of coefficients matches the list
268
+ of monomials returned by
269
+ :meth:`sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular.monomials`.
270
+
271
+ EXAMPLES::
272
+
273
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3, order='degrevlex')
274
+ sage: f = 23*x^6*y^7 + x^3*y+6*x^7*z
275
+ sage: f.coefficients()
276
+ [23, 6, 1]
277
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3, order='lex')
278
+ sage: f = 23*x^6*y^7 + x^3*y+6*x^7*z
279
+ sage: f.coefficients()
280
+ [6, 23, 1]
281
+
282
+ Test the same stuff with base ring `\ZZ` -- different implementation::
283
+
284
+ sage: R.<x,y,z> = PolynomialRing(ZZ, 3, order='degrevlex')
285
+ sage: f = 23*x^6*y^7 + x^3*y+6*x^7*z
286
+ sage: f.coefficients()
287
+ [23, 6, 1]
288
+ sage: R.<x,y,z> = PolynomialRing(ZZ, 3, order='lex')
289
+ sage: f = 23*x^6*y^7 + x^3*y+6*x^7*z
290
+ sage: f.coefficients()
291
+ [6, 23, 1]
292
+
293
+ AUTHOR:
294
+
295
+ - Didier Deshommes
296
+ """
297
+ d = self.monomial_coefficients()
298
+ return [d[i] for i in self.exponents()]
299
+
300
+ def truncate(self, var, n):
301
+ r"""
302
+ Return a new multivariate polynomial obtained from ``self`` by
303
+ deleting all terms that involve the given variable to a power
304
+ at least ``n``.
305
+ """
306
+ cdef int ind
307
+ R = self.parent()
308
+ G = R.gens()
309
+ Z = list(G)
310
+ try:
311
+ ind = Z.index(var)
312
+ except ValueError:
313
+ raise ValueError("var must be one of the generators of the parent polynomial ring.")
314
+ return R({k: c for k, c in self.monomial_coefficients().items()
315
+ if k[ind] < n})
316
+
317
+ def _fast_callable_(self, etb):
318
+ r"""
319
+ Given an :class:`ExpressionTreeBuilder`, return an :class:`Expression` representing
320
+ this value.
321
+
322
+ EXAMPLES::
323
+
324
+ sage: from sage.ext.fast_callable import ExpressionTreeBuilder
325
+ sage: etb = ExpressionTreeBuilder(vars=['x','y','z'])
326
+ sage: K.<x,y,z> = QQ[]
327
+ sage: v = -6/5*x*y*z + 2*y*z^2 - x
328
+ sage: v._fast_callable_(etb)
329
+ add(add(add(0, mul(-6/5, mul(mul(ipow(v_0, 1), ipow(v_1, 1)), ipow(v_2, 1)))), mul(2, mul(ipow(v_1, 1), ipow(v_2, 2)))), mul(-1, ipow(v_0, 1)))
330
+
331
+ TESTS::
332
+
333
+ sage: v = K(0)
334
+ sage: vf = fast_callable(v)
335
+ sage: type(v(0r, 0r, 0r))
336
+ <class 'sage.rings.rational.Rational'>
337
+ sage: type(vf(0r, 0r, 0r))
338
+ <class 'sage.rings.rational.Rational'>
339
+ sage: K.<x,y,z> = QQ[]
340
+ sage: from sage.ext.fast_eval import fast_float
341
+ sage: fast_float(K(0)).op_list()
342
+ [('load_const', 0.0), 'return']
343
+ sage: fast_float(K(17)).op_list()
344
+ [('load_const', 0.0), ('load_const', 17.0), 'add', 'return']
345
+ sage: fast_float(y).op_list()
346
+ [('load_const', 0.0), ('load_const', 1.0), ('load_arg', 1), ('ipow', 1), 'mul', 'add', 'return']
347
+ """
348
+ my_vars = self.parent().variable_names()
349
+ x = [etb.var(v) for v in my_vars]
350
+ n = len(x)
351
+
352
+ expr = etb.constant(self.base_ring().zero())
353
+ for m, c in self.monomial_coefficients().items():
354
+ monom = prod([x[i] ** m[i] for i in range(n) if m[i] != 0],
355
+ etb.constant(c))
356
+ expr = expr + monom
357
+ return expr
358
+
359
+ def derivative(self, *args):
360
+ r"""
361
+ The formal derivative of this polynomial, with respect to
362
+ variables supplied in ``args``.
363
+
364
+ Multiple variables and iteration counts may be supplied; see
365
+ documentation for the global function :func:`derivative` for more details.
366
+
367
+ .. SEEALSO:: :meth:`._derivative`
368
+
369
+ EXAMPLES:
370
+
371
+ Polynomials implemented via Singular::
372
+
373
+ sage: # needs sage.libs.singular
374
+ sage: R.<x, y> = PolynomialRing(FiniteField(5))
375
+ sage: f = x^3*y^5 + x^7*y
376
+ sage: type(f)
377
+ <class 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>
378
+ sage: f.derivative(x)
379
+ 2*x^6*y - 2*x^2*y^5
380
+ sage: f.derivative(y)
381
+ x^7
382
+
383
+ Generic multivariate polynomials::
384
+
385
+ sage: R.<t> = PowerSeriesRing(QQ)
386
+ sage: S.<x, y> = PolynomialRing(R)
387
+ sage: f = (t^2 + O(t^3))*x^2*y^3 + (37*t^4 + O(t^5))*x^3
388
+ sage: type(f)
389
+ <class 'sage.rings.polynomial.multi_polynomial_element.MPolynomial_polydict'>
390
+ sage: f.derivative(x) # with respect to x
391
+ (2*t^2 + O(t^3))*x*y^3 + (111*t^4 + O(t^5))*x^2
392
+ sage: f.derivative(y) # with respect to y
393
+ (3*t^2 + O(t^3))*x^2*y^2
394
+ sage: f.derivative(t) # with respect to t (recurses into base ring)
395
+ (2*t + O(t^2))*x^2*y^3 + (148*t^3 + O(t^4))*x^3
396
+ sage: f.derivative(x, y) # with respect to x and then y
397
+ (6*t^2 + O(t^3))*x*y^2
398
+ sage: f.derivative(y, 3) # with respect to y three times
399
+ (6*t^2 + O(t^3))*x^2
400
+ sage: f.derivative() # can't figure out the variable
401
+ Traceback (most recent call last):
402
+ ...
403
+ ValueError: must specify which variable to differentiate with respect to
404
+
405
+ Polynomials over the symbolic ring (just for fun....)::
406
+
407
+ sage: # needs sage.symbolic
408
+ sage: x = var("x")
409
+ sage: S.<u, v> = PolynomialRing(SR)
410
+ sage: f = u*v*x
411
+ sage: f.derivative(x) == u*v
412
+ True
413
+ sage: f.derivative(u) == v*x
414
+ True
415
+ """
416
+ return multi_derivative(self, args)
417
+
418
+ def polynomial(self, var):
419
+ r"""
420
+ Let ``var`` be one of the variables of the parent of ``self``. This
421
+ returns ``self`` viewed as a univariate polynomial in ``var`` over the
422
+ polynomial ring generated by all the other variables of the parent.
423
+
424
+ EXAMPLES::
425
+
426
+ sage: R.<x,w,z> = QQ[]
427
+ sage: f = x^3 + 3*w*x + w^5 + (17*w^3)*x + z^5
428
+ sage: f.polynomial(x)
429
+ x^3 + (17*w^3 + 3*w)*x + w^5 + z^5
430
+ sage: parent(f.polynomial(x))
431
+ Univariate Polynomial Ring in x
432
+ over Multivariate Polynomial Ring in w, z over Rational Field
433
+
434
+ sage: f.polynomial(w)
435
+ w^5 + 17*x*w^3 + 3*x*w + z^5 + x^3
436
+ sage: f.polynomial(z)
437
+ z^5 + w^5 + 17*x*w^3 + x^3 + 3*x*w
438
+ sage: R.<x,w,z,k> = ZZ[]
439
+ sage: f = x^3 + 3*w*x + w^5 + (17*w^3)*x + z^5 +x*w*z*k + 5
440
+ sage: f.polynomial(x)
441
+ x^3 + (17*w^3 + w*z*k + 3*w)*x + w^5 + z^5 + 5
442
+ sage: f.polynomial(w)
443
+ w^5 + 17*x*w^3 + (x*z*k + 3*x)*w + z^5 + x^3 + 5
444
+ sage: f.polynomial(z)
445
+ z^5 + x*w*k*z + w^5 + 17*x*w^3 + x^3 + 3*x*w + 5
446
+ sage: f.polynomial(k)
447
+ x*w*z*k + w^5 + z^5 + 17*x*w^3 + x^3 + 3*x*w + 5
448
+ sage: R.<x,y> = GF(5)[]
449
+ sage: f = x^2 + x + y
450
+ sage: f.polynomial(x)
451
+ x^2 + x + y
452
+ sage: f.polynomial(y)
453
+ y + x^2 + x
454
+ """
455
+ cdef int ind
456
+ R = self._parent
457
+ cdef list Z = list(R.gens())
458
+ cdef Py_ssize_t i
459
+ cdef dict c, w
460
+ cdef list v
461
+ try:
462
+ ind = Z.index(var)
463
+ except ValueError:
464
+ raise ValueError("var must be one of the generators of the parent polynomial ring")
465
+
466
+ if len(Z) <= 1:
467
+ return self.univariate_polynomial()
468
+
469
+ del Z[ind]
470
+
471
+ # Make polynomial ring over all variables except var.
472
+ S = PolynomialRing(R.base_ring(), Z)
473
+ ring = S[var]
474
+ if not self:
475
+ return ring(0)
476
+
477
+ d = self.degree(var)
478
+ B = ring.base_ring()
479
+ w = {remove_from_tuple(e, ind): val
480
+ for e, val in self.monomial_coefficients().items() if not e[ind]}
481
+ v = [B(w)] # coefficients that don't involve var
482
+ z = var
483
+ for i in range(1, d+1):
484
+ c = <dict> self.coefficient(z).monomial_coefficients()
485
+ w = {remove_from_tuple(e, ind): val for e, val in c.items()}
486
+ v.append(B(w))
487
+ z *= var
488
+ return ring(v)
489
+
490
+ cpdef dict _mpoly_dict_recursive(self, tuple vars=None, base_ring=None):
491
+ r"""
492
+ Return a ``dict`` of coefficient entries suitable for construction
493
+ of a ``MPolynomial_polydict`` with the given variables.
494
+
495
+ EXAMPLES::
496
+
497
+ sage: R = Integers(10)['x,y,z']['t,s']
498
+ sage: t,s = R.gens()
499
+ sage: x,y,z = R.base_ring().gens()
500
+ sage: (x+y+2*z*s+3*t)._mpoly_dict_recursive(('z','t','s'))
501
+ {(0, 0, 0): x + y, (0, 1, 0): 3, (1, 0, 1): 2}
502
+
503
+ TESTS::
504
+
505
+ sage: # needs sage.rings.padics
506
+ sage: R = Qp(7)['x,y,z,t,p']; S = ZZ['x,z,t']['p']
507
+ sage: R(S.0)
508
+ p
509
+ sage: R = QQ['x,y,z,t,p']; S = ZZ['x']['y,z,t']['p']
510
+ sage: z = S.base_ring().gen(1)
511
+ sage: R(z)
512
+ z
513
+ sage: R = QQ['x,y,z,t,p']; S = ZZ['x']['y,z,t']['p']
514
+ sage: z = S.base_ring().gen(1); p = S.0; x = S.base_ring().base_ring().gen()
515
+ sage: R(z+p)
516
+ z + p
517
+ sage: R = Qp(7)['x,y,z,p']; S = ZZ['x']['y,z,t']['p'] # shouldn't work, but should throw a better error
518
+ sage: R(S.0)
519
+ p
520
+
521
+ See :issue:`2601`::
522
+
523
+ sage: R.<a,b,c> = PolynomialRing(QQ, 3)
524
+ sage: a._mpoly_dict_recursive(('c', 'b', 'a'))
525
+ {(0, 0, 1): 1}
526
+ sage: testR.<a,b,c> = PolynomialRing(QQ,3)
527
+ sage: id_ringA = ideal([a^2 - b, b^2 - c, c^2 - a])
528
+ sage: id_ringB = ideal(id_ringA.gens()).change_ring(PolynomialRing(QQ,'c,b,a'))
529
+ """
530
+ if not self:
531
+ return {}
532
+
533
+ if vars is None:
534
+ vars = self._parent.variable_names_recursive()
535
+ cdef tuple my_vars = self._parent.variable_names()
536
+ if vars == my_vars:
537
+ return <dict> self.monomial_coefficients()
538
+ elif my_vars[-1] not in vars:
539
+ x = base_ring(self) if base_ring is not None else self
540
+ const_ix = ETuple((0,)*len(vars))
541
+ return {const_ix: x}
542
+ elif not set(my_vars).issubset(set(vars)):
543
+ # we need to split it up
544
+ p = self.polynomial(self._parent.gen(len(my_vars)-1))
545
+ if not isinstance(p, MPolynomial):
546
+ # Not a multivariate polynomial, so it must be a univariate
547
+ return (<Polynomial> p)._mpoly_dict_recursive(vars, base_ring)
548
+ return (<MPolynomial> p)._mpoly_dict_recursive(vars, base_ring)
549
+
550
+ cdef dict D = {}
551
+ cdef list mapping = [vars.index(z) for z in my_vars]
552
+ cdef list new_map
553
+ cdef Py_ssize_t m = min(mapping)
554
+ cdef tuple prev_vars = vars[:m]
555
+ cdef list tmp
556
+ cdef ETuple postfix
557
+ cdef Py_ssize_t k
558
+ cdef dict mpoly
559
+ if prev_vars:
560
+ new_map = list(mapping)
561
+ for k in range(len(mapping)):
562
+ new_map[k] -= m
563
+ tmp = [0] * (len(vars) - m)
564
+ try:
565
+ for ix, a in self.monomial_coefficients().items():
566
+ for k in range(len(my_vars)):
567
+ tmp[new_map[k]] = ix[k]
568
+ postfix = ETuple(tmp)
569
+ mpoly = <dict> a._mpoly_dict_recursive(prev_vars, base_ring)
570
+ for prefix, b in mpoly.items():
571
+ D[prefix + postfix] = b
572
+ return D
573
+
574
+ except AttributeError:
575
+ pass
576
+
577
+ if base_ring is self.base_ring():
578
+ base_ring = None
579
+
580
+ tmp = [0] * len(vars)
581
+ for ix, a in self.monomial_coefficients().items():
582
+ for k in range(len(my_vars)):
583
+ tmp[mapping[k]] = ix[k]
584
+ if base_ring is not None:
585
+ a = base_ring(a)
586
+ D[ETuple(tmp)] = a
587
+ return D
588
+
589
+ cdef long _hash_c(self) except -1:
590
+ r"""
591
+ This hash incorporates the variable name in an effort to respect the obvious inclusions
592
+ into multi-variable polynomial rings.
593
+
594
+ The tuple algorithm is borrowed from http://effbot.org/zone/python-hash.htm.
595
+
596
+ EXAMPLES::
597
+
598
+ sage: T.<y>=QQ[]
599
+ sage: R.<x>=ZZ[]
600
+ sage: S.<x,y>=ZZ[]
601
+ sage: hash(S.0)==hash(R.0) # respect inclusions into mpoly rings (with matching base rings)
602
+ True
603
+ sage: hash(S.1)==hash(T.0) # respect inclusions into mpoly rings (with unmatched base rings)
604
+ True
605
+ sage: hash(S(12))==hash(12) # respect inclusions of the integers into an mpoly ring
606
+ True
607
+ sage: # the point is to make for more flexible dictionary look ups
608
+ sage: d={S.0:12}
609
+ sage: d[R.0]
610
+ 12
611
+ sage: # or, more to the point, make subs in fraction field elements work
612
+ sage: f=x/y
613
+ sage: f.subs({x:1})
614
+ 1/y
615
+
616
+ TESTS:
617
+
618
+ Verify that :issue:`16251` has been resolved, i.e., polynomials with
619
+ unhashable coefficients are unhashable::
620
+
621
+ sage: K.<a> = Qq(9) # needs sage.rings.padics
622
+ sage: R.<t,s> = K[] # needs sage.rings.padics
623
+ sage: hash(t) # needs sage.rings.padics
624
+ Traceback (most recent call last):
625
+ ...
626
+ TypeError: ...unhashable type: 'sage.rings.padics.qadic_flint_CR.qAdicCappedRelativeElement'...
627
+ """
628
+ cdef long result = 0 # store it in a c-int and just let the overflowing additions wrap
629
+ cdef long result_mon
630
+ var_name_hash = [hash(v) for v in self._parent.variable_names()]
631
+ cdef long c_hash
632
+ for m, c in self.monomial_coefficients().items():
633
+ # I'm assuming (incorrectly) that hashes of zero indicate that the element is 0.
634
+ # This assumption is not true, but I think it is true enough for the purposes and it
635
+ # it allows us to write fast code that omits terms with 0 coefficients. This is
636
+ # important if we want to maintain the '==' relationship with sparse polys.
637
+ c_hash = hash(c)
638
+ if c_hash != 0: # this is always going to be true, because we are sparse (correct?)
639
+ # Hash (self[i], gen_a, exp_a, gen_b, exp_b, gen_c, exp_c, ...) as a tuple according to the algorithm.
640
+ # I omit gen,exp pairs where the exponent is zero.
641
+ result_mon = c_hash
642
+ for p in m.nonzero_positions():
643
+ result_mon = (1000003 * result_mon) ^ var_name_hash[p]
644
+ result_mon = (1000003 * result_mon) ^ m[p]
645
+ result += result_mon
646
+ if result == -1:
647
+ return -2
648
+ return result
649
+
650
+ # you may have to replicate this boilerplate code in derived classes if you override
651
+ # __richcmp__. The python documentation at https://docs.python.org/api/type-structs.html
652
+ # explains how __richcmp__, __hash__, and __cmp__ are tied together.
653
+ def __hash__(self):
654
+ return self._hash_c()
655
+
656
+ def args(self):
657
+ r"""
658
+ Return the names of the arguments of ``self``, in the
659
+ order they are accepted from call.
660
+
661
+ EXAMPLES::
662
+
663
+ sage: R.<x,y> = ZZ[]
664
+ sage: x.args()
665
+ (x, y)
666
+ """
667
+ return self._parent.gens()
668
+
669
+ def homogenize(self, var='h'):
670
+ r"""
671
+ Return the homogenization of this polynomial.
672
+
673
+ The polynomial itself is returned if it is homogeneous already.
674
+ Otherwise, the monomials are multiplied with the smallest powers of
675
+ ``var`` such that they all have the same total degree.
676
+
677
+ INPUT:
678
+
679
+ - ``var`` -- a variable in the polynomial ring (as a string, an element of
680
+ the ring, or a zero-based index in the list of variables) or a name
681
+ for a new variable (default: ``'h'``)
682
+
683
+ OUTPUT:
684
+
685
+ If ``var`` specifies a variable in the polynomial ring, then a
686
+ homogeneous element in that ring is returned. Otherwise, a homogeneous
687
+ element is returned in a polynomial ring with an extra last variable
688
+ ``var``.
689
+
690
+ EXAMPLES::
691
+
692
+ sage: R.<x,y> = QQ[]
693
+ sage: f = x^2 + y + 1 + 5*x*y^10
694
+ sage: f.homogenize()
695
+ 5*x*y^10 + x^2*h^9 + y*h^10 + h^11
696
+
697
+ The parameter ``var`` can be used to specify the name of the variable::
698
+
699
+ sage: g = f.homogenize('z'); g
700
+ 5*x*y^10 + x^2*z^9 + y*z^10 + z^11
701
+ sage: g.parent()
702
+ Multivariate Polynomial Ring in x, y, z over Rational Field
703
+
704
+ However, if the polynomial is homogeneous already, then that parameter
705
+ is ignored and no extra variable is added to the polynomial ring::
706
+
707
+ sage: f = x^2 + y^2
708
+ sage: g = f.homogenize('z'); g
709
+ x^2 + y^2
710
+ sage: g.parent()
711
+ Multivariate Polynomial Ring in x, y over Rational Field
712
+
713
+ If you want the ring of the result to be independent of whether the
714
+ polynomial is homogenized, you can use ``var`` to use an existing
715
+ variable to homogenize::
716
+
717
+ sage: R.<x,y,z> = QQ[]
718
+ sage: f = x^2 + y^2
719
+ sage: g = f.homogenize(z); g
720
+ x^2 + y^2
721
+ sage: g.parent()
722
+ Multivariate Polynomial Ring in x, y, z over Rational Field
723
+ sage: f = x^2 - y
724
+ sage: g = f.homogenize(z); g
725
+ x^2 - y*z
726
+ sage: g.parent()
727
+ Multivariate Polynomial Ring in x, y, z over Rational Field
728
+
729
+ The parameter ``var`` can also be given as a zero-based index in the
730
+ list of variables::
731
+
732
+ sage: g = f.homogenize(2); g
733
+ x^2 - y*z
734
+
735
+ If the variable specified by ``var`` is not present in the polynomial,
736
+ then setting it to 1 yields the original polynomial::
737
+
738
+ sage: g(x,y,1)
739
+ x^2 - y
740
+
741
+ If it is present already, this might not be the case::
742
+
743
+ sage: g = f.homogenize(x); g
744
+ x^2 - x*y
745
+ sage: g(1,y,z)
746
+ -y + 1
747
+
748
+ In particular, this can be surprising in positive characteristic::
749
+
750
+ sage: R.<x,y> = GF(2)[]
751
+ sage: f = x + 1
752
+ sage: f.homogenize(x)
753
+ 0
754
+
755
+ TESTS::
756
+
757
+ sage: R = PolynomialRing(QQ, 'x', 5)
758
+ sage: p = R.random_element()
759
+ sage: q1 = p.homogenize()
760
+ sage: q2 = p.homogenize()
761
+ sage: q1.parent() is q2.parent()
762
+ True
763
+ """
764
+ P = self.parent()
765
+
766
+ if self.is_homogeneous():
767
+ return self
768
+
769
+ if isinstance(var, str):
770
+ V = list(P.variable_names())
771
+ try:
772
+ i = V.index(var)
773
+ return self._homogenize(i)
774
+ except ValueError:
775
+ P = PolynomialRing(P.base_ring(), len(V)+1, V + [var], order=P.term_order())
776
+ return P(self)._homogenize(len(V))
777
+
778
+ elif isinstance(var, MPolynomial) and \
779
+ ((<MPolynomial>var)._parent is P or (<MPolynomial>var)._parent == P):
780
+ V = list(P.gens())
781
+ try:
782
+ i = V.index(var)
783
+ return self._homogenize(i)
784
+ except ValueError:
785
+ P = P.change_ring(names=P.variable_names() + [str(var)])
786
+ return P(self)._homogenize(len(V))
787
+
788
+ elif isinstance(var, (int, Integer)):
789
+ if 0 <= var < P.ngens():
790
+ return self._homogenize(var)
791
+ else:
792
+ raise TypeError("Variable index %d must be < parent(self).ngens()." % var)
793
+ else:
794
+ raise TypeError("Parameter var must be either a variable, a string or an integer.")
795
+
796
+ def is_homogeneous(self):
797
+ r"""
798
+ Return ``True`` if ``self`` is a homogeneous polynomial.
799
+
800
+ TESTS::
801
+
802
+ sage: from sage.rings.polynomial.multi_polynomial import MPolynomial
803
+ sage: P.<x, y> = PolynomialRing(QQ, 2)
804
+ sage: MPolynomial.is_homogeneous(x+y)
805
+ True
806
+ sage: MPolynomial.is_homogeneous(P(0))
807
+ True
808
+ sage: MPolynomial.is_homogeneous(x+y^2)
809
+ False
810
+ sage: MPolynomial.is_homogeneous(x^2 + y^2)
811
+ True
812
+ sage: MPolynomial.is_homogeneous(x^2 + y^2*x)
813
+ False
814
+ sage: MPolynomial.is_homogeneous(x^2*y + y^2*x)
815
+ True
816
+
817
+ .. NOTE::
818
+
819
+ This is a generic implementation which is likely overridden by
820
+ subclasses.
821
+ """
822
+ M = self.monomials()
823
+ if M == []:
824
+ return True
825
+ d = M.pop().degree()
826
+ for m in M:
827
+ if m.degree() != d:
828
+ return False
829
+ else:
830
+ return True
831
+
832
+ def homogeneous_components(self):
833
+ r"""
834
+ Return the homogeneous components of this polynomial.
835
+
836
+ OUTPUT: a dictionary mapping degrees to homogeneous polynomials
837
+
838
+ EXAMPLES::
839
+
840
+ sage: R.<x,y> = QQ[]
841
+ sage: (x^3 + 2*x*y^3 + 4*y^3 + y).homogeneous_components()
842
+ {1: y, 3: x^3 + 4*y^3, 4: 2*x*y^3}
843
+ sage: R.zero().homogeneous_components()
844
+ {}
845
+
846
+ In case of weighted term orders, the polynomials are homogeneous with
847
+ respect to the weights::
848
+
849
+ sage: S.<a,b,c> = PolynomialRing(ZZ, order=TermOrder('wdegrevlex', (1,2,3)))
850
+ sage: (a^6 + b^3 + b*c + a^2*c + c + a + 1).homogeneous_components()
851
+ {0: 1, 1: a, 3: c, 5: a^2*c + b*c, 6: a^6 + b^3}
852
+ """
853
+ cdef ETuple e
854
+ from collections import defaultdict
855
+ d = defaultdict(dict)
856
+ if self._parent.term_order()._weights:
857
+ for c, m in self:
858
+ d[m.degree()][m.exponents()[0]] = c
859
+ else:
860
+ # Otherwise it is unweighted, so we use a faster implementation
861
+ for e, c in self.iterator_exp_coeff():
862
+ d[e.unweighted_degree()][e] = c
863
+ return {k: self._parent(d[k]) for k in d}
864
+
865
+ cpdef _mod_(self, other):
866
+ r"""
867
+ EXAMPLES::
868
+
869
+ sage: R.<x,y> = PolynomialRing(QQ)
870
+ sage: f = (x^2*y + 2*x - 3)
871
+ sage: g = (x + 1)*f
872
+ sage: g % f # needs sage.libs.singular
873
+ 0
874
+
875
+ sage: (g+1) % f # needs sage.libs.singular
876
+ 1
877
+
878
+ sage: M = x*y
879
+ sage: N = x^2*y^3
880
+ sage: M.divides(N) # needs sage.libs.singular
881
+ True
882
+ """
883
+ try:
884
+ quo_rem = self.quo_rem
885
+ except AttributeError:
886
+ raise NotImplementedError
887
+ else:
888
+ _, r = quo_rem(other)
889
+ return r
890
+
891
+ def change_ring(self, R):
892
+ r"""
893
+ Return this polynomial with coefficients converted to ``R``.
894
+
895
+ INPUT:
896
+
897
+ - ``R`` -- a ring or morphism; if a morphism, the coefficients
898
+ are mapped to the codomain of ``R``
899
+
900
+ OUTPUT: a new polynomial with the base ring changed to ``R``
901
+
902
+ EXAMPLES::
903
+
904
+ sage: R.<x,y> = QQ[]
905
+ sage: f = x^3 + 3/5*y + 1
906
+ sage: f.change_ring(GF(7))
907
+ x^3 + 2*y + 1
908
+ sage: g = x^2 + 5*y
909
+ sage: g.change_ring(GF(5))
910
+ x^2
911
+
912
+ ::
913
+
914
+ sage: # needs sage.rings.finite_rings
915
+ sage: R.<x,y> = GF(9,'a')[]
916
+ sage: (x+2*y).change_ring(GF(3))
917
+ x - y
918
+
919
+ ::
920
+
921
+ sage: # needs sage.rings.finite_rings
922
+ sage: F.<a> = GF(7^2)
923
+ sage: R.<x,y> = F[]
924
+ sage: f = x^2 + a^2*y^2 + a*x + a^3*y
925
+ sage: g = f.change_ring(F.frobenius_endomorphism()); g
926
+ x^2 + (-a - 2)*y^2 + (-a + 1)*x + (2*a + 2)*y
927
+ sage: g.change_ring(F.frobenius_endomorphism()) == f
928
+ True
929
+
930
+ ::
931
+
932
+ sage: # needs sage.rings.number_field
933
+ sage: K.<z> = CyclotomicField(3)
934
+ sage: R.<x,y> = K[]
935
+ sage: f = x^2 + z*y
936
+ sage: f.change_ring(K.embeddings(CC)[1])
937
+ x^2 + (-0.500000000000000 - 0.866025403784438*I)*y
938
+
939
+ ::
940
+
941
+ sage: # needs sage.rings.number_field
942
+ sage: K.<w> = CyclotomicField(5)
943
+ sage: R.<x,y> = K[]
944
+ sage: f = x^2 + w*y
945
+ sage: f.change_ring(K.embeddings(QQbar)[1])
946
+ x^2 + (-0.8090169943749474? + 0.5877852522924731?*I)*y
947
+
948
+ TESTS:
949
+
950
+ Check that :issue:`25022` is fixed::
951
+
952
+ sage: # needs sage.rings.number_field sage.symbolic
953
+ sage: K.<x,y> = ZZ[]
954
+ sage: (x*y).change_ring(SR).monomials()
955
+ [x*y]
956
+
957
+ Check that :issue:`36832` is fixed::
958
+
959
+ sage: F = GF(11)
960
+ sage: phi = Hom(F,F).an_element()
961
+ sage: R.<x,y> = F[]
962
+ sage: x.change_ring(phi)
963
+ x
964
+ """
965
+ if isinstance(R, Map):
966
+ return self.map_coefficients(R)
967
+ return self.parent().change_ring(R)(self.monomial_coefficients())
968
+
969
+ def is_symmetric(self, group=None):
970
+ r"""
971
+ Return whether this polynomial is symmetric.
972
+
973
+ INPUT:
974
+
975
+ - ``group`` -- (default: symmetric group) if set, test whether the
976
+ polynomial is invariant with respect to the given permutation group
977
+
978
+ EXAMPLES::
979
+
980
+ sage: # needs sage.groups
981
+ sage: R.<x,y,z> = QQ[]
982
+ sage: p = (x+y+z)**2 - 3 * (x+y)*(x+z)*(y+z)
983
+ sage: p.is_symmetric()
984
+ True
985
+ sage: (x + y - z).is_symmetric()
986
+ False
987
+ sage: R.one().is_symmetric()
988
+ True
989
+ sage: p = (x-y)*(y-z)*(z-x)
990
+ sage: p.is_symmetric()
991
+ False
992
+ sage: p.is_symmetric(AlternatingGroup(3))
993
+ True
994
+
995
+ sage: R.<x,y> = QQ[]
996
+ sage: ((x + y)**2).is_symmetric() # needs sage.groups
997
+ True
998
+ sage: R.one().is_symmetric() # needs sage.groups
999
+ True
1000
+ sage: (x + 2*y).is_symmetric() # needs sage.groups
1001
+ False
1002
+
1003
+ An example with a GAP permutation group (here the quaternions)::
1004
+
1005
+ sage: R = PolynomialRing(QQ, 'x', 8)
1006
+ sage: x = R.gens()
1007
+ sage: p = sum(prod(x[i] for i in e)
1008
+ ....: for e in [(0,1,2), (0,1,7), (0,2,7), (1,2,7),
1009
+ ....: (3,4,5), (3,4,6), (3,5,6), (4,5,6)])
1010
+ sage: p.is_symmetric(libgap.TransitiveGroup(8, 5)) # needs gap_pkg_transgrp sage.groups
1011
+ True
1012
+ sage: p = sum(prod(x[i] for i in e)
1013
+ ....: for e in [(0,1,2), (0,1,7), (0,2,7), (1,2,7),
1014
+ ....: (3,4,5), (3,4,6), (3,5,6)])
1015
+ sage: p.is_symmetric(libgap.TransitiveGroup(8, 5)) # needs gap_pkg_transgrp sage.groups
1016
+ False
1017
+
1018
+ TESTS::
1019
+
1020
+ sage: R = PolynomialRing(QQ, 'x', 3)
1021
+ sage: R.one().is_symmetric(3) # needs sage.groups
1022
+ Traceback (most recent call last):
1023
+ ...
1024
+ ValueError: argument must be a permutation group
1025
+
1026
+ sage: R.one().is_symmetric(SymmetricGroup(4)) # needs sage.groups
1027
+ Traceback (most recent call last):
1028
+ ...
1029
+ ValueError: invalid data to initialize a permutation
1030
+ """
1031
+ n = self.parent().ngens()
1032
+ if n <= 1:
1033
+ return True
1034
+
1035
+ from sage.groups.perm_gps.permgroup_named import SymmetricGroup
1036
+ S = SymmetricGroup(n)
1037
+ if group is None:
1038
+ gens = S.gens()
1039
+ else:
1040
+ try:
1041
+ # for Sage group
1042
+ gens = group.gens()
1043
+ except AttributeError:
1044
+ # for GAP group
1045
+ try:
1046
+ gens = group.GeneratorsOfGroup()
1047
+ except AttributeError:
1048
+ raise ValueError("argument must be a permutation group")
1049
+ gens = [S(g) for g in gens]
1050
+
1051
+ cdef dict coeffs = self.monomial_coefficients()
1052
+ zero = self.base_ring().zero()
1053
+ return all(coeffs.get(g._act_on_etuple_on_position(e), zero) == coeff
1054
+ for e, coeff in coeffs.items() for g in gens)
1055
+
1056
+ def _gap_(self, gap):
1057
+ r"""
1058
+ Return a representation of ``self`` in the GAP interface.
1059
+
1060
+ INPUT:
1061
+
1062
+ - ``gap`` -- a GAP or libgap instance
1063
+
1064
+ TESTS:
1065
+
1066
+ Multivariate polynomial over integers::
1067
+
1068
+ sage: # needs sage.libs.gap
1069
+ sage: R.<x,y,z> = ZZ[]
1070
+ sage: gap(-x*y + 3*z) # indirect doctest
1071
+ -x*y+3*z
1072
+ sage: gap(R.zero()) # indirect doctest
1073
+ 0
1074
+ sage: (x+y+z)._gap_(libgap)
1075
+ x+y+z
1076
+
1077
+ sage: g = gap(x - y + 3*x*y*z) # needs sage.libs.gap
1078
+ sage: R(g) # needs sage.libs.gap
1079
+ 3*x*y*z + x - y
1080
+
1081
+ sage: g = libgap(5*x - y*z) # needs sage.libs.gap
1082
+ sage: R(g) # needs sage.libs.gap
1083
+ -y*z + 5*x
1084
+
1085
+ Multivariate polynomial over a cyclotomic field::
1086
+
1087
+ sage: # needs sage.libs.gap sage.rings.number_field
1088
+ sage: F.<zeta> = CyclotomicField(8)
1089
+ sage: P.<x,y> = F[]
1090
+ sage: p = zeta + zeta^2*x + zeta^3*y + (1+zeta)*x*y
1091
+ sage: gap(p) # indirect doctest
1092
+ (1+E(8))*x*y+E(4)*x+E(8)^3*y+E(8)
1093
+ sage: libgap(p) # indirect doctest
1094
+ (1+E(8))*x*y+E(4)*x+E(8)^3*y+E(8)
1095
+
1096
+ Multivariate polynomial over a polynomial ring over a cyclotomic field::
1097
+
1098
+ sage: # needs sage.libs.gap sage.rings.number_field
1099
+ sage: S.<z> = F[]
1100
+ sage: P.<x,y> = S[]
1101
+ sage: p = zeta + zeta^2*x*z + zeta^3*y*z^2 + (1+zeta)*x*y*z
1102
+ sage: gap(p) # indirect doctest
1103
+ ((1+E(8))*z)*x*y+E(4)*z*x+E(8)^3*z^2*y+E(8)
1104
+ sage: libgap(p) # indirect doctest
1105
+ ((1+E(8))*z)*x*y+E(4)*z*x+E(8)^3*z^2*y+E(8)
1106
+ """
1107
+ R = gap(self.parent())
1108
+ variables = R.IndeterminatesOfPolynomialRing()
1109
+ return self(*variables)
1110
+
1111
+ def _lean_init_(self):
1112
+ r"""
1113
+ Return polynomial as Lean mathlib input.
1114
+ """
1115
+ # as in https://github.com/leanprover-community/mathlib/blob/master/scripts/polyrith_sage_helper.py
1116
+ raise NotImplementedError
1117
+
1118
+ def _libgap_(self):
1119
+ r"""
1120
+ TESTS::
1121
+
1122
+ sage: R.<x,y,z> = ZZ[]
1123
+ sage: libgap(-x*y + 3*z) # indirect doctest # needs sage.libs.gap
1124
+ -x*y+3*z
1125
+ sage: libgap(R.zero()) # indirect doctest # needs sage.libs.gap
1126
+ 0
1127
+ """
1128
+ from sage.libs.gap.libgap import libgap
1129
+ return self._gap_(libgap)
1130
+
1131
+ def _magma_init_(self, magma):
1132
+ r"""
1133
+ Return a Magma string representation of ``self`` valid in the
1134
+ given magma session.
1135
+
1136
+ EXAMPLES::
1137
+
1138
+ sage: # optional - magma, needs sage.rings.finite_rings
1139
+ sage: k.<b> = GF(25); R.<x,y> = k[]
1140
+ sage: f = y*x^2*b + x*(b+1) + 1
1141
+ sage: magma = Magma() # so var names same below
1142
+ sage: magma(f)
1143
+ b*x^2*y + b^22*x + 1
1144
+ sage: f._magma_init_(magma)
1145
+ '_sage_[...]!((_sage_[...]!(_sage_[...]))*_sage_[...]^2*_sage_[...]+(_sage_[...]!(_sage_[...] + 1))*_sage_[...]+(_sage_[...]!(1))*1)'
1146
+
1147
+ A more complicated nested example::
1148
+
1149
+ sage: # optional - magma
1150
+ sage: R.<x,y> = QQ[]; S.<z,w> = R[]; f = (2/3)*x^3*z + w^2 + 5
1151
+ sage: f._magma_init_(magma)
1152
+ '_sage_[...]!((_sage_[...]!((1/1)*1))*_sage_[...]^2+(_sage_[...]!((2/3)*_sage_[...]^3))*_sage_[...]+(_sage_[...]!((5/1)*1))*1)'
1153
+ sage: magma(f)
1154
+ w^2 + 2/3*x^3*z + 5
1155
+ """
1156
+ R = magma(self.parent())
1157
+ g = R.gen_names()
1158
+ v = []
1159
+ for m, c in zip(self.monomials(), self.coefficients()):
1160
+ v.append('(%s)*%s' % (c._magma_init_(magma),
1161
+ m._repr_with_changed_varnames(g)))
1162
+ if len(v) == 0:
1163
+ s = '0'
1164
+ else:
1165
+ s = '+'.join(v)
1166
+
1167
+ return '%s!(%s)' % (R.name(), s)
1168
+
1169
+ def _giac_init_(self):
1170
+ r"""
1171
+ Return a Giac string representation of this polynomial.
1172
+
1173
+ TESTS::
1174
+
1175
+ sage: # needs giac
1176
+ sage: R.<x,y,z> = GF(101)['e,i'][]
1177
+ sage: f = R('e*i') * x + y^2
1178
+ sage: f._giac_init_()
1179
+ '((1)*1)*sageVARy^2+((1)*sageVARe*sageVARi)*sageVARx'
1180
+ sage: giac(f)
1181
+ sageVARy^2+sageVARe*sageVARi*sageVARx
1182
+ sage: giac(R.zero())
1183
+ 0
1184
+ """
1185
+ g = ['sageVAR' + x for x in self.parent().variable_names()]
1186
+ s = '+'.join('(%s)*%s' % (c._giac_init_(),
1187
+ m._repr_with_changed_varnames(g))
1188
+ for c, m in self)
1189
+ return s if s else '0'
1190
+
1191
+ def gradient(self):
1192
+ r"""
1193
+ Return a list of partial derivatives of this polynomial,
1194
+ ordered by the variables of ``self.parent()``.
1195
+
1196
+ EXAMPLES::
1197
+
1198
+ sage: P.<x,y,z> = PolynomialRing(ZZ, 3)
1199
+ sage: f = x*y + 1
1200
+ sage: f.gradient()
1201
+ [y, x, 0]
1202
+ """
1203
+ return [ self.derivative(var) for var in self.parent().gens() ]
1204
+
1205
+ def jacobian_ideal(self):
1206
+ r"""
1207
+ Return the Jacobian ideal of the polynomial ``self``.
1208
+
1209
+ EXAMPLES::
1210
+
1211
+ sage: R.<x,y,z> = QQ[]
1212
+ sage: f = x^3 + y^3 + z^3
1213
+ sage: f.jacobian_ideal()
1214
+ Ideal (3*x^2, 3*y^2, 3*z^2) of
1215
+ Multivariate Polynomial Ring in x, y, z over Rational Field
1216
+ """
1217
+ return self.parent().ideal(self.gradient())
1218
+
1219
+ def newton_polytope(self):
1220
+ r"""
1221
+ Return the Newton polytope of this polynomial.
1222
+
1223
+ EXAMPLES::
1224
+
1225
+ sage: R.<x,y> = QQ[]
1226
+ sage: f = 1 + x*y + x^3 + y^3
1227
+ sage: P = f.newton_polytope(); P # needs sage.geometry.polyhedron
1228
+ A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
1229
+ sage: P.is_simple() # needs sage.geometry.polyhedron
1230
+ True
1231
+
1232
+ TESTS::
1233
+
1234
+ sage: R.<x,y> = QQ[]
1235
+ sage: R(0).newton_polytope() # needs sage.geometry.polyhedron
1236
+ The empty polyhedron in ZZ^0
1237
+ sage: R(1).newton_polytope() # needs sage.geometry.polyhedron
1238
+ A 0-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex
1239
+ sage: R(x^2+y^2).newton_polytope().integral_points() # needs sage.geometry.polyhedron
1240
+ ((0, 2), (1, 1), (2, 0))
1241
+ """
1242
+ from sage.geometry.polyhedron.constructor import Polyhedron
1243
+ e = self.exponents()
1244
+ P = Polyhedron(vertices=e, base_ring=ZZ)
1245
+ return P
1246
+
1247
+ def __iter__(self):
1248
+ r"""
1249
+ Facilitates iterating over the monomials of ``self``,
1250
+ returning tuples of the form ``(coeff, mon)`` for each
1251
+ nonzero monomial.
1252
+
1253
+ EXAMPLES::
1254
+
1255
+ sage: P.<x,y,z> = PolynomialRing(QQ,3)
1256
+ sage: f = 3*x^3*y + 16*x + 7
1257
+ sage: [(c,m) for c,m in f]
1258
+ [(3, x^3*y), (16, x), (7, 1)]
1259
+ sage: f = P.random_element(12,14)
1260
+ sage: sum(c*m for c,m in f) == f
1261
+ True
1262
+ """
1263
+ for exp, coeff in self.iterator_exp_coeff():
1264
+ yield (coeff, self.monomial(exp))
1265
+
1266
+ def iterator_exp_coeff(self, as_ETuples=True):
1267
+ r"""
1268
+ Iterate over ``self`` as pairs of ((E)Tuple, coefficient).
1269
+
1270
+ INPUT:
1271
+
1272
+ - ``as_ETuples`` -- boolean (default: ``True``); if ``True``, iterate over
1273
+ pairs whose first element is an :class:`ETuple`, otherwise as a tuples
1274
+
1275
+ EXAMPLES::
1276
+
1277
+ sage: R.<a,b,c> = QQ[]
1278
+ sage: f = a*c^3 + a^2*b + 2*b^4
1279
+ sage: list(f.iterator_exp_coeff())
1280
+ [((0, 4, 0), 2), ((1, 0, 3), 1), ((2, 1, 0), 1)]
1281
+ sage: list(f.iterator_exp_coeff(as_ETuples=False))
1282
+ [((0, 4, 0), 2), ((1, 0, 3), 1), ((2, 1, 0), 1)]
1283
+
1284
+ sage: R.<a,b,c> = PolynomialRing(QQ, 3, order='lex')
1285
+ sage: f = a*c^3 + a^2*b + 2*b^4
1286
+ sage: list(f.iterator_exp_coeff())
1287
+ [((2, 1, 0), 1), ((1, 0, 3), 1), ((0, 4, 0), 2)]
1288
+ """
1289
+ for exp in self.exponents():
1290
+ yield (exp, self.monomial_coefficient(exp))
1291
+
1292
+ def content(self):
1293
+ r"""
1294
+ Return the content of this polynomial. Here, we define content as
1295
+ the gcd of the coefficients in the base ring.
1296
+
1297
+ .. SEEALSO::
1298
+
1299
+ :meth:`content_ideal`
1300
+
1301
+ EXAMPLES::
1302
+
1303
+ sage: R.<x,y> = ZZ[]
1304
+ sage: f = 4*x+6*y
1305
+ sage: f.content()
1306
+ 2
1307
+ sage: f.content().parent()
1308
+ Integer Ring
1309
+
1310
+ TESTS:
1311
+
1312
+ Since :issue:`10771`, the gcd in QQ restricts to the gcd in ZZ::
1313
+
1314
+ sage: R.<x,y> = QQ[]
1315
+ sage: f = 4*x+6*y
1316
+ sage: f.content(); f.content().parent()
1317
+ 2
1318
+ Rational Field
1319
+ """
1320
+ from sage.arith.misc import GCD as gcd
1321
+ return gcd(self.coefficients())
1322
+
1323
+ def content_ideal(self):
1324
+ r"""
1325
+ Return the content ideal of this polynomial, defined as the ideal
1326
+ generated by its coefficients.
1327
+
1328
+ .. SEEALSO::
1329
+
1330
+ :meth:`content`
1331
+
1332
+ EXAMPLES::
1333
+
1334
+ sage: R.<x,y> = ZZ[]
1335
+ sage: f = 2*x*y + 6*x - 4*y + 2
1336
+ sage: f.content_ideal()
1337
+ Principal ideal (2) of Integer Ring
1338
+ sage: S.<z,t> = R[]
1339
+ sage: g = x*z + y*t
1340
+ sage: g.content_ideal()
1341
+ Ideal (x, y) of Multivariate Polynomial Ring in x, y over Integer Ring
1342
+ """
1343
+ return self.base_ring().ideal(self.coefficients())
1344
+
1345
+ def is_gen(self):
1346
+ r"""
1347
+ Return ``True`` if this polynomial is a generator of its parent.
1348
+
1349
+ EXAMPLES::
1350
+
1351
+ sage: R.<x,y> = ZZ[]
1352
+ sage: x.is_gen()
1353
+ True
1354
+ sage: (x + y - y).is_gen()
1355
+ True
1356
+ sage: (x*y).is_gen()
1357
+ False
1358
+ sage: R.<x,y> = QQ[]
1359
+ sage: x.is_gen()
1360
+ True
1361
+ sage: (x + y - y).is_gen()
1362
+ True
1363
+ sage: (x*y).is_gen()
1364
+ False
1365
+
1366
+ TESTS::
1367
+
1368
+ sage: R.<x,y> = ZZ[]
1369
+ sage: x.is_generator()
1370
+ doctest:warning...:
1371
+ DeprecationWarning: is_generator is deprecated. Please use is_gen instead.
1372
+ See https://github.com/sagemath/sage/issues/38942 for details.
1373
+ True
1374
+ """
1375
+ return self in self.parent().gens()
1376
+
1377
+ is_generator = deprecated_function_alias(38942, is_gen)
1378
+
1379
+ def map_coefficients(self, f, new_base_ring=None):
1380
+ r"""
1381
+ Return the polynomial obtained by applying ``f`` to the nonzero
1382
+ coefficients of ``self``.
1383
+
1384
+ If ``f`` is a :class:`sage.categories.map.Map`, then the resulting
1385
+ polynomial will be defined over the codomain of ``f``. Otherwise, the
1386
+ resulting polynomial will be over the same ring as ``self``. Set
1387
+ ``new_base_ring`` to override this behaviour.
1388
+
1389
+ INPUT:
1390
+
1391
+ - ``f`` -- a callable that will be applied to the coefficients of ``self``
1392
+
1393
+ - ``new_base_ring`` -- (optional) if given, the resulting polynomial
1394
+ will be defined over this ring
1395
+
1396
+ EXAMPLES::
1397
+
1398
+ sage: k.<a> = GF(9); R.<x,y> = k[]; f = x*a + 2*x^3*y*a + a # needs sage.rings.finite_rings
1399
+ sage: f.map_coefficients(lambda a: a + 1) # needs sage.rings.finite_rings
1400
+ (-a + 1)*x^3*y + (a + 1)*x + (a + 1)
1401
+
1402
+ Examples with different base ring::
1403
+
1404
+ sage: # needs sage.rings.finite_rings
1405
+ sage: R.<r> = GF(9); S.<s> = GF(81)
1406
+ sage: h = Hom(R,S)[0]; h
1407
+ Ring morphism:
1408
+ From: Finite Field in r of size 3^2
1409
+ To: Finite Field in s of size 3^4
1410
+ Defn: r |--> 2*s^3 + 2*s^2 + 1
1411
+ sage: T.<X,Y> = R[]
1412
+ sage: f = r*X + Y
1413
+ sage: g = f.map_coefficients(h); g
1414
+ (-s^3 - s^2 + 1)*X + Y
1415
+ sage: g.parent()
1416
+ Multivariate Polynomial Ring in X, Y over Finite Field in s of size 3^4
1417
+ sage: h = lambda x: x.trace()
1418
+ sage: g = f.map_coefficients(h); g
1419
+ X - Y
1420
+ sage: g.parent()
1421
+ Multivariate Polynomial Ring in X, Y over Finite Field in r of size 3^2
1422
+ sage: g = f.map_coefficients(h, new_base_ring=GF(3)); g
1423
+ X - Y
1424
+ sage: g.parent()
1425
+ Multivariate Polynomial Ring in X, Y over Finite Field of size 3
1426
+ """
1427
+ R = self.parent()
1428
+ if new_base_ring is not None:
1429
+ R = R.change_ring(new_base_ring)
1430
+ elif isinstance(f, Map):
1431
+ R = R.change_ring(f.codomain())
1432
+ return R({k: f(v) for k, v in self.monomial_coefficients().items()})
1433
+
1434
+ def _norm_over_nonprime_finite_field(self):
1435
+ r"""
1436
+ Given a multivariate polynomial over a nonprime finite field
1437
+ `\GF{p^e}`, compute the norm of the polynomial down to `\GF{p}`.
1438
+
1439
+ This is the product of the conjugates by the Frobenius action
1440
+ on coefficients, where Frobenius acts by `p`-th power.
1441
+
1442
+ This is (currently) an internal function used in factoring over finite
1443
+ fields.
1444
+
1445
+ EXAMPLES::
1446
+
1447
+ sage: # needs sage.rings.finite_rings
1448
+ sage: k.<a> = GF(9)
1449
+ sage: R.<x,y> = PolynomialRing(k)
1450
+ sage: f = (x-a) * (y-a)
1451
+ sage: f._norm_over_nonprime_finite_field()
1452
+ x^2*y^2 - x^2*y - x*y^2 - x^2 + x*y - y^2 + x + y + 1
1453
+ """
1454
+ P = self.parent()
1455
+ k = P.base_ring()
1456
+ if not k.is_field() and k.is_finite():
1457
+ raise TypeError("k must be a finite field")
1458
+ p = k.characteristic()
1459
+ e = k.degree()
1460
+ v = [self] + [self.map_coefficients(k.hom([k.gen()**(p**i)])) for i in range(1, e)]
1461
+ return prod(v).change_ring(k.prime_subfield())
1462
+
1463
+ def sylvester_matrix(self, right, variable=None):
1464
+ r"""
1465
+ Given two nonzero polynomials ``self`` and ``right``, return the Sylvester
1466
+ matrix of the polynomials with respect to a given variable.
1467
+
1468
+ Note that the Sylvester matrix is not defined if one of the polynomials
1469
+ is zero.
1470
+
1471
+ INPUT:
1472
+
1473
+ - ``self``, ``right`` -- multivariate polynomials
1474
+ - ``variable`` -- (optional) compute the Sylvester matrix with respect
1475
+ to this variable. If ``variable`` is not provided, the first variable
1476
+ of the polynomial ring is used.
1477
+
1478
+ OUTPUT: the Sylvester matrix of ``self`` and ``right``
1479
+
1480
+ EXAMPLES::
1481
+
1482
+ sage: R.<x, y> = PolynomialRing(ZZ)
1483
+ sage: f = (y + 1)*x + 3*x**2
1484
+ sage: g = (y + 2)*x + 4*x**2
1485
+ sage: M = f.sylvester_matrix(g, x) # needs sage.modules
1486
+ sage: M # needs sage.modules
1487
+ [ 3 y + 1 0 0]
1488
+ [ 0 3 y + 1 0]
1489
+ [ 4 y + 2 0 0]
1490
+ [ 0 4 y + 2 0]
1491
+
1492
+ If the polynomials share a non-constant common factor then the
1493
+ determinant of the Sylvester matrix will be zero::
1494
+
1495
+ sage: M.determinant() # needs sage.modules
1496
+ 0
1497
+
1498
+ sage: f.sylvester_matrix(1 + g, x).determinant() # needs sage.modules
1499
+ y^2 - y + 7
1500
+
1501
+ If both polynomials are of positive degree with respect to ``variable``, the
1502
+ determinant of the Sylvester matrix is the resultant::
1503
+
1504
+ sage: f = R.random_element(4) or (x^2 * y^2)
1505
+ sage: g = R.random_element(4) or (x^2 * y^2)
1506
+ sage: f.sylvester_matrix(g, x).determinant() == f.resultant(g, x) # needs sage.libs.singular sage.modules
1507
+ True
1508
+
1509
+ TESTS:
1510
+
1511
+ The variable is optional::
1512
+
1513
+ sage: f = x + y
1514
+ sage: g = x + y
1515
+ sage: f.sylvester_matrix(g) # needs sage.modules
1516
+ [1 y]
1517
+ [1 y]
1518
+
1519
+ Polynomials must be defined over compatible base rings::
1520
+
1521
+ sage: # needs sage.modules
1522
+ sage: K.<x, y> = QQ[]
1523
+ sage: f = x + y
1524
+ sage: L.<x, y> = ZZ[]
1525
+ sage: g = x + y
1526
+ sage: R.<x, y> = GF(25, 'a')[] # needs sage.rings.finite_rings
1527
+ sage: h = x + y
1528
+ sage: f.sylvester_matrix(g, 'x')
1529
+ [1 y]
1530
+ [1 y]
1531
+ sage: g.sylvester_matrix(h, 'x') # needs sage.rings.finite_rings
1532
+ [1 y]
1533
+ [1 y]
1534
+ sage: f.sylvester_matrix(h, 'x') # needs sage.rings.finite_rings
1535
+ Traceback (most recent call last):
1536
+ ...
1537
+ TypeError: no common canonical parent for objects with parents:
1538
+ 'Multivariate Polynomial Ring in x, y over Rational Field' and
1539
+ 'Multivariate Polynomial Ring in x, y over Finite Field in a of size 5^2'
1540
+ sage: K.<x, y, z> = QQ[]
1541
+ sage: f = x + y
1542
+ sage: L.<x, z> = QQ[]
1543
+ sage: g = x + z
1544
+ sage: f.sylvester_matrix(g)
1545
+ [1 y]
1546
+ [1 z]
1547
+
1548
+ Corner cases::
1549
+
1550
+ sage: # needs sage.modules
1551
+ sage: K.<x, y> = QQ[]
1552
+ sage: f = x^2 + 1
1553
+ sage: g = K(0)
1554
+ sage: f.sylvester_matrix(g)
1555
+ Traceback (most recent call last):
1556
+ ...
1557
+ ValueError: The Sylvester matrix is not defined for zero polynomials
1558
+ sage: g.sylvester_matrix(f)
1559
+ Traceback (most recent call last):
1560
+ ...
1561
+ ValueError: The Sylvester matrix is not defined for zero polynomials
1562
+ sage: g.sylvester_matrix(g)
1563
+ Traceback (most recent call last):
1564
+ ...
1565
+ ValueError: The Sylvester matrix is not defined for zero polynomials
1566
+ sage: K(3).sylvester_matrix(x^2)
1567
+ [3 0]
1568
+ [0 3]
1569
+ sage: K(3).sylvester_matrix(K(4))
1570
+ []
1571
+ """
1572
+
1573
+ # This code is almost exactly the same as that of
1574
+ # sylvester_matrix() in polynomial_element.pyx.
1575
+
1576
+ from sage.matrix.constructor import matrix
1577
+
1578
+ if self.parent() != right.parent():
1579
+ a, b = coercion_model.canonical_coercion(self,right)
1580
+ if variable:
1581
+ variable = a.parent()(variable)
1582
+ #We add the variable in case right is a multivariate polynomial
1583
+ return a.sylvester_matrix(b, variable)
1584
+
1585
+ if not variable:
1586
+ variable = self.parent().gen()
1587
+
1588
+ #coerce the variable to a polynomial
1589
+ if variable.parent() != self.parent():
1590
+ variable = self.parent()(variable)
1591
+
1592
+ if self.is_zero() or right.is_zero():
1593
+ raise ValueError("The Sylvester matrix is not defined for zero polynomials")
1594
+
1595
+ m = self.degree(variable)
1596
+ n = right.degree(variable)
1597
+
1598
+ M = matrix(self.parent(), m + n, m + n)
1599
+
1600
+ r = 0
1601
+ offset = 0
1602
+ for _ in range(n):
1603
+ for c in range(m, -1, -1):
1604
+ M[r, m - c + offset] = self.coefficient({variable:c})
1605
+ offset += 1
1606
+ r += 1
1607
+
1608
+ offset = 0
1609
+ for _ in range(m):
1610
+ for c in range(n, -1, -1):
1611
+ M[r, n - c + offset] = right.coefficient({variable:c})
1612
+ offset += 1
1613
+ r += 1
1614
+
1615
+ return M
1616
+
1617
+ def discriminant(self, variable):
1618
+ r"""
1619
+ Return the discriminant of ``self`` with respect to the given variable.
1620
+
1621
+ INPUT:
1622
+
1623
+ - ``variable`` -- the variable with respect to which we compute
1624
+ the discriminant
1625
+
1626
+ OUTPUT: an element of the base ring of the polynomial ring
1627
+
1628
+ EXAMPLES::
1629
+
1630
+ sage: R.<x,y,z> = QQ[]
1631
+ sage: f = 4*x*y^2 + 1/4*x*y*z + 3/2*x*z^2 - 1/2*z^2
1632
+ sage: f.discriminant(x) # needs sage.libs.singular
1633
+ 1
1634
+ sage: f.discriminant(y) # needs sage.libs.singular
1635
+ -383/16*x^2*z^2 + 8*x*z^2
1636
+ sage: f.discriminant(z) # needs sage.libs.singular
1637
+ -383/16*x^2*y^2 + 8*x*y^2
1638
+
1639
+ Note that, unlike the univariate case, the result lives in
1640
+ the same ring as the polynomial::
1641
+
1642
+ sage: R.<x,y> = QQ[]
1643
+ sage: f = x^5*y + 3*x^2*y^2 - 2*x + y - 1
1644
+ sage: f.discriminant(y) # needs sage.libs.singular
1645
+ x^10 + 2*x^5 + 24*x^3 + 12*x^2 + 1
1646
+ sage: f.polynomial(y).discriminant() # needs sage.libs.pari sage.modules
1647
+ x^10 + 2*x^5 + 24*x^3 + 12*x^2 + 1
1648
+ sage: f.discriminant(y).parent() == f.polynomial(y).discriminant().parent() # needs sage.libs.singular sage.modules
1649
+ False
1650
+
1651
+ TESTS:
1652
+
1653
+ Test polynomials over QQbar (:issue:`25265`)::
1654
+
1655
+ sage: # needs sage.rings.number_field
1656
+ sage: R.<x,y> = QQbar[]
1657
+ sage: f = x^5*y + 3*x^2*y^2 - 2*x + y - 1
1658
+ sage: f.discriminant(y) # needs sage.libs.singular
1659
+ x^10 + 2*x^5 + 24*x^3 + 12*x^2 + 1
1660
+
1661
+ AUTHOR: Miguel Marco
1662
+ """
1663
+ if self.is_zero():
1664
+ return self.parent().zero()
1665
+ n = self.degree(variable)
1666
+ d = self.derivative(variable)
1667
+ k = d.degree(variable)
1668
+
1669
+ r = n % 4
1670
+ u = -1 # (-1)**(n*(n-1)/2)
1671
+ if r == 0 or r == 1:
1672
+ u = 1
1673
+ an = self.coefficient(variable**n)**(n - k - 2)
1674
+ return self.parent()(u * self.resultant(d, variable) * an)
1675
+
1676
+ def subresultants(self, other, variable=None):
1677
+ r"""
1678
+ Return the nonzero subresultant polynomials of ``self`` and ``other``.
1679
+
1680
+ INPUT:
1681
+
1682
+ - ``other`` -- a polynomial
1683
+
1684
+ OUTPUT: list of polynomials in the same ring as ``self``
1685
+
1686
+ EXAMPLES::
1687
+
1688
+ sage: R.<x,y> = QQ[]
1689
+ sage: p = (y^2 + 6)*(x - 1) - y*(x^2 + 1)
1690
+ sage: q = (x^2 + 6)*(y - 1) - x*(y^2 + 1)
1691
+ sage: p.subresultants(q, y)
1692
+ [2*x^6 - 22*x^5 + 102*x^4 - 274*x^3 + 488*x^2 - 552*x + 288,
1693
+ -x^3 - x^2*y + 6*x^2 + 5*x*y - 11*x - 6*y + 6]
1694
+ sage: p.subresultants(q, x)
1695
+ [2*y^6 - 22*y^5 + 102*y^4 - 274*y^3 + 488*y^2 - 552*y + 288,
1696
+ x*y^2 + y^3 - 5*x*y - 6*y^2 + 6*x + 11*y - 6]
1697
+ """
1698
+ R = self.parent()
1699
+ if variable is None:
1700
+ x = R.gen(0)
1701
+ else:
1702
+ x = variable
1703
+ p = self.polynomial(x)
1704
+ q = other.polynomial(x)
1705
+ return [R(f) for f in p.subresultants(q)]
1706
+
1707
+ def macaulay_resultant(self, *args):
1708
+ r"""
1709
+ This is an implementation of the Macaulay resultant. It computes
1710
+ the resultant of universal polynomials as well as polynomials
1711
+ with constant coefficients. This is a project done in
1712
+ sage days 55. It's based on the implementation in Maple by
1713
+ Manfred Minimair, which in turn is based on the references [CLO], [Can], [Mac].
1714
+ It calculates the Macaulay resultant for a list of Polynomials,
1715
+ up to sign!
1716
+
1717
+ AUTHORS:
1718
+
1719
+ - Hao Chen, Solomon Vishkautsan (7-2014)
1720
+
1721
+ INPUT:
1722
+
1723
+ - ``args`` -- list of `n-1` homogeneous polynomials in `n` variables;
1724
+ works when ``args[0]`` is the list of polynomials, or ``args`` is
1725
+ itself the list of polynomials
1726
+
1727
+ OUTPUT: the Macaulay resultant
1728
+
1729
+ EXAMPLES:
1730
+
1731
+ The number of polynomials has to match the number of variables::
1732
+
1733
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
1734
+ sage: y.macaulay_resultant(x + z) # needs sage.modules
1735
+ Traceback (most recent call last):
1736
+ ...
1737
+ TypeError: number of polynomials(= 2) must equal number of variables (= 3)
1738
+
1739
+ The polynomials need to be all homogeneous::
1740
+
1741
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
1742
+ sage: y.macaulay_resultant([x + z, z + x^3]) # needs sage.modules
1743
+ Traceback (most recent call last):
1744
+ ...
1745
+ TypeError: resultant for non-homogeneous polynomials is not supported
1746
+
1747
+ All polynomials must be in the same ring::
1748
+
1749
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
1750
+ sage: S.<x,y> = PolynomialRing(QQ, 2)
1751
+ sage: y.macaulay_resultant(z + x, z) # needs sage.modules
1752
+ Traceback (most recent call last):
1753
+ ...
1754
+ TypeError: not all inputs are polynomials in the calling ring
1755
+
1756
+ The following example recreates Proposition 2.10 in Ch.3 of Using Algebraic Geometry::
1757
+
1758
+ sage: K.<x,y> = PolynomialRing(ZZ, 2)
1759
+ sage: flist, R = K._macaulay_resultant_universal_polynomials([1,1,2])
1760
+ sage: flist[0].macaulay_resultant(flist[1:]) # needs sage.modules
1761
+ u2^2*u4^2*u6 - 2*u1*u2*u4*u5*u6 + u1^2*u5^2*u6 - u2^2*u3*u4*u7 + u1*u2*u3*u5*u7
1762
+ + u0*u2*u4*u5*u7 - u0*u1*u5^2*u7 + u1*u2*u3*u4*u8 - u0*u2*u4^2*u8 - u1^2*u3*u5*u8
1763
+ + u0*u1*u4*u5*u8 + u2^2*u3^2*u9 - 2*u0*u2*u3*u5*u9 + u0^2*u5^2*u9
1764
+ - u1*u2*u3^2*u10 + u0*u2*u3*u4*u10 + u0*u1*u3*u5*u10 - u0^2*u4*u5*u10
1765
+ + u1^2*u3^2*u11 - 2*u0*u1*u3*u4*u11 + u0^2*u4^2*u11
1766
+
1767
+ The following example degenerates into the determinant of a `3\times 3` matrix::
1768
+
1769
+ sage: K.<x,y> = PolynomialRing(ZZ, 2)
1770
+ sage: flist, R = K._macaulay_resultant_universal_polynomials([1,1,1])
1771
+ sage: flist[0].macaulay_resultant(flist[1:]) # needs sage.modules
1772
+ -u2*u4*u6 + u1*u5*u6 + u2*u3*u7 - u0*u5*u7 - u1*u3*u8 + u0*u4*u8
1773
+
1774
+ The following example is by Patrick Ingram (:arxiv:`1310.4114`)::
1775
+
1776
+ sage: U = PolynomialRing(ZZ,'y',2); y0,y1 = U.gens()
1777
+ sage: R = PolynomialRing(U,'x',3); x0,x1,x2 = R.gens()
1778
+ sage: f0 = y0*x2^2 - x0^2 + 2*x1*x2
1779
+ sage: f1 = y1*x2^2 - x1^2 + 2*x0*x2
1780
+ sage: f2 = x0*x1 - x2^2
1781
+ sage: f0.macaulay_resultant(f1, f2) # needs sage.modules
1782
+ y0^2*y1^2 - 4*y0^3 - 4*y1^3 + 18*y0*y1 - 27
1783
+
1784
+ a simple example with constant rational coefficients::
1785
+
1786
+ sage: R.<x,y,z,w> = PolynomialRing(QQ, 4)
1787
+ sage: w.macaulay_resultant([z, y, x]) # needs sage.modules
1788
+ 1
1789
+
1790
+ an example where the resultant vanishes::
1791
+
1792
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
1793
+ sage: (x + y).macaulay_resultant([y^2, x]) # needs sage.modules
1794
+ 0
1795
+
1796
+ an example of bad reduction at a prime ``p = 5``::
1797
+
1798
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
1799
+ sage: y.macaulay_resultant([x^3 + 25*y^2*x, 5*z]) # needs sage.libs.pari sage.modules
1800
+ 125
1801
+
1802
+ The input can given as an unpacked list of polynomials::
1803
+
1804
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
1805
+ sage: y.macaulay_resultant(x^3 + 25*y^2*x, 5*z) # needs sage.libs.pari sage.modules
1806
+ 125
1807
+
1808
+ an example when the coefficients live in a finite field::
1809
+
1810
+ sage: F = FiniteField(11)
1811
+ sage: R.<x,y,z,w> = PolynomialRing(F, 4)
1812
+ sage: z.macaulay_resultant([x^3, 5*y, w]) # needs sage.modules sage.rings.finite_rings
1813
+ 4
1814
+
1815
+ example when the denominator in the algorithm vanishes(in this case
1816
+ the resultant is the constant term of the quotient of
1817
+ char polynomials of numerator/denominator)::
1818
+
1819
+ sage: R.<x,y,z> = PolynomialRing(QQ, 3)
1820
+ sage: y.macaulay_resultant([x + z, z^2]) # needs sage.libs.pari sage.modules
1821
+ -1
1822
+
1823
+ When there are only 2 polynomials, the Macaulay resultant degenerates to the traditional resultant::
1824
+
1825
+ sage: R.<x> = PolynomialRing(QQ, 1)
1826
+ sage: f = x^2 + 1; g = x^5 + 1
1827
+ sage: fh = f.homogenize()
1828
+ sage: gh = g.homogenize()
1829
+ sage: RH = fh.parent()
1830
+ sage: f.resultant(g) == fh.macaulay_resultant(gh) # needs sage.modules
1831
+ True
1832
+ """
1833
+ if len(args) == 1 and isinstance(args[0],list):
1834
+ return self.parent().macaulay_resultant(self, *args[0])
1835
+ return self.parent().macaulay_resultant(self, *args)
1836
+
1837
+ def denominator(self):
1838
+ r"""
1839
+ Return a denominator of ``self``.
1840
+
1841
+ First, the lcm of the denominators of the entries of ``self``
1842
+ is computed and returned. If this computation fails, the
1843
+ unit of the parent of ``self`` is returned.
1844
+
1845
+ Note that some subclasses may implement its own denominator
1846
+ function.
1847
+
1848
+ .. warning::
1849
+
1850
+ This is not the denominator of the rational function
1851
+ defined by ``self``, which would always be 1 since ``self`` is a
1852
+ polynomial.
1853
+
1854
+ EXAMPLES:
1855
+
1856
+ First we compute the denominator of a polynomial with
1857
+ integer coefficients, which is of course 1.
1858
+
1859
+ ::
1860
+
1861
+ sage: R.<x,y> = ZZ[]
1862
+ sage: f = x^3 + 17*y + x + y
1863
+ sage: f.denominator()
1864
+ 1
1865
+
1866
+ Next we compute the denominator of a polynomial over a number field.
1867
+
1868
+ ::
1869
+
1870
+ sage: # needs sage.rings.number_field sage.symbolic
1871
+ sage: R.<x,y> = NumberField(symbolic_expression(x^2+3),'a')['x,y']
1872
+ sage: f = (1/17)*x^19 + (1/6)*y - (2/3)*x + 1/3; f
1873
+ 1/17*x^19 - 2/3*x + 1/6*y + 1/3
1874
+ sage: f.denominator()
1875
+ 102
1876
+
1877
+ Finally, we try to compute the denominator of a polynomial with
1878
+ coefficients in the real numbers, which is a ring whose elements do
1879
+ not have a denominator method.
1880
+
1881
+ ::
1882
+
1883
+ sage: # needs sage.rings.real_mpfr
1884
+ sage: R.<a,b,c> = RR[]
1885
+ sage: f = a + b + RR('0.3'); f
1886
+ a + b + 0.300000000000000
1887
+ sage: f.denominator()
1888
+ 1.00000000000000
1889
+
1890
+ Check that the denominator is an element over the base whenever the base
1891
+ has no denominator function. This closes :issue:`9063`::
1892
+
1893
+ sage: R.<a,b,c> = GF(5)[]
1894
+ sage: x = R(0)
1895
+ sage: x.denominator()
1896
+ 1
1897
+ sage: type(x.denominator())
1898
+ <class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>
1899
+ sage: type(a.denominator())
1900
+ <class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>
1901
+ sage: from sage.rings.polynomial.multi_polynomial_element import MPolynomial
1902
+ sage: isinstance(a / b, MPolynomial)
1903
+ False
1904
+ sage: isinstance(a.numerator() / a.denominator(), MPolynomial)
1905
+ True
1906
+ """
1907
+ if self.degree() == -1:
1908
+ return self.base_ring().one()
1909
+ x = self.coefficients()
1910
+ try:
1911
+ d = x[0].denominator()
1912
+ for y in x:
1913
+ d = d.lcm(y.denominator())
1914
+ return d
1915
+ except AttributeError:
1916
+ return self.base_ring().one()
1917
+
1918
+ def numerator(self):
1919
+ r"""
1920
+ Return a numerator of ``self``, computed as ``self * self.denominator()``.
1921
+
1922
+ Note that some subclasses may implement its own numerator
1923
+ function.
1924
+
1925
+ .. warning::
1926
+
1927
+ This is not the numerator of the rational function
1928
+ defined by ``self``, which would always be ``self`` since ``self`` is a
1929
+ polynomial.
1930
+
1931
+ EXAMPLES:
1932
+
1933
+ First we compute the numerator of a polynomial with
1934
+ integer coefficients, which is of course ``self``.
1935
+
1936
+ ::
1937
+
1938
+ sage: R.<x, y> = ZZ[]
1939
+ sage: f = x^3 + 17*x + y + 1
1940
+ sage: f.numerator()
1941
+ x^3 + 17*x + y + 1
1942
+ sage: f == f.numerator()
1943
+ True
1944
+
1945
+ Next we compute the numerator of a polynomial over a number field.
1946
+
1947
+ ::
1948
+
1949
+ sage: # needs sage.rings.number_field sage.symbolic
1950
+ sage: R.<x,y> = NumberField(symbolic_expression(x^2+3), 'a')['x,y']
1951
+ sage: f = (1/17)*y^19 - (2/3)*x + 1/3; f
1952
+ 1/17*y^19 - 2/3*x + 1/3
1953
+ sage: f.numerator()
1954
+ 3*y^19 - 34*x + 17
1955
+ sage: f == f.numerator()
1956
+ False
1957
+
1958
+ We try to compute the numerator of a polynomial with coefficients in
1959
+ the finite field of 3 elements.
1960
+
1961
+ ::
1962
+
1963
+ sage: K.<x,y,z> = GF(3)['x, y, z']
1964
+ sage: f = 2*x*z + 2*z^2 + 2*y + 1; f
1965
+ -x*z - z^2 - y + 1
1966
+ sage: f.numerator()
1967
+ -x*z - z^2 - y + 1
1968
+
1969
+ We check that the computation the numerator and denominator
1970
+ are valid.
1971
+
1972
+ ::
1973
+
1974
+ sage: # needs sage.rings.number_field sage.symbolic
1975
+ sage: K = NumberField(symbolic_expression('x^3+2'), 'a')['x']['s,t']
1976
+ sage: f = K.random_element()
1977
+ sage: f.numerator() / f.denominator() == f
1978
+ True
1979
+ sage: R = RR['x,y,z']
1980
+ sage: f = R.random_element()
1981
+ sage: f.numerator() / f.denominator() == f
1982
+ True
1983
+ """
1984
+ return self * self.denominator()
1985
+
1986
+ def lift(self, I):
1987
+ r"""
1988
+ Given an ideal `I = (f_1,\dots,f_r)` that contains ``self``,
1989
+ find `s_1,\dots,s_r` such that ``self`` `= s_1 f_1 + ... + s_r f_r`.
1990
+
1991
+ INPUT:
1992
+
1993
+ - ``I`` -- an ideal in ``self.parent()`` or tuple of generators of that ideal
1994
+
1995
+ EXAMPLES::
1996
+
1997
+ sage: # needs sage.rings.real_mpfr
1998
+ sage: A.<x,y> = PolynomialRing(CC, 2, order='degrevlex')
1999
+ sage: I = A.ideal([x^10 + x^9*y^2, y^8 - x^2*y^7 ])
2000
+ sage: f = x*y^13 + y^12
2001
+ sage: M = f.lift(I); M # needs sage.libs.singular
2002
+ [y^7, x^7*y^2 + x^8 + x^5*y^3 + x^6*y + x^3*y^4 + x^4*y^2 + x*y^5 + x^2*y^3 + y^4]
2003
+ sage: sum(map(mul, zip(M, I.gens()))) == f # needs sage.libs.singular
2004
+ True
2005
+ """
2006
+ raise NotImplementedError
2007
+
2008
+ def inverse_mod(self, I):
2009
+ r"""
2010
+ Return an inverse of ``self`` modulo the polynomial ideal `I`,
2011
+ namely a multivariate polynomial `f` such that
2012
+ ``self * f - 1`` belongs to `I`.
2013
+
2014
+ INPUT:
2015
+
2016
+ - ``I`` -- an ideal of the polynomial ring in which ``self`` lives,
2017
+ or a single polynomial
2018
+
2019
+ OUTPUT: a multivariate polynomial representing the inverse of ``f`` modulo `I`
2020
+
2021
+ EXAMPLES::
2022
+
2023
+ sage: R.<x1,x2> = QQ[]
2024
+ sage: I = R.ideal(x2**2 + x1 - 2, x1**2 - 1)
2025
+ sage: f = x1 + 3*x2^2; g = f.inverse_mod(I); g # needs sage.libs.singular
2026
+ 1/16*x1 + 3/16
2027
+ sage: (f*g).reduce(I) # needs sage.libs.singular
2028
+ 1
2029
+
2030
+ Test a non-invertible element::
2031
+
2032
+ sage: R.<x1,x2> = QQ[]
2033
+ sage: I = R.ideal(x2**2 + x1 - 2, x1**2 - 1)
2034
+ sage: f = x1 + x2
2035
+ sage: f.inverse_mod(I) # needs sage.libs.singular
2036
+ Traceback (most recent call last):
2037
+ ...
2038
+ ArithmeticError: element is non-invertible
2039
+
2040
+ TESTS::
2041
+
2042
+ sage: R.<x,y> = ZZ[]
2043
+ sage: x.inverse_mod(x*y - 1) # needs sage.libs.singular
2044
+ y
2045
+ """
2046
+ P = self.parent()
2047
+ from sage.rings.ideal import Ideal_generic
2048
+ B = I.gens() if isinstance(I, Ideal_generic) else (I,)
2049
+ try:
2050
+ XY = P.one().lift((self,) + tuple(B))
2051
+ return P(XY[0])
2052
+ except ValueError:
2053
+ raise ArithmeticError("element is non-invertible")
2054
+
2055
+ def weighted_degree(self, *weights):
2056
+ r"""
2057
+ Return the weighted degree of ``self``, which is the maximum weighted
2058
+ degree of all monomials in ``self``; the weighted degree of a monomial
2059
+ is the sum of all powers of the variables in the monomial, each power
2060
+ multiplied with its respective weight in ``weights``.
2061
+
2062
+ This method is given for convenience. It is faster to use polynomial
2063
+ rings with weighted term orders and the standard ``degree`` function.
2064
+
2065
+ INPUT:
2066
+
2067
+ - ``weights`` -- either individual numbers, an iterable or a dictionary,
2068
+ specifying the weights of each variable. If it is a dictionary, it
2069
+ maps each variable of ``self`` to its weight. If it is a sequence of
2070
+ individual numbers or a tuple, the weights are specified in the order
2071
+ of the generators as given by ``self.parent().gens()``.
2072
+
2073
+ EXAMPLES::
2074
+
2075
+ sage: R.<x,y,z> = GF(7)[]
2076
+ sage: p = x^3 + y + x*z^2
2077
+ sage: p.weighted_degree({z:0, x:1, y:2})
2078
+ 3
2079
+ sage: p.weighted_degree(1, 2, 0)
2080
+ 3
2081
+ sage: p.weighted_degree((1, 4, 2))
2082
+ 5
2083
+ sage: p.weighted_degree((1, 4, 1))
2084
+ 4
2085
+ sage: p.weighted_degree(2**64, 2**50, 2**128)
2086
+ 680564733841876926945195958937245974528
2087
+ sage: q = R.random_element(100, 20)
2088
+ sage: q.weighted_degree(1, 1, 1) == q.total_degree()
2089
+ True
2090
+
2091
+ You may also work with negative weights
2092
+
2093
+ ::
2094
+
2095
+ sage: p.weighted_degree(-1, -2, -1)
2096
+ -2
2097
+
2098
+ Note that only integer weights are allowed
2099
+
2100
+ ::
2101
+
2102
+ sage: p.weighted_degree(x, 1, 1)
2103
+ Traceback (most recent call last):
2104
+ ...
2105
+ TypeError: unable to convert non-constant polynomial x to Integer Ring
2106
+ sage: p.weighted_degree(2/1, 1, 1)
2107
+ 6
2108
+
2109
+ The :meth:`weighted_degree` coincides with the :meth:`degree` of a weighted
2110
+ polynomial ring, but the latter is faster.
2111
+
2112
+ ::
2113
+
2114
+ sage: K = PolynomialRing(QQ, 'x,y', order=TermOrder('wdegrevlex', (2,3)))
2115
+ sage: p = K.random_element(10)
2116
+ sage: p.degree() == p.weighted_degree(2,3)
2117
+ True
2118
+
2119
+ TESTS::
2120
+
2121
+ sage: # needs sage.modules
2122
+ sage: R = PolynomialRing(QQ, 'a', 5)
2123
+ sage: f = R.random_element(terms=20)
2124
+ sage: w = random_vector(ZZ,5)
2125
+ sage: d1 = f.weighted_degree(w)
2126
+ sage: d2 = (f*1.0).weighted_degree(w)
2127
+ sage: d1 == d2
2128
+ True
2129
+ """
2130
+ if self.is_zero():
2131
+ #Corner case, note that the degree of zero is an Integer
2132
+ return Integer(-1)
2133
+
2134
+ if len(weights) == 1:
2135
+ # First unwrap it if it is given as one element argument
2136
+ weights = weights[0]
2137
+
2138
+ if isinstance(weights, dict):
2139
+ weights = [weights[g] for g in self.parent().gens()]
2140
+
2141
+ weights = [Integer(w) for w in weights]
2142
+
2143
+ # Go through each monomial, calculating the weight
2144
+ cdef int n = self.parent().ngens()
2145
+ cdef int i, j
2146
+ cdef Integer deg
2147
+ cdef Integer l
2148
+ cdef tuple m
2149
+ A = self.exponents(as_ETuples=False)
2150
+ l = Integer(0)
2151
+ m = <tuple>(A[0])
2152
+ for i in range(n):
2153
+ l += weights[i]*m[i]
2154
+ deg = l
2155
+ for j in range(1, len(A)):
2156
+ l = Integer(0)
2157
+ m = <tuple> A[j]
2158
+ for i in range(n):
2159
+ l += weights[i]*m[i]
2160
+ if deg < l:
2161
+ deg = l
2162
+ return deg
2163
+
2164
+ def gcd(self, other):
2165
+ r"""
2166
+ Return a greatest common divisor of this polynomial and ``other``.
2167
+
2168
+ INPUT:
2169
+
2170
+ - ``other`` -- a polynomial with the same parent as this polynomial
2171
+
2172
+ EXAMPLES::
2173
+
2174
+ sage: Q.<z> = Frac(QQ['z'])
2175
+ sage: R.<x,y> = Q[]
2176
+ sage: r = x*y - (2*z-1)/(z^2+z+1) * x + y/z
2177
+ sage: p = r * (x + z*y - 1/z^2)
2178
+ sage: q = r * (x*y*z + 1)
2179
+ sage: gcd(p, q)
2180
+ (z^3 + z^2 + z)*x*y + (-2*z^2 + z)*x + (z^2 + z + 1)*y
2181
+
2182
+ Polynomials over polynomial rings are converted to a simpler polynomial
2183
+ ring with all variables to compute the gcd::
2184
+
2185
+ sage: A.<z,t> = ZZ[]
2186
+ sage: B.<x,y> = A[]
2187
+ sage: r = x*y*z*t + 1
2188
+ sage: p = r * (x - y + z - t + 1)
2189
+ sage: q = r * (x*z - y*t)
2190
+ sage: gcd(p, q) # needs sage.libs.singular
2191
+ z*t*x*y + 1
2192
+ sage: _.parent()
2193
+ Multivariate Polynomial Ring in x, y over
2194
+ Multivariate Polynomial Ring in z, t over Integer Ring
2195
+
2196
+ Some multivariate polynomial rings have no gcd implementation::
2197
+
2198
+ sage: R.<x,y> = GaussianIntegers()[] # needs sage.rings.number_field
2199
+ sage: x.gcd(x)
2200
+ Traceback (most recent call last):
2201
+ ...
2202
+ NotImplementedError: GCD is not implemented for multivariate polynomials over
2203
+ Gaussian Integers generated by I in Number Field in I with defining polynomial x^2 + 1 with I = 1*I
2204
+
2205
+ TESTS::
2206
+
2207
+ sage: Pol = QQ['x']['x','y']
2208
+ sage: Pol.one().gcd(1)
2209
+ 1
2210
+
2211
+ sage: P = PolynomialRing(QQ, 'x', 0)
2212
+ sage: P.gens()
2213
+ ()
2214
+ """
2215
+ flatten = self._parent.flattening_morphism()
2216
+ tgt = flatten.codomain()
2217
+ if tgt is not self._parent and tgt._has_singular:
2218
+ g = flatten(self).gcd(flatten(other))
2219
+ return flatten.section()(g)
2220
+
2221
+ try:
2222
+ self._parent._singular_().set_ring()
2223
+ g = self._singular_().gcd(other._singular_())
2224
+ return self._parent(g)
2225
+ except (TypeError, AttributeError, ImportError):
2226
+ pass
2227
+
2228
+ gens = self.parent().gens()
2229
+ if not gens:
2230
+ # no variables
2231
+ base = self.parent().base_ring()
2232
+ return base(self).gcd(base(other))
2233
+
2234
+ x = gens[-1]
2235
+ uniself = self.polynomial(x)
2236
+ unibase = uniself.base_ring()
2237
+ try:
2238
+ doit = unibase._gcd_univariate_polynomial
2239
+ except AttributeError:
2240
+ raise NotImplementedError("GCD is not implemented for multivariate polynomials over {}".format(self._parent._mpoly_base_ring()))
2241
+ else:
2242
+ return self.parent()(doit(uniself, other.polynomial(x)))
2243
+
2244
+ def nth_root(self, n):
2245
+ r"""
2246
+ Return a `n`-th root of this element.
2247
+
2248
+ If there is no such root, a :exc:`ValueError` is raised.
2249
+
2250
+ EXAMPLES::
2251
+
2252
+ sage: R.<x,y,z> = QQ[]
2253
+ sage: a = 32 * (x*y + 1)^5 * (x+y+z)^5
2254
+ sage: a.nth_root(5)
2255
+ 2*x^2*y + 2*x*y^2 + 2*x*y*z + 2*x + 2*y + 2*z
2256
+ sage: b = x + 2*y + 3*z
2257
+ sage: b.nth_root(42)
2258
+ Traceback (most recent call last):
2259
+ ...
2260
+ ValueError: not a 42nd power
2261
+
2262
+ sage: R.<x,y> = QQ[]
2263
+ sage: S.<z,t> = R[]
2264
+ sage: T.<u,v> = S[]
2265
+ sage: p = (1 + x*u + y + v) * (1 + z*t)
2266
+ sage: (p**3).nth_root(3)
2267
+ (x*z*t + x)*u + (z*t + 1)*v + (y + 1)*z*t + y + 1
2268
+ sage: (p**3).nth_root(3).parent() is p.parent()
2269
+ True
2270
+ sage: ((1+x+z+t)**2).nth_root(3)
2271
+ Traceback (most recent call last):
2272
+ ...
2273
+ ValueError: not a 3rd power
2274
+ """
2275
+ R = self.parent()
2276
+ phi = R.flattening_morphism()
2277
+ S = phi.codomain()
2278
+ p = phi(self)
2279
+
2280
+ V = p.variables()
2281
+ if not V:
2282
+ # constant
2283
+ root = self.constant_coefficient().nth_root(n)
2284
+ return phi.section()(S(root))
2285
+ elif len(V) == 1:
2286
+ # univariate
2287
+ U = PolynomialRing(S.base_ring(), str(V[0]))
2288
+ pU = U(p)
2289
+ else:
2290
+ # specialize one variable
2291
+ # (in order to call the univariate case)
2292
+ U0 = PolynomialRing(S.base_ring(), [str(v) for v in V[:-1]])
2293
+ U = U0[str(V[-1])]
2294
+ pU = U(p)
2295
+
2296
+ # recursive call
2297
+ root = pU.nth_root(n)
2298
+ return phi.section()(S(root))
2299
+
2300
+ def is_square(self, root=False):
2301
+ r"""
2302
+ Test whether this polynomial is a square.
2303
+
2304
+ INPUT:
2305
+
2306
+ - ``root`` -- if set to ``True``, return a pair ``(True, root)``
2307
+ where ``root`` is a square root or ``(False, None)`` if
2308
+ it is not a square.
2309
+
2310
+ EXAMPLES::
2311
+
2312
+ sage: R.<a,b> = QQ[]
2313
+ sage: a.is_square()
2314
+ False
2315
+ sage: ((1+a*b^2)^2).is_square()
2316
+ True
2317
+ sage: ((1+a*b^2)^2).is_square(root=True)
2318
+ (True, a*b^2 + 1)
2319
+ """
2320
+ try:
2321
+ sqrt = self.nth_root(2)
2322
+ except ValueError:
2323
+ return (False,None) if root else False
2324
+ else:
2325
+ return (True,sqrt) if root else True
2326
+
2327
+ def specialization(self, D=None, phi=None):
2328
+ r"""
2329
+ Specialization of this polynomial.
2330
+
2331
+ Given a family of polynomials defined over a polynomial ring. A specialization
2332
+ is a particular member of that family. The specialization can be specified either
2333
+ by a dictionary or a :class:`SpecializationMorphism`.
2334
+
2335
+ INPUT:
2336
+
2337
+ - ``D`` -- dictionary (optional)
2338
+
2339
+ - ``phi`` -- :class:`SpecializationMorphism` (optional)
2340
+
2341
+ OUTPUT: a new polynomial
2342
+
2343
+ EXAMPLES::
2344
+
2345
+ sage: R.<c> = PolynomialRing(QQ)
2346
+ sage: S.<x,y> = PolynomialRing(R)
2347
+ sage: F = x^2 + c*y^2
2348
+ sage: F.specialization({c:2})
2349
+ x^2 + 2*y^2
2350
+
2351
+ ::
2352
+
2353
+ sage: S.<a,b> = PolynomialRing(QQ)
2354
+ sage: P.<x,y,z> = PolynomialRing(S)
2355
+ sage: RR.<c,d> = PolynomialRing(P)
2356
+ sage: f = a*x^2 + b*y^3 + c*y^2 - b*a*d + d^2 - a*c*b*z^2
2357
+ sage: f.specialization({a:2, z:4, d:2})
2358
+ (y^2 - 32*b)*c + b*y^3 + 2*x^2 - 4*b + 4
2359
+
2360
+ Check that we preserve multi- versus uni-variate::
2361
+
2362
+ sage: R.<l> = PolynomialRing(QQ, 1)
2363
+ sage: S.<k> = PolynomialRing(R)
2364
+ sage: K.<a, b, c> = PolynomialRing(S)
2365
+ sage: F = a*k^2 + b*l + c^2
2366
+ sage: F.specialization({b:56, c:5}).parent()
2367
+ Univariate Polynomial Ring in a over Univariate Polynomial Ring in k
2368
+ over Multivariate Polynomial Ring in l over Rational Field
2369
+ """
2370
+ if D is None:
2371
+ if phi is None:
2372
+ raise ValueError("either the dictionary or the specialization must be provided")
2373
+ else:
2374
+ from sage.rings.polynomial.flatten import SpecializationMorphism
2375
+ phi = SpecializationMorphism(self.parent(),D)
2376
+ return phi(self)
2377
+
2378
+ def reduced_form(self, **kwds):
2379
+ r"""
2380
+ Return a reduced form of this polynomial.
2381
+
2382
+ The algorithm is from Stoll and Cremona's "On the Reduction Theory of
2383
+ Binary Forms" [CS2003]_. This takes a two variable homogeneous polynomial and
2384
+ finds a reduced form. This is a `SL(2,\ZZ)`-equivalent binary form
2385
+ whose covariant in the upper half plane is in the fundamental domain.
2386
+ If the polynomial has multiple roots, they are removed and the algorithm
2387
+ is applied to the portion without multiple roots.
2388
+
2389
+ This reduction should also minimize the sum of the squares of the coefficients,
2390
+ but this is not always the case. By default the coefficient minimizing
2391
+ algorithm in [HS2018]_ is applied. The coefficients can be minimized
2392
+ either with respect to the sum of their squares or the maximum of their
2393
+ global heights.
2394
+
2395
+ A portion of the algorithm uses Newton's method to find a solution to
2396
+ a system of equations. If Newton's method fails to converge to a point
2397
+ in the upper half plane, the function will use the less precise `z_0`
2398
+ covariant from the `Q_0` form as defined on page 7 of [CS2003]_.
2399
+ Additionally, if this polynomial has
2400
+ a root with multiplicity at least half the total degree of the polynomial,
2401
+ then we must also use the `z_0` covariant. See [CS2003]_ for details.
2402
+
2403
+ Note that, if the covariant is within ``error_limit`` of the boundary
2404
+ but outside the fundamental domain, our function will erroneously move
2405
+ it to within the fundamental domain, hence our conjugation will be off
2406
+ by 1. If you don't want this to happen, decrease your ``error_limit``
2407
+ and increase your precision.
2408
+
2409
+ Implemented by Rebecca Lauren Miller as part of GSOC 2016. Smallest
2410
+ coefficients added by Ben Hutz July 2018.
2411
+
2412
+ INPUT: keyword arguments:
2413
+
2414
+ - ``prec`` -- integer (default: 300); sets the precision
2415
+
2416
+ - ``return_conjugation`` -- boolean (default: ``True``); whether to
2417
+ return element of `SL(2, \ZZ)`
2418
+
2419
+ - ``error_limit`` -- sets the error tolerance (default: 0.000001)
2420
+
2421
+ - ``smallest_coeffs`` -- boolean (default: ``True``); whether to find the
2422
+ model with smallest coefficients
2423
+
2424
+ - ``norm_type`` -- either ``'norm'`` or ``'height'``; what type of norm
2425
+ to use for smallest coefficients
2426
+
2427
+ - ``emb`` -- (optional) embedding of based field into ``CC``
2428
+
2429
+ OUTPUT:
2430
+
2431
+ - a polynomial (reduced binary form)
2432
+
2433
+ - a matrix (element of `SL(2, \ZZ)`)
2434
+
2435
+ .. TODO::
2436
+
2437
+ When Newton's Method doesn't converge to a root in the upper half plane.
2438
+ Now we just return `z_0`. It would be better to modify and find the unique root
2439
+ in the upper half plane.
2440
+
2441
+ EXAMPLES::
2442
+
2443
+ sage: R.<x,h> = PolynomialRing(QQ)
2444
+ sage: f = 19*x^8 - 262*x^7*h + 1507*x^6*h^2 - 4784*x^5*h^3 + 9202*x^4*h^4\
2445
+ ....: -10962*x^3*h^5 + 7844*x^2*h^6 - 3040*x*h^7 + 475*h^8
2446
+ sage: f.reduced_form(prec=200, smallest_coeffs=False) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2447
+ (
2448
+ -x^8 - 2*x^7*h + 7*x^6*h^2 + 16*x^5*h^3 + 2*x^4*h^4 - 2*x^3*h^5 + 4*x^2*h^6 - 5*h^8,
2449
+ <BLANKLINE>
2450
+ [ 1 -2]
2451
+ [ 1 -1]
2452
+ )
2453
+
2454
+ An example where the multiplicity is too high::
2455
+
2456
+ sage: R.<x,y> = PolynomialRing(QQ)
2457
+ sage: f = x^3 + 378666*x^2*y - 12444444*x*y^2 + 1234567890*y^3
2458
+ sage: j = f * (x-545*y)^9
2459
+ sage: j.reduced_form(prec=200, smallest_coeffs=False) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2460
+ Traceback (most recent call last):
2461
+ ...
2462
+ ValueError: cannot have a root with multiplicity >= 12/2
2463
+
2464
+ An example where Newton's Method does not find the right root::
2465
+
2466
+ sage: R.<x,y> = PolynomialRing(QQ)
2467
+ sage: F = x^6 + 3*x^5*y - 8*x^4*y^2 - 2*x^3*y^3 - 44*x^2*y^4 - 8*x*y^5
2468
+ sage: F.reduced_form(smallest_coeffs=False, prec=400) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2469
+ Traceback (most recent call last):
2470
+ ...
2471
+ ArithmeticError: Newton's method converged to z not in the upper half plane
2472
+
2473
+ An example with covariant on the boundary, therefore a non-unique form::
2474
+
2475
+ sage: R.<x,y> = PolynomialRing(QQ)
2476
+ sage: F = 5*x^2*y - 5*x*y^2 - 30*y^3
2477
+ sage: F.reduced_form(smallest_coeffs=False) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2478
+ (
2479
+ [1 1]
2480
+ 5*x^2*y + 5*x*y^2 - 30*y^3, [0 1]
2481
+ )
2482
+
2483
+ An example where precision needs to be increased::
2484
+
2485
+ sage: R.<x,y> = PolynomialRing(QQ)
2486
+ sage: F = (-16*x^7 - 114*x^6*y - 345*x^5*y^2 - 599*x^4*y^3
2487
+ ....: - 666*x^3*y^4 - 481*x^2*y^5 - 207*x*y^6 - 40*y^7)
2488
+ sage: F.reduced_form(prec=50, smallest_coeffs=False) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2489
+ Traceback (most recent call last):
2490
+ ...
2491
+ ValueError: accuracy of Newton's root not within tolerance(0.000012... > 1e-06),
2492
+ increase precision
2493
+ sage: F.reduced_form(prec=100, smallest_coeffs=False) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2494
+ (
2495
+ [-1 -1]
2496
+ -x^5*y^2 - 24*x^3*y^4 - 3*x^2*y^5 - 2*x*y^6 + 16*y^7, [ 1 0]
2497
+ )
2498
+
2499
+ ::
2500
+
2501
+ sage: R.<x,y> = PolynomialRing(QQ)
2502
+ sage: F = - 8*x^4 - 3933*x^3*y - 725085*x^2*y^2 - 59411592*x*y^3 - 1825511633*y^4
2503
+ sage: F.reduced_form(return_conjugation=False) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2504
+ x^4 + 9*x^3*y - 3*x*y^3 - 8*y^4
2505
+
2506
+ ::
2507
+
2508
+ sage: R.<x,y> = QQ[]
2509
+ sage: F = -2*x^3 + 2*x^2*y + 3*x*y^2 + 127*y^3
2510
+ sage: F.reduced_form() # needs sage.modules sage.rings.complex_interval_field sage.schemes
2511
+ (
2512
+ [1 4]
2513
+ -2*x^3 - 22*x^2*y - 77*x*y^2 + 43*y^3, [0 1]
2514
+ )
2515
+
2516
+ ::
2517
+
2518
+ sage: R.<x,y> = QQ[]
2519
+ sage: F = -2*x^3 + 2*x^2*y + 3*x*y^2 + 127*y^3
2520
+ sage: F.reduced_form(norm_type='height') # needs sage.modules sage.rings.complex_interval_field sage.schemes
2521
+ (
2522
+ [5 4]
2523
+ -58*x^3 - 47*x^2*y + 52*x*y^2 + 43*y^3, [1 1]
2524
+ )
2525
+
2526
+ ::
2527
+
2528
+ sage: R.<x,y,z> = PolynomialRing(QQ)
2529
+ sage: F = x^4 + x^3*y*z + y^2*z
2530
+ sage: F.reduced_form() # needs sage.modules sage.rings.complex_interval_field sage.schemes
2531
+ Traceback (most recent call last):
2532
+ ...
2533
+ ValueError: (=x^3*y*z + x^4 + y^2*z) must have two variables
2534
+
2535
+ ::
2536
+
2537
+ sage: R.<x,y> = PolynomialRing(ZZ)
2538
+ sage: F = - 8*x^6 - 3933*x^3*y - 725085*x^2*y^2 - 59411592*x*y^3 - 99*y^6
2539
+ sage: F.reduced_form(return_conjugation=False) # needs sage.modules sage.rings.complex_interval_field sage.schemes
2540
+ Traceback (most recent call last):
2541
+ ...
2542
+ ValueError: (=-8*x^6 - 99*y^6 - 3933*x^3*y - 725085*x^2*y^2 -
2543
+ 59411592*x*y^3) must be homogeneous
2544
+
2545
+ ::
2546
+
2547
+ sage: R.<x,y> = PolynomialRing(RR)
2548
+ sage: F = (217.992172373276*x^3 + 96023.1505442490*x^2*y
2549
+ ....: + 1.40987971253579e7*x*y^2 + 6.90016027113216e8*y^3)
2550
+ sage: F.reduced_form(smallest_coeffs=False) # tol 1e-8 # needs sage.modules sage.rings.complex_interval_field sage.schemes
2551
+ (
2552
+ -39.5673942565918*x^3 + 111.874026298523*x^2*y
2553
+ + 231.052762985229*x*y^2 - 138.380829811096*y^3,
2554
+ <BLANKLINE>
2555
+ [-147 -148]
2556
+ [ 1 1]
2557
+ )
2558
+
2559
+ ::
2560
+
2561
+ sage: R.<x,y> = PolynomialRing(CC) # needs sage.rings.real_mpfr
2562
+ sage: F = ((0.759099196558145 + 0.845425869641446*CC.0)*x^3 # needs sage.rings.real_mpfr
2563
+ ....: + (84.8317207268542 + 93.8840848648033*CC.0)*x^2*y
2564
+ ....: + (3159.07040755858 + 3475.33037377779*CC.0)*x*y^2
2565
+ ....: + (39202.5965389079 + 42882.5139724962*CC.0)*y^3)
2566
+ sage: F.reduced_form(smallest_coeffs=False) # tol 1e-11 # needs sage.modules sage.rings.complex_interval_field sage.rings.real_mpfr sage.schemes
2567
+ (
2568
+ (-0.759099196558145 - 0.845425869641446*I)*x^3
2569
+ + (-0.571709908900118 - 0.0418133346027929*I)*x^2*y
2570
+ + (0.856525964330103 - 0.0721403997649759*I)*x*y^2
2571
+ + (-0.965531044130330 + 0.754252314465703*I)*y^3,
2572
+ <BLANKLINE>
2573
+ [-1 37]
2574
+ [ 0 -1]
2575
+ )
2576
+ """
2577
+ from sage.matrix.constructor import matrix
2578
+ from sage.modules.free_module_element import vector
2579
+ from sage.rings.complex_interval_field import ComplexIntervalField
2580
+ from sage.rings.real_mpfr import RealField
2581
+
2582
+ if self.parent().ngens() != 2:
2583
+ raise ValueError("(=%s) must have two variables" % self)
2584
+ if not self.is_homogeneous():
2585
+ raise ValueError("(=%s) must be homogeneous" % self)
2586
+
2587
+ prec = kwds.get('prec', 300)
2588
+ return_conjugation = kwds.get('return_conjugation', True)
2589
+ emb = kwds.get('emb', None)
2590
+
2591
+ # getting a numerical approximation of the roots of our polynomial
2592
+ CF = ComplexIntervalField(prec=prec) # keeps trac of our precision error
2593
+ RF = RealField(prec=prec)
2594
+ R = self.parent()
2595
+ x, y = R.gens()
2596
+
2597
+ # finding quadratic Q_0, gives us our covariant, z_0
2598
+ from sage.rings.polynomial.binary_form_reduce import covariant_z0
2599
+ try:
2600
+ z, th = covariant_z0(self, prec=prec, emb=emb, z0_cov=True)
2601
+ except ValueError:# multiple roots
2602
+ F = self.lc()*prod([p for p, e in self.factor()])
2603
+ z, th = covariant_z0(F, prec=prec, emb=emb, z0_cov=True)
2604
+ z = CF(z)
2605
+ # this moves z_0 to our fundamental domain using the three steps laid
2606
+ # out in the algorithm by [CS2003]
2607
+ # this is found in section 5 of their paper
2608
+ M = matrix(QQ, [[1,0], [0,1]]) # used to keep track of how our z is moved.
2609
+ zc = z.center()
2610
+ while zc.real() < RF(-0.5) or zc.real() >= RF(0.5) or (zc.real() <= RF(0) and zc.abs() < RF(1))\
2611
+ or (zc.real() > RF(0) and zc.abs() <= RF(1)):
2612
+ if (zc.real() < RF(-0.5)) or (zc.real() >= RF(0.5)):
2613
+ # moves z into fundamental domain by m
2614
+ m = zc.real().round() # finds amount to move z's real part by
2615
+ Qm = QQ(m)
2616
+ M = M * matrix(QQ, [[1, Qm], [0, 1]]) # move
2617
+ z -= m # M.inverse()*z is supposed to move z by m
2618
+ elif (zc.real() <= RF(0) and zc.abs() < RF(1)) or (zc.real() > RF(0) and zc.abs() <= RF(1)): # flips z
2619
+ z = -1/z
2620
+ M = M * matrix(QQ, [[0, -1], [1, 0]])# multiply on left because we are taking inverse matrices
2621
+ zc = z.center()
2622
+
2623
+ smallest_coeffs = kwds.get('smallest_coeffs', True)
2624
+ if smallest_coeffs:
2625
+ # since we are searching anyway, don't need the 'true' reduced covariant
2626
+ from sage.rings.polynomial.binary_form_reduce import smallest_poly
2627
+ norm_type = kwds.get('norm_type', 'norm')
2628
+ _, sm_m = smallest_poly(self(tuple(M * vector([x, y]))), prec=prec,
2629
+ norm_type=norm_type, emb=emb)
2630
+ M = M*sm_m
2631
+ else:
2632
+ # solve the minimization problem for 'true' covariant
2633
+ z, th = covariant_z0(self(tuple(M * vector([x,y]))), prec=prec, emb=emb)
2634
+ z = CF(z)
2635
+ zc = z.center()
2636
+ # moves our z to fundamental domain as before
2637
+ while zc.real() < RF(-0.5) or zc.real() >= RF(0.5) or (zc.real() <= RF(0) and zc.abs() < RF(1))\
2638
+ or (zc.real() > RF(0) and zc.abs() <= RF(1)):
2639
+ if (zc.real() < RF(-0.5)) or (zc.real() >= RF(0.5)):
2640
+ # moves z into fundamental domain by m
2641
+ m = zc.real().round() # finds amount to move z's real part by
2642
+ Qm = QQ(m)
2643
+ M = M * matrix(QQ, [[1,Qm], [0,1]]) # move
2644
+ z -= m # M.inverse()*z is supposed to move z by m
2645
+ elif (zc.real() <= RF(0) and zc.abs() < RF(1)) or (zc.real() > RF(0) and zc.abs() <= RF(1)): # flips z
2646
+ z = -1/z
2647
+ M = M * matrix(QQ, [[0,-1], [1,0]])# multiply on left because we are taking inverse matrices
2648
+ zc = z.center()
2649
+
2650
+ if return_conjugation:
2651
+ return (self(tuple(M * vector([x,y]))), M)
2652
+ return self(tuple(M * vector([x,y])))
2653
+
2654
+ def is_unit(self) -> bool:
2655
+ r"""
2656
+ Return ``True`` if ``self`` is a unit, that is, has a
2657
+ multiplicative inverse.
2658
+
2659
+ EXAMPLES::
2660
+
2661
+ sage: # needs sage.rings.number_field
2662
+ sage: R.<x,y> = QQbar[]
2663
+ sage: (x + y).is_unit()
2664
+ False
2665
+ sage: R(0).is_unit()
2666
+ False
2667
+ sage: R(-1).is_unit()
2668
+ True
2669
+ sage: R(-1 + x).is_unit()
2670
+ False
2671
+ sage: R(2).is_unit()
2672
+ True
2673
+
2674
+ Check that :issue:`22454` is fixed::
2675
+
2676
+ sage: _.<x,y> = Zmod(4)[]
2677
+ sage: (1 + 2*x).is_unit()
2678
+ True
2679
+ sage: (x*y).is_unit()
2680
+ False
2681
+ sage: _.<x,y> = Zmod(36)[]
2682
+ sage: (7+ 6*x + 12*y - 18*x*y).is_unit()
2683
+ True
2684
+ """
2685
+ # EXERCISE (Atiyah-McDonald, Ch 1): Let `A[x]` be a polynomial
2686
+ # ring in one variable. Then `f=\sum a_i x^i \in A[x]` is a unit\
2687
+ # if and only if `a_0` is a unit and `a_1,\ldots, a_n` are nilpotent.
2688
+ # (Also noted in Dummit and Foote, "Abstract Algebra", 1991,
2689
+ # Section 7.3 Exercise 33).
2690
+ # Also f is nilpotent if and only if all a_i are nilpotent.
2691
+ # This generalizes easily to the multivariate case, by considering
2692
+ # K[x,y,...] as K[x][y]...
2693
+ if not self.constant_coefficient().is_unit():
2694
+ return False
2695
+ cdef dict d = self.monomial_coefficients()
2696
+ cdef ETuple zero_key = ETuple({}, int(self.parent().ngens()))
2697
+ d.pop(zero_key, None)
2698
+ return all(d[k].is_nilpotent() for k in d)
2699
+
2700
+ def is_nilpotent(self):
2701
+ r"""
2702
+ Return ``True`` if ``self`` is nilpotent, i.e., some power of ``self``
2703
+ is 0.
2704
+
2705
+ EXAMPLES::
2706
+
2707
+ sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
2708
+ sage: (x + y).is_nilpotent() # needs sage.rings.number_field
2709
+ False
2710
+ sage: R(0).is_nilpotent() # needs sage.rings.number_field
2711
+ True
2712
+ sage: _.<x,y> = Zmod(4)[]
2713
+ sage: (2*x).is_nilpotent()
2714
+ True
2715
+ sage: (2 + y*x).is_nilpotent()
2716
+ False
2717
+ sage: _.<x,y> = Zmod(36)[]
2718
+ sage: (4 + 6*x).is_nilpotent()
2719
+ False
2720
+ sage: (6*x + 12*y + 18*x*y + 24*(x^2+y^2)).is_nilpotent()
2721
+ True
2722
+ """
2723
+ # EXERCISE (Atiyah-McDonald, Ch 1): Let `A[x]` be a polynomial
2724
+ # ring in one variable. Then `f=\sum a_i x^i \in A[x]` is
2725
+ # nilpotent if and only if `a_0,\ldots, a_n` are nilpotent.
2726
+ # (Also noted in Dummit and Foote, "Abstract Algebra", 1991,
2727
+ # Section 7.3 Exercise 33).
2728
+ # This generalizes easily to the multivariate case, by considering
2729
+ # K[x,y,...] as K[x][y]...
2730
+ d = self.monomial_coefficients()
2731
+ return all(c.is_nilpotent() for c in d.values())
2732
+
2733
+ def _test_subs(self, tester=None, **options):
2734
+ r"""
2735
+ Run some tests using the ``subs`` method.
2736
+
2737
+ TESTS::
2738
+
2739
+ sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
2740
+ sage: (x + y)._test_subs() # needs sage.rings.number_field
2741
+ """
2742
+ if tester is None:
2743
+ tester = self._tester(**options)
2744
+
2745
+ gens = self.parent().gens()
2746
+
2747
+ if gens:
2748
+ # substituting all variables (in a polynomial ring with variables) with 0
2749
+ d = {str(gen): self.base_ring().zero() for gen in gens}
2750
+ tester.assertEqual(self.subs(**d).parent(), self.parent().base_ring())
2751
+
2752
+ # substituting all variables (in a polynomial ring with variables)
2753
+ # with elements of another ring
2754
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
2755
+ other = PolynomialRing(self.parent().base_ring(), 'other', len(gens))
2756
+ other_gens = other.gens()
2757
+ d = {str(gen): other_gen for gen, other_gen in zip(gens, other_gens)}
2758
+ tester.assertEqual(self.subs(**d).parent(), other)
2759
+
2760
+ if len(gens) > 1:
2761
+ # substituting one variable (in a polynomial ring with variables) with 0
2762
+ d = {str(gens[0]): self.base_ring().zero()}
2763
+ tester.assertEqual(self.subs(**d).parent(), self.parent())
2764
+
2765
+ # test error checking: partial substitution by elements
2766
+ # from another ring is not allowed
2767
+ d = {str(gens[0]): other_gens[0]}
2768
+ with tester.assertRaises((ValueError, TypeError)):
2769
+ self.subs(**d)
2770
+
2771
+ def is_lorentzian(self, explain=False):
2772
+ r"""
2773
+ Return whether this is a Lorentzian polynomial.
2774
+
2775
+ INPUT:
2776
+
2777
+ - ``explain`` -- boolean (default: ``False``); if ``True``
2778
+ return a tuple whose first element is the boolean result of the test,
2779
+ and the second element is a string describing the reason the test failed,
2780
+ or ``None`` if the test succeeded.
2781
+
2782
+ Lorentzian polynomials are a class of polynomials connected with the area
2783
+ of discrete convex analysis. A polynomial `f` with positive real coefficients
2784
+ is Lorentzian if:
2785
+
2786
+ - `f` is homogeneous;
2787
+
2788
+ - the support of `f` is `M`-convex
2789
+
2790
+ - `f` has degree less than `2`, or if its degree is at least two,
2791
+ the collection of sequential partial derivatives of `f` which are
2792
+ quadratic forms have Gram matrices with at most one positive eigenvalue.
2793
+
2794
+ Note in particular that the zero polynomial is Lorentzian. Examples of
2795
+ Lorentzian polynomials include homogeneous stable polynomials, volume
2796
+ polynomials of convex bodies and projective varieties, and Schur polynomials
2797
+ after renormalizing the coefficient of each monomial `x^\alpha` by `1/\alpha!`.
2798
+
2799
+ EXAMPLES:
2800
+
2801
+ Renormalized Schur polynomials are Lorentzian, but not in general if the
2802
+ renormalization is skipped::
2803
+
2804
+ sage: P.<x,y> = QQ[]
2805
+ sage: p = (x^2 / 2) + x*y + (y^2 / 2)
2806
+ sage: p.is_lorentzian()
2807
+ True
2808
+ sage: p = x^2 + x*y + y^2
2809
+ sage: p.is_lorentzian()
2810
+ False
2811
+
2812
+ Homogeneous linear forms and constant polynomials with positive
2813
+ coefficients are Lorentzian, as well as the zero polynomial::
2814
+
2815
+ sage: p = x + 2*y
2816
+ sage: p.is_lorentzian()
2817
+ True
2818
+ sage: p = P(5)
2819
+ sage: p.is_lorentzian()
2820
+ True
2821
+ sage: P.zero().is_lorentzian()
2822
+ True
2823
+
2824
+ Inhomogeneous polynomials and polynomials with negative coefficients
2825
+ are not Lorentzian::
2826
+
2827
+ sage: p = x^2 + 2*x + y^2
2828
+ sage: p.is_lorentzian()
2829
+ False
2830
+ sage: p = 2*x^2 - y^2
2831
+ sage: p.is_lorentzian()
2832
+ False
2833
+
2834
+ It is an error to check if a polynomial is Lorentzian if its base ring
2835
+ is not a subring of the real numbers, as the notion is not defined in
2836
+ this case::
2837
+
2838
+ sage: # needs sage.rings.real_mpfr
2839
+ sage: Q.<z,w> = CC[]
2840
+ sage: q = z^2 + w^2
2841
+ sage: q.is_lorentzian()
2842
+ Traceback (most recent call last):
2843
+ ...
2844
+ NotImplementedError: is_lorentzian only implemented for real polynomials
2845
+
2846
+ The method can give a reason for a polynomial failing to be Lorentzian::
2847
+
2848
+ sage: p = x^2 + 2*x + y^2
2849
+ sage: p.is_lorentzian(explain=True)
2850
+ (False, 'inhomogeneous')
2851
+
2852
+ REFERENCES:
2853
+
2854
+ For full definitions and related discussion, see [BrHu2019]_ and
2855
+ [HMMS2019]_. The second reference gives the characterization of
2856
+ Lorentzian polynomials applied in this implementation explicitly.
2857
+ """
2858
+ from sage.rings.imaginary_unit import I
2859
+
2860
+ # function to handle return value when reason requested
2861
+ def result(val, explanation=None):
2862
+ return (val, explanation) if explain else val
2863
+
2864
+ try:
2865
+ # this would better be handled by a category of RealFields()
2866
+ self.base_ring()(I)
2867
+ except (ValueError, TypeError):
2868
+ pass
2869
+ else:
2870
+ raise NotImplementedError("is_lorentzian only implemented for real polynomials")
2871
+
2872
+ if self.is_zero():
2873
+ return result(True)
2874
+
2875
+ if not self.is_homogeneous():
2876
+ return result(False, "inhomogeneous")
2877
+
2878
+ if any(coeff < 0 for coeff in self.coefficients()):
2879
+ return result(False, "negative coefficient")
2880
+
2881
+ # for degree <= 1, homogeneous with positive coefficients is sufficient
2882
+ if self.degree() <= 1:
2883
+ return result(True)
2884
+
2885
+ # check support is M-convex
2886
+ if not _is_M_convex_(self.exponents()):
2887
+ return result(False, "not M-convex")
2888
+
2889
+ # compute quadratic forms coming from a sequence of partial derivatives
2890
+ if self.degree() == 2:
2891
+ quadratic_derivs = set([self])
2892
+ else:
2893
+ from sage.combinat.integer_lists.invlex import IntegerListsLex
2894
+
2895
+ gens = self.parent().gens()
2896
+ quadratic_derivs = set()
2897
+ multi_exponents = IntegerListsLex(self.degree() - 2, length=len(gens))
2898
+ for alpha in multi_exponents:
2899
+ # construct list [gen_1, exp_1, ..., gen_n, exp_n] for derivative function
2900
+ d_list = chain(*zip(gens, alpha))
2901
+ d = self.derivative(*d_list)
2902
+ quadratic_derivs.add(d)
2903
+
2904
+ # check derivative quadratic forms have at most one positive eigenvalue
2905
+ for deriv in quadratic_derivs:
2906
+ from sage.quadratic_forms.quadratic_form import QuadraticForm
2907
+ G = QuadraticForm(deriv).Gram_matrix()
2908
+ spectrum = sorted(G.eigenvalues(), reverse=True)
2909
+ if len(spectrum) > 1 and spectrum[1] > 0:
2910
+ return result(False, "multiple positive eigenvalues")
2911
+
2912
+ return result(True)
2913
+
2914
+ def crt(self, y, m, n):
2915
+ """
2916
+ Return a polynomial congruent to ``self`` modulo ``m`` and
2917
+ to ``y`` modulo ``n``.
2918
+
2919
+ INPUT:
2920
+
2921
+ - ``y`` -- a polynomial in the same ring as ``self``
2922
+ - ``m``, ``n`` -- polynomials or ideals in the same ring as ``self``; ideals
2923
+ may also be specified as a list/tuple of generators
2924
+
2925
+ EXAMPLES::
2926
+
2927
+ sage: # needs sage.libs.singular
2928
+ sage: R.<x> = PolynomialRing(QQ, implementation="singular")
2929
+ sage: f = R(3)
2930
+ sage: f.crt(5, x-1, x-2) % ((x-1)*(x-2))
2931
+ 2*x + 1
2932
+ sage: f.crt(5, R.ideal(x-1), [x-2]) % ((x-1)*(x-2))
2933
+ 2*x + 1
2934
+ """
2935
+ # could be moved up to ModuleElement as long as lift() is defined
2936
+ # the current definition of lift() requires ideal(), so maybe only RingElement
2937
+ R = self._parent
2938
+ y = R(y)
2939
+ m = R.ideal(m).gens()
2940
+ n = R.ideal(n).gens()
2941
+ # result == self - sum a_i * m_i == y + sum b_i * n_i
2942
+ # self - y == sum b_i * n_i + sum a_i * m_i
2943
+ ab_values = (self - y).lift(m + n)
2944
+ return R.sum([y] + [bi * ni for bi, ni in zip(ab_values[len(m):], n)])
2945
+
2946
+ def canonical_associate(self):
2947
+ """
2948
+ Return a canonical associate.
2949
+
2950
+ EXAMPLES::
2951
+
2952
+ sage: R.<x,y>=QQ[]
2953
+ sage: (-2*x^2+3*x+5*y).canonical_associate()
2954
+ (x^2 - 3/2*x - 5/2*y, -2)
2955
+ sage: R.<x,y>=ZZ[]
2956
+ sage: (-2*x^2+3*x+5*y).canonical_associate()
2957
+ (2*x^2 - 3*x - 5*y, -1)
2958
+ """
2959
+ lc = self.leading_coefficient()
2960
+ n, u = lc.canonical_associate()
2961
+ return (u.inverse_of_unit() * self, u)
2962
+
2963
+
2964
+ def _is_M_convex_(points) -> bool:
2965
+ r"""
2966
+ Return whether ``points`` represents a set of integer lattice points
2967
+ which are M-convex.
2968
+
2969
+ Utility function for method ``is_lorentzian``, which would more properly
2970
+ fit with code related to discrete convex geometry, generalized permutahedra,
2971
+ or polymatroids, which are not currently implemented in Sage.
2972
+
2973
+ INPUT:
2974
+
2975
+ - ``points`` -- iterable for a list of integer lattice points of the
2976
+ same dimension
2977
+
2978
+ Examples of M-convex sets include the vertices of a matroid polytope, and the
2979
+ support sets of Schur polynomials.
2980
+
2981
+ EXAMPLES:
2982
+
2983
+ The following points represent the vertices of a matroid polytope (indicator
2984
+ vectors of the bases) of rank `2` on five elements::
2985
+
2986
+ sage: from sage.rings.polynomial.multi_polynomial import _is_M_convex_
2987
+ sage: P = [[1,1,0,0], [1,0,1,0], [0,1,1,0], [0,1,0,1], [0,0,1,1]]
2988
+ sage: _is_M_convex_(P)
2989
+ True
2990
+
2991
+ These points are the support of the Schur polynomial in three variables for
2992
+ the partition `(2,2)`::
2993
+
2994
+ sage: P = [[2,2,0], [2,0,2], [0,2,2], [2,1,1], [1,2,1], [1,1,2]]
2995
+ sage: _is_M_convex_(P)
2996
+ True
2997
+
2998
+ The following are not examples of `M`-convex sets of points::
2999
+
3000
+ sage: P = [[1, 0, 0], [1, 1, 0], [1, 1, 1]]
3001
+ sage: _is_M_convex_(P)
3002
+ False
3003
+
3004
+ sage: P = [[0, 1, 2], [2, 1]]
3005
+ sage: _is_M_convex_(P)
3006
+ Traceback (most recent call last):
3007
+ ...
3008
+ ValueError: input points are not the same dimension
3009
+
3010
+ sage: P = [[0, 0.5, 1], [1, 1.5, 2]]
3011
+ sage: _is_M_convex_(P)
3012
+ Traceback (most recent call last):
3013
+ ...
3014
+ ValueError: input points are not integer lattice points
3015
+
3016
+ REFERENCES:
3017
+
3018
+ See [BrHu2019]_ for a definition of M-convexity.
3019
+ """
3020
+ points_set = set(map(tuple, points))
3021
+ if not points_set:
3022
+ return True
3023
+ dim = len(next(iter(points_set)))
3024
+ if any(len(p) != dim for p in points_set):
3025
+ raise ValueError("input points are not the same dimension")
3026
+ if any(entry not in ZZ for p in points_set for entry in p):
3027
+ raise ValueError("input points are not integer lattice points")
3028
+ for p1 in points_set:
3029
+ list_p1 = list(p1)
3030
+ for p2 in points_set:
3031
+ if p2 == p1:
3032
+ continue
3033
+ for i in range(dim):
3034
+ if p2[i] > p1[i]:
3035
+ # modify list_p1 to represent point p1 + e_i - e_j for various i, j
3036
+ list_p1[i] += 1 # add e_i
3037
+ # check exchange condition is satisfied by some index j
3038
+ for j in range(dim):
3039
+ if p2[j] < p1[j]:
3040
+ list_p1[j] -= 1 # subtract e_j
3041
+ exch = tuple(list_p1) # p1 + e_i - e_j
3042
+ list_p1[j] += 1 # add e_j again
3043
+ if tuple(exch) in points_set:
3044
+ break
3045
+ else:
3046
+ return False
3047
+ list_p1[i] -= 1 # subtract e_i
3048
+ # list_p1 should now have same entries as p1 again
3049
+ return True
3050
+
3051
+
3052
+ cdef remove_from_tuple(e, int ind):
3053
+ w = list(e)
3054
+ del w[ind]
3055
+ if len(w) == 1:
3056
+ return w[0]
3057
+ else:
3058
+ return tuple(w)
3059
+
3060
+
3061
+ cdef class MPolynomial_libsingular(MPolynomial):
3062
+ r"""
3063
+ Abstract base class for :class:`~sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular`.
3064
+
3065
+ This class is defined for the purpose of :func:`isinstance` tests. It should not be
3066
+ instantiated.
3067
+
3068
+ EXAMPLES::
3069
+
3070
+ sage: from sage.rings.polynomial.multi_polynomial import MPolynomial_libsingular
3071
+ sage: R1.<x> = QQ[]
3072
+ sage: isinstance(x, MPolynomial_libsingular)
3073
+ False
3074
+ sage: R2.<y,z> = QQ[]
3075
+ sage: isinstance(y, MPolynomial_libsingular) # needs sage.libs.singular
3076
+ True
3077
+
3078
+ By design, there is a unique direct subclass::
3079
+
3080
+ sage: len(sage.rings.polynomial.multi_polynomial.MPolynomial_libsingular.__subclasses__()) <= 1
3081
+ True
3082
+ """