passagemath-pari 10.6.32__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (331) hide show
  1. PARIKernel/__init__.py +2 -0
  2. PARIKernel/__main__.py +5 -0
  3. PARIKernel/io.cpython-314-x86_64-linux-musl.so +0 -0
  4. PARIKernel/io.pxd +7 -0
  5. PARIKernel/io.pyx +84 -0
  6. PARIKernel/kernel.cpython-314-x86_64-linux-musl.so +0 -0
  7. PARIKernel/kernel.pyx +260 -0
  8. PARIKernel/paridecl.pxd +95 -0
  9. PARIKernel/svg.cpython-314-x86_64-linux-musl.so +0 -0
  10. PARIKernel/svg.pyx +52 -0
  11. cypari2/__init__.py +8 -0
  12. cypari2/auto_paridecl.pxd +1070 -0
  13. cypari2/closure.cpython-314-x86_64-linux-musl.so +0 -0
  14. cypari2/closure.pxd +5 -0
  15. cypari2/closure.pyx +246 -0
  16. cypari2/convert.cpython-314-x86_64-linux-musl.so +0 -0
  17. cypari2/convert.pxd +80 -0
  18. cypari2/convert.pyx +613 -0
  19. cypari2/custom_block.cpython-314-x86_64-linux-musl.so +0 -0
  20. cypari2/custom_block.pyx +30 -0
  21. cypari2/cypari.h +13 -0
  22. cypari2/gen.cpython-314-x86_64-linux-musl.so +0 -0
  23. cypari2/gen.pxd +69 -0
  24. cypari2/gen.pyx +4819 -0
  25. cypari2/handle_error.cpython-314-x86_64-linux-musl.so +0 -0
  26. cypari2/handle_error.pxd +7 -0
  27. cypari2/handle_error.pyx +232 -0
  28. cypari2/pari_instance.cpython-314-x86_64-linux-musl.so +0 -0
  29. cypari2/pari_instance.pxd +27 -0
  30. cypari2/pari_instance.pyx +1438 -0
  31. cypari2/paridecl.pxd +5353 -0
  32. cypari2/paripriv.pxd +34 -0
  33. cypari2/pycore_long.h +98 -0
  34. cypari2/pycore_long.pxd +9 -0
  35. cypari2/stack.cpython-314-x86_64-linux-musl.so +0 -0
  36. cypari2/stack.pxd +27 -0
  37. cypari2/stack.pyx +278 -0
  38. cypari2/string_utils.cpython-314-x86_64-linux-musl.so +0 -0
  39. cypari2/string_utils.pxd +29 -0
  40. cypari2/string_utils.pyx +65 -0
  41. cypari2/types.pxd +147 -0
  42. passagemath_pari-10.6.32.data/data/etc/jupyter/nbconfig/notebook.d/gp-mode.json +5 -0
  43. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.js +28 -0
  44. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.json +6 -0
  45. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/logo-64x64.png +0 -0
  46. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/kernel.json +13 -0
  47. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-32x32.png +0 -0
  48. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-64x64.png +0 -0
  49. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-svg.svg +75 -0
  50. passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/gp.js +284 -0
  51. passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/main.js +15 -0
  52. passagemath_pari-10.6.32.dist-info/METADATA +209 -0
  53. passagemath_pari-10.6.32.dist-info/RECORD +331 -0
  54. passagemath_pari-10.6.32.dist-info/WHEEL +5 -0
  55. passagemath_pari-10.6.32.dist-info/top_level.txt +4 -0
  56. passagemath_pari.libs/libcrypto-f04afe95.so.3 +0 -0
  57. passagemath_pari.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
  58. passagemath_pari.libs/libgcc_s-0cd532bd.so.1 +0 -0
  59. passagemath_pari.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
  60. passagemath_pari.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
  61. passagemath_pari.libs/libgivaro-9a94c711.so.9.2.1 +0 -0
  62. passagemath_pari.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  63. passagemath_pari.libs/libgmpxx-9e08595c.so.4.7.0 +0 -0
  64. passagemath_pari.libs/libgsl-42cda06f.so.28.0.0 +0 -0
  65. passagemath_pari.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
  66. passagemath_pari.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
  67. passagemath_pari.libs/libntl-26885ca2.so.44.0.1 +0 -0
  68. passagemath_pari.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
  69. passagemath_pari.libs/libpari-gmp-tls-f31f908f.so.2.17.2 +0 -0
  70. passagemath_pari.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
  71. passagemath_pari.libs/libreadline-06542304.so.8.2 +0 -0
  72. passagemath_pari.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
  73. passagemath_pari.libs/libuuid-f3770415.so.1.3.0 +0 -0
  74. passagemath_pari.libs/libxeus-735780ff.so.13.1.0 +0 -0
  75. passagemath_pari.libs/libxeus-zmq-c68577b4.so.6.0.1 +0 -0
  76. passagemath_pari.libs/libzmq-1ba9a3da.so.5.2.5 +0 -0
  77. sage/all__sagemath_pari.py +26 -0
  78. sage/databases/all__sagemath_pari.py +7 -0
  79. sage/databases/conway.py +274 -0
  80. sage/ext/all__sagemath_pari.py +1 -0
  81. sage/ext/memory.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/ext/memory.pyx +98 -0
  83. sage/ext_data/pari/buzzard/DimensionSk.g +286 -0
  84. sage/ext_data/pari/buzzard/Tpprog.g +179 -0
  85. sage/ext_data/pari/buzzard/genusn.g +129 -0
  86. sage/ext_data/pari/dokchitser/computel.gp +740 -0
  87. sage/ext_data/pari/dokchitser/computel.gp.template +740 -0
  88. sage/ext_data/pari/dokchitser/ex-bsw +43 -0
  89. sage/ext_data/pari/dokchitser/ex-chgen +48 -0
  90. sage/ext_data/pari/dokchitser/ex-chqua +37 -0
  91. sage/ext_data/pari/dokchitser/ex-delta +35 -0
  92. sage/ext_data/pari/dokchitser/ex-eisen +30 -0
  93. sage/ext_data/pari/dokchitser/ex-gen2 +38 -0
  94. sage/ext_data/pari/dokchitser/ex-gen3 +49 -0
  95. sage/ext_data/pari/dokchitser/ex-gen4 +54 -0
  96. sage/ext_data/pari/dokchitser/ex-nf +48 -0
  97. sage/ext_data/pari/dokchitser/ex-shin +50 -0
  98. sage/ext_data/pari/dokchitser/ex-tau2 +30 -0
  99. sage/ext_data/pari/dokchitser/ex-zeta +27 -0
  100. sage/ext_data/pari/dokchitser/ex-zeta2 +47 -0
  101. sage/ext_data/pari/dokchitser/testall +13 -0
  102. sage/ext_data/pari/simon/ell.gp +2129 -0
  103. sage/ext_data/pari/simon/ellQ.gp +2151 -0
  104. sage/ext_data/pari/simon/ellcommon.gp +126 -0
  105. sage/ext_data/pari/simon/qfsolve.gp +722 -0
  106. sage/ext_data/pari/simon/resultant3.gp +306 -0
  107. sage/groups/all__sagemath_pari.py +3 -0
  108. sage/groups/pari_group.py +175 -0
  109. sage/interfaces/all__sagemath_pari.py +1 -0
  110. sage/interfaces/genus2reduction.py +464 -0
  111. sage/interfaces/gp.py +1114 -0
  112. sage/libs/all__sagemath_pari.py +2 -0
  113. sage/libs/linkages/__init__.py +1 -0
  114. sage/libs/linkages/padics/API.pxi +617 -0
  115. sage/libs/linkages/padics/Polynomial_ram.pxi +388 -0
  116. sage/libs/linkages/padics/Polynomial_shared.pxi +554 -0
  117. sage/libs/linkages/padics/__init__.py +1 -0
  118. sage/libs/linkages/padics/fmpz_poly_unram.pxi +869 -0
  119. sage/libs/linkages/padics/mpz.pxi +691 -0
  120. sage/libs/linkages/padics/relaxed/API.pxi +518 -0
  121. sage/libs/linkages/padics/relaxed/__init__.py +1 -0
  122. sage/libs/linkages/padics/relaxed/flint.pxi +543 -0
  123. sage/libs/linkages/padics/unram_shared.pxi +247 -0
  124. sage/libs/pari/__init__.py +210 -0
  125. sage/libs/pari/all.py +5 -0
  126. sage/libs/pari/convert_flint.cpython-314-x86_64-linux-musl.so +0 -0
  127. sage/libs/pari/convert_flint.pxd +14 -0
  128. sage/libs/pari/convert_flint.pyx +159 -0
  129. sage/libs/pari/convert_gmp.cpython-314-x86_64-linux-musl.so +0 -0
  130. sage/libs/pari/convert_gmp.pxd +14 -0
  131. sage/libs/pari/convert_gmp.pyx +210 -0
  132. sage/libs/pari/convert_sage.cpython-314-x86_64-linux-musl.so +0 -0
  133. sage/libs/pari/convert_sage.pxd +16 -0
  134. sage/libs/pari/convert_sage.pyx +588 -0
  135. sage/libs/pari/convert_sage_complex_double.cpython-314-x86_64-linux-musl.so +0 -0
  136. sage/libs/pari/convert_sage_complex_double.pxd +14 -0
  137. sage/libs/pari/convert_sage_complex_double.pyx +132 -0
  138. sage/libs/pari/convert_sage_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/libs/pari/convert_sage_matrix.pyx +106 -0
  140. sage/libs/pari/convert_sage_real_double.cpython-314-x86_64-linux-musl.so +0 -0
  141. sage/libs/pari/convert_sage_real_double.pxd +5 -0
  142. sage/libs/pari/convert_sage_real_double.pyx +14 -0
  143. sage/libs/pari/convert_sage_real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  144. sage/libs/pari/convert_sage_real_mpfr.pxd +7 -0
  145. sage/libs/pari/convert_sage_real_mpfr.pyx +108 -0
  146. sage/libs/pari/misc.cpython-314-x86_64-linux-musl.so +0 -0
  147. sage/libs/pari/misc.pxd +4 -0
  148. sage/libs/pari/misc.pyx +26 -0
  149. sage/libs/pari/tests.py +1848 -0
  150. sage/matrix/all__sagemath_pari.py +1 -0
  151. sage/matrix/matrix_integer_pari.cpython-314-x86_64-linux-musl.so +0 -0
  152. sage/matrix/matrix_integer_pari.pyx +187 -0
  153. sage/matrix/matrix_rational_pari.cpython-314-x86_64-linux-musl.so +0 -0
  154. sage/matrix/matrix_rational_pari.pyx +160 -0
  155. sage/quadratic_forms/all__sagemath_pari.py +10 -0
  156. sage/quadratic_forms/genera/all.py +9 -0
  157. sage/quadratic_forms/genera/genus.py +3506 -0
  158. sage/quadratic_forms/genera/normal_form.py +1519 -0
  159. sage/quadratic_forms/genera/spinor_genus.py +243 -0
  160. sage/quadratic_forms/qfsolve.py +255 -0
  161. sage/quadratic_forms/quadratic_form__automorphisms.py +427 -0
  162. sage/quadratic_forms/quadratic_form__genus.py +141 -0
  163. sage/quadratic_forms/quadratic_form__local_density_interfaces.py +140 -0
  164. sage/quadratic_forms/quadratic_form__local_normal_form.py +421 -0
  165. sage/quadratic_forms/quadratic_form__local_representation_conditions.py +889 -0
  166. sage/quadratic_forms/quadratic_form__mass.py +69 -0
  167. sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +663 -0
  168. sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +373 -0
  169. sage/quadratic_forms/quadratic_form__siegel_product.py +198 -0
  170. sage/quadratic_forms/special_values.py +323 -0
  171. sage/rings/all__sagemath_pari.py +15 -0
  172. sage/rings/factorint_pari.cpython-314-x86_64-linux-musl.so +0 -0
  173. sage/rings/factorint_pari.pyx +80 -0
  174. sage/rings/finite_rings/all__sagemath_pari.py +1 -0
  175. sage/rings/finite_rings/element_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  176. sage/rings/finite_rings/element_givaro.pxd +91 -0
  177. sage/rings/finite_rings/element_givaro.pyx +1769 -0
  178. sage/rings/finite_rings/element_ntl_gf2e.cpython-314-x86_64-linux-musl.so +0 -0
  179. sage/rings/finite_rings/element_ntl_gf2e.pxd +22 -0
  180. sage/rings/finite_rings/element_ntl_gf2e.pyx +1333 -0
  181. sage/rings/finite_rings/element_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
  182. sage/rings/finite_rings/element_pari_ffelt.pxd +13 -0
  183. sage/rings/finite_rings/element_pari_ffelt.pyx +1441 -0
  184. sage/rings/finite_rings/finite_field_givaro.py +612 -0
  185. sage/rings/finite_rings/finite_field_pari_ffelt.py +238 -0
  186. sage/rings/finite_rings/hom_finite_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  187. sage/rings/finite_rings/hom_finite_field_givaro.pxd +28 -0
  188. sage/rings/finite_rings/hom_finite_field_givaro.pyx +280 -0
  189. sage/rings/finite_rings/residue_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  190. sage/rings/finite_rings/residue_field_givaro.pyx +133 -0
  191. sage/rings/finite_rings/residue_field_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
  192. sage/rings/finite_rings/residue_field_pari_ffelt.pyx +128 -0
  193. sage/rings/function_field/all__sagemath_pari.py +1 -0
  194. sage/rings/function_field/valuation.py +1450 -0
  195. sage/rings/function_field/valuation_ring.py +212 -0
  196. sage/rings/number_field/all__sagemath_pari.py +14 -0
  197. sage/rings/number_field/totallyreal.cpython-314-x86_64-linux-musl.so +0 -0
  198. sage/rings/number_field/totallyreal.pyx +509 -0
  199. sage/rings/number_field/totallyreal_data.cpython-314-x86_64-linux-musl.so +0 -0
  200. sage/rings/number_field/totallyreal_data.pxd +26 -0
  201. sage/rings/number_field/totallyreal_data.pyx +928 -0
  202. sage/rings/number_field/totallyreal_phc.py +144 -0
  203. sage/rings/number_field/totallyreal_rel.py +1018 -0
  204. sage/rings/padics/CA_template.pxi +1847 -0
  205. sage/rings/padics/CA_template_header.pxi +50 -0
  206. sage/rings/padics/CR_template.pxi +2563 -0
  207. sage/rings/padics/CR_template_header.pxi +57 -0
  208. sage/rings/padics/FM_template.pxi +1575 -0
  209. sage/rings/padics/FM_template_header.pxi +50 -0
  210. sage/rings/padics/FP_template.pxi +2176 -0
  211. sage/rings/padics/FP_template_header.pxi +57 -0
  212. sage/rings/padics/all.py +3 -0
  213. sage/rings/padics/all__sagemath_pari.py +11 -0
  214. sage/rings/padics/common_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  215. sage/rings/padics/common_conversion.pxd +15 -0
  216. sage/rings/padics/common_conversion.pyx +508 -0
  217. sage/rings/padics/eisenstein_extension_generic.py +232 -0
  218. sage/rings/padics/factory.py +3623 -0
  219. sage/rings/padics/generic_nodes.py +1615 -0
  220. sage/rings/padics/lattice_precision.py +2889 -0
  221. sage/rings/padics/morphism.cpython-314-x86_64-linux-musl.so +0 -0
  222. sage/rings/padics/morphism.pxd +11 -0
  223. sage/rings/padics/morphism.pyx +366 -0
  224. sage/rings/padics/padic_base_generic.py +467 -0
  225. sage/rings/padics/padic_base_leaves.py +1235 -0
  226. sage/rings/padics/padic_capped_absolute_element.cpython-314-x86_64-linux-musl.so +0 -0
  227. sage/rings/padics/padic_capped_absolute_element.pxd +15 -0
  228. sage/rings/padics/padic_capped_absolute_element.pyx +520 -0
  229. sage/rings/padics/padic_capped_relative_element.cpython-314-x86_64-linux-musl.so +0 -0
  230. sage/rings/padics/padic_capped_relative_element.pxd +14 -0
  231. sage/rings/padics/padic_capped_relative_element.pyx +614 -0
  232. sage/rings/padics/padic_extension_generic.py +990 -0
  233. sage/rings/padics/padic_extension_leaves.py +738 -0
  234. sage/rings/padics/padic_fixed_mod_element.cpython-314-x86_64-linux-musl.so +0 -0
  235. sage/rings/padics/padic_fixed_mod_element.pxd +15 -0
  236. sage/rings/padics/padic_fixed_mod_element.pyx +584 -0
  237. sage/rings/padics/padic_floating_point_element.cpython-314-x86_64-linux-musl.so +0 -0
  238. sage/rings/padics/padic_floating_point_element.pxd +14 -0
  239. sage/rings/padics/padic_floating_point_element.pyx +447 -0
  240. sage/rings/padics/padic_generic_element.cpython-314-x86_64-linux-musl.so +0 -0
  241. sage/rings/padics/padic_generic_element.pxd +48 -0
  242. sage/rings/padics/padic_generic_element.pyx +4642 -0
  243. sage/rings/padics/padic_lattice_element.py +1342 -0
  244. sage/rings/padics/padic_printing.cpython-314-x86_64-linux-musl.so +0 -0
  245. sage/rings/padics/padic_printing.pxd +38 -0
  246. sage/rings/padics/padic_printing.pyx +1505 -0
  247. sage/rings/padics/padic_relaxed_element.cpython-314-x86_64-linux-musl.so +0 -0
  248. sage/rings/padics/padic_relaxed_element.pxd +56 -0
  249. sage/rings/padics/padic_relaxed_element.pyx +18 -0
  250. sage/rings/padics/padic_relaxed_errors.cpython-314-x86_64-linux-musl.so +0 -0
  251. sage/rings/padics/padic_relaxed_errors.pxd +11 -0
  252. sage/rings/padics/padic_relaxed_errors.pyx +71 -0
  253. sage/rings/padics/padic_template_element.pxi +1212 -0
  254. sage/rings/padics/padic_template_element_header.pxi +50 -0
  255. sage/rings/padics/padic_valuation.py +1423 -0
  256. sage/rings/padics/pow_computer_flint.cpython-314-x86_64-linux-musl.so +0 -0
  257. sage/rings/padics/pow_computer_flint.pxd +38 -0
  258. sage/rings/padics/pow_computer_flint.pyx +641 -0
  259. sage/rings/padics/pow_computer_relative.cpython-314-x86_64-linux-musl.so +0 -0
  260. sage/rings/padics/pow_computer_relative.pxd +29 -0
  261. sage/rings/padics/pow_computer_relative.pyx +415 -0
  262. sage/rings/padics/qadic_flint_CA.cpython-314-x86_64-linux-musl.so +0 -0
  263. sage/rings/padics/qadic_flint_CA.pxd +21 -0
  264. sage/rings/padics/qadic_flint_CA.pyx +130 -0
  265. sage/rings/padics/qadic_flint_CR.cpython-314-x86_64-linux-musl.so +0 -0
  266. sage/rings/padics/qadic_flint_CR.pxd +13 -0
  267. sage/rings/padics/qadic_flint_CR.pyx +172 -0
  268. sage/rings/padics/qadic_flint_FM.cpython-314-x86_64-linux-musl.so +0 -0
  269. sage/rings/padics/qadic_flint_FM.pxd +14 -0
  270. sage/rings/padics/qadic_flint_FM.pyx +111 -0
  271. sage/rings/padics/qadic_flint_FP.cpython-314-x86_64-linux-musl.so +0 -0
  272. sage/rings/padics/qadic_flint_FP.pxd +12 -0
  273. sage/rings/padics/qadic_flint_FP.pyx +165 -0
  274. sage/rings/padics/relative_extension_leaves.py +429 -0
  275. sage/rings/padics/relative_ramified_CA.cpython-314-x86_64-linux-musl.so +0 -0
  276. sage/rings/padics/relative_ramified_CA.pxd +9 -0
  277. sage/rings/padics/relative_ramified_CA.pyx +33 -0
  278. sage/rings/padics/relative_ramified_CR.cpython-314-x86_64-linux-musl.so +0 -0
  279. sage/rings/padics/relative_ramified_CR.pxd +8 -0
  280. sage/rings/padics/relative_ramified_CR.pyx +33 -0
  281. sage/rings/padics/relative_ramified_FM.cpython-314-x86_64-linux-musl.so +0 -0
  282. sage/rings/padics/relative_ramified_FM.pxd +9 -0
  283. sage/rings/padics/relative_ramified_FM.pyx +33 -0
  284. sage/rings/padics/relative_ramified_FP.cpython-314-x86_64-linux-musl.so +0 -0
  285. sage/rings/padics/relative_ramified_FP.pxd +8 -0
  286. sage/rings/padics/relative_ramified_FP.pyx +33 -0
  287. sage/rings/padics/relaxed_template.pxi +4229 -0
  288. sage/rings/padics/relaxed_template_header.pxi +160 -0
  289. sage/rings/padics/tests.py +35 -0
  290. sage/rings/padics/tutorial.py +341 -0
  291. sage/rings/padics/unramified_extension_generic.py +335 -0
  292. sage/rings/padics/witt_vector.py +917 -0
  293. sage/rings/padics/witt_vector_ring.py +934 -0
  294. sage/rings/pari_ring.py +235 -0
  295. sage/rings/polynomial/all__sagemath_pari.py +1 -0
  296. sage/rings/polynomial/padics/all.py +1 -0
  297. sage/rings/polynomial/padics/polynomial_padic.py +360 -0
  298. sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +1324 -0
  299. sage/rings/polynomial/padics/polynomial_padic_flat.py +72 -0
  300. sage/rings/power_series_pari.cpython-314-x86_64-linux-musl.so +0 -0
  301. sage/rings/power_series_pari.pxd +6 -0
  302. sage/rings/power_series_pari.pyx +934 -0
  303. sage/rings/tate_algebra.py +1282 -0
  304. sage/rings/tate_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  305. sage/rings/tate_algebra_element.pxd +49 -0
  306. sage/rings/tate_algebra_element.pyx +3464 -0
  307. sage/rings/tate_algebra_ideal.cpython-314-x86_64-linux-musl.so +0 -0
  308. sage/rings/tate_algebra_ideal.pxd +7 -0
  309. sage/rings/tate_algebra_ideal.pyx +1307 -0
  310. sage/rings/valuation/all.py +7 -0
  311. sage/rings/valuation/augmented_valuation.py +2118 -0
  312. sage/rings/valuation/developing_valuation.py +362 -0
  313. sage/rings/valuation/gauss_valuation.py +812 -0
  314. sage/rings/valuation/inductive_valuation.py +1686 -0
  315. sage/rings/valuation/limit_valuation.py +946 -0
  316. sage/rings/valuation/mapped_valuation.py +656 -0
  317. sage/rings/valuation/scaled_valuation.py +322 -0
  318. sage/rings/valuation/trivial_valuation.py +382 -0
  319. sage/rings/valuation/valuation.py +1119 -0
  320. sage/rings/valuation/valuation_space.py +1615 -0
  321. sage/rings/valuation/valuations_catalog.py +10 -0
  322. sage/rings/valuation/value_group.py +697 -0
  323. sage/schemes/all__sagemath_pari.py +1 -0
  324. sage/schemes/elliptic_curves/all__sagemath_pari.py +1 -0
  325. sage/schemes/elliptic_curves/descent_two_isogeny_pari.cpython-314-x86_64-linux-musl.so +0 -0
  326. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pyx +46 -0
  327. sage_wheels/bin/gp +0 -0
  328. sage_wheels/bin/gp2c +0 -0
  329. sage_wheels/bin/gp2c-run +57 -0
  330. sage_wheels/bin/xeus-gp +0 -0
  331. sage_wheels/share/gp2c/func.dsc +18414 -0
@@ -0,0 +1,2118 @@
1
+ # sage_setup: distribution = sagemath-pari
2
+ r"""
3
+ Augmented valuations on polynomial rings
4
+
5
+ Implements augmentations of (inductive) valuations.
6
+
7
+ AUTHORS:
8
+
9
+ - Julian Rüth (2013-04-15): initial version
10
+
11
+ EXAMPLES:
12
+
13
+ Starting from a :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>`, we can create augmented valuations on
14
+ polynomial rings::
15
+
16
+ sage: R.<x> = QQ[]
17
+ sage: v = GaussValuation(R, QQ.valuation(2))
18
+ sage: w = v.augmentation(x, 1); w
19
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 1 ]
20
+ sage: w(x)
21
+ 1
22
+
23
+ This also works for polynomial rings over base rings which are not fields.
24
+ However, much of the functionality is only available over fields::
25
+
26
+ sage: R.<x> = ZZ[]
27
+ sage: v = GaussValuation(R, ZZ.valuation(2))
28
+ sage: w = v.augmentation(x, 1); w
29
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 1 ]
30
+ sage: w(x)
31
+ 1
32
+
33
+ TESTS::
34
+
35
+ sage: R.<x> = QQ[]
36
+ sage: v = GaussValuation(R, QQ.valuation(2))
37
+ sage: w = v.augmentation(x, 1)
38
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
39
+ sage: w = v.augmentation(x, 2)
40
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
41
+
42
+ Run the test suite for a valuation with a residual extension::
43
+
44
+ sage: R.<x> = QQ[]
45
+ sage: v = GaussValuation(R, QQ.valuation(2))
46
+ sage: w = v.augmentation(x^2 + x + 1, 1)
47
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
48
+
49
+ Run the test suite for an iterated residual extension starting from a
50
+ non-prime residue field::
51
+
52
+ sage: # needs sage.libs.ntl
53
+ sage: R.<u> = Qq(4, 40)
54
+ sage: S.<x> = R[]
55
+ sage: v = GaussValuation(S)
56
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
57
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
58
+ sage: ww = w.augmentation(x^8 + 4*x^7 + 2*x^6 + 2*x^5 + x^4 + 2*x^3
59
+ ....: + 4*(u + 1)*x^2 + 6*(u + 1)*x + 4 + 3*u, 10)
60
+ sage: TestSuite(ww).run() # long time
61
+
62
+ Run the test suite for an augmentation of a ramified augmentation::
63
+
64
+ sage: # needs sage.libs.ntl
65
+ sage: R.<u> = Qq(4, 5)
66
+ sage: S.<x> = R[]
67
+ sage: v = GaussValuation(S)
68
+ sage: w = v.augmentation(x, 3/4)
69
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
70
+ sage: ww = w.augmentation(x^4 + 8, 5)
71
+ sage: TestSuite(ww).run() # long time # needs sage.numerical.mip
72
+
73
+ Run the test suite for a ramified augmentation of an unramified augmentation::
74
+
75
+ sage: R.<x> = QQ[]
76
+ sage: v = GaussValuation(R, QQ.valuation(2))
77
+ sage: w = v.augmentation(x^2 + x + 1, 1)
78
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
79
+ sage: ww = w.augmentation(x^4 + 2*x^3 + 5*x^2 + 8*x + 3, 16/3)
80
+ sage: TestSuite(ww).run() # long time # needs sage.numerical.mip
81
+
82
+ Run the test suite for a ramified augmentation of a ramified augmentation::
83
+
84
+ sage: # needs sage.libs.ntl
85
+ sage: R.<u> = Qq(4, 20)
86
+ sage: S.<x> = R[]
87
+ sage: v = GaussValuation(S)
88
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
89
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
90
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
91
+ sage: TestSuite(ww).run() # long time # needs sage.numerical.mip
92
+
93
+ Run the test suite for another augmentation with iterated residue field extensions::
94
+
95
+ sage: # needs sage.libs.ntl
96
+ sage: R.<u> = Qq(4, 10)
97
+ sage: S.<x> = R[]
98
+ sage: v = GaussValuation(S)
99
+ sage: w = v.augmentation(x^2 + x + u, 1)
100
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
101
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3)
102
+ sage: TestSuite(ww).run() # long time # needs sage.numerical.mip
103
+
104
+ Run the test suite for a rather trivial pseudo-valuation::
105
+
106
+ sage: # needs sage.libs.ntl
107
+ sage: R.<u> = Qq(4, 5)
108
+ sage: S.<x> = R[]
109
+ sage: v = GaussValuation(S)
110
+ sage: w = v.augmentation(x, infinity)
111
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
112
+
113
+ Run the test suite for an infinite valuation which extends the residue field::
114
+
115
+ sage: # needs sage.libs.ntl
116
+ sage: R.<u> = Qq(4, 5)
117
+ sage: S.<x> = R[]
118
+ sage: v = GaussValuation(S)
119
+ sage: w = v.augmentation(x^2 + x + u, infinity)
120
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
121
+
122
+ Run the test suite for an infinite valuation which extends a valuation which
123
+ extends the residue field::
124
+
125
+ sage: # needs sage.libs.ntl
126
+ sage: R.<u> = Qq(4, 5)
127
+ sage: S.<x> = R[]
128
+ sage: v = GaussValuation(S)
129
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
130
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
131
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, infinity)
132
+ sage: TestSuite(ww).run() # long time # needs sage.numerical.mip
133
+
134
+ Run the test suite if the polynomial ring is not over a field::
135
+
136
+ sage: R.<x> = ZZ[]
137
+ sage: v = GaussValuation(R, ZZ.valuation(2))
138
+ sage: w = v.augmentation(x, 1)
139
+ sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron
140
+
141
+ REFERENCES:
142
+
143
+ Augmentations are described originally in [Mac1936I]_ and [Mac1936II]_. An
144
+ overview can also be found in Chapter 4 of [Rüt2014]_.
145
+ """
146
+ # ****************************************************************************
147
+ # Copyright (C) 2013-2017 Julian Rüth <julian.rueth@fsfe.org>
148
+ #
149
+ # Distributed under the terms of the GNU General Public License (GPL)
150
+ # as published by the Free Software Foundation; either version 2 of
151
+ # the License, or (at your option) any later version.
152
+ # https://www.gnu.org/licenses/
153
+ # ****************************************************************************
154
+ from itertools import islice
155
+
156
+ from .inductive_valuation import _lift_to_maximal_precision
157
+ from .inductive_valuation import FinalInductiveValuation, NonFinalInductiveValuation, FiniteInductiveValuation, InfiniteInductiveValuation, InductiveValuation
158
+
159
+ from sage.misc.cachefunc import cached_method
160
+ from sage.rings.infinity import infinity
161
+ from sage.rings.rational_field import QQ
162
+ from sage.structure.factory import UniqueFactory
163
+
164
+
165
+ class AugmentedValuationFactory(UniqueFactory):
166
+ r"""
167
+ Factory for augmented valuations.
168
+
169
+ EXAMPLES:
170
+
171
+ This factory is not meant to be called directly. Instead,
172
+ :meth:`~sage.rings.valuation.inductive_valuation.NonFinalInductiveValuation.augmentation`
173
+ of a valuation should be called::
174
+
175
+ sage: R.<x> = QQ[]
176
+ sage: v = GaussValuation(R, QQ.valuation(2))
177
+ sage: w = v.augmentation(x, 1) # indirect doctest
178
+
179
+ Note that trivial parts of the augmented valuation might be dropped, so you
180
+ should not rely on ``_base_valuation`` to be the valuation you started
181
+ with::
182
+
183
+ sage: ww = w.augmentation(x, 2)
184
+ sage: ww._base_valuation is v
185
+ True
186
+ """
187
+ def create_key(self, base_valuation, phi, mu, check=True):
188
+ r"""
189
+ Create a key which uniquely identifies the valuation over
190
+ ``base_valuation`` which sends ``phi`` to ``mu``.
191
+
192
+ .. NOTE::
193
+
194
+ The uniqueness that this factory provides is not why we chose to
195
+ use a factory. However, it makes pickling and equality checks much
196
+ easier. At the same time, going through a factory makes it easier
197
+ to enforce that all instances correctly inherit methods from the
198
+ parent Hom space.
199
+
200
+ TESTS::
201
+
202
+ sage: R.<x> = QQ[]
203
+ sage: v = GaussValuation(R, QQ.valuation(2))
204
+ sage: w = v.augmentation(x, 1) # indirect doctest
205
+ sage: ww = v.augmentation(x, 1)
206
+ sage: w is ww
207
+ True
208
+ """
209
+ if check:
210
+ is_key, reason = base_valuation.is_key(phi, explain=True)
211
+ if not is_key:
212
+ raise ValueError(reason)
213
+ if mu <= base_valuation(phi):
214
+ raise ValueError("the value of the key polynomial must strictly increase but `%s` does not exceed `%s`." % (mu, base_valuation(phi)))
215
+ if not isinstance(base_valuation, InductiveValuation):
216
+ raise TypeError("base_valuation must be inductive")
217
+
218
+ phi = base_valuation.domain().coerce(phi)
219
+ if mu is not infinity:
220
+ mu = QQ(mu)
221
+
222
+ if isinstance(base_valuation, AugmentedValuation_base):
223
+ if phi.degree() == base_valuation.phi().degree():
224
+ # drop base_valuation and extend base_valuation._base_valuation instead
225
+ return self.create_key(base_valuation._base_valuation, phi, mu, check=check)
226
+
227
+ return base_valuation, phi, mu
228
+
229
+ def create_object(self, version, key):
230
+ r"""
231
+ Create the augmented valuation represented by ``key``.
232
+
233
+ TESTS::
234
+
235
+ sage: R.<x> = QQ[]
236
+ sage: v = GaussValuation(R, QQ.valuation(2))
237
+ sage: w = v.augmentation(x^2 + x + 1, 1) # indirect doctest
238
+ """
239
+ base_valuation, phi, mu = key
240
+
241
+ from .valuation_space import DiscretePseudoValuationSpace
242
+ parent = DiscretePseudoValuationSpace(base_valuation.domain())
243
+ if mu is not infinity:
244
+ if base_valuation.is_trivial():
245
+ return parent.__make_element_class__(FinalFiniteAugmentedValuation)(parent, base_valuation, phi, mu)
246
+ else:
247
+ return parent.__make_element_class__(NonFinalFiniteAugmentedValuation)(parent, base_valuation, phi, mu)
248
+ else:
249
+ return parent.__make_element_class__(InfiniteAugmentedValuation)(parent, base_valuation, phi, mu)
250
+
251
+
252
+ AugmentedValuation = AugmentedValuationFactory("sage.rings.valuation.augmented_valuation.AugmentedValuation")
253
+
254
+
255
+ class AugmentedValuation_base(InductiveValuation):
256
+ r"""
257
+ An augmented valuation is a discrete valuation on a polynomial ring. It
258
+ extends another discrete valuation `v` by setting the valuation of a
259
+ polynomial `f` to the minimum of `v(f_i)i\mu` when writing `f=\sum_i
260
+ f_i\phi^i`.
261
+
262
+ INPUT:
263
+
264
+ - ``v`` -- a :class:`~sage.rings.valuation.inductive_valuation.InductiveValuation` on a polynomial ring
265
+
266
+ - ``phi`` -- a :meth:`key polynomial <sage.rings.valuation.inductive_valuation.NonFinalInductiveValuation.is_key>` over ``v``
267
+
268
+ - ``mu`` -- a rational number such that ``mu > v(phi)`` or ``infinity``
269
+
270
+ EXAMPLES::
271
+
272
+ sage: # needs sage.rings.number_field
273
+ sage: K.<u> = CyclotomicField(5)
274
+ sage: R.<x> = K[]
275
+ sage: v = GaussValuation(R, K.valuation(2))
276
+ sage: w = v.augmentation(x, 1/2); w # indirect doctest
277
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 1/2 ]
278
+ sage: ww = w.augmentation(x^4 + 2*x^2 + 4*u, 3); ww
279
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 1/2, v(x^4 + 2*x^2 + 4*u) = 3 ]
280
+
281
+ TESTS::
282
+
283
+ sage: # needs sage.rings.number_field
284
+ sage: TestSuite(w).run() # long time
285
+ sage: TestSuite(ww).run() # long time
286
+ """
287
+ def __init__(self, parent, v, phi, mu):
288
+ r"""
289
+ TESTS::
290
+
291
+ sage: # needs sage.libs.ntl
292
+ sage: K.<u> = Qq(4, 5)
293
+ sage: R.<x> = K[]
294
+ sage: v = GaussValuation(R)
295
+ sage: from sage.rings.valuation.augmented_valuation import AugmentedValuation
296
+ sage: w = AugmentedValuation(v, x, 1/2)
297
+ sage: from sage.rings.valuation.augmented_valuation import AugmentedValuation_base
298
+ sage: isinstance(w, AugmentedValuation_base)
299
+ True
300
+ sage: TestSuite(w).run() # long time # needs sage.numerical.mip
301
+ """
302
+ InductiveValuation.__init__(self, parent, phi)
303
+
304
+ self._base_valuation = v
305
+ self._mu = mu
306
+
307
+ @cached_method
308
+ def equivalence_unit(self, s, reciprocal=False):
309
+ r"""
310
+ Return an equivalence unit of minimal degree and valuation ``s``.
311
+
312
+ INPUT:
313
+
314
+ - ``s`` -- a rational number
315
+
316
+ - ``reciprocal`` -- boolean (default: ``False``); whether or not to
317
+ return the equivalence unit as the :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.equivalence_reciprocal`
318
+ of the equivalence unit of valuation ``-s``.
319
+
320
+ OUTPUT:
321
+
322
+ A polynomial in the domain of this valuation which
323
+ :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.is_equivalence_unit` for this valuation.
324
+
325
+ EXAMPLES::
326
+
327
+ sage: # needs sage.libs.ntl
328
+ sage: R.<u> = Qq(4, 5)
329
+ sage: S.<x> = R[]
330
+ sage: v = GaussValuation(S)
331
+ sage: w = v.augmentation(x^2 + x + u, 1)
332
+ sage: w.equivalence_unit(0)
333
+ 1 + O(2^5)
334
+ sage: w.equivalence_unit(-4)
335
+ 2^-4 + O(2)
336
+
337
+ Since an equivalence unit is of effective degree zero, `\phi` must not
338
+ divide it. Therefore, its valuation is in the value group of the base
339
+ valuation::
340
+
341
+ sage: w = v.augmentation(x, 1/2) # needs sage.libs.ntl
342
+ sage: w.equivalence_unit(3/2) # needs sage.libs.ntl
343
+ Traceback (most recent call last):
344
+ ...
345
+ ValueError: 3/2 is not in the value semigroup of 2-adic valuation
346
+ sage: w.equivalence_unit(1) # needs sage.libs.ntl
347
+ 2 + O(2^6)
348
+
349
+ An equivalence unit might not be integral, even if ``s >= 0``::
350
+
351
+ sage: w = v.augmentation(x, 3/4) # needs sage.libs.ntl
352
+ sage: ww = w.augmentation(x^4 + 8, 5) # needs sage.libs.ntl
353
+ sage: ww.equivalence_unit(1/2) # needs sage.libs.ntl
354
+ (2^-1 + O(2^4))*x^2
355
+ """
356
+ if reciprocal:
357
+ ret = self._base_valuation.element_with_valuation(s)
358
+ residue = self.reduce(ret * self._base_valuation.element_with_valuation(-s), check=False)
359
+ assert residue.is_constant()
360
+ ret *= self.lift(~(residue[0]))
361
+ else:
362
+ ret = self._base_valuation.element_with_valuation(s)
363
+
364
+ assert self.is_equivalence_unit(ret)
365
+ assert self(ret) == s
366
+ return ret
367
+
368
+ @cached_method
369
+ def element_with_valuation(self, s):
370
+ r"""
371
+ Create an element of minimal degree and of valuation ``s``.
372
+
373
+ INPUT:
374
+
375
+ - ``s`` -- a rational number in the value group of this valuation
376
+
377
+ OUTPUT: an element in the domain of this valuation
378
+
379
+ EXAMPLES::
380
+
381
+ sage: # needs sage.libs.ntl
382
+ sage: R.<u> = Qq(4, 5)
383
+ sage: S.<x> = R[]
384
+ sage: v = GaussValuation(S)
385
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
386
+ sage: w.element_with_valuation(0)
387
+ 1 + O(2^5)
388
+ sage: w.element_with_valuation(1/2)
389
+ (1 + O(2^5))*x^2 + (1 + O(2^5))*x + u + O(2^5)
390
+ sage: w.element_with_valuation(1)
391
+ 2 + O(2^6)
392
+ sage: c = w.element_with_valuation(-1/2); c
393
+ (2^-1 + O(2^4))*x^2 + (2^-1 + O(2^4))*x + u*2^-1 + O(2^4)
394
+ sage: w(c)
395
+ -1/2
396
+ sage: w.element_with_valuation(1/3)
397
+ Traceback (most recent call last):
398
+ ...
399
+ ValueError: s must be in the value group of the valuation
400
+ but 1/3 is not in Additive Abelian Group generated by 1/2.
401
+ """
402
+ if s not in self.value_group():
403
+ raise ValueError("s must be in the value group of the valuation but %r is not in %r." % (s, self.value_group()))
404
+ error = s
405
+
406
+ ret = self.domain().one()
407
+ while s not in self._base_valuation.value_group():
408
+ ret *= self._phi
409
+ s -= self._mu
410
+ ret = ret * self._base_valuation.element_with_valuation(s)
411
+ return self.simplify(ret, error=error)
412
+
413
+ def _repr_(self):
414
+ r"""
415
+ Return a printable representation of this valuation.
416
+
417
+ EXAMPLES::
418
+
419
+ sage: # needs sage.libs.ntl
420
+ sage: R.<u> = Qq(4, 5)
421
+ sage: S.<x> = R[]
422
+ sage: v = GaussValuation(S)
423
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
424
+ sage: w # indirect doctest
425
+ [ Gauss valuation induced by 2-adic valuation,
426
+ v((1 + O(2^5))*x^2 + (1 + O(2^5))*x + u + O(2^5)) = 1/2 ]
427
+ """
428
+ vals = self.augmentation_chain()
429
+ vals.reverse()
430
+ vals = ["v(%s) = %s" % (v._phi, v._mu) if isinstance(v, AugmentedValuation_base) else str(v) for v in vals]
431
+ return "[ %s ]" % ", ".join(vals)
432
+
433
+ def augmentation_chain(self):
434
+ r"""
435
+ Return a list with the chain of augmentations down to the underlying :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>`.
436
+
437
+ .. NOTE::
438
+
439
+ This method runs in time linear in the length of the chain (though
440
+ the printed representation might seem to indicate that it takes
441
+ quadratic time to construct the chain.)
442
+
443
+ EXAMPLES::
444
+
445
+ sage: R.<x> = QQ[]
446
+ sage: v = GaussValuation(R, QQ.valuation(2))
447
+ sage: w = v.augmentation(x, 1)
448
+ sage: w.augmentation_chain()
449
+ [[ Gauss valuation induced by 2-adic valuation, v(x) = 1 ],
450
+ Gauss valuation induced by 2-adic valuation]
451
+
452
+ For performance reasons, (and to simplify the underlying
453
+ implementation,) trivial augmentations might get dropped. You should
454
+ not rely on :meth:`augmentation_chain` to contain all the steps that
455
+ you specified to create the current valuation::
456
+
457
+ sage: ww = w.augmentation(x, 2)
458
+ sage: ww.augmentation_chain()
459
+ [[ Gauss valuation induced by 2-adic valuation, v(x) = 2 ],
460
+ Gauss valuation induced by 2-adic valuation]
461
+ """
462
+ return [self] + self._base_valuation.augmentation_chain()
463
+
464
+ @cached_method
465
+ def psi(self):
466
+ r"""
467
+ Return the minimal polynomial of the residue field extension of this valuation.
468
+
469
+ OUTPUT: a polynomial in the residue ring of the base valuation
470
+
471
+ EXAMPLES::
472
+
473
+ sage: # needs sage.libs.ntl
474
+ sage: R.<u> = Qq(4, 5)
475
+ sage: S.<x> = R[]
476
+ sage: v = GaussValuation(S)
477
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
478
+ sage: w.psi()
479
+ x^2 + x + u0
480
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
481
+ sage: ww.psi()
482
+ x + 1
483
+ """
484
+ R = self._base_valuation.equivalence_unit(-self._base_valuation(self._phi))
485
+ F = self._base_valuation.reduce(self._phi * R, check=False).monic()
486
+ assert F.is_irreducible()
487
+ return F
488
+
489
+ @cached_method
490
+ def E(self):
491
+ r"""
492
+ Return the ramification index of this valuation over its underlying
493
+ Gauss valuation.
494
+
495
+ EXAMPLES::
496
+
497
+ sage: # needs sage.libs.ntl
498
+ sage: R.<u> = Qq(4, 5)
499
+ sage: S.<x> = R[]
500
+ sage: v = GaussValuation(S)
501
+ sage: w = v.augmentation(x^2 + x + u, 1)
502
+ sage: w.E()
503
+ 1
504
+ sage: w = v.augmentation(x, 1/2)
505
+ sage: w.E()
506
+ 2
507
+ """
508
+ if self.augmentation_chain()[-1]._base_valuation.is_trivial():
509
+ raise NotImplementedError("ramification index is not defined over a trivial Gauss valuation")
510
+ return self.value_group().index(self._base_valuation.value_group()) * self._base_valuation.E()
511
+
512
+ @cached_method
513
+ def F(self):
514
+ r"""
515
+ Return the degree of the residue field extension of this valuation
516
+ over the underlying Gauss valuation.
517
+
518
+ EXAMPLES::
519
+
520
+ sage: # needs sage.libs.ntl
521
+ sage: R.<u> = Qq(4, 5)
522
+ sage: S.<x> = R[]
523
+ sage: v = GaussValuation(S)
524
+ sage: w = v.augmentation(x^2 + x + u, 1)
525
+ sage: w.F()
526
+ 2
527
+ sage: w = v.augmentation(x, 1/2)
528
+ sage: w.F()
529
+ 1
530
+ """
531
+ return self.phi().degree() // self._base_valuation.E()
532
+
533
+ def extensions(self, ring):
534
+ r"""
535
+ Return the extensions of this valuation to ``ring``.
536
+
537
+ EXAMPLES::
538
+
539
+ sage: R.<x> = QQ[]
540
+ sage: v = GaussValuation(R, QQ.valuation(2))
541
+ sage: w = v.augmentation(x^2 + x + 1, 1)
542
+ sage: w.extensions(GaussianIntegers().fraction_field()['x']) # needs sage.geometry.polyhedron sage.rings.number_field
543
+ [[ Gauss valuation induced by 2-adic valuation, v(x^2 + x + 1) = 1 ]]
544
+ """
545
+ if ring is self.domain():
546
+ return [self]
547
+
548
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
549
+ if isinstance(ring, PolynomialRing_generic): # univariate
550
+ base_valuations = self._base_valuation.extensions(ring)
551
+ phi = self.phi().change_ring(ring.base_ring())
552
+
553
+ ret = []
554
+ for v in base_valuations:
555
+ if v.is_key(phi):
556
+ ret.append(AugmentedValuation(v, phi, self._mu))
557
+ else:
558
+ F = v.equivalence_decomposition(phi)
559
+ for f, e in F:
560
+ # We construct a valuation with [v, w(phi) = mu] which should be such that
561
+ # self(phi) = self._mu, i.e., w(phi) = w(unit) + sum e_i * w(f_i) where
562
+ # the sum runs over all the factors in the equivalence decomposition of phi
563
+ # Solving for mu gives
564
+ mu = (self._mu - v(F.unit()) - sum([ee * v(ff) for ff, ee in F if ff != f])) / e
565
+ ret.append(AugmentedValuation(v, f, mu))
566
+ return ret
567
+
568
+ return super().extensions(ring)
569
+
570
+ def restriction(self, ring):
571
+ r"""
572
+ Return the restriction of this valuation to ``ring``.
573
+
574
+ EXAMPLES::
575
+
576
+ sage: # needs sage.geometry.polyhedron sage.libs.singular sage.rings.number_field
577
+ sage: K = GaussianIntegers().fraction_field()
578
+ sage: R.<x> = K[]
579
+ sage: v = GaussValuation(R, K.valuation(2))
580
+ sage: w = v.augmentation(x^2 + x + 1, 1)
581
+ sage: w.restriction(QQ['x'])
582
+ [ Gauss valuation induced by 2-adic valuation, v(x^2 + x + 1) = 1 ]
583
+ """
584
+ if ring.is_subring(self.domain()):
585
+ base = self._base_valuation.restriction(ring)
586
+ if ring.is_subring(self.domain().base_ring()):
587
+ return base
588
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
589
+ if isinstance(ring, PolynomialRing_generic): # univariate
590
+ return base.augmentation(self.phi().change_ring(ring.base_ring()), self._mu)
591
+ return super().restriction(ring)
592
+
593
+ def uniformizer(self):
594
+ r"""
595
+ Return a uniformizing element for this valuation.
596
+
597
+ EXAMPLES::
598
+
599
+ sage: R.<x> = QQ[]
600
+ sage: v = GaussValuation(R, QQ.valuation(2))
601
+ sage: w = v.augmentation(x^2 + x + 1, 1)
602
+
603
+ sage: w.uniformizer()
604
+ 2
605
+ """
606
+ return self.element_with_valuation(self.value_group()._generator)
607
+
608
+ def is_gauss_valuation(self):
609
+ r"""
610
+ Return whether this valuation is a Gauss valuation.
611
+
612
+ EXAMPLES::
613
+
614
+ sage: R.<x> = QQ[]
615
+ sage: v = GaussValuation(R, QQ.valuation(2))
616
+ sage: w = v.augmentation(x^2 + x + 1, 1)
617
+
618
+ sage: w.is_gauss_valuation()
619
+ False
620
+ """
621
+ assert (self._mu > 0)
622
+ return False
623
+
624
+ def monic_integral_model(self, G):
625
+ r"""
626
+ Return a monic integral irreducible polynomial which defines the same
627
+ extension of the base ring of the domain as the irreducible polynomial
628
+ ``G`` together with maps between the old and the new polynomial.
629
+
630
+ EXAMPLES::
631
+
632
+ sage: R.<x> = QQ[]
633
+ sage: v = GaussValuation(R, QQ.valuation(2))
634
+ sage: w = v.augmentation(x^2 + x + 1, 1)
635
+ sage: w.monic_integral_model(5*x^2 + 1/2*x + 1/4)
636
+ (Ring endomorphism of Univariate Polynomial Ring in x over Rational Field
637
+ Defn: x |--> 1/2*x,
638
+ Ring endomorphism of Univariate Polynomial Ring in x over Rational Field
639
+ Defn: x |--> 2*x,
640
+ x^2 + 1/5*x + 1/5)
641
+ """
642
+ return self._base_valuation.monic_integral_model(G)
643
+
644
+ def _ge_(self, other):
645
+ r"""
646
+ Return whether this valuation is greater or equal than ``other``
647
+ everywhere.
648
+
649
+ EXAMPLES::
650
+
651
+ sage: R.<x> = QQ[]
652
+ sage: v = GaussValuation(R, QQ.valuation(2))
653
+ sage: w = v.augmentation(x^2 + x + 1, 1)
654
+ sage: w >= v
655
+ True
656
+ sage: ww = v.augmentation(x^2 + x + 1, 2)
657
+ sage: ww >= w
658
+ True
659
+ sage: www = w.augmentation(x^4 + 2*x^3 + 5*x^2 + 8*x + 3, 16/3)
660
+ sage: www >= w
661
+ True
662
+ sage: www >= ww
663
+ False
664
+ """
665
+ from .gauss_valuation import GaussValuation_generic
666
+ if other.is_trivial():
667
+ return other.is_discrete_valuation()
668
+ if isinstance(other, GaussValuation_generic):
669
+ return self._base_valuation >= other
670
+ if isinstance(other, AugmentedValuation_base):
671
+ if self(other._phi) >= other._mu:
672
+ return self >= other._base_valuation
673
+ else:
674
+ return False
675
+
676
+ return super()._ge_(other)
677
+
678
+ def is_trivial(self):
679
+ r"""
680
+ Return whether this valuation is trivial, i.e., zero outside of zero.
681
+
682
+ EXAMPLES::
683
+
684
+ sage: R.<x> = QQ[]
685
+ sage: v = GaussValuation(R, QQ.valuation(2))
686
+ sage: w = v.augmentation(x^2 + x + 1, 1)
687
+ sage: w.is_trivial()
688
+ False
689
+ """
690
+ # We need to override the default implementation from valuation_space
691
+ # because that one uses uniformizer() which might not be implemented if
692
+ # the base ring is not a field.
693
+ return False
694
+
695
+ def scale(self, scalar):
696
+ r"""
697
+ Return this valuation scaled by ``scalar``.
698
+
699
+ EXAMPLES::
700
+
701
+ sage: R.<x> = QQ[]
702
+ sage: v = GaussValuation(R, QQ.valuation(2))
703
+ sage: w = v.augmentation(x^2 + x + 1, 1)
704
+ sage: 3*w # indirect doctest
705
+ [ Gauss valuation induced by 3 * 2-adic valuation, v(x^2 + x + 1) = 3 ]
706
+ """
707
+ if scalar in QQ and scalar > 0 and scalar != 1:
708
+ return self._base_valuation.scale(scalar).augmentation(self.phi(), scalar * self._mu)
709
+ return super().scale(scalar)
710
+
711
+ def _residue_ring_generator_name(self):
712
+ r"""
713
+ Return a name for a generator of the residue ring.
714
+
715
+ This method is used by :meth:`residue_ring` to work around name clashes
716
+ with names in subrings of the residue ring.
717
+
718
+ EXAMPLES::
719
+
720
+ sage: R.<x> = QQ[]
721
+ sage: v = GaussValuation(R, QQ.valuation(2))
722
+ sage: w = v.augmentation(x^2 + x + 1, 1)
723
+ sage: w._residue_ring_generator_name()
724
+ 'u1'
725
+ """
726
+ base = self._base_valuation.residue_ring().base()
727
+ # we need a name for a generator that is not present already in base
728
+ generator = 'u' + str(len(self.augmentation_chain()) - 1)
729
+ while True:
730
+ try:
731
+ base(generator)
732
+ generator = 'u' + generator
733
+ except NameError:
734
+ # use this name, it has no meaning in base
735
+ return generator
736
+ except TypeError:
737
+ # use this name, base can not handle strings, so hopefully,
738
+ # there are no variable names (such as in QQ or GF(p))
739
+ return generator
740
+
741
+ def _relative_size(self, f):
742
+ r"""
743
+ Return an estimate on the coefficient size of ``f``.
744
+
745
+ The number returned is an estimate on the factor between the number of
746
+ bits used by ``f`` and the minimal number of bits used by an element
747
+ congruent to ``f``.
748
+
749
+ This is used by :meth:`simplify` to decide whether simplification of
750
+ coefficients is going to lead to a significant shrinking of the
751
+ coefficients of ``f``.
752
+
753
+ EXAMPLES::
754
+
755
+ sage: # needs sage.rings.number_field
756
+ sage: R.<u> = QQ[]
757
+ sage: K.<u> = QQ.extension(u^2 + u + 1)
758
+ sage: S.<x> = K[]
759
+ sage: v = GaussValuation(S, K.valuation(2))
760
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
761
+ sage: w._relative_size(x^2 + x + 1)
762
+ 1
763
+ sage: w._relative_size(1048576*x^2 + 1048576*x + 1048576)
764
+ 11
765
+ """
766
+ return self._base_valuation._relative_size(f)
767
+
768
+ def is_negative_pseudo_valuation(self):
769
+ r"""
770
+ Return whether this valuation attains `-\infty`.
771
+
772
+ EXAMPLES:
773
+
774
+ No element in the domain of an augmented valuation can have valuation
775
+ `-\infty`, so this method always returns ``False``::
776
+
777
+ sage: R.<x> = QQ[]
778
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
779
+ sage: w = v.augmentation(x, infinity)
780
+ sage: w.is_negative_pseudo_valuation()
781
+ False
782
+ """
783
+ return False
784
+
785
+ def change_domain(self, ring):
786
+ r"""
787
+ Return this valuation over ``ring``.
788
+
789
+ EXAMPLES:
790
+
791
+ We can change the domain of an augmented valuation even if there is no coercion between rings::
792
+
793
+ sage: # needs sage.geometry.polyhedron sage.rings.number_field
794
+ sage: R.<x> = GaussianIntegers()[]
795
+ sage: v = GaussValuation(R, GaussianIntegers().valuation(2))
796
+ sage: v = v.augmentation(x, 1)
797
+ sage: v.change_domain(QQ['x'])
798
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 1 ]
799
+ """
800
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
801
+ if isinstance(ring, PolynomialRing_generic) and ring.variable_name() == self.domain().variable_name():
802
+ return self._base_valuation.change_domain(ring).augmentation(self.phi().change_ring(ring.base_ring()), self._mu, check=False)
803
+ return super().change_domain(ring)
804
+
805
+
806
+ class FinalAugmentedValuation(AugmentedValuation_base, FinalInductiveValuation):
807
+ r"""
808
+ An augmented valuation which can not be augmented anymore, either because
809
+ it augments a trivial valuation or because it is infinite.
810
+
811
+ EXAMPLES::
812
+
813
+ sage: R.<x> = QQ[]
814
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
815
+ sage: w = v.augmentation(x, 1)
816
+ """
817
+ def __init__(self, parent, v, phi, mu):
818
+ r"""
819
+ TESTS::
820
+
821
+ sage: R.<x> = QQ[]
822
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
823
+ sage: w = v.augmentation(x, 1)
824
+ sage: from sage.rings.valuation.augmented_valuation import FinalAugmentedValuation
825
+ sage: isinstance(w, FinalAugmentedValuation)
826
+ True
827
+ """
828
+ AugmentedValuation_base.__init__(self, parent, v, phi, mu)
829
+ FinalInductiveValuation.__init__(self, parent, phi)
830
+
831
+ @cached_method
832
+ def residue_ring(self):
833
+ r"""
834
+ Return the residue ring of this valuation, i.e., the elements of
835
+ nonnegative valuation modulo the elements of positive valuation.
836
+
837
+ EXAMPLES::
838
+
839
+ sage: R.<x> = QQ[]
840
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
841
+
842
+ sage: w = v.augmentation(x, 1)
843
+ sage: w.residue_ring()
844
+ Rational Field
845
+
846
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
847
+ sage: w.residue_ring() # needs sage.rings.number_field
848
+ Number Field in u1 with defining polynomial x^2 + x + 1
849
+
850
+ An example with a non-trivial base valuation::
851
+
852
+ sage: v = GaussValuation(R, QQ.valuation(2))
853
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
854
+ sage: w.residue_ring() # needs sage.rings.finite_rings
855
+ Finite Field in u1 of size 2^2
856
+
857
+ Since trivial extensions of finite fields are not implemented, the
858
+ resulting ring might be identical to the residue ring of the underlying
859
+ valuation::
860
+
861
+ sage: w = v.augmentation(x, infinity)
862
+ sage: w.residue_ring()
863
+ Finite Field of size 2
864
+
865
+ TESTS:
866
+
867
+ We avoid clashes in generator names::
868
+
869
+ sage: # needs sage.rings.function_field
870
+ sage: K.<x> = FunctionField(QQ)
871
+ sage: v = K.valuation(x^2 + 2)
872
+ sage: R.<y> = K[]
873
+ sage: L.<y> = K.extension(y^2 + x^2)
874
+ sage: w = v.extension(L)
875
+ sage: w.residue_field()
876
+ Number Field in uu1 with defining polynomial y^2 - 2 over its base field
877
+ sage: w.residue_field().base_field()
878
+ Number Field in u1 with defining polynomial x^2 + 2
879
+ """
880
+ # the following is correct, even if the polynomial ring is not over a field
881
+
882
+ base = self._base_valuation.residue_ring().base()
883
+ if self.psi().degree() > 1:
884
+ generator = self._residue_ring_generator_name()
885
+ return base.extension(self.psi(), names=generator)
886
+ else:
887
+ # Do not call extension() if self.psi().degree() == 1:
888
+ # In that case the resulting field appears to be the same as the original field,
889
+ # however, it is not == to the original field (for finite fields at
890
+ # least) but a distinct copy (this is a bug in finite field's
891
+ # extension() implementation.)
892
+ return base
893
+
894
+ def reduce(self, f, check=True, degree_bound=None, coefficients=None, valuations=None):
895
+ r"""
896
+ Reduce ``f`` module this valuation.
897
+
898
+ INPUT:
899
+
900
+ - ``f`` -- an element in the domain of this valuation
901
+
902
+ - ``check`` -- whether or not to check whether ``f`` has nonnegative
903
+ valuation (default: ``True``)
904
+
905
+ - ``degree_bound`` -- an a-priori known bound on the degree of the
906
+ result which can speed up the computation (default: not set)
907
+
908
+ - ``coefficients`` -- the coefficients of ``f`` as produced by
909
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients`
910
+ or ``None`` (default: ``None``); this can be used to speed up the
911
+ computation when the expansion of ``f`` is already known from a
912
+ previous computation.
913
+
914
+ - ``valuations`` -- the valuations of ``coefficients`` or ``None``
915
+ (default: ``None``); ignored
916
+
917
+ OUTPUT:
918
+
919
+ an element of the :meth:`residue_ring` of this valuation, the reduction
920
+ modulo the ideal of elements of positive valuation
921
+
922
+ EXAMPLES::
923
+
924
+ sage: R.<x> = QQ[]
925
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
926
+
927
+ sage: w = v.augmentation(x, 1)
928
+ sage: w.reduce(x^2 + x + 1)
929
+ 1
930
+
931
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
932
+ sage: w.reduce(x) # needs sage.rings.number_field
933
+ u1
934
+
935
+ TESTS:
936
+
937
+ Cases with non-trivial base valuation::
938
+
939
+ sage: # needs sage.libs.ntl
940
+ sage: R.<u> = Qq(4, 10)
941
+ sage: S.<x> = R[]
942
+ sage: v = GaussValuation(S)
943
+ sage: v.reduce(x)
944
+ x
945
+ sage: v.reduce(S(u))
946
+ u0
947
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
948
+ sage: w.reduce(S.one())
949
+ 1
950
+ sage: w.reduce(S(2))
951
+ 0
952
+ sage: w.reduce(S(u))
953
+ u0
954
+ sage: w.reduce(x) # this gives the generator of the residue field extension of w over v
955
+ u1
956
+ sage: f = (x^2 + x + u)^2 / 2
957
+ sage: w.reduce(f)
958
+ x
959
+ sage: w.reduce(f + x + 1)
960
+ x + u1 + 1
961
+ sage: # needs sage.libs.ntl
962
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
963
+ sage: g = ((x^2 + x + u)^2 + 2)^3 / 2^5
964
+ sage: ww.reduce(g)
965
+ x
966
+ sage: ww.reduce(f)
967
+ 1
968
+ sage: ww.is_equivalent(f, 1)
969
+ True
970
+ sage: ww.reduce(f * g)
971
+ x
972
+ sage: ww.reduce(f + g)
973
+ x + 1
974
+ """
975
+ f = self.domain().coerce(f)
976
+
977
+ if check:
978
+ v = self(f)
979
+ if v < 0:
980
+ raise ValueError("f must have nonnegative valuation")
981
+ elif v > 0:
982
+ return self.residue_ring().zero()
983
+
984
+ if coefficients is None:
985
+ constant_term = next(self.coefficients(f))
986
+ else:
987
+ constant_term = coefficients[0]
988
+ constant_term_reduced = self._base_valuation.reduce(constant_term)
989
+ return constant_term_reduced(self._residue_field_generator())
990
+
991
+ @cached_method
992
+ def _residue_field_generator(self):
993
+ r"""
994
+ Return a root of :meth:`psi` in :meth:`residue_ring`.
995
+
996
+ EXAMPLES::
997
+
998
+ sage: R.<x> = QQ[]
999
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
1000
+
1001
+ sage: w = v.augmentation(x, 1)
1002
+ sage: w._residue_field_generator()
1003
+ 0
1004
+
1005
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
1006
+ sage: w._residue_field_generator() # needs sage.rings.number_field
1007
+ u1
1008
+
1009
+ A case with non-trivial base valuation::
1010
+
1011
+ sage: # needs sage.libs.ntl
1012
+ sage: R.<u> = Qq(4, 10)
1013
+ sage: S.<x> = R[]
1014
+ sage: v = GaussValuation(S)
1015
+ sage: w = v.augmentation(x^2 + x + u, infinity)
1016
+ sage: w._residue_field_generator() # needs sage.rings.number_field
1017
+ u1
1018
+ """
1019
+ if self.psi().degree() == 1:
1020
+ ret = self.residue_ring()(-self.psi()[0])
1021
+ else:
1022
+ ret = self.residue_ring().gen()
1023
+
1024
+ assert self.psi()(ret).is_zero()
1025
+ return ret
1026
+
1027
+ def lift(self, F):
1028
+ r"""
1029
+ Return a polynomial which reduces to ``F``.
1030
+
1031
+ INPUT:
1032
+
1033
+ - ``F`` -- an element of the :meth:`residue_ring`
1034
+
1035
+ ALGORITHM:
1036
+
1037
+ We simply undo the steps performed in :meth:`reduce`.
1038
+
1039
+ OUTPUT: a polynomial in the domain of the valuation with reduction ``F``
1040
+
1041
+ EXAMPLES::
1042
+
1043
+ sage: R.<x> = QQ[]
1044
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
1045
+
1046
+ sage: w = v.augmentation(x, 1)
1047
+ sage: w.lift(1/2)
1048
+ 1/2
1049
+
1050
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
1051
+ sage: w.lift(w.residue_ring().gen()) # needs sage.libs.singular sage.rings.number_field
1052
+ x
1053
+
1054
+ A case with non-trivial base valuation::
1055
+
1056
+ sage: # needs sage.libs.ntl
1057
+ sage: R.<u> = Qq(4, 10)
1058
+ sage: S.<x> = R[]
1059
+ sage: v = GaussValuation(S)
1060
+ sage: w = v.augmentation(x^2 + x + u, infinity)
1061
+ sage: w.lift(w.residue_ring().gen()) # needs sage.libs.singular sage.rings.number_field
1062
+ (1 + O(2^10))*x
1063
+
1064
+ TESTS:
1065
+
1066
+ Verify that :issue:`30305` has been resolved::
1067
+
1068
+ sage: # needs sage.rings.number_field
1069
+ sage: R.<T> = QQ[]
1070
+ sage: K.<zeta> = NumberField(T^2 + T + 1)
1071
+ sage: R.<x> = K[]
1072
+ sage: v0 = GaussValuation(R, valuations.TrivialValuation(K))
1073
+ sage: v = v0.augmentation(x^2 + x + 2, 1)
1074
+ sage: v.lift(v.reduce(x)) == x # needs sage.libs.singular
1075
+ True
1076
+ """
1077
+ F = self.residue_ring().coerce(F)
1078
+
1079
+ if F.is_zero():
1080
+ return self.domain().zero()
1081
+ if F.is_one():
1082
+ return self.domain().one()
1083
+
1084
+ # Write F as a polynomial in self._residue_field_generator()
1085
+ # We only have to do that if psi is non-trivial
1086
+ if self.psi().degree() > 1:
1087
+ from sage.rings.polynomial.polynomial_quotient_ring_element import PolynomialQuotientRingElement
1088
+ from sage.rings.function_field.element_polymod import FunctionFieldElement_polymod
1089
+ from sage.rings.number_field.number_field_element import NumberFieldElement_relative
1090
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
1091
+ if isinstance(F, PolynomialQuotientRingElement):
1092
+ G = F.lift()
1093
+ elif isinstance(F, FunctionFieldElement_polymod):
1094
+ G = F.element()
1095
+ elif isinstance(F, NumberFieldElement_relative):
1096
+ G = PolynomialRing(F.base_ring(), 'x')(list(F))
1097
+ else:
1098
+ G = F.polynomial()
1099
+ assert (G(self._residue_field_generator()) == F)
1100
+ F = G.change_variable_name(self._base_valuation.residue_ring().variable_name())
1101
+
1102
+ H = self._base_valuation.lift(F)
1103
+ return self.domain()(H)
1104
+
1105
+
1106
+ class NonFinalAugmentedValuation(AugmentedValuation_base, NonFinalInductiveValuation):
1107
+ r"""
1108
+ An augmented valuation which can be augmented further.
1109
+
1110
+ EXAMPLES::
1111
+
1112
+ sage: R.<x> = QQ[]
1113
+ sage: v = GaussValuation(R, QQ.valuation(2))
1114
+ sage: w = v.augmentation(x^2 + x + 1, 1)
1115
+ """
1116
+ def __init__(self, parent, v, phi, mu):
1117
+ r"""
1118
+ TESTS::
1119
+
1120
+ sage: R.<x> = QQ[]
1121
+ sage: v = GaussValuation(R, QQ.valuation(2))
1122
+ sage: w = v.augmentation(x^2 + x + 1, 1)
1123
+ sage: from sage.rings.valuation.augmented_valuation import NonFinalAugmentedValuation
1124
+ sage: isinstance(w, NonFinalAugmentedValuation)
1125
+ True
1126
+ """
1127
+ AugmentedValuation_base.__init__(self, parent, v, phi, mu)
1128
+ NonFinalInductiveValuation.__init__(self, parent, phi)
1129
+
1130
+ @cached_method
1131
+ def residue_ring(self):
1132
+ r"""
1133
+ Return the residue ring of this valuation, i.e., the elements of
1134
+ nonnegative valuation modulo the elements of positive valuation.
1135
+
1136
+ EXAMPLES::
1137
+
1138
+ sage: R.<x> = QQ[]
1139
+ sage: v = GaussValuation(R, QQ.valuation(2))
1140
+ sage: w = v.augmentation(x^2 + x + 1, 1)
1141
+ sage: w.residue_ring() # needs sage.rings.finite_rings
1142
+ Univariate Polynomial Ring in x over Finite Field in u1 of size 2^2
1143
+
1144
+ Since trivial valuations of finite fields are not implemented, the
1145
+ resulting ring might be identical to the residue ring of the underlying
1146
+ valuation::
1147
+
1148
+ sage: w = v.augmentation(x, 1)
1149
+ sage: w.residue_ring()
1150
+ Univariate Polynomial Ring in x over Finite Field of size 2 (using ...)
1151
+ """
1152
+ from sage.categories.fields import Fields
1153
+ if self.domain().base() not in Fields():
1154
+ raise NotImplementedError("only implemented for polynomial rings over fields")
1155
+
1156
+ base = self._base_valuation.residue_ring().base()
1157
+ if self.psi().degree() > 1:
1158
+ generator = self._residue_ring_generator_name()
1159
+ base = base.extension(self.psi(), names=generator)
1160
+ else:
1161
+ # Do not call extension() if self.psi().degree() == 1:
1162
+ # In that case the resulting field appears to be the same as the original field,
1163
+ # however, it is not == to the original field (for finite fields at
1164
+ # least) but a distinct copy (this is a bug in finite field's
1165
+ # extension() implementation.)
1166
+ pass
1167
+ return base[self.domain().variable_name()]
1168
+
1169
+ def reduce(self, f, check=True, degree_bound=None, coefficients=None, valuations=None):
1170
+ r"""
1171
+ Reduce ``f`` module this valuation.
1172
+
1173
+ INPUT:
1174
+
1175
+ - ``f`` -- an element in the domain of this valuation
1176
+
1177
+ - ``check`` -- whether or not to check whether ``f`` has nonnegative
1178
+ valuation (default: ``True``)
1179
+
1180
+ - ``degree_bound`` -- an a-priori known bound on the degree of the
1181
+ result which can speed up the computation (default: not set)
1182
+
1183
+ - ``coefficients`` -- the coefficients of ``f`` as produced by
1184
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients`
1185
+ or ``None`` (default: ``None``); this can be used to speed up the
1186
+ computation when the expansion of ``f`` is already known from a
1187
+ previous computation.
1188
+
1189
+ - ``valuations`` -- the valuations of ``coefficients`` or ``None``
1190
+ (default: ``None``)
1191
+
1192
+ OUTPUT:
1193
+
1194
+ an element of the :meth:`residue_ring` of this valuation, the reduction
1195
+ modulo the ideal of elements of positive valuation
1196
+
1197
+ ALGORITHM:
1198
+
1199
+ We follow the algorithm given in the proof of Theorem 12.1 of [Mac1936I]_:
1200
+ If ``f`` has positive valuation, the reduction is simply zero.
1201
+ Otherwise, let `f=\sum f_i\phi^i` be the expansion of `f`, as computed
1202
+ by
1203
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients`.
1204
+ Since the valuation is zero, the exponents `i` must all be multiples of
1205
+ `\tau`, the index the value group of the base valuation in the value
1206
+ group of this valuation. Hence, there is an
1207
+ :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.equivalence_unit`
1208
+ `Q` with the same valuation as `\phi^\tau`. Let `Q'` be its
1209
+ :meth:`~sage.rings.valuation.inductive_valuation.InductiveValuation.equivalence_reciprocal`.
1210
+ Now, rewrite each term `f_i\phi^{i\tau}=(f_iQ^i)(\phi^\tau Q^{-1})^i`;
1211
+ it turns out that the second factor in this expression is a lift of the
1212
+ generator of the :meth:`~sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace.ElementMethods.residue_field`.
1213
+ The reduction of the first factor can be computed recursively.
1214
+
1215
+ EXAMPLES::
1216
+
1217
+ sage: # needs sage.libs.ntl
1218
+ sage: R.<u> = Qq(4, 10)
1219
+ sage: S.<x> = R[]
1220
+ sage: v = GaussValuation(S)
1221
+ sage: v.reduce(x)
1222
+ x
1223
+ sage: v.reduce(S(u))
1224
+ u0
1225
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1226
+ sage: w.reduce(S.one())
1227
+ 1
1228
+ sage: w.reduce(S(2))
1229
+ 0
1230
+ sage: w.reduce(S(u))
1231
+ u0
1232
+ sage: w.reduce(x) # this gives the generator of the residue field extension of w over v
1233
+ u1
1234
+ sage: f = (x^2 + x + u)^2 / 2
1235
+ sage: w.reduce(f)
1236
+ x
1237
+ sage: w.reduce(f + x + 1)
1238
+ x + u1 + 1
1239
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
1240
+ sage: g = ((x^2 + x + u)^2 + 2)^3 / 2^5
1241
+ sage: ww.reduce(g)
1242
+ x
1243
+ sage: ww.reduce(f)
1244
+ 1
1245
+ sage: ww.is_equivalent(f, 1)
1246
+ True
1247
+ sage: ww.reduce(f * g)
1248
+ x
1249
+ sage: ww.reduce(f + g)
1250
+ x + 1
1251
+ """
1252
+ f = self.domain().coerce(f)
1253
+
1254
+ if self.lower_bound(f) > 0:
1255
+ return self.residue_ring().zero()
1256
+
1257
+ tau = self.value_group().index(self._base_valuation.value_group())
1258
+
1259
+ if coefficients is None:
1260
+ coefficients = self.coefficients(f)
1261
+ if degree_bound is not None:
1262
+ coefficients = islice(coefficients, 0, tau*degree_bound + 1, 1)
1263
+ coefficients = list(coefficients)
1264
+
1265
+ if valuations is None:
1266
+ valuations = []
1267
+ valuations = valuations[::tau]
1268
+
1269
+ # rewrite as sum of f_i phi^{i tau}, i.e., drop the coefficients that
1270
+ # can have no influence on the reduction
1271
+ for i, c in enumerate(coefficients):
1272
+ if i % tau != 0:
1273
+ if check:
1274
+ v = self._base_valuation(c) + i*self._mu
1275
+ assert v != 0 # this can not happen for an augmented valuation
1276
+ if v < 0:
1277
+ raise ValueError("f must not have negative valuation")
1278
+ else:
1279
+ # the validity of the coefficients with i % tau == 0 is checked by
1280
+ # the recursive call to reduce below
1281
+ # replace f_i by f_i Q^{i tau}
1282
+ if i//tau >= len(valuations):
1283
+ # we do not know the correct valuation of the coefficient, but
1284
+ # the computation is faster if we know that the coefficient
1285
+ # has positive valuation
1286
+ valuations.append(self._base_valuation.lower_bound(c) + i*self._mu)
1287
+ v = valuations[i//tau]
1288
+ if v is infinity or v > 0:
1289
+ coefficients[i] = self.domain().zero()
1290
+ valuations[i//tau] = infinity
1291
+ else:
1292
+ coefficients[i] = c * self._Q(i//tau)
1293
+ valuations[i//tau] -= i*self._mu
1294
+
1295
+ coefficients = coefficients[::tau]
1296
+
1297
+ # recursively reduce the f_i Q^{i tau}
1298
+ C = [self._base_valuation.reduce(c, check=False)(self._residue_field_generator())
1299
+ if valuations[i] is not infinity
1300
+ else self._base_valuation.residue_ring().zero()
1301
+ for i, c in enumerate(coefficients)]
1302
+
1303
+ # reduce the Q'^i phi^i
1304
+ return self.residue_ring()(C)
1305
+
1306
+ @cached_method
1307
+ def _residue_field_generator(self):
1308
+ r"""
1309
+ Return a root of :meth:`psi` in :meth:`residue_ring`.
1310
+
1311
+ EXAMPLES::
1312
+
1313
+ sage: # needs sage.libs.ntl
1314
+ sage: R.<u> = Qq(4, 10)
1315
+ sage: S.<x> = R[]
1316
+ sage: v = GaussValuation(S)
1317
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1318
+ sage: w._residue_field_generator()
1319
+ u1
1320
+ """
1321
+ if self.residue_ring() == self._base_valuation.residue_ring():
1322
+ assert self.psi().degree() == 1
1323
+ ret = self.residue_ring().base()(-self.psi()[0])
1324
+ else:
1325
+ ret = self.residue_ring().base().gen()
1326
+
1327
+ assert ret.parent() is self.residue_ring().base()
1328
+ assert self.psi()(ret).is_zero()
1329
+ return ret
1330
+
1331
+ def lift(self, F, report_coefficients=False):
1332
+ r"""
1333
+ Return a polynomial which reduces to ``F``.
1334
+
1335
+ INPUT:
1336
+
1337
+ - ``F`` -- an element of the :meth:`residue_ring`
1338
+
1339
+ - ``report_coefficients`` -- whether to return the coefficients of the
1340
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic
1341
+ expansion or the actual polynomial (default: ``False``, i.e., return
1342
+ the polynomial)
1343
+
1344
+ OUTPUT:
1345
+
1346
+ A polynomial in the domain of the valuation with reduction ``F``, monic
1347
+ if ``F`` is monic.
1348
+
1349
+ ALGORITHM:
1350
+
1351
+ Since this is the inverse of :meth:`reduce`, we only have to go backwards
1352
+ through the algorithm described there.
1353
+
1354
+ EXAMPLES::
1355
+
1356
+ sage: # needs sage.libs.ntl
1357
+ sage: R.<u> = Qq(4, 10)
1358
+ sage: S.<x> = R[]
1359
+ sage: v = GaussValuation(S)
1360
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1361
+ sage: y = w.residue_ring().gen()
1362
+ sage: u1 = w.residue_ring().base().gen()
1363
+ sage: w.lift(1)
1364
+ 1 + O(2^10)
1365
+ sage: w.lift(0)
1366
+ 0
1367
+ sage: w.lift(u1)
1368
+ (1 + O(2^10))*x
1369
+ sage: w.reduce(w.lift(y)) == y
1370
+ True
1371
+ sage: w.reduce(w.lift(y + u1 + 1)) == y + u1 + 1
1372
+ True
1373
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
1374
+ sage: y = ww.residue_ring().gen()
1375
+ sage: u2 = ww.residue_ring().base().gen()
1376
+ sage: ww.reduce(ww.lift(y)) == y
1377
+ True
1378
+ sage: ww.reduce(ww.lift(1)) == 1
1379
+ True
1380
+ sage: ww.reduce(ww.lift(y + 1)) == y + 1
1381
+ True
1382
+
1383
+ A more complicated example::
1384
+
1385
+ sage: # needs sage.libs.ntl
1386
+ sage: v = GaussValuation(S)
1387
+ sage: w = v.augmentation(x^2 + x + u, 1)
1388
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3)
1389
+ sage: u = ww.residue_ring().base().gen()
1390
+ sage: F = ww.residue_ring()(u); F
1391
+ u2
1392
+ sage: f = ww.lift(F); f
1393
+ (2^-1 + O(2^9))*x^2 + (2^-1 + O(2^9))*x + u*2^-1 + O(2^9)
1394
+ sage: F == ww.reduce(f)
1395
+ True
1396
+ """
1397
+ F = self.residue_ring().coerce(F)
1398
+
1399
+ from sage.categories.fields import Fields
1400
+ if self.domain().base_ring() not in Fields():
1401
+ raise NotImplementedError("only implemented for polynomial rings over fields")
1402
+
1403
+ if F.is_constant():
1404
+ if F.is_zero():
1405
+ return self.domain().zero()
1406
+ if F.is_one():
1407
+ return self.domain().one()
1408
+
1409
+ R0 = self._base_valuation.residue_ring()
1410
+
1411
+ # in the last step of reduce, the f_iQ^i are reduced, and evaluated at
1412
+ # the generator of the residue field
1413
+ # here, we undo this:
1414
+ coeffs = [R0(c if self.psi().degree() == 1
1415
+ else list(c._vector_() if hasattr(c, '_vector_')
1416
+ else c.list()))
1417
+ for c in F.coefficients(sparse=False)]
1418
+ coeffs = [self._base_valuation.lift(c) for c in coeffs]
1419
+ # now the coefficients correspond to the expansion with (f_iQ^i)(Q^{-1} phi)^i
1420
+
1421
+ # now we undo the factors of Q^i (the if else is necessary to handle the case when mu is infinity, i.e., when _Q_reciprocal() is undefined)
1422
+ coeffs = [(c if i == 0 else c*self._Q_reciprocal(i)).map_coefficients(_lift_to_maximal_precision)
1423
+ for i, c in enumerate(coeffs)]
1424
+ # reduce the coefficients mod phi; the part that exceeds phi has no effect on the reduction of the coefficient
1425
+ coeffs = [next(self.coefficients(c)) for c in coeffs]
1426
+
1427
+ if report_coefficients:
1428
+ return coeffs
1429
+
1430
+ RR = self.domain().change_ring(self.domain())
1431
+
1432
+ tau = self.value_group().index(self._base_valuation.value_group())
1433
+ ret = RR(coeffs)(self.phi()**tau)
1434
+ ret = ret.map_coefficients(_lift_to_maximal_precision)
1435
+ return ret
1436
+
1437
+ def lift_to_key(self, F, check=True):
1438
+ r"""
1439
+ Lift the irreducible polynomial ``F`` to a key polynomial.
1440
+
1441
+ INPUT:
1442
+
1443
+ - ``F`` -- an irreducible non-constant polynomial in the
1444
+ :meth:`residue_ring` of this valuation
1445
+
1446
+ - ``check`` -- whether or not to check correctness of ``F`` (default:
1447
+ ``True``)
1448
+
1449
+ OUTPUT:
1450
+
1451
+ A polynomial `f` in the domain of this valuation which is a key
1452
+ polynomial for this valuation and which, for a suitable equivalence
1453
+ unit `R`, satisfies that the reduction of `Rf` is ``F``
1454
+
1455
+ ALGORITHM:
1456
+
1457
+ We follow the algorithm described in Theorem 13.1 [Mac1936I]_ which, after
1458
+ a :meth:`lift` of ``F``, essentially shifts the valuations of all terms
1459
+ in the `\phi`-adic expansion up and then kills the leading coefficient.
1460
+
1461
+ EXAMPLES::
1462
+
1463
+ sage: # needs sage.libs.ntl
1464
+ sage: R.<u> = Qq(4, 10)
1465
+ sage: S.<x> = R[]
1466
+ sage: v = GaussValuation(S)
1467
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1468
+ sage: y = w.residue_ring().gen()
1469
+ sage: f = w.lift_to_key(y + 1); f
1470
+ (1 + O(2^10))*x^4 + (2 + O(2^11))*x^3 + (1 + u*2 + O(2^10))*x^2 + (u*2 + O(2^11))*x + (u + 1) + u*2 + O(2^10)
1471
+ sage: w.is_key(f)
1472
+ True
1473
+
1474
+ A more complicated example::
1475
+
1476
+ sage: # needs sage.libs.ntl
1477
+ sage: v = GaussValuation(S)
1478
+ sage: w = v.augmentation(x^2 + x + u, 1)
1479
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3)
1480
+ sage: u = ww.residue_ring().base().gen()
1481
+ sage: y = ww.residue_ring().gen()
1482
+ sage: f = ww.lift_to_key(y^3+y+u)
1483
+ sage: f.degree()
1484
+ 12
1485
+ sage: ww.is_key(f)
1486
+ True
1487
+ """
1488
+ F = self.residue_ring().coerce(F)
1489
+
1490
+ from sage.categories.fields import Fields
1491
+ if self.domain().base_ring() not in Fields():
1492
+ raise NotImplementedError("only implemented for polynomial rings over fields")
1493
+
1494
+ if check:
1495
+ if self._base_valuation.is_gauss_valuation() and self._mu is infinity:
1496
+ raise TypeError("there are no keys over this valuation")
1497
+ if F.is_constant():
1498
+ raise ValueError("F must not be constant")
1499
+ if not F.is_monic():
1500
+ raise ValueError("F must be monic")
1501
+ if not F.is_irreducible():
1502
+ raise ValueError("F must be irreducible")
1503
+
1504
+ if F == F.parent().gen():
1505
+ return self.phi()
1506
+
1507
+ coefficients = self.lift(F, report_coefficients=True)[:-1]
1508
+ coefficients = [c * self._Q(F.degree()) for i, c in enumerate(coefficients)] + [self.domain().one()]
1509
+ if len(coefficients) >= 2:
1510
+ # In the phi-adic development, the second-highest coefficient could
1511
+ # spill over into the highest coefficient (which is a constant one)
1512
+ # so we need to mod it away.
1513
+ # This can not happen for other coefficients because self._Q() has
1514
+ # degree at most the degree of phi.
1515
+ coefficients[-2] %= self.phi()
1516
+ tau = self.value_group().index(self._base_valuation.value_group())
1517
+ vf = self._mu * tau * F.degree()
1518
+ ret = self.domain().change_ring(self.domain())(coefficients)(self.phi()**tau)
1519
+ ret = self.simplify(ret, error=vf, force=True)
1520
+ ret = ret.map_coefficients(_lift_to_maximal_precision)
1521
+ assert (ret == self.phi()) == (F == F.parent().gen())
1522
+ assert self.is_key(ret)
1523
+ return ret
1524
+
1525
+ @cached_method
1526
+ def _Q(self, e):
1527
+ r"""
1528
+ Return the polynomial `Q^e` used in the construction to :meth:`reduce` an
1529
+ element to the :meth:`residue_ring`.
1530
+
1531
+ EXAMPLES::
1532
+
1533
+ sage: R.<x> = QQ[]
1534
+ sage: v = GaussValuation(R, QQ.valuation(2))
1535
+ sage: w = v.augmentation(x^2 + x + 1, 1)
1536
+
1537
+ sage: w._Q(1)
1538
+ 2
1539
+ """
1540
+ tau = self.value_group().index(self._base_valuation.value_group())
1541
+ v = self._mu * tau
1542
+ return self._pow(self.equivalence_unit(v), e, error=v*e, effective_degree=0)
1543
+
1544
+ @cached_method
1545
+ def _Q_reciprocal(self, e=1):
1546
+ r"""
1547
+ Return the :meth:`equivalence_reciprocal` of the ``e``-th power of
1548
+ :meth:`_Q`.
1549
+
1550
+ EXAMPLES::
1551
+
1552
+ sage: R.<x> = QQ[]
1553
+ sage: v = GaussValuation(R, QQ.valuation(2))
1554
+ sage: w = v.augmentation(x^2 + x + 1, 1)
1555
+
1556
+ sage: w._Q_reciprocal()
1557
+ 1/2
1558
+ """
1559
+ if e == 1:
1560
+ return self.equivalence_reciprocal(self._Q(1), check=False)
1561
+
1562
+ tau = self.value_group().index(self._base_valuation.value_group())
1563
+ v = -self._mu * tau
1564
+ ret = self._pow(self._Q_reciprocal(1), e, error=v*e, effective_degree=0)
1565
+
1566
+ assert self.is_equivalence_unit(ret)
1567
+ # essentially this checks that the reduction of Q'*phi^tau is the
1568
+ # generator of the residue field
1569
+ assert self._base_valuation.reduce(self._Q(e)*ret)(self._residue_field_generator()).is_one()
1570
+
1571
+ return ret
1572
+
1573
+
1574
+ class FiniteAugmentedValuation(AugmentedValuation_base, FiniteInductiveValuation):
1575
+ r"""
1576
+ A finite augmented valuation, i.e., an augmented valuation which is
1577
+ discrete, or equivalently an augmented valuation which assigns to its last
1578
+ key polynomial a finite valuation.
1579
+
1580
+ EXAMPLES::
1581
+
1582
+ sage: # needs sage.libs.ntl
1583
+ sage: R.<u> = Qq(4, 5)
1584
+ sage: S.<x> = R[]
1585
+ sage: v = GaussValuation(S)
1586
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1587
+ """
1588
+ def __init__(self, parent, v, phi, mu):
1589
+ r"""
1590
+ EXAMPLES::
1591
+
1592
+ sage: # needs sage.libs.ntl
1593
+ sage: R.<u> = Qq(4, 5)
1594
+ sage: S.<x> = R[]
1595
+ sage: v = GaussValuation(S)
1596
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1597
+ sage: from sage.rings.valuation.augmented_valuation import FiniteAugmentedValuation
1598
+ sage: isinstance(w, FiniteAugmentedValuation)
1599
+ True
1600
+ """
1601
+ AugmentedValuation_base.__init__(self, parent, v, phi, mu)
1602
+ FiniteInductiveValuation.__init__(self, parent, phi)
1603
+
1604
+ @cached_method
1605
+ def value_group(self):
1606
+ r"""
1607
+ Return the value group of this valuation.
1608
+
1609
+ EXAMPLES::
1610
+
1611
+ sage: # needs sage.libs.ntl
1612
+ sage: R.<u> = Qq(4, 5)
1613
+ sage: S.<x> = R[]
1614
+ sage: v = GaussValuation(S)
1615
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1616
+ sage: w.value_group()
1617
+ Additive Abelian Group generated by 1/2
1618
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
1619
+ sage: ww.value_group()
1620
+ Additive Abelian Group generated by 1/6
1621
+ """
1622
+ return self._base_valuation.value_group() + self._mu
1623
+
1624
+ def value_semigroup(self):
1625
+ r"""
1626
+ Return the value semigroup of this valuation.
1627
+
1628
+ EXAMPLES::
1629
+
1630
+ sage: # needs sage.libs.ntl
1631
+ sage: R.<u> = Zq(4, 5)
1632
+ sage: S.<x> = R[]
1633
+ sage: v = GaussValuation(S)
1634
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1635
+ sage: w.value_semigroup()
1636
+ Additive Abelian Semigroup generated by 1/2
1637
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
1638
+ sage: ww.value_semigroup()
1639
+ Additive Abelian Semigroup generated by 1/2, 5/3
1640
+ """
1641
+ return self._base_valuation.value_semigroup() + self._mu
1642
+
1643
+ def valuations(self, f, coefficients=None, call_error=False):
1644
+ r"""
1645
+ Return the valuations of the `f_i\phi^i` in the expansion `f=\sum_i
1646
+ f_i\phi^i`.
1647
+
1648
+ INPUT:
1649
+
1650
+ - ``f`` -- a polynomial in the domain of this valuation
1651
+
1652
+ - ``coefficients`` -- the coefficients of ``f`` as produced by
1653
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients`
1654
+ or ``None`` (default: ``None``); this can be used to speed up the
1655
+ computation when the expansion of ``f`` is already known from a
1656
+ previous computation.
1657
+
1658
+ - ``call_error`` -- whether or not to speed up the computation by
1659
+ assuming that the result is only used to compute the valuation of
1660
+ ``f`` (default: ``False``)
1661
+
1662
+ OUTPUT:
1663
+
1664
+ An iterator over rational numbers (or infinity) `[v(f_0), v(f_1\phi), \dots]`
1665
+
1666
+ EXAMPLES::
1667
+
1668
+ sage: # needs sage.libs.ntl
1669
+ sage: R.<u> = Qq(4, 5)
1670
+ sage: S.<x> = R[]
1671
+ sage: v = GaussValuation(S)
1672
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1673
+ sage: list(w.valuations( x^2 + 1 ))
1674
+ [0, 1/2]
1675
+ sage: ww = w.augmentation((x^2 + x + u)^2 + 2, 5/3)
1676
+ sage: list(ww.valuations( ((x^2 + x + u)^2 + 2)^3 ))
1677
+ [+Infinity, +Infinity, +Infinity, 5]
1678
+ """
1679
+ f = self.domain().coerce(f)
1680
+
1681
+ if call_error:
1682
+ lowest_valuation = infinity
1683
+ for i, c in enumerate(coefficients or self.coefficients(f)):
1684
+ if call_error:
1685
+ if lowest_valuation is not infinity:
1686
+ v = self._base_valuation.lower_bound(c)
1687
+ if v is infinity or v >= lowest_valuation:
1688
+ yield infinity
1689
+ continue
1690
+ v = self._base_valuation(c)
1691
+ if v is infinity:
1692
+ yield v
1693
+ else:
1694
+ ret = v + i*self._mu
1695
+ if call_error:
1696
+ if lowest_valuation is infinity or ret < lowest_valuation:
1697
+ lowest_valuation = ret
1698
+ yield ret
1699
+
1700
+ def simplify(self, f, error=None, force=False, effective_degree=None, size_heuristic_bound=32, phiadic=False):
1701
+ r"""
1702
+ Return a simplified version of ``f``.
1703
+
1704
+ Produce an element which differs from ``f`` by an element of valuation
1705
+ strictly greater than the valuation of ``f`` (or strictly greater than
1706
+ ``error`` if set.)
1707
+
1708
+ INPUT:
1709
+
1710
+ - ``f`` -- an element in the domain of this valuation
1711
+
1712
+ - ``error`` -- a rational, infinity, or ``None`` (default: ``None``),
1713
+ the error allowed to introduce through the simplification
1714
+
1715
+ - ``force`` -- whether or not to simplify ``f`` even if there is
1716
+ heuristically no change in the coefficient size of ``f`` expected
1717
+ (default: ``False``)
1718
+
1719
+ - ``effective_degree`` -- when set, assume that coefficients beyond
1720
+ ``effective_degree`` in the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic development can be
1721
+ safely dropped (default: ``None``)
1722
+
1723
+ - ``size_heuristic_bound`` -- when ``force`` is not set, the expected
1724
+ factor by which the coefficients need to shrink to perform an actual
1725
+ simplification (default: 32)
1726
+
1727
+ - ``phiadic`` -- whether to simplify the coefficients in the
1728
+ `\phi`-adic expansion recursively. This often times leads to huge
1729
+ coefficients in the `x`-adic expansion (default: ``False``, i.e., use
1730
+ an `x`-adic expansion.)
1731
+
1732
+ EXAMPLES::
1733
+
1734
+ sage: # needs sage.libs.ntl
1735
+ sage: R.<u> = Qq(4, 5)
1736
+ sage: S.<x> = R[]
1737
+ sage: v = GaussValuation(S)
1738
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1739
+ sage: w.simplify(x^10/2 + 1, force=True)
1740
+ (u + 1)*2^-1 + O(2^4)
1741
+
1742
+ Check that :issue:`25607` has been resolved, i.e., the coefficients
1743
+ in the following example are small::
1744
+
1745
+ sage: # needs sage.geometry.polyhedron sage.libs.ntl sage.rings.number_field
1746
+ sage: R.<x> = QQ[]
1747
+ sage: K.<a> = NumberField(x^3 + 6)
1748
+ sage: R.<x> = K[]
1749
+ sage: v = GaussValuation(R, K.valuation(2))
1750
+ sage: v = v.augmentation(x, 3/2)
1751
+ sage: v = v.augmentation(x^2 + 8, 13/4)
1752
+ sage: v = v.augmentation(x^4 + 16*x^2 + 32*x + 64, 20/3)
1753
+ sage: F.<x> = FunctionField(K)
1754
+ sage: S.<y> = F[]
1755
+ sage: v = F.valuation(v)
1756
+ sage: G = y^2 - 2*x^5 + 8*x^3 + 80*x^2 + 128*x + 192
1757
+ sage: v.mac_lane_approximants(G)
1758
+ [[ Gauss valuation induced by
1759
+ Valuation on rational function field induced by
1760
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3/2,
1761
+ v(x^2 + 8) = 13/4, v(x^4 + 16*x^2 + 32*x + 64) = 20/3 ],
1762
+ v(y + 4*x + 8) = 31/8 ]]
1763
+ """
1764
+ f = self.domain().coerce(f)
1765
+
1766
+ if effective_degree is not None:
1767
+ if (QQ(f.degree()) / self.phi().degree()).ceil() > effective_degree:
1768
+ f = self.domain().change_ring(self.domain())(list(islice(self.coefficients(f), 0, int(effective_degree) + 1, 1)))(self.phi())
1769
+
1770
+ if f.degree() < self.phi().degree():
1771
+ return self._base_valuation.simplify(f, error=error, force=force, size_heuristic_bound=size_heuristic_bound, phiadic=phiadic)
1772
+
1773
+ if not force and self._relative_size(f) < size_heuristic_bound:
1774
+ return f
1775
+
1776
+ if error is None:
1777
+ # if the caller was sure that we should simplify, then we should try to do the best simplification possible
1778
+ error = self(f) if force else self.upper_bound(f)
1779
+
1780
+ if phiadic is None:
1781
+ phiadic = False
1782
+ # We ignore the user's choice when x == phi, as the non-phi-adic
1783
+ # algorithm is the same but slower then.
1784
+ if phiadic or self.phi() == self.phi().parent().gen():
1785
+ coefficients = list(self.coefficients(f))
1786
+ valuations = list(self.valuations(f, coefficients=coefficients))
1787
+ return self.domain().change_ring(self.domain())([
1788
+ 0 if valuations[i] > error
1789
+ else self._base_valuation.simplify(c, error=error-i*self._mu, force=force, phiadic=True)
1790
+ for (i, c) in enumerate(coefficients)])(self.phi())
1791
+ else:
1792
+ # We iterate through the coefficients of the polynomial (in the
1793
+ # usual x-adic way) starting from the leading coefficient and try
1794
+ # to replace the coefficient with a simpler one recursively.
1795
+ # This is a quite expensive operation but small coefficients can
1796
+ # speed up the surrounding calls drastically.
1797
+ for i in range(f.degree(), -1, -1):
1798
+ j = i // self.phi().degree()
1799
+
1800
+ coefficients = list(islice(f.list(), int(j * self.phi().degree()),
1801
+ int(i) + 1))
1802
+ g = self.domain()(coefficients)
1803
+ ng = self._base_valuation.simplify(g, error=error-j*self._mu, force=force, phiadic=False)
1804
+ if g != ng:
1805
+ f -= (g - ng)*self.phi()**j
1806
+ return f
1807
+
1808
+ def lower_bound(self, f):
1809
+ r"""
1810
+ Return a lower bound of this valuation at ``f``.
1811
+
1812
+ Use this method to get an approximation of the valuation of ``f``
1813
+ when speed is more important than accuracy.
1814
+
1815
+ ALGORITHM:
1816
+
1817
+ The main cost of evaluation is the computation of the
1818
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients`
1819
+ of the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic
1820
+ expansion of ``f`` (which often leads to coefficient bloat.) So unless
1821
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`
1822
+ is trivial, we fall back to valuation which this valuation augments
1823
+ since it is guaranteed to be smaller everywhere.
1824
+
1825
+ EXAMPLES::
1826
+
1827
+ sage: # needs sage.libs.ntl
1828
+ sage: R.<u> = Qq(4, 5)
1829
+ sage: S.<x> = R[]
1830
+ sage: v = GaussValuation(S)
1831
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1832
+ sage: w.lower_bound(x^2 + x + u)
1833
+ 0
1834
+ """
1835
+ f = self.domain().coerce(f)
1836
+
1837
+ if self.phi() == self.domain().gen():
1838
+ constant_valuation = self.restriction(f.base_ring())
1839
+ ret = infinity
1840
+ for i, c in enumerate(f.coefficients(sparse=False)):
1841
+ v = constant_valuation.lower_bound(c)
1842
+ if v is infinity:
1843
+ continue
1844
+ v += i * self._mu
1845
+ if ret is infinity or v < ret:
1846
+ ret = v
1847
+ return ret
1848
+ else:
1849
+ return self._base_valuation.lower_bound(f)
1850
+
1851
+ def upper_bound(self, f):
1852
+ r"""
1853
+ Return an upper bound of this valuation at ``f``.
1854
+
1855
+ Use this method to get an approximation of the valuation of ``f``
1856
+ when speed is more important than accuracy.
1857
+
1858
+ ALGORITHM:
1859
+
1860
+ Any entry of :meth:`valuations` serves as an upper bound. However,
1861
+ computation of the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic
1862
+ expansion of ``f`` is quite costly.
1863
+ Therefore, we produce an upper bound on the last entry of
1864
+ :meth:`valuations`, namely the valuation of the leading coefficient of
1865
+ ``f`` plus the valuation of the appropriate power of :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`.
1866
+
1867
+ EXAMPLES::
1868
+
1869
+ sage: # needs sage.libs.ntl
1870
+ sage: R.<u> = Qq(4, 5)
1871
+ sage: S.<x> = R[]
1872
+ sage: v = GaussValuation(S)
1873
+ sage: w = v.augmentation(x^2 + x + u, 1/2)
1874
+ sage: w.upper_bound(x^2 + x + u)
1875
+ 1/2
1876
+ """
1877
+ f = self.domain().coerce(f)
1878
+
1879
+ len_coefficients_bound = (QQ(f.degree()) / self.phi().degree()).ceil()
1880
+ return self.restriction(f.base_ring())(f.leading_coefficient()) + len_coefficients_bound * self._mu
1881
+
1882
+
1883
+ class FinalFiniteAugmentedValuation(FiniteAugmentedValuation, FinalAugmentedValuation):
1884
+ r"""
1885
+ An augmented valuation which is discrete, i.e., which assigns a finite
1886
+ valuation to its last key polynomial, but which can not be further
1887
+ augmented.
1888
+
1889
+ EXAMPLES::
1890
+
1891
+ sage: R.<x> = QQ[]
1892
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
1893
+ sage: w = v.augmentation(x, 1)
1894
+ """
1895
+ def __init__(self, parent, v, phi, mu):
1896
+ r"""
1897
+ TESTS::
1898
+
1899
+ sage: R.<x> = QQ[]
1900
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
1901
+ sage: w = v.augmentation(x, 1)
1902
+ sage: from sage.rings.valuation.augmented_valuation import FinalFiniteAugmentedValuation
1903
+ sage: isinstance(w, FinalFiniteAugmentedValuation)
1904
+ True
1905
+ """
1906
+ FiniteAugmentedValuation.__init__(self, parent, v, phi, mu)
1907
+ FinalAugmentedValuation.__init__(self, parent, v, phi, mu)
1908
+
1909
+
1910
+ class NonFinalFiniteAugmentedValuation(FiniteAugmentedValuation, NonFinalAugmentedValuation):
1911
+ r"""
1912
+ An augmented valuation which is discrete, i.e., which assigns a finite
1913
+ valuation to its last key polynomial, and which can be augmented further.
1914
+
1915
+ EXAMPLES::
1916
+
1917
+ sage: R.<x> = QQ[]
1918
+ sage: v = GaussValuation(R, QQ.valuation(2))
1919
+ sage: w = v.augmentation(x, 1)
1920
+ """
1921
+ def __init__(self, parent, v, phi, mu):
1922
+ r"""
1923
+ TESTS::
1924
+
1925
+ sage: R.<x> = QQ[]
1926
+ sage: v = GaussValuation(R, QQ.valuation(2))
1927
+ sage: w = v.augmentation(x, 1)
1928
+ sage: from sage.rings.valuation.augmented_valuation import NonFinalFiniteAugmentedValuation
1929
+ sage: isinstance(w, NonFinalFiniteAugmentedValuation)
1930
+ True
1931
+ """
1932
+ FiniteAugmentedValuation.__init__(self, parent, v, phi, mu)
1933
+ NonFinalAugmentedValuation.__init__(self, parent, v, phi, mu)
1934
+
1935
+
1936
+ class InfiniteAugmentedValuation(FinalAugmentedValuation, InfiniteInductiveValuation):
1937
+ r"""
1938
+ An augmented valuation which is infinite, i.e., which assigns valuation
1939
+ infinity to its last key polynomial (and which can therefore not be
1940
+ augmented further.)
1941
+
1942
+ EXAMPLES::
1943
+
1944
+ sage: R.<x> = QQ[]
1945
+ sage: v = GaussValuation(R, QQ.valuation(2))
1946
+ sage: w = v.augmentation(x, infinity)
1947
+ """
1948
+ def __init__(self, parent, v, phi, mu):
1949
+ r"""
1950
+ TESTS::
1951
+
1952
+ sage: R.<x> = QQ[]
1953
+ sage: v = GaussValuation(R, QQ.valuation(2))
1954
+ sage: w = v.augmentation(x, infinity)
1955
+ sage: from sage.rings.valuation.augmented_valuation import InfiniteAugmentedValuation
1956
+ sage: isinstance(w, InfiniteAugmentedValuation)
1957
+ True
1958
+ """
1959
+ FinalAugmentedValuation.__init__(self, parent, v, phi, mu)
1960
+ InfiniteInductiveValuation.__init__(self, parent, phi)
1961
+
1962
+ @cached_method
1963
+ def value_group(self):
1964
+ r"""
1965
+ Return the value group of this valuation.
1966
+
1967
+ EXAMPLES::
1968
+
1969
+ sage: # needs sage.libs.ntl
1970
+ sage: R.<u> = Qq(4, 5)
1971
+ sage: S.<x> = R[]
1972
+ sage: v = GaussValuation(S)
1973
+ sage: w = v.augmentation(x, infinity)
1974
+ sage: w.value_group()
1975
+ Additive Abelian Group generated by 1
1976
+ """
1977
+ return self._base_valuation.value_group()
1978
+
1979
+ @cached_method
1980
+ def value_semigroup(self):
1981
+ r"""
1982
+ Return the value semigroup of this valuation.
1983
+
1984
+ EXAMPLES::
1985
+
1986
+ sage: # needs sage.libs.ntl
1987
+ sage: R.<u> = Zq(4, 5)
1988
+ sage: S.<x> = R[]
1989
+ sage: v = GaussValuation(S)
1990
+ sage: w = v.augmentation(x, infinity)
1991
+ sage: w.value_semigroup()
1992
+ Additive Abelian Semigroup generated by 1
1993
+ """
1994
+ return self._base_valuation.value_semigroup()
1995
+
1996
+ def valuations(self, f, coefficients=None, call_error=False):
1997
+ r"""
1998
+ Return the valuations of the `f_i\phi^i` in the expansion `f=\sum_i
1999
+ f_i\phi^i`.
2000
+
2001
+ INPUT:
2002
+
2003
+ - ``f`` -- a polynomial in the domain of this valuation
2004
+
2005
+ - ``coefficients`` -- the coefficients of ``f`` as produced by
2006
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.coefficients`
2007
+ or ``None`` (default: ``None``); this can be used to speed up the
2008
+ computation when the expansion of ``f`` is already known from a
2009
+ previous computation.
2010
+
2011
+ - ``call_error`` -- whether or not to speed up the computation by
2012
+ assuming that the result is only used to compute the valuation of
2013
+ ``f`` (default: ``False``)
2014
+
2015
+ OUTPUT:
2016
+
2017
+ An iterator over rational numbers (or infinity) `[v(f_0), v(f_1\phi), \dots]`
2018
+
2019
+ EXAMPLES::
2020
+
2021
+ sage: # needs sage.libs.ntl
2022
+ sage: R.<u> = Qq(4, 5)
2023
+ sage: S.<x> = R[]
2024
+ sage: v = GaussValuation(S)
2025
+ sage: w = v.augmentation(x, infinity)
2026
+ sage: list(w.valuations(x^2 + 1))
2027
+ [0, +Infinity, +Infinity]
2028
+ """
2029
+ f = self.domain().coerce(f)
2030
+
2031
+ num_infty_coefficients = f.degree() // self.phi().degree()
2032
+ if coefficients is not None:
2033
+ constant_coefficient = coefficients[0]
2034
+ else:
2035
+ constant_coefficient = next(self.coefficients(f))
2036
+ yield self._base_valuation(constant_coefficient)
2037
+ for i in range(num_infty_coefficients):
2038
+ yield infinity
2039
+
2040
+ def simplify(self, f, error=None, force=False, effective_degree=None):
2041
+ r"""
2042
+ Return a simplified version of ``f``.
2043
+
2044
+ Produce an element which differs from ``f`` by an element of valuation
2045
+ strictly greater than the valuation of ``f`` (or strictly greater than
2046
+ ``error`` if set.)
2047
+
2048
+ INPUT:
2049
+
2050
+ - ``f`` -- an element in the domain of this valuation
2051
+
2052
+ - ``error`` -- a rational, infinity, or ``None`` (default: ``None``),
2053
+ the error allowed to introduce through the simplification
2054
+
2055
+ - ``force`` -- whether or not to simplify ``f`` even if there is
2056
+ heuristically no change in the coefficient size of ``f`` expected
2057
+ (default: ``False``)
2058
+
2059
+ - ``effective_degree`` -- ignored; for compatibility with other
2060
+ ``simplify`` methods
2061
+
2062
+ EXAMPLES::
2063
+
2064
+ sage: # needs sage.libs.ntl
2065
+ sage: R.<u> = Qq(4, 5)
2066
+ sage: S.<x> = R[]
2067
+ sage: v = GaussValuation(S)
2068
+ sage: w = v.augmentation(x^2 + x + u, infinity)
2069
+ sage: w.simplify(x^10/2 + 1, force=True)
2070
+ (u + 1)*2^-1 + O(2^4)
2071
+ """
2072
+ f = self.domain().coerce(f)
2073
+
2074
+ if error is None:
2075
+ error = self(f) if force else self.upper_bound(f)
2076
+
2077
+ if error is infinity:
2078
+ return f
2079
+
2080
+ return self.domain()(self._base_valuation.simplify(next(self.coefficients(f)), error=error, force=force))
2081
+
2082
+ def lower_bound(self, f):
2083
+ r"""
2084
+ Return a lower bound of this valuation at ``f``.
2085
+
2086
+ Use this method to get an approximation of the valuation of ``f``
2087
+ when speed is more important than accuracy.
2088
+
2089
+ EXAMPLES::
2090
+
2091
+ sage: # needs sage.libs.ntl
2092
+ sage: R.<u> = Qq(4, 5)
2093
+ sage: S.<x> = R[]
2094
+ sage: v = GaussValuation(S)
2095
+ sage: w = v.augmentation(x^2 + x + u, infinity)
2096
+ sage: w.lower_bound(x^2 + x + u)
2097
+ +Infinity
2098
+ """
2099
+ return self._base_valuation.lower_bound(next(self.coefficients(f)))
2100
+
2101
+ def upper_bound(self, f):
2102
+ r"""
2103
+ Return an upper bound of this valuation at ``f``.
2104
+
2105
+ Use this method to get an approximation of the valuation of ``f``
2106
+ when speed is more important than accuracy.
2107
+
2108
+ EXAMPLES::
2109
+
2110
+ sage: # needs sage.libs.ntl
2111
+ sage: R.<u> = Qq(4, 5)
2112
+ sage: S.<x> = R[]
2113
+ sage: v = GaussValuation(S)
2114
+ sage: w = v.augmentation(x^2 + x + u, infinity)
2115
+ sage: w.upper_bound(x^2 + x + u)
2116
+ +Infinity
2117
+ """
2118
+ return self._base_valuation.upper_bound(next(self.coefficients(f)))