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.
- PARIKernel/__init__.py +2 -0
- PARIKernel/__main__.py +5 -0
- PARIKernel/io.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/io.pxd +7 -0
- PARIKernel/io.pyx +84 -0
- PARIKernel/kernel.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/kernel.pyx +260 -0
- PARIKernel/paridecl.pxd +95 -0
- PARIKernel/svg.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/svg.pyx +52 -0
- cypari2/__init__.py +8 -0
- cypari2/auto_paridecl.pxd +1070 -0
- cypari2/closure.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/closure.pxd +5 -0
- cypari2/closure.pyx +246 -0
- cypari2/convert.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/convert.pxd +80 -0
- cypari2/convert.pyx +613 -0
- cypari2/custom_block.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/custom_block.pyx +30 -0
- cypari2/cypari.h +13 -0
- cypari2/gen.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/gen.pxd +69 -0
- cypari2/gen.pyx +4819 -0
- cypari2/handle_error.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/handle_error.pxd +7 -0
- cypari2/handle_error.pyx +232 -0
- cypari2/pari_instance.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/pari_instance.pxd +27 -0
- cypari2/pari_instance.pyx +1438 -0
- cypari2/paridecl.pxd +5353 -0
- cypari2/paripriv.pxd +34 -0
- cypari2/pycore_long.h +98 -0
- cypari2/pycore_long.pxd +9 -0
- cypari2/stack.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/stack.pxd +27 -0
- cypari2/stack.pyx +278 -0
- cypari2/string_utils.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/string_utils.pxd +29 -0
- cypari2/string_utils.pyx +65 -0
- cypari2/types.pxd +147 -0
- passagemath_pari-10.6.32.data/data/etc/jupyter/nbconfig/notebook.d/gp-mode.json +5 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.js +28 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.json +6 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/kernel.json +13 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-32x32.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-svg.svg +75 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/gp.js +284 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/main.js +15 -0
- passagemath_pari-10.6.32.dist-info/METADATA +209 -0
- passagemath_pari-10.6.32.dist-info/RECORD +331 -0
- passagemath_pari-10.6.32.dist-info/WHEEL +5 -0
- passagemath_pari-10.6.32.dist-info/top_level.txt +4 -0
- passagemath_pari.libs/libcrypto-f04afe95.so.3 +0 -0
- passagemath_pari.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
- passagemath_pari.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_pari.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
- passagemath_pari.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_pari.libs/libgivaro-9a94c711.so.9.2.1 +0 -0
- passagemath_pari.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_pari.libs/libgmpxx-9e08595c.so.4.7.0 +0 -0
- passagemath_pari.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_pari.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_pari.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
- passagemath_pari.libs/libntl-26885ca2.so.44.0.1 +0 -0
- passagemath_pari.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_pari.libs/libpari-gmp-tls-f31f908f.so.2.17.2 +0 -0
- passagemath_pari.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
- passagemath_pari.libs/libreadline-06542304.so.8.2 +0 -0
- passagemath_pari.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
- passagemath_pari.libs/libuuid-f3770415.so.1.3.0 +0 -0
- passagemath_pari.libs/libxeus-735780ff.so.13.1.0 +0 -0
- passagemath_pari.libs/libxeus-zmq-c68577b4.so.6.0.1 +0 -0
- passagemath_pari.libs/libzmq-1ba9a3da.so.5.2.5 +0 -0
- sage/all__sagemath_pari.py +26 -0
- sage/databases/all__sagemath_pari.py +7 -0
- sage/databases/conway.py +274 -0
- sage/ext/all__sagemath_pari.py +1 -0
- sage/ext/memory.cpython-314-x86_64-linux-musl.so +0 -0
- sage/ext/memory.pyx +98 -0
- sage/ext_data/pari/buzzard/DimensionSk.g +286 -0
- sage/ext_data/pari/buzzard/Tpprog.g +179 -0
- sage/ext_data/pari/buzzard/genusn.g +129 -0
- sage/ext_data/pari/dokchitser/computel.gp +740 -0
- sage/ext_data/pari/dokchitser/computel.gp.template +740 -0
- sage/ext_data/pari/dokchitser/ex-bsw +43 -0
- sage/ext_data/pari/dokchitser/ex-chgen +48 -0
- sage/ext_data/pari/dokchitser/ex-chqua +37 -0
- sage/ext_data/pari/dokchitser/ex-delta +35 -0
- sage/ext_data/pari/dokchitser/ex-eisen +30 -0
- sage/ext_data/pari/dokchitser/ex-gen2 +38 -0
- sage/ext_data/pari/dokchitser/ex-gen3 +49 -0
- sage/ext_data/pari/dokchitser/ex-gen4 +54 -0
- sage/ext_data/pari/dokchitser/ex-nf +48 -0
- sage/ext_data/pari/dokchitser/ex-shin +50 -0
- sage/ext_data/pari/dokchitser/ex-tau2 +30 -0
- sage/ext_data/pari/dokchitser/ex-zeta +27 -0
- sage/ext_data/pari/dokchitser/ex-zeta2 +47 -0
- sage/ext_data/pari/dokchitser/testall +13 -0
- sage/ext_data/pari/simon/ell.gp +2129 -0
- sage/ext_data/pari/simon/ellQ.gp +2151 -0
- sage/ext_data/pari/simon/ellcommon.gp +126 -0
- sage/ext_data/pari/simon/qfsolve.gp +722 -0
- sage/ext_data/pari/simon/resultant3.gp +306 -0
- sage/groups/all__sagemath_pari.py +3 -0
- sage/groups/pari_group.py +175 -0
- sage/interfaces/all__sagemath_pari.py +1 -0
- sage/interfaces/genus2reduction.py +464 -0
- sage/interfaces/gp.py +1114 -0
- sage/libs/all__sagemath_pari.py +2 -0
- sage/libs/linkages/__init__.py +1 -0
- sage/libs/linkages/padics/API.pxi +617 -0
- sage/libs/linkages/padics/Polynomial_ram.pxi +388 -0
- sage/libs/linkages/padics/Polynomial_shared.pxi +554 -0
- sage/libs/linkages/padics/__init__.py +1 -0
- sage/libs/linkages/padics/fmpz_poly_unram.pxi +869 -0
- sage/libs/linkages/padics/mpz.pxi +691 -0
- sage/libs/linkages/padics/relaxed/API.pxi +518 -0
- sage/libs/linkages/padics/relaxed/__init__.py +1 -0
- sage/libs/linkages/padics/relaxed/flint.pxi +543 -0
- sage/libs/linkages/padics/unram_shared.pxi +247 -0
- sage/libs/pari/__init__.py +210 -0
- sage/libs/pari/all.py +5 -0
- sage/libs/pari/convert_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_flint.pxd +14 -0
- sage/libs/pari/convert_flint.pyx +159 -0
- sage/libs/pari/convert_gmp.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_gmp.pxd +14 -0
- sage/libs/pari/convert_gmp.pyx +210 -0
- sage/libs/pari/convert_sage.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage.pxd +16 -0
- sage/libs/pari/convert_sage.pyx +588 -0
- sage/libs/pari/convert_sage_complex_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_complex_double.pxd +14 -0
- sage/libs/pari/convert_sage_complex_double.pyx +132 -0
- sage/libs/pari/convert_sage_matrix.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_matrix.pyx +106 -0
- sage/libs/pari/convert_sage_real_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_double.pxd +5 -0
- sage/libs/pari/convert_sage_real_double.pyx +14 -0
- sage/libs/pari/convert_sage_real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_mpfr.pxd +7 -0
- sage/libs/pari/convert_sage_real_mpfr.pyx +108 -0
- sage/libs/pari/misc.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/misc.pxd +4 -0
- sage/libs/pari/misc.pyx +26 -0
- sage/libs/pari/tests.py +1848 -0
- sage/matrix/all__sagemath_pari.py +1 -0
- sage/matrix/matrix_integer_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_integer_pari.pyx +187 -0
- sage/matrix/matrix_rational_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_rational_pari.pyx +160 -0
- sage/quadratic_forms/all__sagemath_pari.py +10 -0
- sage/quadratic_forms/genera/all.py +9 -0
- sage/quadratic_forms/genera/genus.py +3506 -0
- sage/quadratic_forms/genera/normal_form.py +1519 -0
- sage/quadratic_forms/genera/spinor_genus.py +243 -0
- sage/quadratic_forms/qfsolve.py +255 -0
- sage/quadratic_forms/quadratic_form__automorphisms.py +427 -0
- sage/quadratic_forms/quadratic_form__genus.py +141 -0
- sage/quadratic_forms/quadratic_form__local_density_interfaces.py +140 -0
- sage/quadratic_forms/quadratic_form__local_normal_form.py +421 -0
- sage/quadratic_forms/quadratic_form__local_representation_conditions.py +889 -0
- sage/quadratic_forms/quadratic_form__mass.py +69 -0
- sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +663 -0
- sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +373 -0
- sage/quadratic_forms/quadratic_form__siegel_product.py +198 -0
- sage/quadratic_forms/special_values.py +323 -0
- sage/rings/all__sagemath_pari.py +15 -0
- sage/rings/factorint_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/factorint_pari.pyx +80 -0
- sage/rings/finite_rings/all__sagemath_pari.py +1 -0
- sage/rings/finite_rings/element_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_givaro.pxd +91 -0
- sage/rings/finite_rings/element_givaro.pyx +1769 -0
- sage/rings/finite_rings/element_ntl_gf2e.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_ntl_gf2e.pxd +22 -0
- sage/rings/finite_rings/element_ntl_gf2e.pyx +1333 -0
- sage/rings/finite_rings/element_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_pari_ffelt.pxd +13 -0
- sage/rings/finite_rings/element_pari_ffelt.pyx +1441 -0
- sage/rings/finite_rings/finite_field_givaro.py +612 -0
- sage/rings/finite_rings/finite_field_pari_ffelt.py +238 -0
- sage/rings/finite_rings/hom_finite_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pxd +28 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pyx +280 -0
- sage/rings/finite_rings/residue_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_givaro.pyx +133 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.pyx +128 -0
- sage/rings/function_field/all__sagemath_pari.py +1 -0
- sage/rings/function_field/valuation.py +1450 -0
- sage/rings/function_field/valuation_ring.py +212 -0
- sage/rings/number_field/all__sagemath_pari.py +14 -0
- sage/rings/number_field/totallyreal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal.pyx +509 -0
- sage/rings/number_field/totallyreal_data.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal_data.pxd +26 -0
- sage/rings/number_field/totallyreal_data.pyx +928 -0
- sage/rings/number_field/totallyreal_phc.py +144 -0
- sage/rings/number_field/totallyreal_rel.py +1018 -0
- sage/rings/padics/CA_template.pxi +1847 -0
- sage/rings/padics/CA_template_header.pxi +50 -0
- sage/rings/padics/CR_template.pxi +2563 -0
- sage/rings/padics/CR_template_header.pxi +57 -0
- sage/rings/padics/FM_template.pxi +1575 -0
- sage/rings/padics/FM_template_header.pxi +50 -0
- sage/rings/padics/FP_template.pxi +2176 -0
- sage/rings/padics/FP_template_header.pxi +57 -0
- sage/rings/padics/all.py +3 -0
- sage/rings/padics/all__sagemath_pari.py +11 -0
- sage/rings/padics/common_conversion.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/common_conversion.pxd +15 -0
- sage/rings/padics/common_conversion.pyx +508 -0
- sage/rings/padics/eisenstein_extension_generic.py +232 -0
- sage/rings/padics/factory.py +3623 -0
- sage/rings/padics/generic_nodes.py +1615 -0
- sage/rings/padics/lattice_precision.py +2889 -0
- sage/rings/padics/morphism.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/morphism.pxd +11 -0
- sage/rings/padics/morphism.pyx +366 -0
- sage/rings/padics/padic_base_generic.py +467 -0
- sage/rings/padics/padic_base_leaves.py +1235 -0
- sage/rings/padics/padic_capped_absolute_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_absolute_element.pxd +15 -0
- sage/rings/padics/padic_capped_absolute_element.pyx +520 -0
- sage/rings/padics/padic_capped_relative_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_relative_element.pxd +14 -0
- sage/rings/padics/padic_capped_relative_element.pyx +614 -0
- sage/rings/padics/padic_extension_generic.py +990 -0
- sage/rings/padics/padic_extension_leaves.py +738 -0
- sage/rings/padics/padic_fixed_mod_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_fixed_mod_element.pxd +15 -0
- sage/rings/padics/padic_fixed_mod_element.pyx +584 -0
- sage/rings/padics/padic_floating_point_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_floating_point_element.pxd +14 -0
- sage/rings/padics/padic_floating_point_element.pyx +447 -0
- sage/rings/padics/padic_generic_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_generic_element.pxd +48 -0
- sage/rings/padics/padic_generic_element.pyx +4642 -0
- sage/rings/padics/padic_lattice_element.py +1342 -0
- sage/rings/padics/padic_printing.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_printing.pxd +38 -0
- sage/rings/padics/padic_printing.pyx +1505 -0
- sage/rings/padics/padic_relaxed_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_element.pxd +56 -0
- sage/rings/padics/padic_relaxed_element.pyx +18 -0
- sage/rings/padics/padic_relaxed_errors.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_errors.pxd +11 -0
- sage/rings/padics/padic_relaxed_errors.pyx +71 -0
- sage/rings/padics/padic_template_element.pxi +1212 -0
- sage/rings/padics/padic_template_element_header.pxi +50 -0
- sage/rings/padics/padic_valuation.py +1423 -0
- sage/rings/padics/pow_computer_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_flint.pxd +38 -0
- sage/rings/padics/pow_computer_flint.pyx +641 -0
- sage/rings/padics/pow_computer_relative.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_relative.pxd +29 -0
- sage/rings/padics/pow_computer_relative.pyx +415 -0
- sage/rings/padics/qadic_flint_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CA.pxd +21 -0
- sage/rings/padics/qadic_flint_CA.pyx +130 -0
- sage/rings/padics/qadic_flint_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CR.pxd +13 -0
- sage/rings/padics/qadic_flint_CR.pyx +172 -0
- sage/rings/padics/qadic_flint_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FM.pxd +14 -0
- sage/rings/padics/qadic_flint_FM.pyx +111 -0
- sage/rings/padics/qadic_flint_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FP.pxd +12 -0
- sage/rings/padics/qadic_flint_FP.pyx +165 -0
- sage/rings/padics/relative_extension_leaves.py +429 -0
- sage/rings/padics/relative_ramified_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CA.pxd +9 -0
- sage/rings/padics/relative_ramified_CA.pyx +33 -0
- sage/rings/padics/relative_ramified_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CR.pxd +8 -0
- sage/rings/padics/relative_ramified_CR.pyx +33 -0
- sage/rings/padics/relative_ramified_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FM.pxd +9 -0
- sage/rings/padics/relative_ramified_FM.pyx +33 -0
- sage/rings/padics/relative_ramified_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FP.pxd +8 -0
- sage/rings/padics/relative_ramified_FP.pyx +33 -0
- sage/rings/padics/relaxed_template.pxi +4229 -0
- sage/rings/padics/relaxed_template_header.pxi +160 -0
- sage/rings/padics/tests.py +35 -0
- sage/rings/padics/tutorial.py +341 -0
- sage/rings/padics/unramified_extension_generic.py +335 -0
- sage/rings/padics/witt_vector.py +917 -0
- sage/rings/padics/witt_vector_ring.py +934 -0
- sage/rings/pari_ring.py +235 -0
- sage/rings/polynomial/all__sagemath_pari.py +1 -0
- sage/rings/polynomial/padics/all.py +1 -0
- sage/rings/polynomial/padics/polynomial_padic.py +360 -0
- sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +1324 -0
- sage/rings/polynomial/padics/polynomial_padic_flat.py +72 -0
- sage/rings/power_series_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/power_series_pari.pxd +6 -0
- sage/rings/power_series_pari.pyx +934 -0
- sage/rings/tate_algebra.py +1282 -0
- sage/rings/tate_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_element.pxd +49 -0
- sage/rings/tate_algebra_element.pyx +3464 -0
- sage/rings/tate_algebra_ideal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_ideal.pxd +7 -0
- sage/rings/tate_algebra_ideal.pyx +1307 -0
- sage/rings/valuation/all.py +7 -0
- sage/rings/valuation/augmented_valuation.py +2118 -0
- sage/rings/valuation/developing_valuation.py +362 -0
- sage/rings/valuation/gauss_valuation.py +812 -0
- sage/rings/valuation/inductive_valuation.py +1686 -0
- sage/rings/valuation/limit_valuation.py +946 -0
- sage/rings/valuation/mapped_valuation.py +656 -0
- sage/rings/valuation/scaled_valuation.py +322 -0
- sage/rings/valuation/trivial_valuation.py +382 -0
- sage/rings/valuation/valuation.py +1119 -0
- sage/rings/valuation/valuation_space.py +1615 -0
- sage/rings/valuation/valuations_catalog.py +10 -0
- sage/rings/valuation/value_group.py +697 -0
- sage/schemes/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pyx +46 -0
- sage_wheels/bin/gp +0 -0
- sage_wheels/bin/gp2c +0 -0
- sage_wheels/bin/gp2c-run +57 -0
- sage_wheels/bin/xeus-gp +0 -0
- sage_wheels/share/gp2c/func.dsc +18414 -0
|
@@ -0,0 +1,1119 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
r"""
|
|
3
|
+
Discrete valuations
|
|
4
|
+
|
|
5
|
+
This file defines abstract base classes for discrete (pseudo-)valuations.
|
|
6
|
+
|
|
7
|
+
AUTHORS:
|
|
8
|
+
|
|
9
|
+
- Julian Rüth (2013-03-16): initial version
|
|
10
|
+
|
|
11
|
+
EXAMPLES:
|
|
12
|
+
|
|
13
|
+
Discrete valuations can be created on a variety of rings::
|
|
14
|
+
|
|
15
|
+
sage: ZZ.valuation(2)
|
|
16
|
+
2-adic valuation
|
|
17
|
+
sage: GaussianIntegers().valuation(3) # needs sage.rings.number_field
|
|
18
|
+
3-adic valuation
|
|
19
|
+
sage: QQ.valuation(5)
|
|
20
|
+
5-adic valuation
|
|
21
|
+
sage: Zp(7).valuation()
|
|
22
|
+
7-adic valuation
|
|
23
|
+
|
|
24
|
+
::
|
|
25
|
+
|
|
26
|
+
sage: # needs sage.rings.function_field
|
|
27
|
+
sage: K.<x> = FunctionField(QQ)
|
|
28
|
+
sage: K.valuation(x)
|
|
29
|
+
(x)-adic valuation
|
|
30
|
+
sage: K.valuation(x^2 + 1)
|
|
31
|
+
(x^2 + 1)-adic valuation
|
|
32
|
+
sage: K.valuation(1/x)
|
|
33
|
+
Valuation at the infinite place
|
|
34
|
+
|
|
35
|
+
::
|
|
36
|
+
|
|
37
|
+
sage: R.<x> = QQ[]
|
|
38
|
+
sage: v = QQ.valuation(2)
|
|
39
|
+
sage: w = GaussValuation(R, v)
|
|
40
|
+
sage: w.augmentation(x, 3)
|
|
41
|
+
[ Gauss valuation induced by 2-adic valuation, v(x) = 3 ]
|
|
42
|
+
|
|
43
|
+
We can also define discrete pseudo-valuations, i.e., discrete valuations that
|
|
44
|
+
send more than just zero to infinity::
|
|
45
|
+
|
|
46
|
+
sage: w.augmentation(x, infinity)
|
|
47
|
+
[ Gauss valuation induced by 2-adic valuation, v(x) = +Infinity ]
|
|
48
|
+
"""
|
|
49
|
+
# ****************************************************************************
|
|
50
|
+
# Copyright (C) 2013-2017 Julian Rüth <julian.rueth@fsfe.org>
|
|
51
|
+
#
|
|
52
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
53
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
54
|
+
# the License, or (at your option) any later version.
|
|
55
|
+
# https://www.gnu.org/licenses/
|
|
56
|
+
# ****************************************************************************
|
|
57
|
+
|
|
58
|
+
from sage.categories.morphism import Morphism
|
|
59
|
+
from sage.structure.richcmp import op_EQ, op_NE, op_LE, op_LT, op_GE, op_GT
|
|
60
|
+
|
|
61
|
+
from sage.misc.cachefunc import cached_method
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class DiscretePseudoValuation(Morphism):
|
|
65
|
+
r"""
|
|
66
|
+
Abstract base class for discrete pseudo-valuations, i.e., discrete
|
|
67
|
+
valuations which might send more that just zero to infinity.
|
|
68
|
+
|
|
69
|
+
INPUT:
|
|
70
|
+
|
|
71
|
+
- ``domain`` -- an integral domain
|
|
72
|
+
|
|
73
|
+
EXAMPLES::
|
|
74
|
+
|
|
75
|
+
sage: v = ZZ.valuation(2); v # indirect doctest
|
|
76
|
+
2-adic valuation
|
|
77
|
+
|
|
78
|
+
TESTS::
|
|
79
|
+
|
|
80
|
+
sage: TestSuite(v).run() # long time # needs sage.geometry.polyhedron
|
|
81
|
+
"""
|
|
82
|
+
def __init__(self, parent):
|
|
83
|
+
r"""
|
|
84
|
+
TESTS::
|
|
85
|
+
|
|
86
|
+
sage: from sage.rings.valuation.valuation import DiscretePseudoValuation
|
|
87
|
+
sage: isinstance(ZZ.valuation(2), DiscretePseudoValuation)
|
|
88
|
+
True
|
|
89
|
+
"""
|
|
90
|
+
Morphism.__init__(self, parent=parent)
|
|
91
|
+
|
|
92
|
+
def is_equivalent(self, f, g):
|
|
93
|
+
r"""
|
|
94
|
+
Return whether ``f`` and ``g`` are equivalent.
|
|
95
|
+
|
|
96
|
+
EXAMPLES::
|
|
97
|
+
|
|
98
|
+
sage: v = QQ.valuation(2)
|
|
99
|
+
sage: v.is_equivalent(2, 1)
|
|
100
|
+
False
|
|
101
|
+
sage: v.is_equivalent(2, -2)
|
|
102
|
+
True
|
|
103
|
+
sage: v.is_equivalent(2, 0)
|
|
104
|
+
False
|
|
105
|
+
sage: v.is_equivalent(0, 0)
|
|
106
|
+
True
|
|
107
|
+
"""
|
|
108
|
+
from sage.rings.infinity import infinity
|
|
109
|
+
if self(f) is infinity:
|
|
110
|
+
return self(g) is infinity
|
|
111
|
+
|
|
112
|
+
return self(f - g) > self(f)
|
|
113
|
+
|
|
114
|
+
def __hash__(self):
|
|
115
|
+
r"""
|
|
116
|
+
The hash value of this valuation.
|
|
117
|
+
|
|
118
|
+
We redirect to :meth:`_hash_`, so that subclasses can only override
|
|
119
|
+
:meth:`_hash_` and :meth:`_eq_` if they want to provide a different
|
|
120
|
+
notion of equality but they can leave the partial and total operators
|
|
121
|
+
untouched.
|
|
122
|
+
|
|
123
|
+
EXAMPLES::
|
|
124
|
+
|
|
125
|
+
sage: v = QQ.valuation(2)
|
|
126
|
+
sage: hash(v) == hash(v) # indirect doctest
|
|
127
|
+
True
|
|
128
|
+
"""
|
|
129
|
+
return self._hash_()
|
|
130
|
+
|
|
131
|
+
def _hash_(self):
|
|
132
|
+
r"""
|
|
133
|
+
Return a hash value for this valuation.
|
|
134
|
+
|
|
135
|
+
We override the strange default provided by
|
|
136
|
+
:class:`sage.categories.morphism.Morphism` here and implement equality by
|
|
137
|
+
``id``. This works fine for objects which use unique representation.
|
|
138
|
+
|
|
139
|
+
Note that the vast majority of valuations come out of a
|
|
140
|
+
:class:`sage.structure.factory.UniqueFactory` and therefore override
|
|
141
|
+
our implementation of :meth:`__hash__` and :meth:`__eq__`.
|
|
142
|
+
|
|
143
|
+
EXAMPLES::
|
|
144
|
+
|
|
145
|
+
sage: v = QQ.valuation(2)
|
|
146
|
+
sage: hash(v) == hash(v) # indirect doctest
|
|
147
|
+
True
|
|
148
|
+
"""
|
|
149
|
+
return id(self)
|
|
150
|
+
|
|
151
|
+
def _richcmp_(self, other, op):
|
|
152
|
+
r"""
|
|
153
|
+
Compare this element to ``other``.
|
|
154
|
+
|
|
155
|
+
We redirect to methods :meth:`_eq_`, :meth:`_lt_`, and :meth:`_gt_` to
|
|
156
|
+
make it easier for subclasses to override only parts of this
|
|
157
|
+
functionality.
|
|
158
|
+
|
|
159
|
+
Note that valuations usually implement ``x == y`` as ``x`` and ``y``
|
|
160
|
+
are indistinguishable. Whereas ``x <= y`` and ``x >= y`` are
|
|
161
|
+
implemented with respect to the natural partial order of valuations.
|
|
162
|
+
As a result, ``x <= y and x >= y`` does not imply ``x == y``.
|
|
163
|
+
|
|
164
|
+
EXAMPLES::
|
|
165
|
+
|
|
166
|
+
sage: v = QQ.valuation(2)
|
|
167
|
+
sage: v == v
|
|
168
|
+
True
|
|
169
|
+
sage: v != v
|
|
170
|
+
False
|
|
171
|
+
sage: w = QQ.valuation(3)
|
|
172
|
+
sage: v == w
|
|
173
|
+
False
|
|
174
|
+
sage: v != w
|
|
175
|
+
True
|
|
176
|
+
"""
|
|
177
|
+
if op == op_LT:
|
|
178
|
+
return self <= other and not (self >= other)
|
|
179
|
+
if op == op_LE:
|
|
180
|
+
return self._le_(other)
|
|
181
|
+
if op == op_EQ:
|
|
182
|
+
return self._eq_(other)
|
|
183
|
+
if op == op_NE:
|
|
184
|
+
return not self == other
|
|
185
|
+
if op == op_GT:
|
|
186
|
+
return self >= other and not (self <= other)
|
|
187
|
+
if op == op_GE:
|
|
188
|
+
return self._ge_(other)
|
|
189
|
+
raise NotImplementedError("Operator not implemented for this valuation")
|
|
190
|
+
|
|
191
|
+
def _eq_(self, other):
|
|
192
|
+
r"""
|
|
193
|
+
Return whether this valuation and ``other`` are indistinguishable.
|
|
194
|
+
|
|
195
|
+
We override the strange default provided by
|
|
196
|
+
:class:`sage.categories.morphism.Morphism` here and implement equality by
|
|
197
|
+
``id``. This is the right behaviour in many cases.
|
|
198
|
+
|
|
199
|
+
Note that the vast majority of valuations come out of a
|
|
200
|
+
:class:`sage.structure.factory.UniqueFactory` and therefore override
|
|
201
|
+
our implementation of :meth:`__hash__` and :meth:`__eq__`.
|
|
202
|
+
|
|
203
|
+
When overriding this method, you can assume that ``other`` is a
|
|
204
|
+
(pseudo-)valuation on the same domain.
|
|
205
|
+
|
|
206
|
+
EXAMPLES::
|
|
207
|
+
|
|
208
|
+
sage: v = valuations.TrivialValuation(QQ)
|
|
209
|
+
sage: v == v
|
|
210
|
+
True
|
|
211
|
+
"""
|
|
212
|
+
return self is other
|
|
213
|
+
|
|
214
|
+
def _le_(self, other):
|
|
215
|
+
r"""
|
|
216
|
+
Return whether this valuation is less than or equal to ``other``
|
|
217
|
+
pointwise.
|
|
218
|
+
|
|
219
|
+
When overriding this method, you can assume that ``other`` is a
|
|
220
|
+
(pseudo-)valuation on the same domain.
|
|
221
|
+
|
|
222
|
+
EXAMPLES::
|
|
223
|
+
|
|
224
|
+
sage: v = valuations.TrivialValuation(QQ)
|
|
225
|
+
sage: w = QQ.valuation(2)
|
|
226
|
+
sage: v <= w
|
|
227
|
+
True
|
|
228
|
+
"""
|
|
229
|
+
return other >= self
|
|
230
|
+
|
|
231
|
+
def _ge_(self, other):
|
|
232
|
+
r"""
|
|
233
|
+
Return whether this valuation is greater than or equal to ``other``
|
|
234
|
+
pointwise.
|
|
235
|
+
|
|
236
|
+
When overriding this method, you can assume that ``other`` is a
|
|
237
|
+
(pseudo-)valuation on the same domain.
|
|
238
|
+
|
|
239
|
+
EXAMPLES::
|
|
240
|
+
|
|
241
|
+
sage: v = valuations.TrivialValuation(QQ)
|
|
242
|
+
sage: w = QQ.valuation(2)
|
|
243
|
+
sage: v >= w
|
|
244
|
+
False
|
|
245
|
+
"""
|
|
246
|
+
if self == other:
|
|
247
|
+
return True
|
|
248
|
+
from .scaled_valuation import ScaledValuation_generic
|
|
249
|
+
if isinstance(other, ScaledValuation_generic):
|
|
250
|
+
return other <= self
|
|
251
|
+
raise NotImplementedError("Operator not implemented for this valuation")
|
|
252
|
+
|
|
253
|
+
# Remove the default implementation of Map.__reduce__ that does not play
|
|
254
|
+
# nice with factories (a factory, does not override Map.__reduce__ because
|
|
255
|
+
# it is not the generic reduce of object) and that does not match equality
|
|
256
|
+
# by id.
|
|
257
|
+
__reduce__ = object.__reduce__
|
|
258
|
+
|
|
259
|
+
def _test_valuation_inheritance(self, **options):
|
|
260
|
+
r"""
|
|
261
|
+
Test that every instance of this class is either a
|
|
262
|
+
:class:`InfiniteDiscretePseudoValuation` or a
|
|
263
|
+
:class:`DiscreteValuation`.
|
|
264
|
+
|
|
265
|
+
EXAMPLES::
|
|
266
|
+
|
|
267
|
+
sage: QQ.valuation(2)._test_valuation_inheritance()
|
|
268
|
+
"""
|
|
269
|
+
tester = self._tester(**options)
|
|
270
|
+
tester.assertNotEqual(isinstance(self, InfiniteDiscretePseudoValuation),
|
|
271
|
+
isinstance(self, DiscreteValuation))
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class InfiniteDiscretePseudoValuation(DiscretePseudoValuation):
|
|
275
|
+
r"""
|
|
276
|
+
Abstract base class for infinite discrete pseudo-valuations, i.e., discrete
|
|
277
|
+
pseudo-valuations which are not discrete valuations.
|
|
278
|
+
|
|
279
|
+
EXAMPLES::
|
|
280
|
+
|
|
281
|
+
sage: v = QQ.valuation(2)
|
|
282
|
+
sage: R.<x> = QQ[]
|
|
283
|
+
sage: v = GaussValuation(R, v)
|
|
284
|
+
sage: w = v.augmentation(x, infinity); w # indirect doctest
|
|
285
|
+
[ Gauss valuation induced by 2-adic valuation, v(x) = +Infinity ]
|
|
286
|
+
|
|
287
|
+
TESTS::
|
|
288
|
+
|
|
289
|
+
sage: from sage.rings.valuation.valuation import InfiniteDiscretePseudoValuation
|
|
290
|
+
sage: isinstance(w, InfiniteDiscretePseudoValuation)
|
|
291
|
+
True
|
|
292
|
+
sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron sage.rings.padics
|
|
293
|
+
"""
|
|
294
|
+
def is_discrete_valuation(self):
|
|
295
|
+
r"""
|
|
296
|
+
Return whether this valuation is a discrete valuation.
|
|
297
|
+
|
|
298
|
+
EXAMPLES::
|
|
299
|
+
|
|
300
|
+
sage: v = QQ.valuation(2)
|
|
301
|
+
sage: R.<x> = QQ[]
|
|
302
|
+
sage: v = GaussValuation(R, v)
|
|
303
|
+
sage: v.is_discrete_valuation()
|
|
304
|
+
True
|
|
305
|
+
sage: w = v.augmentation(x, infinity)
|
|
306
|
+
sage: w.is_discrete_valuation()
|
|
307
|
+
False
|
|
308
|
+
"""
|
|
309
|
+
return False
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class NegativeInfiniteDiscretePseudoValuation(InfiniteDiscretePseudoValuation):
|
|
313
|
+
r"""
|
|
314
|
+
Abstract base class for pseudo-valuations which attain the value `\infty`
|
|
315
|
+
and `-\infty`, i.e., whose domain contains an element of valuation `\infty`
|
|
316
|
+
and its inverse.
|
|
317
|
+
|
|
318
|
+
EXAMPLES::
|
|
319
|
+
|
|
320
|
+
sage: R.<x> = QQ[]
|
|
321
|
+
sage: v = GaussValuation(R, valuations.TrivialValuation(QQ)).augmentation(x, infinity)
|
|
322
|
+
sage: K.<x> = FunctionField(QQ)
|
|
323
|
+
sage: w = K.valuation(v)
|
|
324
|
+
|
|
325
|
+
TESTS::
|
|
326
|
+
|
|
327
|
+
sage: TestSuite(w).run() # long time
|
|
328
|
+
"""
|
|
329
|
+
def is_negative_pseudo_valuation(self):
|
|
330
|
+
r"""
|
|
331
|
+
Return whether this valuation attains the value `-\infty`.
|
|
332
|
+
|
|
333
|
+
EXAMPLES::
|
|
334
|
+
|
|
335
|
+
sage: R.<x> = QQ[]
|
|
336
|
+
sage: u = GaussValuation(R, valuations.TrivialValuation(QQ))
|
|
337
|
+
sage: v = u.augmentation(x, infinity)
|
|
338
|
+
sage: v.is_negative_pseudo_valuation()
|
|
339
|
+
False
|
|
340
|
+
sage: K.<x> = FunctionField(QQ)
|
|
341
|
+
sage: w = K.valuation(v)
|
|
342
|
+
sage: w.is_negative_pseudo_valuation()
|
|
343
|
+
True
|
|
344
|
+
"""
|
|
345
|
+
return True
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
class DiscreteValuation(DiscretePseudoValuation):
|
|
349
|
+
r"""
|
|
350
|
+
Abstract base class for discrete valuations.
|
|
351
|
+
|
|
352
|
+
EXAMPLES::
|
|
353
|
+
|
|
354
|
+
sage: v = QQ.valuation(2)
|
|
355
|
+
sage: R.<x> = QQ[]
|
|
356
|
+
sage: v = GaussValuation(R, v)
|
|
357
|
+
sage: w = v.augmentation(x, 1337); w # indirect doctest
|
|
358
|
+
[ Gauss valuation induced by 2-adic valuation, v(x) = 1337 ]
|
|
359
|
+
|
|
360
|
+
TESTS::
|
|
361
|
+
|
|
362
|
+
sage: from sage.rings.valuation.valuation import DiscreteValuation
|
|
363
|
+
sage: isinstance(w, DiscreteValuation)
|
|
364
|
+
True
|
|
365
|
+
sage: TestSuite(w).run() # long time # needs sage.geometry.polyhedron sage.rings.padics
|
|
366
|
+
"""
|
|
367
|
+
def is_discrete_valuation(self):
|
|
368
|
+
r"""
|
|
369
|
+
Return whether this valuation is a discrete valuation.
|
|
370
|
+
|
|
371
|
+
EXAMPLES::
|
|
372
|
+
|
|
373
|
+
sage: v = valuations.TrivialValuation(ZZ)
|
|
374
|
+
sage: v.is_discrete_valuation()
|
|
375
|
+
True
|
|
376
|
+
"""
|
|
377
|
+
return True
|
|
378
|
+
|
|
379
|
+
def mac_lane_approximants(self, G, assume_squarefree=False, require_final_EF=True, required_precision=-1, require_incomparability=False, require_maximal_degree=False, algorithm='serial'):
|
|
380
|
+
r"""
|
|
381
|
+
Return approximants on `K[x]` for the extensions of this valuation to
|
|
382
|
+
`L=K[x]/(G)`.
|
|
383
|
+
|
|
384
|
+
If `G` is an irreducible polynomial, then this corresponds to
|
|
385
|
+
extensions of this valuation to the completion of `L`.
|
|
386
|
+
|
|
387
|
+
INPUT:
|
|
388
|
+
|
|
389
|
+
- ``G`` -- a monic squarefree integral polynomial in a
|
|
390
|
+
univariate polynomial ring over the domain of this valuation
|
|
391
|
+
|
|
392
|
+
- ``assume_squarefree`` -- boolean (default: ``False``); whether to
|
|
393
|
+
assume that ``G`` is squarefree. If ``True``, the squafreeness of
|
|
394
|
+
``G`` is not verified though it is necessary when
|
|
395
|
+
``require_final_EF`` is set for the algorithm to terminate.
|
|
396
|
+
|
|
397
|
+
- ``require_final_EF`` -- boolean (default: ``True``); whether to
|
|
398
|
+
require the returned key polynomials to be in one-to-one
|
|
399
|
+
correspondence to the extensions of this valuation to ``L`` and
|
|
400
|
+
require them to have the ramification index and residue degree of the
|
|
401
|
+
valuations they correspond to.
|
|
402
|
+
|
|
403
|
+
- ``required_precision`` -- a number or infinity (default: -1); whether
|
|
404
|
+
to require the last key polynomial of the returned valuations to have
|
|
405
|
+
at least that valuation.
|
|
406
|
+
|
|
407
|
+
- ``require_incomparability`` -- boolean (default: ``False``);
|
|
408
|
+
whether to require the returned valuations to be incomparable
|
|
409
|
+
(with respect to the partial order on valuations defined by comparing
|
|
410
|
+
them pointwise.)
|
|
411
|
+
|
|
412
|
+
- ``require_maximal_degree`` -- boolean (default: ``False``); whether
|
|
413
|
+
to require the last key polynomial of the returned valuation to have
|
|
414
|
+
maximal degree. This is most relevant when using this algorithm to
|
|
415
|
+
compute approximate factorizations of ``G``, when set to ``True``,
|
|
416
|
+
the last key polynomial has the same degree as the corresponding
|
|
417
|
+
factor.
|
|
418
|
+
|
|
419
|
+
- ``algorithm`` -- one of ``'serial'`` or ``'parallel'`` (default:
|
|
420
|
+
``'serial'``); whether or not to parallelize the algorithm
|
|
421
|
+
|
|
422
|
+
EXAMPLES::
|
|
423
|
+
|
|
424
|
+
sage: v = QQ.valuation(2)
|
|
425
|
+
sage: R.<x> = QQ[]
|
|
426
|
+
sage: v.mac_lane_approximants(x^2 + 1) # needs sage.geometry.polyhedron
|
|
427
|
+
[[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1/2 ]]
|
|
428
|
+
sage: v.mac_lane_approximants(x^2 + 1, required_precision=infinity) # needs sage.geometry.polyhedron
|
|
429
|
+
[[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1/2,
|
|
430
|
+
v(x^2 + 1) = +Infinity ]]
|
|
431
|
+
sage: v.mac_lane_approximants(x^2 + x + 1)
|
|
432
|
+
[[ Gauss valuation induced by 2-adic valuation, v(x^2 + x + 1) = +Infinity ]]
|
|
433
|
+
|
|
434
|
+
Note that ``G`` does not need to be irreducible. Here, we detect a
|
|
435
|
+
factor `x + 1` and an approximate factor `x + 1` (which is an
|
|
436
|
+
approximation to `x - 1`)::
|
|
437
|
+
|
|
438
|
+
sage: v.mac_lane_approximants(x^2 - 1) # needs sage.geometry.polyhedron sage.rings.padics
|
|
439
|
+
[[ Gauss valuation induced by 2-adic valuation, v(x + 1) = +Infinity ],
|
|
440
|
+
[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1 ]]
|
|
441
|
+
|
|
442
|
+
However, it needs to be squarefree::
|
|
443
|
+
|
|
444
|
+
sage: v.mac_lane_approximants(x^2)
|
|
445
|
+
Traceback (most recent call last):
|
|
446
|
+
...
|
|
447
|
+
ValueError: G must be squarefree
|
|
448
|
+
|
|
449
|
+
TESTS:
|
|
450
|
+
|
|
451
|
+
Some difficult cases provided by Mark van Hoeij::
|
|
452
|
+
|
|
453
|
+
sage: # needs sage.rings.finite_rings sage.rings.function_field
|
|
454
|
+
sage: k = GF(2)
|
|
455
|
+
sage: K.<x> = FunctionField(k)
|
|
456
|
+
sage: R.<y> = K[]
|
|
457
|
+
sage: F = y^21 + x*y^20 + (x^3 + x + 1)*y^18 + (x^3 + 1)*y^17 + (x^4 + x)*y^16 + (x^7 + x^6 + x^3 + x + 1)*y^15 + x^7*y^14 + (x^8 + x^7 + x^6 + x^4 + x^3 + 1)*y^13 + (x^9 + x^8 + x^4 + 1)*y^12 + (x^11 + x^9 + x^8 + x^5 + x^4 + x^3 + x^2)*y^11 + (x^12 + x^9 + x^8 + x^7 + x^5 + x^3 + x + 1)*y^10 + (x^14 + x^13 + x^10 + x^9 + x^8 + x^7 + x^6 + x^3 + x^2 + 1)*y^9 + (x^13 + x^9 + x^8 + x^6 + x^4 + x^3 + x)*y^8 + (x^16 + x^15 + x^13 + x^12 + x^11 + x^7 + x^3 + x)*y^7 + (x^17 + x^16 + x^13 + x^9 + x^8 + x)*y^6 + (x^17 + x^16 + x^12 + x^7 + x^5 + x^2 + x + 1)*y^5 + (x^19 + x^16 + x^15 + x^12 + x^6 + x^5 + x^3 + 1)*y^4 + (x^18 + x^15 + x^12 + x^10 + x^9 + x^7 + x^4 + x)*y^3 + (x^22 + x^21 + x^20 + x^18 + x^13 + x^12 + x^9 + x^8 + x^7 + x^5 + x^4 + x^3)*y^2 + (x^23 + x^22 + x^20 + x^17 + x^15 + x^14 + x^12 + x^9)*y + x^25 + x^23 + x^19 + x^17 + x^15 + x^13 + x^11 + x^5
|
|
458
|
+
sage: x = K._ring.gen()
|
|
459
|
+
sage: v0 = K.valuation(GaussValuation(K._ring, valuations.TrivialValuation(k)).augmentation(x,1))
|
|
460
|
+
sage: v0.mac_lane_approximants(F, assume_squarefree=True) # assumes squarefree for speed # needs sage.geometry.polyhedron
|
|
461
|
+
[[ Gauss valuation induced by (x)-adic valuation, v(y + x + 1) = 3/2 ],
|
|
462
|
+
[ Gauss valuation induced by (x)-adic valuation, v(y) = 1 ],
|
|
463
|
+
[ Gauss valuation induced by (x)-adic valuation, v(y) = 4/3 ],
|
|
464
|
+
[ Gauss valuation induced by (x)-adic valuation, v(y^15 + y^13 + y^12 + y^10 + y^9 + y^8 + y^4 + y^3 + y^2 + y + 1) = 1 ]]
|
|
465
|
+
sage: v0 = K.valuation(GaussValuation(K._ring, valuations.TrivialValuation(k)).augmentation(x+1,1))
|
|
466
|
+
sage: v0.mac_lane_approximants(F, assume_squarefree=True) # assumes squarefree for speed # needs sage.geometry.polyhedron
|
|
467
|
+
[[ Gauss valuation induced by (x + 1)-adic valuation, v(y + x^2 + 1) = 7/2 ],
|
|
468
|
+
[ Gauss valuation induced by (x + 1)-adic valuation, v(y) = 3/4 ],
|
|
469
|
+
[ Gauss valuation induced by (x + 1)-adic valuation, v(y) = 7/2 ],
|
|
470
|
+
[ Gauss valuation induced by (x + 1)-adic valuation, v(y^13 + y^12 + y^10 + y^7 + y^6 + y^3 + 1) = 1 ]]
|
|
471
|
+
sage: v0 = valuations.FunctionFieldValuation(K, GaussValuation(K._ring, valuations.TrivialValuation(k)).augmentation(x^3+x^2+1,1))
|
|
472
|
+
sage: v0.mac_lane_approximants(F, assume_squarefree=True) # assumes squarefree for speed # needs sage.geometry.polyhedron
|
|
473
|
+
[[ Gauss valuation induced by (x^3 + x^2 + 1)-adic valuation, v(y + x^3 + x^2 + x) = 2, v(y^2 + (x^6 + x^4 + 1)*y + x^14 + x^10 + x^9 + x^8 + x^5 + x^4 + x^3 + x^2 + x) = 5 ],
|
|
474
|
+
[ Gauss valuation induced by (x^3 + x^2 + 1)-adic valuation, v(y^2 + (x^2 + x)*y + 1) = 1 ],
|
|
475
|
+
[ Gauss valuation induced by (x^3 + x^2 + 1)-adic valuation, v(y^3 + (x + 1)*y^2 + (x + 1)*y + x^2 + x + 1) = 1 ],
|
|
476
|
+
[ Gauss valuation induced by (x^3 + x^2 + 1)-adic valuation, v(y^3 + x^2*y + x) = 1 ],
|
|
477
|
+
[ Gauss valuation induced by (x^3 + x^2 + 1)-adic valuation, v(y^4 + (x + 1)*y^3 + x^2*y^2 + (x^2 + x)*y + x) = 1 ],
|
|
478
|
+
[ Gauss valuation induced by (x^3 + x^2 + 1)-adic valuation, v(y^7 + x^2*y^6 + (x + 1)*y^4 + x^2*y^3 + (x^2 + x + 1)*y^2 + x^2*y + x) = 1 ]]
|
|
479
|
+
|
|
480
|
+
Cases with trivial residue field extensions::
|
|
481
|
+
|
|
482
|
+
sage: K.<x> = FunctionField(QQ)
|
|
483
|
+
sage: S.<y> = K[]
|
|
484
|
+
sage: F = y^2 - x^2 - x^3 - 3
|
|
485
|
+
sage: v0 = GaussValuation(K._ring, QQ.valuation(3))
|
|
486
|
+
sage: v1 = v0.augmentation(K._ring.gen(),1/3)
|
|
487
|
+
sage: mu0 = valuations.FunctionFieldValuation(K, v1)
|
|
488
|
+
sage: mu0.mac_lane_approximants(F) # needs sage.geometry.polyhedron
|
|
489
|
+
[[ Gauss valuation induced by Valuation on rational function field induced by [ Gauss valuation induced by 3-adic valuation, v(x) = 1/3 ], v(y + 2*x) = 2/3 ],
|
|
490
|
+
[ Gauss valuation induced by Valuation on rational function field induced by [ Gauss valuation induced by 3-adic valuation, v(x) = 1/3 ], v(y + x) = 2/3 ]]
|
|
491
|
+
|
|
492
|
+
Over a complete base field::
|
|
493
|
+
|
|
494
|
+
sage: # needs sage.libs.ntl
|
|
495
|
+
sage: k = Qp(2,10)
|
|
496
|
+
sage: v = k.valuation()
|
|
497
|
+
sage: R.<x> = k[]
|
|
498
|
+
sage: G = x
|
|
499
|
+
sage: v.mac_lane_approximants(G)
|
|
500
|
+
[Gauss valuation induced by 2-adic valuation]
|
|
501
|
+
sage: v.mac_lane_approximants(G, required_precision=infinity)
|
|
502
|
+
[[ Gauss valuation induced by 2-adic valuation, v((1 + O(2^10))*x) = +Infinity ]]
|
|
503
|
+
sage: G = x^2 + 1
|
|
504
|
+
sage: v.mac_lane_approximants(G) # needs sage.geometry.polyhedron
|
|
505
|
+
[[ Gauss valuation induced by 2-adic valuation, v((1 + O(2^10))*x + 1 + O(2^10)) = 1/2 ]]
|
|
506
|
+
sage: v.mac_lane_approximants(G, required_precision=infinity) # needs sage.geometry.polyhedron
|
|
507
|
+
[[ Gauss valuation induced by 2-adic valuation, v((1 + O(2^10))*x + 1 + O(2^10)) = 1/2,
|
|
508
|
+
v((1 + O(2^10))*x^2 + 1 + O(2^10)) = +Infinity ]]
|
|
509
|
+
sage: G = x^4 + 2*x^3 + 2*x^2 - 2*x + 2
|
|
510
|
+
sage: v.mac_lane_approximants(G) # needs sage.geometry.polyhedron
|
|
511
|
+
[[ Gauss valuation induced by 2-adic valuation, v((1 + O(2^10))*x) = 1/4 ]]
|
|
512
|
+
sage: v.mac_lane_approximants(G, required_precision=infinity) # needs sage.geometry.polyhedron
|
|
513
|
+
[[ Gauss valuation induced by 2-adic valuation, v((1 + O(2^10))*x) = 1/4,
|
|
514
|
+
v((1 + O(2^10))*x^4 + (2 + O(2^11))*x^3 + (2 + O(2^11))*x^2 + (2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^9 + 2^10 + O(2^11))*x + 2 + O(2^11)) = +Infinity ]]
|
|
515
|
+
|
|
516
|
+
The factorization of primes in the Gaussian integers can be read off
|
|
517
|
+
the Mac Lane approximants::
|
|
518
|
+
|
|
519
|
+
sage: v0 = QQ.valuation(2)
|
|
520
|
+
sage: R.<x> = QQ[]
|
|
521
|
+
sage: G = x^2 + 1
|
|
522
|
+
sage: v0.mac_lane_approximants(G) # needs sage.geometry.polyhedron sage.rings.padics
|
|
523
|
+
[[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1/2 ]]
|
|
524
|
+
|
|
525
|
+
sage: v0 = QQ.valuation(3)
|
|
526
|
+
sage: v0.mac_lane_approximants(G)
|
|
527
|
+
[[ Gauss valuation induced by 3-adic valuation, v(x^2 + 1) = +Infinity ]]
|
|
528
|
+
|
|
529
|
+
sage: v0 = QQ.valuation(5)
|
|
530
|
+
sage: v0.mac_lane_approximants(G) # needs sage.geometry.polyhedron sage.rings.padics
|
|
531
|
+
[[ Gauss valuation induced by 5-adic valuation, v(x + 2) = 1 ],
|
|
532
|
+
[ Gauss valuation induced by 5-adic valuation, v(x + 3) = 1 ]]
|
|
533
|
+
sage: v0.mac_lane_approximants(G, required_precision=10) # needs sage.geometry.polyhedron sage.rings.padics
|
|
534
|
+
[[ Gauss valuation induced by 5-adic valuation, v(x + 3116/237) = 10 ],
|
|
535
|
+
[ Gauss valuation induced by 5-adic valuation, v(x - 3116/237) = 10 ]]
|
|
536
|
+
|
|
537
|
+
The same example over the 5-adic numbers. In the quadratic extension
|
|
538
|
+
`\QQ[x]/(x^2+1)`, 5 factors `-(x - 2)(x + 2)`, this behaviour can be
|
|
539
|
+
read off the Mac Lane approximants::
|
|
540
|
+
|
|
541
|
+
sage: # needs sage.rings.padics
|
|
542
|
+
sage: k = Qp(5,4)
|
|
543
|
+
sage: v = k.valuation()
|
|
544
|
+
sage: R.<x> = k[] # needs sage.libs.ntl
|
|
545
|
+
sage: G = x^2 + 1
|
|
546
|
+
sage: v1,v2 = v.mac_lane_approximants(G); v1,v2 # needs sage.geometry.polyhedron
|
|
547
|
+
([ Gauss valuation induced by 5-adic valuation,
|
|
548
|
+
v((1 + O(5^4))*x + 2 + O(5^4)) = 1 ],
|
|
549
|
+
[ Gauss valuation induced by 5-adic valuation,
|
|
550
|
+
v((1 + O(5^4))*x + 3 + O(5^4)) = 1 ])
|
|
551
|
+
sage: w1, w2 = v.mac_lane_approximants(G, required_precision=2); w1, w2 # needs sage.geometry.polyhedron
|
|
552
|
+
([ Gauss valuation induced by 5-adic valuation,
|
|
553
|
+
v((1 + O(5^4))*x + 2 + 5 + O(5^4)) = 2 ],
|
|
554
|
+
[ Gauss valuation induced by 5-adic valuation,
|
|
555
|
+
v((1 + O(5^4))*x + 3 + 3*5 + O(5^4)) = 2 ])
|
|
556
|
+
|
|
557
|
+
Note how the latter give a better approximation to the factors of `x^2 + 1`::
|
|
558
|
+
|
|
559
|
+
sage: # needs sage.geometry.polyhedron sage.rings.padics
|
|
560
|
+
sage: v1.phi() * v2.phi() - G
|
|
561
|
+
O(5^4)*x^2 + (5 + O(5^4))*x + 5 + O(5^4)
|
|
562
|
+
sage: w1.phi() * w2.phi() - G
|
|
563
|
+
O(5^4)*x^2 + (5^2 + O(5^4))*x + 5^3 + O(5^4)
|
|
564
|
+
|
|
565
|
+
In this example, the process stops with a factorization of `x^2 + 1`::
|
|
566
|
+
|
|
567
|
+
sage: # needs sage.geometry.polyhedron sage.rings.padics
|
|
568
|
+
sage: v.mac_lane_approximants(G, required_precision=infinity)
|
|
569
|
+
[[ Gauss valuation induced by 5-adic valuation,
|
|
570
|
+
v((1 + O(5^4))*x + 2 + 5 + 2*5^2 + 5^3 + O(5^4)) = +Infinity ],
|
|
571
|
+
[ Gauss valuation induced by 5-adic valuation,
|
|
572
|
+
v((1 + O(5^4))*x + 3 + 3*5 + 2*5^2 + 3*5^3 + O(5^4)) = +Infinity ]]
|
|
573
|
+
|
|
574
|
+
This obviously cannot happen over the rationals where we only get an
|
|
575
|
+
approximate factorization::
|
|
576
|
+
|
|
577
|
+
sage: v = QQ.valuation(5)
|
|
578
|
+
sage: R.<x> = QQ[]
|
|
579
|
+
sage: G = x^2 + 1
|
|
580
|
+
sage: v.mac_lane_approximants(G) # needs sage.geometry.polyhedron
|
|
581
|
+
[[ Gauss valuation induced by 5-adic valuation, v(x + 2) = 1 ],
|
|
582
|
+
[ Gauss valuation induced by 5-adic valuation, v(x + 3) = 1 ]]
|
|
583
|
+
sage: v.mac_lane_approximants(G, required_precision=5) # needs sage.geometry.polyhedron
|
|
584
|
+
[[ Gauss valuation induced by 5-adic valuation, v(x + 79/3) = 5 ],
|
|
585
|
+
[ Gauss valuation induced by 5-adic valuation, v(x - 79/3) = 5 ]]
|
|
586
|
+
|
|
587
|
+
Initial versions ran into problems with the trivial residue field
|
|
588
|
+
extensions in this case::
|
|
589
|
+
|
|
590
|
+
sage: # needs sage.libs.ntl
|
|
591
|
+
sage: K = Qp(3, 20, print_mode='digits')
|
|
592
|
+
sage: R.<T> = K[]
|
|
593
|
+
sage: alpha = T^3/4
|
|
594
|
+
sage: G = 3^3*T^3*(alpha^4 - alpha)^2 - (4*alpha^3 - 1)^3
|
|
595
|
+
sage: G = G/G.leading_coefficient()
|
|
596
|
+
sage: K.valuation().mac_lane_approximants(G) # needs sage.geometry.polyhedron
|
|
597
|
+
[[ Gauss valuation induced by 3-adic valuation, v(...1*T + ...2) = 1/9,
|
|
598
|
+
v(...1*T^9 + ...20*T^8 + ...210*T^7 + ...20*T^6 + ...20*T^5 + ...10*T^4
|
|
599
|
+
+ ...220*T^3 + ...20*T^2 + ...110*T + ...122) = 55/27 ]]
|
|
600
|
+
|
|
601
|
+
A similar example::
|
|
602
|
+
|
|
603
|
+
sage: R.<x> = QQ[]
|
|
604
|
+
sage: v = QQ.valuation(3)
|
|
605
|
+
sage: G = (x^3 + 3)^3 - 81
|
|
606
|
+
sage: v.mac_lane_approximants(G) # needs sage.geometry.polyhedron sage.rings.padics
|
|
607
|
+
[[ Gauss valuation induced by 3-adic valuation,
|
|
608
|
+
v(x) = 1/3, v(x^3 + 3*x + 3) = 13/9 ]]
|
|
609
|
+
|
|
610
|
+
Another problematic case::
|
|
611
|
+
|
|
612
|
+
sage: # needs sage.geometry.polyhedron sage.rings.number_field sage.rings.padics
|
|
613
|
+
sage: R.<x> = QQ[]
|
|
614
|
+
sage: Delta = (x^12 + 20*x^11 + 154*x^10 + 664*x^9 + 1873*x^8 + 3808*x^7 + 5980*x^6
|
|
615
|
+
....: + 7560*x^5 + 7799*x^4 + 6508*x^3 + 4290*x^2 + 2224*x + 887)
|
|
616
|
+
sage: K.<theta> = NumberField(x^6 + 108)
|
|
617
|
+
sage: K.is_galois() # needs sage.groups
|
|
618
|
+
True
|
|
619
|
+
sage: vK = QQ.valuation(2).extension(K)
|
|
620
|
+
sage: vK(2)
|
|
621
|
+
1
|
|
622
|
+
sage: vK(theta)
|
|
623
|
+
1/3
|
|
624
|
+
sage: G = Delta.change_ring(K)
|
|
625
|
+
sage: vK.mac_lane_approximants(G)
|
|
626
|
+
[[ Gauss valuation induced by 2-adic valuation,
|
|
627
|
+
v(x + 1) = 1/4, v(x^4 + 1/2*theta^4 + 3*theta + 1) = 3/2 ],
|
|
628
|
+
[ Gauss valuation induced by 2-adic valuation,
|
|
629
|
+
v(x + 1) = 1/4, v(x^4 + 1/2*theta^4 + theta + 1) = 3/2 ],
|
|
630
|
+
[ Gauss valuation induced by 2-adic valuation,
|
|
631
|
+
v(x + 1) = 1/4, v(x^4 + 2*theta + 1) = 3/2 ]]
|
|
632
|
+
|
|
633
|
+
An easy case that produced the wrong error at some point::
|
|
634
|
+
|
|
635
|
+
sage: R.<x> = QQ[]
|
|
636
|
+
sage: v = QQ.valuation(2)
|
|
637
|
+
sage: v.mac_lane_approximants(x^2 - 1/2)
|
|
638
|
+
Traceback (most recent call last):
|
|
639
|
+
...
|
|
640
|
+
ValueError: G must be integral
|
|
641
|
+
|
|
642
|
+
Some examples that Sebastian Pauli used in a talk at Sage Days 87.
|
|
643
|
+
Here we use ``assume_squarefree=True`` because :meth:`is_squarefree`
|
|
644
|
+
is not properly implemented yet.
|
|
645
|
+
|
|
646
|
+
::
|
|
647
|
+
|
|
648
|
+
sage: R = ZpFM(3, 7, print_mode='terse')
|
|
649
|
+
sage: S.<x> = R[]
|
|
650
|
+
sage: v = R.valuation()
|
|
651
|
+
sage: f = x^4 + 234
|
|
652
|
+
sage: len(v.mac_lane_approximants(f, assume_squarefree=True)) # needs sage.geometry.polyhedron
|
|
653
|
+
....:
|
|
654
|
+
2
|
|
655
|
+
|
|
656
|
+
::
|
|
657
|
+
|
|
658
|
+
sage: R = ZpFM(2, 50, print_mode='terse')
|
|
659
|
+
sage: S.<x> = R[]
|
|
660
|
+
sage: f = (x^32 + 16)*(x^32 + 16 + 2^16*x^2) + 2^34
|
|
661
|
+
sage: v = R.valuation()
|
|
662
|
+
sage: len(v.mac_lane_approximants(f, assume_squarefree=True)) # needs sage.geometry.polyhedron
|
|
663
|
+
....:
|
|
664
|
+
2
|
|
665
|
+
|
|
666
|
+
A case that triggered an assertion at some point::
|
|
667
|
+
|
|
668
|
+
sage: v = QQ.valuation(3)
|
|
669
|
+
sage: R.<x> = QQ[]
|
|
670
|
+
sage: f = (x^36 + 60552000*x^33 + 268157412*x^30 + 173881701*x^27 + 266324841*x^24
|
|
671
|
+
....: + 83125683*x^21 + 111803814*x^18 + 31925826*x^15 + 205726716*x^12
|
|
672
|
+
....: + 17990262*x^9 + 351459648*x^6 + 127014399*x^3 + 359254116)
|
|
673
|
+
sage: v.mac_lane_approximants(f) # needs sage.geometry.polyhedron
|
|
674
|
+
[[ Gauss valuation induced by 3-adic valuation,
|
|
675
|
+
v(x) = 1/3,
|
|
676
|
+
v(x^3 - 3) = 3/2,
|
|
677
|
+
v(x^12 - 3*x^9 + 54*x^6 + 27/2*x^3 + 405/2) = 13/2,
|
|
678
|
+
v(x^36 + 60552000*x^33 + 268157412*x^30 + 173881701*x^27 + 266324841*x^24
|
|
679
|
+
+ 83125683*x^21 + 111803814*x^18 + 31925826*x^15 + 205726716*x^12
|
|
680
|
+
+ 17990262*x^9 + 351459648*x^6 + 127014399*x^3 + 359254116) = +Infinity ]]
|
|
681
|
+
"""
|
|
682
|
+
R = G.parent()
|
|
683
|
+
if R.base_ring() is not self.domain():
|
|
684
|
+
raise ValueError("G must be defined over the domain of this valuation")
|
|
685
|
+
|
|
686
|
+
from sage.misc.verbose import verbose
|
|
687
|
+
verbose("Approximants of %r on %r towards %r" % (self, self.domain(), G), level=3)
|
|
688
|
+
|
|
689
|
+
from sage.rings.valuation.gauss_valuation import GaussValuation
|
|
690
|
+
|
|
691
|
+
if not all(self(c) >= 0 for c in G.coefficients()):
|
|
692
|
+
raise ValueError("G must be integral")
|
|
693
|
+
|
|
694
|
+
if require_maximal_degree:
|
|
695
|
+
# we can only assert maximality of degrees when E and F are final
|
|
696
|
+
require_final_EF = True
|
|
697
|
+
|
|
698
|
+
if not assume_squarefree:
|
|
699
|
+
if require_final_EF and not G.is_squarefree():
|
|
700
|
+
raise ValueError("G must be squarefree")
|
|
701
|
+
else:
|
|
702
|
+
# if only required_precision is set, we do not need to check
|
|
703
|
+
# whether G is squarefree. If G is not squarefree, we compute
|
|
704
|
+
# valuations corresponding to approximants for all the
|
|
705
|
+
# squarefree factors of G (up to required_precision.)
|
|
706
|
+
pass
|
|
707
|
+
|
|
708
|
+
def is_sufficient(leaf, others):
|
|
709
|
+
if leaf.valuation.mu() < required_precision:
|
|
710
|
+
return False
|
|
711
|
+
if require_final_EF and not leaf.ef:
|
|
712
|
+
return False
|
|
713
|
+
if require_maximal_degree and leaf.valuation.phi().degree() != leaf.valuation.E() * leaf.valuation.F():
|
|
714
|
+
return False
|
|
715
|
+
if require_incomparability:
|
|
716
|
+
if any(leaf.valuation <= o.valuation for o in others):
|
|
717
|
+
return False
|
|
718
|
+
return True
|
|
719
|
+
|
|
720
|
+
seed = MacLaneApproximantNode(GaussValuation(R, self), None, G.degree() == 1, G.degree(), None, None)
|
|
721
|
+
seed.forced_leaf = is_sufficient(seed, [])
|
|
722
|
+
|
|
723
|
+
def create_children(node):
|
|
724
|
+
new_leafs = []
|
|
725
|
+
if node.forced_leaf:
|
|
726
|
+
return new_leafs
|
|
727
|
+
augmentations = node.valuation.mac_lane_step(G,
|
|
728
|
+
report_degree_bounds_and_caches=True,
|
|
729
|
+
coefficients=node.coefficients,
|
|
730
|
+
valuations=node.valuations,
|
|
731
|
+
check=False,
|
|
732
|
+
# We do not want to see augmentations that are
|
|
733
|
+
# already part of other branches of the tree of
|
|
734
|
+
# valuations for obvious performance reasons and
|
|
735
|
+
# also because the principal_part_bound would be
|
|
736
|
+
# incorrect for these.
|
|
737
|
+
allow_equivalent_key=node.valuation.is_gauss_valuation(),
|
|
738
|
+
# The length of an edge in the Newton polygon in
|
|
739
|
+
# one MacLane step bounds the length of the
|
|
740
|
+
# principal part (i.e., the part with negative
|
|
741
|
+
# slopes) of the Newton polygons in the next
|
|
742
|
+
# MacLane step. Therefore, mac_lane_step does not
|
|
743
|
+
# need to compute valuations for coefficients
|
|
744
|
+
# beyond that bound as they do not contribute any
|
|
745
|
+
# augmentations.
|
|
746
|
+
principal_part_bound=node.principal_part_bound)
|
|
747
|
+
for w, bound, principal_part_bound, coefficients, valuations in augmentations:
|
|
748
|
+
ef = bound == w.E()*w.F()
|
|
749
|
+
new_leafs.append(MacLaneApproximantNode(w, node, ef, principal_part_bound, coefficients, valuations))
|
|
750
|
+
for leaf in new_leafs:
|
|
751
|
+
if is_sufficient(leaf, [l for l in new_leafs if l is not leaf]):
|
|
752
|
+
leaf.forced_leaf = True
|
|
753
|
+
return new_leafs
|
|
754
|
+
|
|
755
|
+
def reduce_tree(v, w):
|
|
756
|
+
return v + w
|
|
757
|
+
|
|
758
|
+
from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
|
|
759
|
+
tree = RecursivelyEnumeratedSet([seed],
|
|
760
|
+
successors=create_children,
|
|
761
|
+
structure='forest',
|
|
762
|
+
enumeration='breadth')
|
|
763
|
+
# this is a tad faster but annoying for profiling / debugging
|
|
764
|
+
if algorithm == 'parallel':
|
|
765
|
+
nodes = tree.map_reduce(map_function=lambda x: [x],
|
|
766
|
+
reduce_init=[])
|
|
767
|
+
elif algorithm == 'serial':
|
|
768
|
+
from sage.parallel.map_reduce import RESetMapReduce
|
|
769
|
+
nodes = RESetMapReduce(forest=tree,
|
|
770
|
+
map_function=lambda x: [x],
|
|
771
|
+
reduce_init=[]).run_serial()
|
|
772
|
+
else:
|
|
773
|
+
raise NotImplementedError(algorithm)
|
|
774
|
+
leafs = {node.valuation for node in nodes}
|
|
775
|
+
for node in nodes:
|
|
776
|
+
if node.parent is None:
|
|
777
|
+
continue
|
|
778
|
+
v = node.parent.valuation
|
|
779
|
+
if v in leafs:
|
|
780
|
+
leafs.remove(v)
|
|
781
|
+
|
|
782
|
+
# The order of the leafs is not predictable in parallel mode and in
|
|
783
|
+
# serial mode it depends on the hash functions and so on the underlying
|
|
784
|
+
# architecture (32/64 bit). There is no natural ordering on these
|
|
785
|
+
# valuations but it is very convenient for doctesting to return them in
|
|
786
|
+
# some stable order, so we just order them by their string
|
|
787
|
+
# representation which should be very fast.
|
|
788
|
+
try:
|
|
789
|
+
ret = sorted(leafs, key=str)
|
|
790
|
+
except Exception:
|
|
791
|
+
# if for some reason the valuation can not be printed, we leave them unsorted
|
|
792
|
+
ret = list(leafs)
|
|
793
|
+
|
|
794
|
+
return ret
|
|
795
|
+
|
|
796
|
+
@cached_method
|
|
797
|
+
def _pow(self, x, e, error):
|
|
798
|
+
r"""
|
|
799
|
+
Return `x^e`.
|
|
800
|
+
|
|
801
|
+
This method does not compute the exact value of `x^e` but only an
|
|
802
|
+
element that differs from the correct result by an error with valuation
|
|
803
|
+
at least ``error``.
|
|
804
|
+
|
|
805
|
+
EXAMPLES::
|
|
806
|
+
|
|
807
|
+
sage: v = QQ.valuation(2)
|
|
808
|
+
sage: v._pow(2, 2, error=4)
|
|
809
|
+
4
|
|
810
|
+
sage: v._pow(2, 1000, error=4)
|
|
811
|
+
0
|
|
812
|
+
"""
|
|
813
|
+
if e == 0:
|
|
814
|
+
return self.domain().one()
|
|
815
|
+
if e == 1:
|
|
816
|
+
return self.simplify(x, error=error)
|
|
817
|
+
if e % 2 == 0:
|
|
818
|
+
return self._pow(self.simplify(x*x, error=error*2/e), e//2, error=error)
|
|
819
|
+
else:
|
|
820
|
+
return self.simplify(x*self._pow(x, e-1, error=error*(e-1)/e), error=error)
|
|
821
|
+
|
|
822
|
+
def mac_lane_approximant(self, G, valuation, approximants=None):
|
|
823
|
+
r"""
|
|
824
|
+
Return the approximant from :meth:`mac_lane_approximants` for ``G``
|
|
825
|
+
which is approximated by or approximates ``valuation``.
|
|
826
|
+
|
|
827
|
+
INPUT:
|
|
828
|
+
|
|
829
|
+
- ``G`` -- a monic squarefree integral polynomial in a univariate
|
|
830
|
+
polynomial ring over the domain of this valuation
|
|
831
|
+
|
|
832
|
+
- ``valuation`` -- a valuation on the parent of ``G``
|
|
833
|
+
|
|
834
|
+
- ``approximants`` -- the output of :meth:`mac_lane_approximants`;
|
|
835
|
+
if not given, it is computed
|
|
836
|
+
|
|
837
|
+
EXAMPLES::
|
|
838
|
+
|
|
839
|
+
sage: v = QQ.valuation(2)
|
|
840
|
+
sage: R.<x> = QQ[]
|
|
841
|
+
sage: G = x^2 + 1
|
|
842
|
+
|
|
843
|
+
We can select an approximant by approximating it::
|
|
844
|
+
|
|
845
|
+
sage: w = GaussValuation(R, v).augmentation(x + 1, 1/2)
|
|
846
|
+
sage: v.mac_lane_approximant(G, w) # needs sage.geometry.polyhedron sage.rings.padics
|
|
847
|
+
[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1/2 ]
|
|
848
|
+
|
|
849
|
+
As long as this is the only matching approximant, the approximation can
|
|
850
|
+
be very coarse::
|
|
851
|
+
|
|
852
|
+
sage: w = GaussValuation(R, v)
|
|
853
|
+
sage: v.mac_lane_approximant(G, w) # needs sage.geometry.polyhedron sage.rings.padics
|
|
854
|
+
[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1/2 ]
|
|
855
|
+
|
|
856
|
+
Or it can be very specific::
|
|
857
|
+
|
|
858
|
+
sage: w = GaussValuation(R, v).augmentation(x + 1, 1/2).augmentation(G, infinity)
|
|
859
|
+
sage: v.mac_lane_approximant(G, w) # needs sage.geometry.polyhedron sage.rings.padics
|
|
860
|
+
[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1/2 ]
|
|
861
|
+
|
|
862
|
+
But it must be an approximation of an approximant::
|
|
863
|
+
|
|
864
|
+
sage: w = GaussValuation(R, v).augmentation(x, 1/2)
|
|
865
|
+
sage: v.mac_lane_approximant(G, w)
|
|
866
|
+
Traceback (most recent call last):
|
|
867
|
+
...
|
|
868
|
+
ValueError: The valuation
|
|
869
|
+
[ Gauss valuation induced by 2-adic valuation, v(x) = 1/2 ] is
|
|
870
|
+
not an approximant for a valuation which extends 2-adic valuation
|
|
871
|
+
with respect to x^2 + 1 since the valuation of x^2 + 1
|
|
872
|
+
does not increase in every step
|
|
873
|
+
|
|
874
|
+
The ``valuation`` must single out one approximant::
|
|
875
|
+
|
|
876
|
+
sage: G = x^2 - 1
|
|
877
|
+
sage: w = GaussValuation(R, v)
|
|
878
|
+
sage: v.mac_lane_approximant(G, w) # needs sage.geometry.polyhedron sage.rings.padics
|
|
879
|
+
Traceback (most recent call last):
|
|
880
|
+
...
|
|
881
|
+
ValueError: The valuation Gauss valuation induced by 2-adic valuation
|
|
882
|
+
does not approximate a unique extension of 2-adic valuation
|
|
883
|
+
with respect to x^2 - 1
|
|
884
|
+
|
|
885
|
+
sage: w = GaussValuation(R, v).augmentation(x + 1, 1)
|
|
886
|
+
sage: v.mac_lane_approximant(G, w) # needs sage.geometry.polyhedron sage.rings.padics
|
|
887
|
+
Traceback (most recent call last):
|
|
888
|
+
...
|
|
889
|
+
ValueError: The valuation
|
|
890
|
+
[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1 ] does not
|
|
891
|
+
approximate a unique extension of 2-adic valuation with respect to x^2 - 1
|
|
892
|
+
|
|
893
|
+
sage: w = GaussValuation(R, v).augmentation(x + 1, 2)
|
|
894
|
+
sage: v.mac_lane_approximant(G, w) # needs sage.geometry.polyhedron sage.rings.padics
|
|
895
|
+
[ Gauss valuation induced by 2-adic valuation, v(x + 1) = +Infinity ]
|
|
896
|
+
|
|
897
|
+
sage: w = GaussValuation(R, v).augmentation(x + 3, 2)
|
|
898
|
+
sage: v.mac_lane_approximant(G, w) # needs sage.geometry.polyhedron sage.rings.padics
|
|
899
|
+
[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 1 ]
|
|
900
|
+
"""
|
|
901
|
+
if valuation.restriction(valuation.domain().base_ring()) is not self:
|
|
902
|
+
raise ValueError
|
|
903
|
+
|
|
904
|
+
# Check that valuation is an approximant for a valuation
|
|
905
|
+
# on domain that extends its restriction to the base field.
|
|
906
|
+
from sage.rings.infinity import infinity
|
|
907
|
+
if valuation(G) is not infinity:
|
|
908
|
+
v = valuation
|
|
909
|
+
while not v.is_gauss_valuation():
|
|
910
|
+
if v(G) <= v._base_valuation(G):
|
|
911
|
+
raise ValueError("The valuation %r is not an approximant for a valuation which extends %r with respect to %r since the valuation of %r does not increase in every step" % (valuation, self, G, G))
|
|
912
|
+
v = v._base_valuation
|
|
913
|
+
|
|
914
|
+
if approximants is None:
|
|
915
|
+
approximants = self.mac_lane_approximants(G)
|
|
916
|
+
|
|
917
|
+
assert all(approximant.domain() is valuation.domain() for approximant in approximants)
|
|
918
|
+
|
|
919
|
+
greater_approximants = [w for w in approximants if w >= valuation]
|
|
920
|
+
if len(greater_approximants) > 1:
|
|
921
|
+
raise ValueError("The valuation %r does not approximate a unique extension of %r with respect to %r" % (valuation, self, G))
|
|
922
|
+
if len(greater_approximants) == 1:
|
|
923
|
+
return greater_approximants[0]
|
|
924
|
+
|
|
925
|
+
smaller_approximants = [w for w in approximants if w <= valuation]
|
|
926
|
+
if len(smaller_approximants) > 1:
|
|
927
|
+
raise ValueError("The valuation %r is not approximated by a unique extension of %r with respect to %r" % (valuation, self, G))
|
|
928
|
+
if len(smaller_approximants) == 0:
|
|
929
|
+
raise ValueError("The valuation %r is not related to an extension of %r with respect to %r" % (valuation, self, G))
|
|
930
|
+
return smaller_approximants[0]
|
|
931
|
+
|
|
932
|
+
def montes_factorization(self, G, assume_squarefree=False, required_precision=None):
|
|
933
|
+
"""
|
|
934
|
+
Factor ``G`` over the completion of the domain of this valuation.
|
|
935
|
+
|
|
936
|
+
INPUT:
|
|
937
|
+
|
|
938
|
+
- ``G`` -- a monic polynomial over the domain of this valuation
|
|
939
|
+
|
|
940
|
+
- ``assume_squarefree`` -- boolean (default: ``False``); whether to
|
|
941
|
+
assume ``G`` to be squarefree
|
|
942
|
+
|
|
943
|
+
- ``required_precision`` -- a number or infinity (default:
|
|
944
|
+
infinity); if ``infinity``, the returned polynomials are actual factors of
|
|
945
|
+
``G``, otherwise they are only factors with precision at least
|
|
946
|
+
``required_precision``.
|
|
947
|
+
|
|
948
|
+
ALGORITHM:
|
|
949
|
+
|
|
950
|
+
We compute :meth:`mac_lane_approximants` with ``required_precision``.
|
|
951
|
+
The key polynomials approximate factors of ``G``. This can be very
|
|
952
|
+
slow unless ``required_precision`` is set to zero. Single factor
|
|
953
|
+
lifting could improve this significantly.
|
|
954
|
+
|
|
955
|
+
EXAMPLES::
|
|
956
|
+
|
|
957
|
+
sage: # needs sage.libs.ntl
|
|
958
|
+
sage: k = Qp(5,4)
|
|
959
|
+
sage: v = k.valuation()
|
|
960
|
+
sage: R.<x> = k[]
|
|
961
|
+
sage: G = x^2 + 1
|
|
962
|
+
sage: v.montes_factorization(G) # needs sage.geometry.polyhedron
|
|
963
|
+
((1 + O(5^4))*x + 2 + 5 + 2*5^2 + 5^3 + O(5^4))
|
|
964
|
+
* ((1 + O(5^4))*x + 3 + 3*5 + 2*5^2 + 3*5^3 + O(5^4))
|
|
965
|
+
|
|
966
|
+
The computation might not terminate over incomplete fields (in
|
|
967
|
+
particular because the factors can not be represented there)::
|
|
968
|
+
|
|
969
|
+
sage: R.<x> = QQ[]
|
|
970
|
+
sage: v = QQ.valuation(2)
|
|
971
|
+
sage: v.montes_factorization(x^6 - 1) # needs sage.geometry.polyhedron sage.rings.padics
|
|
972
|
+
(x - 1) * (x + 1) * (x^2 - x + 1) * (x^2 + x + 1)
|
|
973
|
+
|
|
974
|
+
sage: v.montes_factorization(x^7 - 1) # not tested # needs sage.rings.padics
|
|
975
|
+
|
|
976
|
+
sage: v.montes_factorization(x^7 - 1, required_precision=5) # needs sage.geometry.polyhedron sage.rings.padics
|
|
977
|
+
(x - 1) * (x^3 - 5*x^2 - 6*x - 1) * (x^3 + 6*x^2 + 5*x - 1)
|
|
978
|
+
|
|
979
|
+
TESTS:
|
|
980
|
+
|
|
981
|
+
Some examples that Sebastian Pauli used in a talk at Sage Days 87.
|
|
982
|
+
|
|
983
|
+
In this example, ``f`` factors as three factors of degree 50 over an
|
|
984
|
+
unramified extension::
|
|
985
|
+
|
|
986
|
+
sage: # needs sage.libs.flint
|
|
987
|
+
sage: R.<u> = ZqFM(125)
|
|
988
|
+
sage: S.<x> = R[]
|
|
989
|
+
sage: f = (x^6+2)^25 + 5
|
|
990
|
+
sage: v = R.valuation()
|
|
991
|
+
sage: v.montes_factorization(f, assume_squarefree=True, required_precision=0) # needs sage.geometry.polyhedron
|
|
992
|
+
(x^50 + 2*5*x^45 + 5*x^40 + 5*x^30 + 2*x^25 + 3*5*x^20 + 2*5*x^10 + 2*5*x^5 + 5*x + 3 + 5) * (x^50 + 3*5*x^45 + 5*x^40 + 5*x^30 + (3 + 4*5)*x^25 + 3*5*x^20 + 2*5*x^10 + 3*5*x^5 + 4*5*x + 3 + 5) * (x^50 + 3*5*x^40 + 3*5*x^30 + 4*5*x^20 + 5*x^10 + 3 + 5)
|
|
993
|
+
|
|
994
|
+
In this case, ``f`` factors into degrees 1, 2, and 5 over a totally ramified extension::
|
|
995
|
+
|
|
996
|
+
sage: # needs sage.libs.ntl
|
|
997
|
+
sage: R = Zp(5)
|
|
998
|
+
sage: S.<w> = R[]
|
|
999
|
+
sage: R.<w> = R.extension(w^3 + 5)
|
|
1000
|
+
sage: S.<x> = R[]
|
|
1001
|
+
sage: f = (x^3 + 5)*(x^5 + w) + 625
|
|
1002
|
+
sage: v = R.valuation()
|
|
1003
|
+
sage: v.montes_factorization(f, assume_squarefree=True, required_precision=0) # needs sage.geometry.polyhedron sage.libs.flint
|
|
1004
|
+
((1 + O(w^60))*x + 4*w + O(w^61)) * ((1 + O(w^60))*x^2 + (w + O(w^61))*x + w^2 + O(w^62)) * ((1 + O(w^60))*x^5 + w + O(w^61))
|
|
1005
|
+
|
|
1006
|
+
REFERENCES:
|
|
1007
|
+
|
|
1008
|
+
The underlying algorithm is described in [Mac1936II]_ and thoroughly
|
|
1009
|
+
analyzed in [GMN2008]_.
|
|
1010
|
+
"""
|
|
1011
|
+
if required_precision is None:
|
|
1012
|
+
from sage.rings.infinity import infinity
|
|
1013
|
+
required_precision = infinity
|
|
1014
|
+
|
|
1015
|
+
R = G.parent()
|
|
1016
|
+
if R.base_ring() is not self.domain():
|
|
1017
|
+
raise ValueError("G must be defined over the domain of this valuation")
|
|
1018
|
+
if not G.is_monic():
|
|
1019
|
+
raise ValueError("G must be monic")
|
|
1020
|
+
if not all(self(c) >= 0 for c in G.coefficients()):
|
|
1021
|
+
raise ValueError("G must be integral")
|
|
1022
|
+
|
|
1023
|
+
# W contains approximate factors of G
|
|
1024
|
+
W = self.mac_lane_approximants(G, required_precision=required_precision, require_maximal_degree=True, assume_squarefree=assume_squarefree)
|
|
1025
|
+
ret = [w.phi() for w in W]
|
|
1026
|
+
|
|
1027
|
+
from sage.structure.factorization import Factorization
|
|
1028
|
+
return Factorization([(g, 1) for g in ret], simplify=False)
|
|
1029
|
+
|
|
1030
|
+
def _ge_(self, other):
|
|
1031
|
+
r"""
|
|
1032
|
+
Return whether this valuation is greater than or equal to ``other``
|
|
1033
|
+
pointwise.
|
|
1034
|
+
|
|
1035
|
+
EXAMPLES::
|
|
1036
|
+
|
|
1037
|
+
sage: v = valuations.TrivialValuation(QQ)
|
|
1038
|
+
sage: w = QQ.valuation(2)
|
|
1039
|
+
sage: v >= w
|
|
1040
|
+
False
|
|
1041
|
+
"""
|
|
1042
|
+
if other.is_trivial():
|
|
1043
|
+
return other.is_discrete_valuation()
|
|
1044
|
+
return super()._ge_(other)
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
class MacLaneApproximantNode:
|
|
1048
|
+
r"""
|
|
1049
|
+
A node in the tree computed by :meth:`DiscreteValuation.mac_lane_approximants`.
|
|
1050
|
+
|
|
1051
|
+
Leaves in the computation of the tree of approximants
|
|
1052
|
+
:meth:`~DiscreteValuation.mac_lane_approximants`. Each vertex consists of a
|
|
1053
|
+
tuple ``(v,ef,p,coeffs,vals)`` where ``v`` is an approximant, i.e., a
|
|
1054
|
+
valuation, ef is a boolean, ``p`` is the parent of this vertex, and
|
|
1055
|
+
``coeffs`` and ``vals`` are cached values. (Only ``v`` and ``ef`` are
|
|
1056
|
+
relevant, everything else are caches/debug info.) The boolean ``ef``
|
|
1057
|
+
denotes whether ``v`` already has the final ramification index E and
|
|
1058
|
+
residue degree F of this approximant. An edge V -- P represents the
|
|
1059
|
+
relation ``P.v`` `≤` ``V.v`` (pointwise on the polynomial ring K[x]) between the
|
|
1060
|
+
valuations.
|
|
1061
|
+
|
|
1062
|
+
TESTS::
|
|
1063
|
+
|
|
1064
|
+
sage: v = ZZ.valuation(3)
|
|
1065
|
+
sage: v.extension(GaussianIntegers()) # indirect doctest # needs sage.rings.number_field sage.rings.padics
|
|
1066
|
+
3-adic valuation
|
|
1067
|
+
"""
|
|
1068
|
+
def __init__(self, valuation, parent, ef, principal_part_bound, coefficients, valuations):
|
|
1069
|
+
r"""
|
|
1070
|
+
TESTS::
|
|
1071
|
+
|
|
1072
|
+
sage: from sage.rings.valuation.valuation import MacLaneApproximantNode
|
|
1073
|
+
sage: node = MacLaneApproximantNode(QQ.valuation(2), None, 1, None, None, None)
|
|
1074
|
+
sage: TestSuite(node).run()
|
|
1075
|
+
"""
|
|
1076
|
+
self.valuation = valuation
|
|
1077
|
+
self.parent = parent
|
|
1078
|
+
self.ef = ef
|
|
1079
|
+
self.principal_part_bound = principal_part_bound
|
|
1080
|
+
self.coefficients = coefficients
|
|
1081
|
+
self.valuations = valuations
|
|
1082
|
+
self.forced_leaf = False
|
|
1083
|
+
|
|
1084
|
+
def __eq__(self, other):
|
|
1085
|
+
r"""
|
|
1086
|
+
Return whether this node is equal to ``other``.
|
|
1087
|
+
|
|
1088
|
+
EXAMPLES::
|
|
1089
|
+
|
|
1090
|
+
sage: from sage.rings.valuation.valuation import MacLaneApproximantNode
|
|
1091
|
+
sage: n = MacLaneApproximantNode(QQ.valuation(2), None, 1, None, None, None)
|
|
1092
|
+
sage: m = MacLaneApproximantNode(QQ.valuation(3), None, 1, None, None, None)
|
|
1093
|
+
sage: n == m
|
|
1094
|
+
False
|
|
1095
|
+
sage: n == n
|
|
1096
|
+
True
|
|
1097
|
+
"""
|
|
1098
|
+
if type(self) is not type(other):
|
|
1099
|
+
return False
|
|
1100
|
+
return (self.valuation, self.parent, self.ef, self.principal_part_bound, self.coefficients, self.valuations, self.forced_leaf) == (other.valuation, other.parent, other.ef, other.principal_part_bound, other.coefficients, other.valuations, other.forced_leaf)
|
|
1101
|
+
|
|
1102
|
+
def __ne__(self, other):
|
|
1103
|
+
r"""
|
|
1104
|
+
Return whether this node is not equal to ``other``.
|
|
1105
|
+
|
|
1106
|
+
EXAMPLES::
|
|
1107
|
+
|
|
1108
|
+
sage: from sage.rings.valuation.valuation import MacLaneApproximantNode
|
|
1109
|
+
sage: n = MacLaneApproximantNode(QQ.valuation(2), None, 1, None, None, None)
|
|
1110
|
+
sage: m = MacLaneApproximantNode(QQ.valuation(3), None, 1, None, None, None)
|
|
1111
|
+
sage: n != m
|
|
1112
|
+
True
|
|
1113
|
+
sage: n != n
|
|
1114
|
+
False
|
|
1115
|
+
"""
|
|
1116
|
+
return not (self == other)
|
|
1117
|
+
|
|
1118
|
+
# mutable object - not hashable
|
|
1119
|
+
__hash__ = None
|