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,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)))
|