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,1307 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
"""
|
|
3
|
+
Ideals in Tate algebra
|
|
4
|
+
|
|
5
|
+
The module gives tools for manipulating ideals in Tate algebras
|
|
6
|
+
and, in particular, provides an implementation of the Buchberger
|
|
7
|
+
algorithm in this context.
|
|
8
|
+
|
|
9
|
+
AUTHORS:
|
|
10
|
+
|
|
11
|
+
- Xavier Caruso, Thibaut Verron (2018-09): Buchberger algorithm
|
|
12
|
+
|
|
13
|
+
- Xavier Caruso, Thibaut Verron (2019-04): F5-type algorithms (PoTe and VaPoTe)
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# ***************************************************************************
|
|
17
|
+
# Copyright (C) 2018 Xavier Caruso <xavier.caruso@normalesup.org>
|
|
18
|
+
# Thibaut Verron <thibaut.verron@gmail.com>
|
|
19
|
+
#
|
|
20
|
+
# This program is free software: you can redistribute it and/or modify
|
|
21
|
+
# it under the terms of the GNU General Public License as published by
|
|
22
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
23
|
+
# (at your option) any later version.
|
|
24
|
+
# https://www.gnu.org/licenses/
|
|
25
|
+
# ***************************************************************************
|
|
26
|
+
|
|
27
|
+
from sage.rings.ideal import Ideal_generic
|
|
28
|
+
|
|
29
|
+
from sage.structure.richcmp import op_EQ, op_NE, op_LT, op_GT, op_LE, op_GE
|
|
30
|
+
|
|
31
|
+
from sage.rings.polynomial.polydict cimport PolyDict
|
|
32
|
+
|
|
33
|
+
from sage.rings.tate_algebra_element cimport TateAlgebraTerm
|
|
34
|
+
from sage.rings.tate_algebra_element cimport TateAlgebraElement
|
|
35
|
+
from heapq import heappush, heappop
|
|
36
|
+
|
|
37
|
+
from cysignals.signals cimport sig_check
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TateAlgebraIdeal(Ideal_generic):
|
|
41
|
+
r"""
|
|
42
|
+
Initialize a class for ideals in a Tate series algebra.
|
|
43
|
+
|
|
44
|
+
EXAMPLES::
|
|
45
|
+
|
|
46
|
+
sage: R = Zp(3, prec=10, print_mode='digits')
|
|
47
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
48
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
49
|
+
sage: g = 5*x^2*y + 3
|
|
50
|
+
sage: I = A.ideal([f,g]); I
|
|
51
|
+
Ideal (...0000000012*x*y^2 + ...00000000010*x^2, ...0000000012*x^2*y + ...00000000010) of Tate Algebra in x (val >= 0), y (val >= 0) over 3-adic Field with capped relative precision 10
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
#@cached_method
|
|
55
|
+
def groebner_basis(self, prec=None, algorithm='VaPoTe', **options):
|
|
56
|
+
r"""
|
|
57
|
+
Compute a Groebner basis of the ideal.
|
|
58
|
+
|
|
59
|
+
INPUT:
|
|
60
|
+
|
|
61
|
+
- ``prec`` -- integer or ``None`` (default: ``None``); the precision
|
|
62
|
+
at which the computations are carried. If ``None``, defaults to the
|
|
63
|
+
algebra precision cap.
|
|
64
|
+
|
|
65
|
+
- ``algorithm`` -- string (default: ``'VaPoTe'``), the algorithm to
|
|
66
|
+
use in the calculations; available algorithms are:
|
|
67
|
+
|
|
68
|
+
- ``'buchberger'``: classical Buchberger algorithm
|
|
69
|
+
|
|
70
|
+
- ``'buchberger-integral'``: first computes a Groebner basis of the
|
|
71
|
+
ideal generated by the same generators over the ring of integers
|
|
72
|
+
(provides better numerical stability)
|
|
73
|
+
|
|
74
|
+
- ``'PoTe'``: a F5-type algorithm where signatures are ordered by
|
|
75
|
+
position over term
|
|
76
|
+
|
|
77
|
+
- ``'VaPoTe'``: a F5-type algorithm where signatures are ordered
|
|
78
|
+
by valuation over position over term
|
|
79
|
+
|
|
80
|
+
We refer to [CVV2019]_ and [CVV2020]_ for a detailed description
|
|
81
|
+
of these algorithms.
|
|
82
|
+
|
|
83
|
+
- ``options`` -- extra arguments that are passed in to the
|
|
84
|
+
algorithm; this notably include the keyword ``verbose`` (only
|
|
85
|
+
available for ``PoTe`` and ``VaPoTe``) which is an integer
|
|
86
|
+
defining the verbosity level:
|
|
87
|
+
|
|
88
|
+
- ``0``: no verbosity (quiet)
|
|
89
|
+
|
|
90
|
+
- ``1``: print each new generator and a notification each time a
|
|
91
|
+
J-pair is popped
|
|
92
|
+
|
|
93
|
+
- ``2``: in addition, print the outcome of the treatment of a J-pair
|
|
94
|
+
|
|
95
|
+
- ``3``: in addition, print all added J-pairs
|
|
96
|
+
|
|
97
|
+
- ``4``: print entire series instead of only their leading terms
|
|
98
|
+
|
|
99
|
+
OUTPUT:
|
|
100
|
+
|
|
101
|
+
The Groebner basis `(g_1,\dots,g_n)` of this ideal, uniquely determined
|
|
102
|
+
by the following conditions::
|
|
103
|
+
|
|
104
|
+
- it is minimal, in the sense that the leading coefficient of `g_i`
|
|
105
|
+
does not divide the leading coefficient of `g_j` if `i \neq j`,
|
|
106
|
+
|
|
107
|
+
- it is reduced, in the sense that each term of `g_i` is not divisible
|
|
108
|
+
by leading term of `g_j` for `j \neq i` or the leading term of
|
|
109
|
+
`\pi g_i` where `\pi` is the uniformizer,
|
|
110
|
+
|
|
111
|
+
- it is normalized so that the leading coefficient of each `g_i` is
|
|
112
|
+
a power of the uniformizer and moreover, if we are working over a Tate
|
|
113
|
+
algebra (and not its ring of integers), each `g_i` has valuation `0`,
|
|
114
|
+
|
|
115
|
+
- it is sorted, in the sense that the leading term of `g_i` is greater
|
|
116
|
+
than the leading of `g_{i+1}` for all `i`.
|
|
117
|
+
|
|
118
|
+
.. NOTE::
|
|
119
|
+
|
|
120
|
+
The result of this method is cached.
|
|
121
|
+
|
|
122
|
+
EXAMPLES::
|
|
123
|
+
|
|
124
|
+
sage: R = Zp(3, prec=10, print_mode='digits')
|
|
125
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
126
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
127
|
+
sage: g = 5*x^2*y + 3
|
|
128
|
+
sage: I = A.ideal([f,g])
|
|
129
|
+
sage: I.groebner_basis()
|
|
130
|
+
[...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
131
|
+
...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
132
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>)]
|
|
133
|
+
|
|
134
|
+
The algorithm ``buchberger`` is faster than ``buchberger-integral``
|
|
135
|
+
but may lose more precision::
|
|
136
|
+
|
|
137
|
+
sage: R = Zp(2, 5, print_mode='digits')
|
|
138
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
139
|
+
sage: f = x^2*y^6 + x^4 + 25*y^2 + 2*x^3*y^3 + 10*x*y^4 + 10*x^2*y
|
|
140
|
+
sage: g = x^4*y^5 + x^5*y^2 + x^4 + 5*x^2*y + 2*x^5*y^4 + 2*x^6*y + 6*x^3*y^3
|
|
141
|
+
sage: h = 2*x^6*y^4 + 2*x^4 + 4*x^5*y^2 + 8*x^8*y^2 + 8*x^7*y^3 + 8*x^6*y
|
|
142
|
+
sage: I = A.ideal([f,g,h])
|
|
143
|
+
sage: I.groebner_basis(algorithm='buchberger-integral')
|
|
144
|
+
[...0001*x^4 + O(2^4 * <x, y>),
|
|
145
|
+
...0001*x^2*y + O(2^4 * <x, y>),
|
|
146
|
+
...0001*y^2 + O(2^4 * <x, y>)]
|
|
147
|
+
sage: I.groebner_basis(algorithm='buchberger')
|
|
148
|
+
[...001*x^4 + O(2^3 * <x, y>),
|
|
149
|
+
...001*x^2*y + O(2^3 * <x, y>),
|
|
150
|
+
...001*y^2 + O(2^3 * <x, y>)]
|
|
151
|
+
|
|
152
|
+
TESTS::
|
|
153
|
+
|
|
154
|
+
sage: I.groebner_basis(algorithm='F4')
|
|
155
|
+
Traceback (most recent call last):
|
|
156
|
+
...
|
|
157
|
+
NotImplementedError: available algorithms are 'buchberger', 'buchberger-integral', 'PoTe' and 'VaPoTe'
|
|
158
|
+
"""
|
|
159
|
+
if prec is None:
|
|
160
|
+
prec = self.ring().precision_cap()
|
|
161
|
+
if algorithm == "buchberger":
|
|
162
|
+
return groebner_basis_buchberger(self, prec, False, **options)
|
|
163
|
+
elif algorithm == "buchberger-integral":
|
|
164
|
+
return groebner_basis_buchberger(self, prec, True, **options)
|
|
165
|
+
elif algorithm == "pote" or algorithm == "PoTe":
|
|
166
|
+
return groebner_basis_pote(self, prec, **options)
|
|
167
|
+
elif algorithm == "vapote" or algorithm == "VaPoTe":
|
|
168
|
+
return groebner_basis_vapote(self, prec, **options)
|
|
169
|
+
else:
|
|
170
|
+
raise NotImplementedError("available algorithms are 'buchberger', 'buchberger-integral', 'PoTe' and 'VaPoTe'")
|
|
171
|
+
|
|
172
|
+
def _contains_(self, x):
|
|
173
|
+
r"""
|
|
174
|
+
Return ``True`` if ``x`` lies in this ideal.
|
|
175
|
+
|
|
176
|
+
INPUT:
|
|
177
|
+
|
|
178
|
+
- ``x`` -- a Tate series
|
|
179
|
+
|
|
180
|
+
EXAMPLES::
|
|
181
|
+
|
|
182
|
+
sage: R = Zp(3, 10)
|
|
183
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
184
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
185
|
+
sage: g = 5*x^2*y + 3
|
|
186
|
+
sage: I = A.ideal([f,g])
|
|
187
|
+
sage: f in I # indirect doctest
|
|
188
|
+
True
|
|
189
|
+
sage: (f+g) in I # indirect doctest
|
|
190
|
+
True
|
|
191
|
+
sage: (f+1) in I # indirect doctest
|
|
192
|
+
False
|
|
193
|
+
|
|
194
|
+
TESTS::
|
|
195
|
+
|
|
196
|
+
sage: I.random_element() in I
|
|
197
|
+
True
|
|
198
|
+
"""
|
|
199
|
+
rgb = self.groebner_basis()
|
|
200
|
+
return (x % rgb).is_zero()
|
|
201
|
+
|
|
202
|
+
def _contains_ideal(self, I):
|
|
203
|
+
r"""
|
|
204
|
+
Return ``True`` if ``I`` is contained in this ideal.
|
|
205
|
+
|
|
206
|
+
INPUT:
|
|
207
|
+
|
|
208
|
+
- ``I`` -- an ideal in a Tate series algebra
|
|
209
|
+
|
|
210
|
+
EXAMPLES::
|
|
211
|
+
|
|
212
|
+
sage: R = Zp(3,prec=10,print_mode='digits')
|
|
213
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
214
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
215
|
+
sage: g = 5*x^2*y + 3
|
|
216
|
+
sage: I = A.ideal([f,g])
|
|
217
|
+
sage: A.ideal([f]) < I # indirect doctest
|
|
218
|
+
True
|
|
219
|
+
sage: I < A.ideal([f]) # indirect doctest
|
|
220
|
+
False
|
|
221
|
+
sage: A.ideal([1]) < I # indirect doctest
|
|
222
|
+
False
|
|
223
|
+
sage: I < A.ideal([1]) # indirect doctest
|
|
224
|
+
True
|
|
225
|
+
"""
|
|
226
|
+
self.groebner_basis()
|
|
227
|
+
return all(f in self for f in I.gens())
|
|
228
|
+
|
|
229
|
+
def _richcmp_(self, other, op):
|
|
230
|
+
r"""
|
|
231
|
+
Compare this ideal with ``other`` for the rich comparison
|
|
232
|
+
operator ``op``
|
|
233
|
+
|
|
234
|
+
INPUT:
|
|
235
|
+
|
|
236
|
+
- ``other`` -- an ideal in a Tate series algebra
|
|
237
|
+
|
|
238
|
+
- ``op`` -- a comparison operator
|
|
239
|
+
|
|
240
|
+
EXAMPLES::
|
|
241
|
+
|
|
242
|
+
sage: R = Zp(3, 10)
|
|
243
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
244
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
245
|
+
sage: g = 5*x^2*y + 3
|
|
246
|
+
sage: I = A.ideal([f,g])
|
|
247
|
+
sage: A.ideal([f]) < I
|
|
248
|
+
True
|
|
249
|
+
sage: I < A.ideal([f])
|
|
250
|
+
False
|
|
251
|
+
sage: A.ideal([1]) < I
|
|
252
|
+
False
|
|
253
|
+
sage: I < A.ideal([1])
|
|
254
|
+
True
|
|
255
|
+
sage: I <= A.ideal([f,g])
|
|
256
|
+
True
|
|
257
|
+
sage: I == A.ideal([f,g])
|
|
258
|
+
True
|
|
259
|
+
sage: I <= A.ideal([f])
|
|
260
|
+
False
|
|
261
|
+
sage: A.ideal([f]) <= I
|
|
262
|
+
True
|
|
263
|
+
sage: A.ideal([f]) == I
|
|
264
|
+
False
|
|
265
|
+
"""
|
|
266
|
+
if op == op_GT:
|
|
267
|
+
return self._contains_ideal(other) and not other._contains_ideal(self)
|
|
268
|
+
elif op == op_GE:
|
|
269
|
+
return self._contains_ideal(other)
|
|
270
|
+
elif op == op_EQ:
|
|
271
|
+
return self._contains_ideal(other) and other._contains_ideal(self)
|
|
272
|
+
elif op == op_NE:
|
|
273
|
+
return not(self._contains_ideal(other) and other._contains_ideal(self))
|
|
274
|
+
elif op == op_LE:
|
|
275
|
+
return other._contains_ideal(self)
|
|
276
|
+
elif op == op_LT:
|
|
277
|
+
return other._contains_ideal(self) and not self._contains_ideal(other)
|
|
278
|
+
|
|
279
|
+
def is_saturated(self):
|
|
280
|
+
r"""
|
|
281
|
+
Return ``True`` if this ideal is saturated.
|
|
282
|
+
|
|
283
|
+
The ideal `I` is saturated if `\pi f \in I` implies `f \in I`
|
|
284
|
+
for any `f` in the underlying ring. Here `\pi` denotes a
|
|
285
|
+
uniformizer of the field of coefficients.
|
|
286
|
+
|
|
287
|
+
.. NOTE::
|
|
288
|
+
|
|
289
|
+
All ideals are saturated when `\pi` is invertible.
|
|
290
|
+
|
|
291
|
+
EXAMPLES:
|
|
292
|
+
|
|
293
|
+
Over classical Tate algebras (where `\pi` is invertible), this
|
|
294
|
+
method always returns ``True``::
|
|
295
|
+
|
|
296
|
+
sage: R = Zp(3, prec=10, print_mode='digits')
|
|
297
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
298
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
299
|
+
sage: g = 5*x^2*y + 3
|
|
300
|
+
sage: A.ideal([f,g]).is_saturated()
|
|
301
|
+
True
|
|
302
|
+
sage: A.ideal([f,3*g]).is_saturated()
|
|
303
|
+
True
|
|
304
|
+
|
|
305
|
+
The test is only relevant over the rings of integers of Tate
|
|
306
|
+
algebras::
|
|
307
|
+
|
|
308
|
+
sage: Ao = A.integer_ring()
|
|
309
|
+
sage: Io = Ao.ideal([f,g])
|
|
310
|
+
sage: Io.is_saturated()
|
|
311
|
+
False
|
|
312
|
+
sage: Io.groebner_basis()
|
|
313
|
+
[...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
314
|
+
...0000000001*x*y^2 + ...1210121020*x^2 + O(3^10 * <x, y>),
|
|
315
|
+
...0000000010*x^3 + ...2222222220*y + O(3^10 * <x, y>),
|
|
316
|
+
...0000000010*y^2 + ...2101210200*x + O(3^10 * <x, y>)]
|
|
317
|
+
|
|
318
|
+
Principal ideals are not always saturated::
|
|
319
|
+
|
|
320
|
+
sage: Ao.ideal([3*f]).is_saturated()
|
|
321
|
+
False
|
|
322
|
+
"""
|
|
323
|
+
if self.ring().base_ring().is_field():
|
|
324
|
+
return True
|
|
325
|
+
gb = self.groebner_basis()
|
|
326
|
+
for g in gb:
|
|
327
|
+
if g.valuation() > 0:
|
|
328
|
+
return False
|
|
329
|
+
return True
|
|
330
|
+
|
|
331
|
+
def saturate(self):
|
|
332
|
+
r"""
|
|
333
|
+
Return the ideal obtained by saturating this ideal.
|
|
334
|
+
|
|
335
|
+
In other words, the result is the ideal
|
|
336
|
+
|
|
337
|
+
.. MATH::
|
|
338
|
+
|
|
339
|
+
(I:\pi^\infty) = \{f \in A : \exists n \in \mathbb{N}, \pi^n f \in I\}`
|
|
340
|
+
|
|
341
|
+
where `A` is the underlying ring and `\pi` is the uniformizer of the
|
|
342
|
+
field of coefficients.
|
|
343
|
+
|
|
344
|
+
.. NOTE::
|
|
345
|
+
|
|
346
|
+
When `\pi` is invertible in `A`, all ideals are saturated.
|
|
347
|
+
|
|
348
|
+
EXAMPLES:
|
|
349
|
+
|
|
350
|
+
Over classical Tate algebras (where `\pi` is invertible), this
|
|
351
|
+
method always returns the same ideal::
|
|
352
|
+
|
|
353
|
+
sage: R = Zp(3, prec=10, print_mode='digits')
|
|
354
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
355
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
356
|
+
sage: g = 5*x^2*y + 3
|
|
357
|
+
sage: I = A.ideal([f,g]); I
|
|
358
|
+
Ideal (...0000000012*x*y^2 + ...00000000010*x^2, ...0000000012*x^2*y + ...00000000010)
|
|
359
|
+
of Tate Algebra in x (val >= 0), y (val >= 0) over 3-adic Field with capped relative precision 10
|
|
360
|
+
sage: I.saturate()
|
|
361
|
+
Ideal (...0000000012*x*y^2 + ...00000000010*x^2, ...0000000012*x^2*y + ...00000000010)
|
|
362
|
+
of Tate Algebra in x (val >= 0), y (val >= 0) over 3-adic Field with capped relative precision 10
|
|
363
|
+
|
|
364
|
+
sage: I.saturate() == I
|
|
365
|
+
True
|
|
366
|
+
|
|
367
|
+
However, the result might be different over the ring of integers
|
|
368
|
+
of a Tate algebra::
|
|
369
|
+
|
|
370
|
+
sage: Ao = A.integer_ring()
|
|
371
|
+
sage: Io = Ao.ideal([f,g])
|
|
372
|
+
sage: Ios = Io.saturate(); Ios
|
|
373
|
+
Ideal (...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
374
|
+
...0000000001*x*y^2 + ...1210121020*x^2 + O(3^10 * <x, y>),
|
|
375
|
+
...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
376
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>))
|
|
377
|
+
of Integer ring of the Tate Algebra in x (val >= 0), y (val >= 0) over 3-adic Field with capped relative precision 10
|
|
378
|
+
|
|
379
|
+
sage: Io == Ios
|
|
380
|
+
False
|
|
381
|
+
sage: Ios.is_saturated()
|
|
382
|
+
True
|
|
383
|
+
|
|
384
|
+
TESTS::
|
|
385
|
+
|
|
386
|
+
sage: Io < Ios
|
|
387
|
+
True
|
|
388
|
+
sage: 3*Ios < Io
|
|
389
|
+
True
|
|
390
|
+
"""
|
|
391
|
+
if self.ring().base_ring().is_field():
|
|
392
|
+
return self
|
|
393
|
+
gb = self.groebner_basis()
|
|
394
|
+
gens = [ g.monic() for g in gb ]
|
|
395
|
+
return self.ring().ideal(gens)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
# Grobner bases computations
|
|
399
|
+
############################
|
|
400
|
+
|
|
401
|
+
# Buchberger algorithm
|
|
402
|
+
|
|
403
|
+
def groebner_basis_buchberger(I, prec, py_integral):
|
|
404
|
+
r"""
|
|
405
|
+
Compute a Groebner basis of the Tate algebra ideal I using Buchberger's algorithm.
|
|
406
|
+
|
|
407
|
+
INPUT:
|
|
408
|
+
|
|
409
|
+
- ``I`` -- an ideal in a Tate series algebra
|
|
410
|
+
|
|
411
|
+
- ``prec`` -- the related precision at which the initial generators
|
|
412
|
+
are truncated
|
|
413
|
+
|
|
414
|
+
- ``integral`` -- boolean; if ``True``, first compute a
|
|
415
|
+
Grobner basis of the ideal generated by the same generators over
|
|
416
|
+
the ring over the ring of integers
|
|
417
|
+
|
|
418
|
+
.. NOTE::
|
|
419
|
+
|
|
420
|
+
This function is not meant to be called directly, but through the
|
|
421
|
+
``groebner_basis`` method of Tate algebra ideals.
|
|
422
|
+
|
|
423
|
+
EXAMPLES::
|
|
424
|
+
|
|
425
|
+
sage: R = Zp(3, prec=10, print_mode='digits');
|
|
426
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
427
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
428
|
+
sage: g = 5*x^2*y + 3
|
|
429
|
+
sage: I = A.ideal([f,g]); I
|
|
430
|
+
Ideal (...0000000012*x*y^2 + ...00000000010*x^2, ...0000000012*x^2*y + ...00000000010) of Tate Algebra in x (val >= 0), y (val >= 0) over 3-adic Field with capped relative precision 10
|
|
431
|
+
sage: I.groebner_basis() # indirect doctest
|
|
432
|
+
[...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
433
|
+
...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
434
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>)]
|
|
435
|
+
"""
|
|
436
|
+
cdef list gb, rgb, indices, ts, S = [ ]
|
|
437
|
+
cdef int i, j, l
|
|
438
|
+
cdef TateAlgebraTerm ti, tj, t
|
|
439
|
+
cdef TateAlgebraElement f, g, r, s
|
|
440
|
+
cdef bint do_reduce = True
|
|
441
|
+
cdef bint integral = py_integral
|
|
442
|
+
|
|
443
|
+
gb = [ ]
|
|
444
|
+
l = 0
|
|
445
|
+
for f in I.gens():
|
|
446
|
+
if not f:
|
|
447
|
+
continue
|
|
448
|
+
g = f.add_bigoh(f.valuation() + prec)
|
|
449
|
+
if not g:
|
|
450
|
+
continue
|
|
451
|
+
gb.append(g)
|
|
452
|
+
l += 1
|
|
453
|
+
indices = list(range(l))
|
|
454
|
+
|
|
455
|
+
# We minimize the family of generators
|
|
456
|
+
rgb = gb[:]
|
|
457
|
+
i = 0
|
|
458
|
+
while i < len(rgb):
|
|
459
|
+
ti = (<TateAlgebraElement>rgb[i])._terms_c()[0]
|
|
460
|
+
for j in range(len(rgb)):
|
|
461
|
+
tj = (<TateAlgebraElement>rgb[j])._terms_c()[0]
|
|
462
|
+
if j != i and tj._divides_c(ti, integral):
|
|
463
|
+
del rgb[i]
|
|
464
|
+
del indices[i]
|
|
465
|
+
break
|
|
466
|
+
else:
|
|
467
|
+
i += 1
|
|
468
|
+
|
|
469
|
+
# We compute the initial S-polynomials
|
|
470
|
+
for i in range(l):
|
|
471
|
+
ti = (<TateAlgebraElement>gb[i])._terms_c()[0]
|
|
472
|
+
for j in range(i+1, l):
|
|
473
|
+
tj = (<TateAlgebraElement>gb[j])._terms_c()[0]
|
|
474
|
+
if not ti.is_coprime_with(tj):
|
|
475
|
+
s = (<TateAlgebraElement>gb[i])._Spoly_c(<TateAlgebraElement>gb[j])
|
|
476
|
+
if not s.is_zero():
|
|
477
|
+
t = s._terms_c()[0]
|
|
478
|
+
heappush(S, (t._valuation_c(), t._exponent, i, j, s))
|
|
479
|
+
|
|
480
|
+
# Main loop of Buchberger algorithm
|
|
481
|
+
# Loop invariant:
|
|
482
|
+
# the S-polynomials of pairs of elements in rgb
|
|
483
|
+
# all reduce to zero modulo (rgb,S)
|
|
484
|
+
while S:
|
|
485
|
+
sig_check()
|
|
486
|
+
# We reduce the Grobner basis if needed
|
|
487
|
+
if do_reduce:
|
|
488
|
+
do_reduce = False
|
|
489
|
+
for i in range(len(rgb)-1, -1, -1):
|
|
490
|
+
g = rgb[i]
|
|
491
|
+
rgb[i] = g._positive_lshift_c(1)
|
|
492
|
+
_, rgb[i] = g._quo_rem_c(rgb, False, True, True)
|
|
493
|
+
gb[indices[i]] = rgb[i]
|
|
494
|
+
|
|
495
|
+
# We pop a new S-polynomial
|
|
496
|
+
_, _, i, j, f = heappop(S)
|
|
497
|
+
if i >= 0 and (gb[i] is None or gb[j] is None):
|
|
498
|
+
continue
|
|
499
|
+
_, r = f._quo_rem_c(rgb, False, True, integral)
|
|
500
|
+
if r.is_zero():
|
|
501
|
+
continue
|
|
502
|
+
|
|
503
|
+
# We add it to our Grobner basis
|
|
504
|
+
tj = r._terms_c()[0]
|
|
505
|
+
j = len(gb)
|
|
506
|
+
for i in range(j):
|
|
507
|
+
g = gb[i]
|
|
508
|
+
if g is None: continue
|
|
509
|
+
ti = g._terms_c()[0]
|
|
510
|
+
if not ti.is_coprime_with(tj): # first Buchberger criterium
|
|
511
|
+
s = g._Spoly_c(r)
|
|
512
|
+
if not s.is_zero():
|
|
513
|
+
t = s._terms_c()[0]
|
|
514
|
+
heappush(S, (t._valuation_c(), t._exponent, i, j, s))
|
|
515
|
+
gb.append(r)
|
|
516
|
+
|
|
517
|
+
# We minimize the Grobner basis
|
|
518
|
+
i = 0
|
|
519
|
+
while i < len(rgb):
|
|
520
|
+
ti = (<TateAlgebraElement>rgb[i])._terms_c()[0]
|
|
521
|
+
if tj._divides_c(ti, integral):
|
|
522
|
+
if indices[i] >= l:
|
|
523
|
+
heappush(S, (ti._valuation_c(), ti._exponent, -1, -1, rgb[i]))
|
|
524
|
+
gb[indices[i]] = None
|
|
525
|
+
del rgb[i]
|
|
526
|
+
del indices[i]
|
|
527
|
+
else:
|
|
528
|
+
i += 1
|
|
529
|
+
rgb.append(r)
|
|
530
|
+
indices.append(j)
|
|
531
|
+
# and reduce it
|
|
532
|
+
do_reduce = True
|
|
533
|
+
|
|
534
|
+
base = I.ring().base_ring()
|
|
535
|
+
if base.is_field():
|
|
536
|
+
if integral:
|
|
537
|
+
# We need to minimize and reduce the Groebner basis again
|
|
538
|
+
i = 0
|
|
539
|
+
while i < len(rgb):
|
|
540
|
+
ti = (<TateAlgebraElement>rgb[i])._terms_c()[0]
|
|
541
|
+
for j in range(len(rgb)):
|
|
542
|
+
tj = (<TateAlgebraElement>rgb[j])._terms_c()[0]
|
|
543
|
+
if j != i and tj._divides_c(ti, False):
|
|
544
|
+
del rgb[i]
|
|
545
|
+
break
|
|
546
|
+
else:
|
|
547
|
+
rgb[i] = rgb[i].monic()
|
|
548
|
+
i += 1
|
|
549
|
+
for i in range(len(rgb)):
|
|
550
|
+
g = rgb[i]
|
|
551
|
+
rgb[i] = g._positive_lshift_c(1)
|
|
552
|
+
_, rgb[i] = g._quo_rem_c(rgb, False, True, True)
|
|
553
|
+
else:
|
|
554
|
+
rgb = [ g.monic() for g in rgb ]
|
|
555
|
+
else:
|
|
556
|
+
rgb = [ g * base(g.leading_coefficient().unit_part()).inverse_of_unit() for g in rgb ]
|
|
557
|
+
|
|
558
|
+
rgb.sort(reverse=True)
|
|
559
|
+
return rgb
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
# F5 algorithms
|
|
563
|
+
|
|
564
|
+
cdef Jpair(p1, p2):
|
|
565
|
+
r"""
|
|
566
|
+
Return the J-pair of ``p1`` and ``p2``.
|
|
567
|
+
|
|
568
|
+
INPUT:
|
|
569
|
+
|
|
570
|
+
- ``p1`` -- a pair (signature, series)
|
|
571
|
+
|
|
572
|
+
- ``p2`` -- a pair (signature, series)
|
|
573
|
+
"""
|
|
574
|
+
cdef TateAlgebraTerm s1, s2
|
|
575
|
+
cdef TateAlgebraElement v1, v2
|
|
576
|
+
cdef TateAlgebraTerm t, t1, t2, su1, su2, sv1, sv2
|
|
577
|
+
s1, v1 = p1 # we assume that s1 is not None
|
|
578
|
+
s2, v2 = p2
|
|
579
|
+
if v1 == 0 or v2 == 0:
|
|
580
|
+
return
|
|
581
|
+
sv1 = v1.leading_term()
|
|
582
|
+
sv2 = v2.leading_term()
|
|
583
|
+
# TODO: Maybe can be made more efficient when we know the elements are "monic"
|
|
584
|
+
t = sv1.lcm(sv2)
|
|
585
|
+
t1 = t // sv1
|
|
586
|
+
t2 = t // sv2
|
|
587
|
+
su1 = t1*s1
|
|
588
|
+
if s2 is None:
|
|
589
|
+
return su1, t1*v1
|
|
590
|
+
su2 = t2*s2
|
|
591
|
+
if su1 > su2:
|
|
592
|
+
return su1, t1*v1
|
|
593
|
+
elif su2 > su1:
|
|
594
|
+
return su2, t2*v2
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
cdef TateAlgebraElement regular_reduce(sgb, TateAlgebraTerm s, TateAlgebraElement v, stopval):
|
|
598
|
+
r"""
|
|
599
|
+
Return the result of the regular reduction of the pair ``(s,v)`` by ``sgb``.
|
|
600
|
+
|
|
601
|
+
INPUT:
|
|
602
|
+
|
|
603
|
+
- ``sgb`` -- list of pairs (signature, series), candidate to be a strong
|
|
604
|
+
Groebner basis; all leading coefficients are assumed to be a power of the
|
|
605
|
+
uniformizer
|
|
606
|
+
|
|
607
|
+
- ``s`` -- a term (the signature)
|
|
608
|
+
|
|
609
|
+
- ``v`` -- a series
|
|
610
|
+
|
|
611
|
+
- ``stopval`` -- the valuation until which reductions are performed
|
|
612
|
+
|
|
613
|
+
TESTS::
|
|
614
|
+
|
|
615
|
+
sage: cython( # needs sage.misc.cython
|
|
616
|
+
....: '''
|
|
617
|
+
....: from sage.rings.tate_algebra_ideal cimport regular_reduce
|
|
618
|
+
....: def python_regular_reduce(gb, s, v, stopval):
|
|
619
|
+
....: return regular_reduce(gb, s, v, stopval)
|
|
620
|
+
....: ''')
|
|
621
|
+
|
|
622
|
+
sage: R = Zp(3, prec=8)
|
|
623
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
624
|
+
sage: tx = x.leading_term() # the term x
|
|
625
|
+
sage: ty = y.leading_term() # the term y
|
|
626
|
+
sage: v = (x + y + 2*x^2*y - x^3).add_bigoh(8)
|
|
627
|
+
sage: p1 = (tx, x^3 + 9*x*y)
|
|
628
|
+
sage: p2 = (ty, x*y + 3*x^2*y)
|
|
629
|
+
|
|
630
|
+
sage: python_regular_reduce([p1,p2], tx*ty, v, 8) # indirect doctest # needs sage.misc.cython
|
|
631
|
+
(2 + O(3^8))*x^2*y + (1 + O(3^8))*x + (1 + O(3^8))*y + O(3^8 * <x, y>)
|
|
632
|
+
|
|
633
|
+
sage: python_regular_reduce([p1,p2], tx, v, 8) # indirect doctest # needs sage.misc.cython
|
|
634
|
+
(2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + O(3^8))*x^3
|
|
635
|
+
+ (2 + O(3^8))*x^2*y + (1 + O(3^8))*x + (1 + O(3^8))*y + O(3^8 * <x, y>)
|
|
636
|
+
"""
|
|
637
|
+
# We assume that the elements of the sgb are such that lt(g) = p^v lm(g) to
|
|
638
|
+
# avoid performing divisions
|
|
639
|
+
cdef dict coeffs = { }
|
|
640
|
+
cdef TateAlgebraElement f
|
|
641
|
+
cdef TateAlgebraTerm lt, factor
|
|
642
|
+
cdef list ltds = [ (<TateAlgebraElement>(d[1]))._terms_c()[0] for d in sgb ]
|
|
643
|
+
cdef list terms = v._terms_c()
|
|
644
|
+
cdef int index = 0
|
|
645
|
+
cdef int i
|
|
646
|
+
cdef bint in_rem
|
|
647
|
+
|
|
648
|
+
f = v._new_c()
|
|
649
|
+
f._poly = PolyDict(v._poly.__repn, None)
|
|
650
|
+
f._prec = v._prec
|
|
651
|
+
factor = (<TateAlgebraTerm>terms[0])._new_c()
|
|
652
|
+
while len(terms) > index:
|
|
653
|
+
sig_check()
|
|
654
|
+
lt = terms[index]
|
|
655
|
+
if (not lt) or (lt._valuation_c() >= stopval):
|
|
656
|
+
break
|
|
657
|
+
for i in range(len(sgb)):
|
|
658
|
+
sig_check()
|
|
659
|
+
# The comparison below does not perform a division, it only compares valuation and exponents
|
|
660
|
+
if (<TateAlgebraTerm>ltds[i])._divides_c(lt, integral=True):
|
|
661
|
+
# Here we need the elements of sgb to be "monic"
|
|
662
|
+
factor._exponent = lt._exponent.esub((<TateAlgebraTerm>ltds[i])._exponent)
|
|
663
|
+
factor._coeff = lt._coeff >> (<TateAlgebraTerm>ltds[i])._valuation_c()
|
|
664
|
+
if sgb[i][0] is None or factor * sgb[i][0] < s:
|
|
665
|
+
f = f - (<TateAlgebraElement>sgb[i][1])._term_mul_c(factor)
|
|
666
|
+
terms = f._terms_c()
|
|
667
|
+
index = 0
|
|
668
|
+
break
|
|
669
|
+
else:
|
|
670
|
+
if lt._exponent in coeffs:
|
|
671
|
+
coeffs[lt._exponent] += lt._coeff
|
|
672
|
+
else:
|
|
673
|
+
coeffs[lt._exponent] = lt._coeff
|
|
674
|
+
del f._poly.__repn[lt._exponent]
|
|
675
|
+
index += 1
|
|
676
|
+
f._poly += PolyDict(coeffs, None)
|
|
677
|
+
f._terms = None
|
|
678
|
+
return f
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
cdef TateAlgebraElement reduce(gb, TateAlgebraElement v, stopval):
|
|
682
|
+
r"""
|
|
683
|
+
Return the result of the reduction of ``v`` by ``gb``.
|
|
684
|
+
|
|
685
|
+
INPUT:
|
|
686
|
+
|
|
687
|
+
- ``gb`` -- list of reductors
|
|
688
|
+
|
|
689
|
+
- ``v`` -- a series
|
|
690
|
+
|
|
691
|
+
- ``stopval`` -- the valuation until which reductions are performed
|
|
692
|
+
|
|
693
|
+
TESTS::
|
|
694
|
+
|
|
695
|
+
sage: cython(''' # optional - sage.misc.cython
|
|
696
|
+
....: from sage.rings.tate_algebra_ideal cimport reduce
|
|
697
|
+
....: def python_reduce(gb, v, stopval):
|
|
698
|
+
....: return reduce(gb, v, stopval)
|
|
699
|
+
....: ''')
|
|
700
|
+
|
|
701
|
+
sage: R = Zp(3, prec=8)
|
|
702
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
703
|
+
sage: v = (x + y + 2*x^2*y - x^3*y^2).add_bigoh(8)
|
|
704
|
+
sage: g1 = x*y + 3*x^2*y
|
|
705
|
+
sage: g2 = x^3 + 9*y
|
|
706
|
+
sage: python_reduce([g1,g2], v, 8) # indirect doctest # needs sage.misc.cython
|
|
707
|
+
(1 + O(3^8))*x + (1 + O(3^8))*y + O(3^8 * <x, y>)
|
|
708
|
+
|
|
709
|
+
sage: python_reduce([g1,g2], v, 5) # indirect doctest # needs sage.misc.cython
|
|
710
|
+
(1 + O(3^8))*x + (1 + O(3^8))*y + (3^5 + O(3^8))*x^8*y^2
|
|
711
|
+
+ (3^5 + 2*3^6 + 2*3^7 + O(3^8))*x^7*y + O(3^8 * <x, y>)
|
|
712
|
+
"""
|
|
713
|
+
cdef dict coeffs = { }
|
|
714
|
+
cdef TateAlgebraElement f
|
|
715
|
+
cdef TateAlgebraTerm lt, factor
|
|
716
|
+
cdef list ltds = [ (<TateAlgebraElement>d)._terms_c()[0] for d in gb ]
|
|
717
|
+
cdef list terms = v._terms_c()
|
|
718
|
+
cdef int index = 0
|
|
719
|
+
cdef int i
|
|
720
|
+
|
|
721
|
+
f = v._new_c()
|
|
722
|
+
f._poly = PolyDict(v._poly.__repn, None)
|
|
723
|
+
f._prec = v._prec
|
|
724
|
+
while len(terms) > index:
|
|
725
|
+
lt = terms[index]
|
|
726
|
+
if (not lt) or (lt._valuation_c() >= stopval):
|
|
727
|
+
break
|
|
728
|
+
for i in range(len(gb)):
|
|
729
|
+
if (<TateAlgebraTerm>ltds[i])._divides_c(lt, integral=True):
|
|
730
|
+
factor = lt._floordiv_c(<TateAlgebraTerm>ltds[i])
|
|
731
|
+
f = f - (<TateAlgebraElement>gb[i])._term_mul_c(factor)
|
|
732
|
+
terms = f._terms_c()
|
|
733
|
+
index = 0
|
|
734
|
+
break
|
|
735
|
+
else:
|
|
736
|
+
if lt._exponent in coeffs:
|
|
737
|
+
coeffs[lt._exponent] += lt._coeff
|
|
738
|
+
else:
|
|
739
|
+
coeffs[lt._exponent] = lt._coeff
|
|
740
|
+
del f._poly.__repn[lt._exponent]
|
|
741
|
+
index += 1
|
|
742
|
+
f._poly += PolyDict(coeffs, None)
|
|
743
|
+
f._terms = None
|
|
744
|
+
return f
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
def print_pair(p, verbose):
|
|
748
|
+
r"""
|
|
749
|
+
Return a string representation of the pair ``p``.
|
|
750
|
+
|
|
751
|
+
INPUT:
|
|
752
|
+
|
|
753
|
+
- ``p`` -- a pair (signature, series)
|
|
754
|
+
|
|
755
|
+
- ``verbose`` -- integer
|
|
756
|
+
|
|
757
|
+
TESTS::
|
|
758
|
+
|
|
759
|
+
sage: from sage.rings.tate_algebra_ideal import print_pair
|
|
760
|
+
sage: R = Zp(3, prec=10, print_mode='digits')
|
|
761
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
762
|
+
sage: v = 3*x^2 + 5*x*y^2
|
|
763
|
+
sage: s = v.leading_term()
|
|
764
|
+
sage: p = (s,v)
|
|
765
|
+
|
|
766
|
+
When ``verbose`` is less than 4, only the leading term of
|
|
767
|
+
the series is printed::
|
|
768
|
+
|
|
769
|
+
sage: print_pair(p, 0)
|
|
770
|
+
'(sign = ...0000000012*x*y^2, series = ...0000000012*x*y^2 + ...)'
|
|
771
|
+
|
|
772
|
+
When ``verbose`` is at least 4, the entire series is printed::
|
|
773
|
+
|
|
774
|
+
sage: print_pair(p, 4)
|
|
775
|
+
'(sign = ...0000000012*x*y^2, series = ...0000000012*x*y^2 + ...00000000010*x^2)'
|
|
776
|
+
"""
|
|
777
|
+
if verbose > 3:
|
|
778
|
+
return "(sign = %s, series = %s)" % p
|
|
779
|
+
else:
|
|
780
|
+
s, v = p
|
|
781
|
+
return "(sign = %s, series = %s + ...)" % (s, v.leading_term())
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
def groebner_basis_pote(I, prec, verbose=0):
|
|
785
|
+
r"""
|
|
786
|
+
Run the PoTe algorithm to compute the Groebner basis of ``I``
|
|
787
|
+
and return it
|
|
788
|
+
|
|
789
|
+
INPUT:
|
|
790
|
+
|
|
791
|
+
- ``I`` -- an ideal
|
|
792
|
+
|
|
793
|
+
- ``prec`` -- the precision at which the Groebner basis is computed
|
|
794
|
+
|
|
795
|
+
- ``verbose`` -- integer (default: 0)
|
|
796
|
+
|
|
797
|
+
TESTS::
|
|
798
|
+
|
|
799
|
+
sage: R = Zp(3, prec=10, print_mode='digits')
|
|
800
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
801
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
802
|
+
sage: g = 5*x^2*y + 3
|
|
803
|
+
sage: I = A.ideal([f,g])
|
|
804
|
+
sage: I.groebner_basis(algorithm='PoTe') # indirect doctest
|
|
805
|
+
[...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
806
|
+
...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
807
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>)]
|
|
808
|
+
|
|
809
|
+
sage: I.groebner_basis(algorithm='PoTe', verbose=2) # indirect doctest
|
|
810
|
+
---
|
|
811
|
+
new generator: ...0000000001*x*y^2 + ...
|
|
812
|
+
0 initial J-pairs
|
|
813
|
+
1 elements in GB before minimization
|
|
814
|
+
1 elements in GB after minimization
|
|
815
|
+
grobner basis reduced
|
|
816
|
+
---
|
|
817
|
+
new generator: ...0000000001*x^2*y + ...
|
|
818
|
+
1 initial J-pairs
|
|
819
|
+
current J-pair: (sign = ...0000000001*y, series = ...0000000001*x^2*y^2 + ...)
|
|
820
|
+
0 remaining J-pairs
|
|
821
|
+
| new element in SGB: (sign = ...0000000001*y, series = ...0000000010*x^3 + ...)
|
|
822
|
+
| add 2 J-pairs
|
|
823
|
+
current J-pair: (sign = ...000000001*y^2, series = ...0000000010*x^3*y + ...)
|
|
824
|
+
1 remaining J-pairs
|
|
825
|
+
| new element in SGB: (sign = ...000000001*y^2, series = ...0000000010*y^2 + ...)
|
|
826
|
+
| add 3 J-pairs
|
|
827
|
+
current J-pair: (sign = ...000000001*y^3, series = ...0000000010*x^3*y^2 + ...)
|
|
828
|
+
3 remaining J-pairs
|
|
829
|
+
| skip: cover by (sign = ...000000001*y^2, series = ...0000000010*y^2 + ...)
|
|
830
|
+
current J-pair: (sign = ...000000001*x*y^2, series = ...0000000010*x*y^2 + ...)
|
|
831
|
+
2 remaining J-pairs
|
|
832
|
+
| skip: sygyzy criterium; signature = ...0000000001*x*y^2
|
|
833
|
+
current J-pair: (sign = ...000000001*x^2*y^2, series = ...0000000010*x^2*y^2 + ...)
|
|
834
|
+
1 remaining J-pairs
|
|
835
|
+
| skip: sygyzy criterium; signature = ...0000000001*x*y^2
|
|
836
|
+
current J-pair: (sign = ...000000001*x^3*y^2, series = ...0000000010*x^3*y^2 + ...)
|
|
837
|
+
0 remaining J-pairs
|
|
838
|
+
| skip: sygyzy criterium; signature = ...0000000001*x*y^2
|
|
839
|
+
4 elements in GB before minimization
|
|
840
|
+
3 elements in GB after minimization
|
|
841
|
+
grobner basis reduced
|
|
842
|
+
[...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
843
|
+
...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
844
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>)]
|
|
845
|
+
|
|
846
|
+
We check that :issue:`30101` is fixed::
|
|
847
|
+
|
|
848
|
+
sage: I.groebner_basis(algorithm='PoTe', prec=100) # indirect doctest
|
|
849
|
+
[...0000000001*x^3 + ...2222222222*y + ...000000000*x^2*y^2 + O(3^99 * <x, y>),
|
|
850
|
+
...0000000001*x^2*y + ...01210121020 + O(3^100 * <x, y>),
|
|
851
|
+
...0000000001*y^2 + ...01210121020*x + ...0000000000*x^3*y + O(3^99 * <x, y>)]
|
|
852
|
+
"""
|
|
853
|
+
cdef TateAlgebraElement g, v
|
|
854
|
+
cdef TateAlgebraTerm s, sv, S, ti, tj
|
|
855
|
+
cdef list terms
|
|
856
|
+
cdef TateAlgebraTerm term_one = I.ring().monoid_of_terms().one()
|
|
857
|
+
cdef bint integral = not I.ring().base_ring().is_field()
|
|
858
|
+
|
|
859
|
+
gb = [ ]
|
|
860
|
+
|
|
861
|
+
for f in sorted(I.gens()):
|
|
862
|
+
sig_check()
|
|
863
|
+
if not f: # Maybe reduce first?
|
|
864
|
+
continue
|
|
865
|
+
|
|
866
|
+
# TODO: this should probably be a single function call
|
|
867
|
+
f = f.monic() << f.valuation()
|
|
868
|
+
|
|
869
|
+
if verbose > 0:
|
|
870
|
+
print("---")
|
|
871
|
+
print("new generator: %s + ..." % f.leading_term())
|
|
872
|
+
# Initial strong Grobner basis:
|
|
873
|
+
# we add signatures
|
|
874
|
+
sgb = [ (None, g) for g in gb if g ]
|
|
875
|
+
# We compute initial J-pairs
|
|
876
|
+
l = len(sgb)
|
|
877
|
+
p = (term_one, f.add_bigoh(prec))
|
|
878
|
+
Jpairs = [ ]
|
|
879
|
+
for P in sgb:
|
|
880
|
+
sig_check()
|
|
881
|
+
J = Jpair(p, P)
|
|
882
|
+
if J is not None:
|
|
883
|
+
heappush(Jpairs, J)
|
|
884
|
+
sgb.append(p)
|
|
885
|
+
|
|
886
|
+
# For the syzygy criterium
|
|
887
|
+
gb0 = [ g.leading_term() for g in gb ]
|
|
888
|
+
|
|
889
|
+
if verbose > 1:
|
|
890
|
+
print("%s initial J-pairs" % len(Jpairs))
|
|
891
|
+
if verbose > 2:
|
|
892
|
+
for s,v in Jpairs:
|
|
893
|
+
print("| " + print_pair((s,v),verbose))
|
|
894
|
+
|
|
895
|
+
while Jpairs:
|
|
896
|
+
sig_check()
|
|
897
|
+
s, v = heappop(Jpairs)
|
|
898
|
+
sv = v.leading_term()
|
|
899
|
+
|
|
900
|
+
if verbose == 1:
|
|
901
|
+
print("pop one J-pair; %s remaining J-pairs" % len(Jpairs))
|
|
902
|
+
if verbose > 1:
|
|
903
|
+
print("current J-pair: " + print_pair((s,v), verbose))
|
|
904
|
+
print("%s remaining J-pairs" % len(Jpairs))
|
|
905
|
+
|
|
906
|
+
# The syzygy criterium
|
|
907
|
+
syzygy = None
|
|
908
|
+
for S in gb0:
|
|
909
|
+
sig_check()
|
|
910
|
+
if S.divides(s):
|
|
911
|
+
syzygy = S
|
|
912
|
+
break
|
|
913
|
+
if syzygy is not None:
|
|
914
|
+
if verbose > 1:
|
|
915
|
+
print("| skip: sygyzy criterium; signature = %s" % syzygy)
|
|
916
|
+
continue
|
|
917
|
+
|
|
918
|
+
# We check if (s,v) is covered by
|
|
919
|
+
# the current strong Grobner basis
|
|
920
|
+
cover = None
|
|
921
|
+
for S, V in sgb:
|
|
922
|
+
sig_check()
|
|
923
|
+
if S is not None and S.divides(s):
|
|
924
|
+
sV = V.leading_term()
|
|
925
|
+
if (s // S)*sV < sv:
|
|
926
|
+
cover = (S,V)
|
|
927
|
+
break
|
|
928
|
+
if cover is not None:
|
|
929
|
+
if verbose > 1:
|
|
930
|
+
print("| skip: cover by " + print_pair(cover, verbose))
|
|
931
|
+
continue
|
|
932
|
+
|
|
933
|
+
# We perform regular top-reduction
|
|
934
|
+
sgb.append((None, v._positive_lshift_c(1)))
|
|
935
|
+
v = regular_reduce(sgb, s, v, prec)
|
|
936
|
+
terms = v._terms_c()
|
|
937
|
+
if terms:
|
|
938
|
+
sv = terms[0]
|
|
939
|
+
if not sv:
|
|
940
|
+
v = v.add_bigoh(sv._coeff.precision_absolute())
|
|
941
|
+
del sgb[-1]
|
|
942
|
+
|
|
943
|
+
if not v or v.valuation() >= prec:
|
|
944
|
+
# We have a new element in (I0:f) whose signature
|
|
945
|
+
# could be useful to strengthen the syzygy criterium
|
|
946
|
+
gb0.append(s)
|
|
947
|
+
else:
|
|
948
|
+
# We update the current strong Grobner basis
|
|
949
|
+
# and the J-pairs accordingly
|
|
950
|
+
vv = v.monic() << v.valuation()
|
|
951
|
+
p = (s,vv)
|
|
952
|
+
if verbose > 1:
|
|
953
|
+
print("| new element in SGB: " + print_pair(p, verbose))
|
|
954
|
+
count = 0
|
|
955
|
+
for P in sgb:
|
|
956
|
+
sig_check()
|
|
957
|
+
J = Jpair(p, P)
|
|
958
|
+
if J is not None:
|
|
959
|
+
count += 1
|
|
960
|
+
if verbose > 2:
|
|
961
|
+
print("| add J-pair: " + print_pair(J, verbose))
|
|
962
|
+
heappush(Jpairs, J)
|
|
963
|
+
if verbose > 1:
|
|
964
|
+
print("| add %s J-pairs" % count)
|
|
965
|
+
sgb.append(p)
|
|
966
|
+
|
|
967
|
+
# We forget signatures
|
|
968
|
+
gb = [g for (s,g) in sgb]
|
|
969
|
+
if verbose > 1:
|
|
970
|
+
print("%s elements in GB before minimization" % len(gb))
|
|
971
|
+
if verbose > 3:
|
|
972
|
+
for g in gb:
|
|
973
|
+
print("| %s" % g)
|
|
974
|
+
|
|
975
|
+
# We minimize the Grobner basis
|
|
976
|
+
i = 0
|
|
977
|
+
while i < len(gb):
|
|
978
|
+
ti = (<TateAlgebraElement>gb[i])._terms_c()[0]
|
|
979
|
+
for j in range(len(gb)):
|
|
980
|
+
sig_check()
|
|
981
|
+
tj = (<TateAlgebraElement>gb[j])._terms_c()[0]
|
|
982
|
+
if j != i and tj._divides_c(ti, integral):
|
|
983
|
+
del gb[i]
|
|
984
|
+
break
|
|
985
|
+
else:
|
|
986
|
+
i += 1
|
|
987
|
+
if verbose > 0:
|
|
988
|
+
if verbose > 1:
|
|
989
|
+
aft = " after minimization"
|
|
990
|
+
else:
|
|
991
|
+
aft = ""
|
|
992
|
+
print("%s elements in GB%s" % (len(gb), aft))
|
|
993
|
+
if verbose > 3:
|
|
994
|
+
for g in gb:
|
|
995
|
+
print("| %s" % g)
|
|
996
|
+
# and reduce it
|
|
997
|
+
for i in range(len(gb)-1, -1, -1):
|
|
998
|
+
sig_check()
|
|
999
|
+
g = gb[i]
|
|
1000
|
+
gb[i] = g._positive_lshift_c(1)
|
|
1001
|
+
_, gb[i] = g._quo_rem_c(gb, False, True, True)
|
|
1002
|
+
if verbose > 1:
|
|
1003
|
+
print("grobner basis reduced")
|
|
1004
|
+
if verbose > 3:
|
|
1005
|
+
for g in gb:
|
|
1006
|
+
print("| %s" % g)
|
|
1007
|
+
|
|
1008
|
+
if not integral:
|
|
1009
|
+
gb = [ f.monic() for f in gb ]
|
|
1010
|
+
gb.sort(reverse=True)
|
|
1011
|
+
return gb
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
def groebner_basis_vapote(I, prec, verbose=0, interrupt_red_with_val=False, interrupt_interred_with_val=False):
|
|
1015
|
+
r"""
|
|
1016
|
+
Run the VaPoTe algorithm to compute the Groebner basis of ``I``
|
|
1017
|
+
and return it
|
|
1018
|
+
|
|
1019
|
+
INPUT:
|
|
1020
|
+
|
|
1021
|
+
- ``I`` -- an ideal
|
|
1022
|
+
|
|
1023
|
+
- ``prec`` -- the precision at which the Groebner basis is computed
|
|
1024
|
+
|
|
1025
|
+
- ``verbose`` -- integer (default: 0)
|
|
1026
|
+
|
|
1027
|
+
- ``interrupt_red_with_val`` -- boolean (default: ``False``); if
|
|
1028
|
+
regular reductions have to be interrupted as soon as the valuation
|
|
1029
|
+
raises
|
|
1030
|
+
|
|
1031
|
+
- ``interrupt_interred_with_val`` -- boolean (default: ``False'');
|
|
1032
|
+
if intermediate interreductions of the Groebner basis have to be
|
|
1033
|
+
interrupted as soon as the valuation raises
|
|
1034
|
+
|
|
1035
|
+
TESTS::
|
|
1036
|
+
|
|
1037
|
+
sage: R = Zp(3, prec=10, print_mode='digits')
|
|
1038
|
+
sage: A.<x,y> = TateAlgebra(R)
|
|
1039
|
+
sage: f = 3*x^2 + 5*x*y^2
|
|
1040
|
+
sage: g = 5*x^2*y + 3
|
|
1041
|
+
sage: I = A.ideal([f,g])
|
|
1042
|
+
sage: I.groebner_basis(algorithm='VaPoTe') # indirect doctest
|
|
1043
|
+
[...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
1044
|
+
...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
1045
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>)]
|
|
1046
|
+
|
|
1047
|
+
sage: I.groebner_basis(algorithm='VaPoTe', interrupt_red_with_val=True) # indirect doctest
|
|
1048
|
+
[...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
1049
|
+
...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
1050
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>)]
|
|
1051
|
+
|
|
1052
|
+
sage: I.groebner_basis(algorithm='VaPoTe', verbose=2) # indirect doctest
|
|
1053
|
+
grobner basis reduced
|
|
1054
|
+
---
|
|
1055
|
+
new generator: ...0000000012*x*y^2 + ...
|
|
1056
|
+
generator reduced
|
|
1057
|
+
0 initial J-pairs
|
|
1058
|
+
1 elements in GB before minimization
|
|
1059
|
+
1 elements in GB after minimization
|
|
1060
|
+
grobner basis reduced
|
|
1061
|
+
---
|
|
1062
|
+
new generator: ...0000000012*x^2*y + ...
|
|
1063
|
+
generator reduced
|
|
1064
|
+
1 initial J-pairs
|
|
1065
|
+
pop one J-pair; 0 remaining J-pairs
|
|
1066
|
+
| add signature for syzygy criterium: ...0000000001*y
|
|
1067
|
+
2 elements in GB before minimization
|
|
1068
|
+
2 elements in GB after minimization
|
|
1069
|
+
grobner basis reduced
|
|
1070
|
+
---
|
|
1071
|
+
new generator: ...0000000010*x^3 + ...
|
|
1072
|
+
generator reduced
|
|
1073
|
+
2 initial J-pairs
|
|
1074
|
+
pop one J-pair; 1 remaining J-pairs
|
|
1075
|
+
| new element is SGB: (sign = ...000000001*y, series = ...0000000010*y^2 + ...)
|
|
1076
|
+
| add 3 J-pairs
|
|
1077
|
+
pop one J-pair; 3 remaining J-pairs
|
|
1078
|
+
| skip: cover by (sign = ...000000001*y, series = ...0000000010*y^2 + ...)
|
|
1079
|
+
pop one J-pair; 2 remaining J-pairs
|
|
1080
|
+
| add signature for syzygy criterium: ...000000001*x*y
|
|
1081
|
+
pop one J-pair; 1 remaining J-pairs
|
|
1082
|
+
| skip: sygyzy criterium; signature = ...0000000001*x^2*y
|
|
1083
|
+
pop one J-pair; 0 remaining J-pairs
|
|
1084
|
+
| skip: sygyzy criterium; signature = ...0000000001*x^2*y
|
|
1085
|
+
4 elements in GB before minimization
|
|
1086
|
+
3 elements in GB after minimization
|
|
1087
|
+
grobner basis reduced
|
|
1088
|
+
[...000000001*x^3 + ...222222222*y + O(3^9 * <x, y>),
|
|
1089
|
+
...0000000001*x^2*y + ...1210121020 + O(3^10 * <x, y>),
|
|
1090
|
+
...000000001*y^2 + ...210121020*x + O(3^9 * <x, y>)]
|
|
1091
|
+
|
|
1092
|
+
We check that :issue:`30101` is fixed::
|
|
1093
|
+
|
|
1094
|
+
sage: I.groebner_basis(algorithm='VaPoTe', prec=100) # indirect doctest
|
|
1095
|
+
[...0000000001*x^3 + ...2222222222*y + ...000000000*x^2*y^2 + O(3^99 * <x, y>),
|
|
1096
|
+
...0000000001*x^2*y + ...01210121020 + O(3^100 * <x, y>),
|
|
1097
|
+
...0000000001*y^2 + ...01210121020*x + ...0000000000*x^3*y + O(3^99 * <x, y>)]
|
|
1098
|
+
"""
|
|
1099
|
+
cdef TateAlgebraElement g, v
|
|
1100
|
+
cdef TateAlgebraTerm s, S, sv, ti, tj
|
|
1101
|
+
cdef list terms
|
|
1102
|
+
cdef bint do_reduce, integral
|
|
1103
|
+
term_one = I.ring().monoid_of_terms().one()
|
|
1104
|
+
gb = [ ]
|
|
1105
|
+
|
|
1106
|
+
gens = [ ]
|
|
1107
|
+
for f in I.gens():
|
|
1108
|
+
if f:
|
|
1109
|
+
val = f.valuation()
|
|
1110
|
+
if val < prec:
|
|
1111
|
+
heappush(gens, (val, f.add_bigoh(prec)))
|
|
1112
|
+
|
|
1113
|
+
do_reduce = False
|
|
1114
|
+
integral = not I.ring().base_ring().is_field()
|
|
1115
|
+
|
|
1116
|
+
while gens:
|
|
1117
|
+
sig_check()
|
|
1118
|
+
val, f = heappop(gens)
|
|
1119
|
+
if val > prec:
|
|
1120
|
+
break
|
|
1121
|
+
|
|
1122
|
+
# We reduce the current Gröbner basis
|
|
1123
|
+
if val == 0 or do_reduce:
|
|
1124
|
+
for i in range(len(gb)-1, -1, -1):
|
|
1125
|
+
sig_check()
|
|
1126
|
+
g = gb[i]
|
|
1127
|
+
gb[i] = g._positive_lshift_c(1)
|
|
1128
|
+
tgtval = val + 1 if interrupt_interred_with_val else prec
|
|
1129
|
+
gb[i] = reduce(gb, g, tgtval)
|
|
1130
|
+
if verbose > 1:
|
|
1131
|
+
print("grobner basis reduced")
|
|
1132
|
+
if verbose > 3:
|
|
1133
|
+
for g in gb:
|
|
1134
|
+
print("| %s" % g)
|
|
1135
|
+
do_reduce = False
|
|
1136
|
+
|
|
1137
|
+
if verbose > 0:
|
|
1138
|
+
print("---")
|
|
1139
|
+
print("new generator: %s + ..." % f.leading_term())
|
|
1140
|
+
|
|
1141
|
+
tgtval = val + 1 if interrupt_red_with_val else prec
|
|
1142
|
+
f = reduce(gb, f, tgtval)
|
|
1143
|
+
if verbose > 1:
|
|
1144
|
+
print("generator reduced")
|
|
1145
|
+
|
|
1146
|
+
if not f:
|
|
1147
|
+
if verbose > 0:
|
|
1148
|
+
print("reduction to zero")
|
|
1149
|
+
continue
|
|
1150
|
+
|
|
1151
|
+
f = f.monic() << f.valuation()
|
|
1152
|
+
|
|
1153
|
+
if f and f.valuation() > val:
|
|
1154
|
+
if verbose > 0:
|
|
1155
|
+
print("reduction increases the valuation")
|
|
1156
|
+
heappush(gens, (f.valuation(), f))
|
|
1157
|
+
continue
|
|
1158
|
+
|
|
1159
|
+
# Initial strong Grobner basis:
|
|
1160
|
+
# we add signatures
|
|
1161
|
+
sgb = [ (None, g) for g in gb if g ]
|
|
1162
|
+
# We compute initial J-pairs
|
|
1163
|
+
l = len(sgb)
|
|
1164
|
+
p = (term_one, f.add_bigoh(prec))
|
|
1165
|
+
Jpairs = [ ]
|
|
1166
|
+
for P in sgb:
|
|
1167
|
+
J = Jpair(p, P)
|
|
1168
|
+
if J is not None:
|
|
1169
|
+
heappush(Jpairs, J)
|
|
1170
|
+
sgb.append(p)
|
|
1171
|
+
|
|
1172
|
+
# For the syzygy criterium
|
|
1173
|
+
gb0 = [ g.leading_term() for g in gb ]
|
|
1174
|
+
|
|
1175
|
+
if verbose > 1:
|
|
1176
|
+
print("%s initial J-pairs" % len(Jpairs))
|
|
1177
|
+
if verbose > 2:
|
|
1178
|
+
for s,v in Jpairs:
|
|
1179
|
+
print("| " + print_pair((s,v),verbose))
|
|
1180
|
+
|
|
1181
|
+
while Jpairs:
|
|
1182
|
+
sig_check()
|
|
1183
|
+
s, v = heappop(Jpairs)
|
|
1184
|
+
sv = v.leading_term()
|
|
1185
|
+
|
|
1186
|
+
if verbose == 2:
|
|
1187
|
+
print("pop one J-pair; %s remaining J-pairs" % len(Jpairs))
|
|
1188
|
+
if verbose > 2:
|
|
1189
|
+
print("current J-pair: " + print_pair((s,v), verbose))
|
|
1190
|
+
print("%s remaining J-pairs" % len(Jpairs))
|
|
1191
|
+
|
|
1192
|
+
# The syzygy criterium
|
|
1193
|
+
syzygy = None
|
|
1194
|
+
for S in gb0:
|
|
1195
|
+
sig_check()
|
|
1196
|
+
if S.divides(s):
|
|
1197
|
+
syzygy = S
|
|
1198
|
+
break
|
|
1199
|
+
if syzygy is not None:
|
|
1200
|
+
if verbose > 1:
|
|
1201
|
+
print("| skip: sygyzy criterium; signature = %s" % syzygy)
|
|
1202
|
+
continue
|
|
1203
|
+
|
|
1204
|
+
# We check if (s,v) is covered by
|
|
1205
|
+
# the current strong Grobner basis
|
|
1206
|
+
cover = None
|
|
1207
|
+
for S, V in sgb:
|
|
1208
|
+
sig_check()
|
|
1209
|
+
if S is not None and S.divides(s):
|
|
1210
|
+
sV = V.leading_term()
|
|
1211
|
+
# FIXME: should be a monic division
|
|
1212
|
+
if (s // S)*sV < sv:
|
|
1213
|
+
cover = (S,V)
|
|
1214
|
+
break
|
|
1215
|
+
if cover is not None:
|
|
1216
|
+
if verbose > 1:
|
|
1217
|
+
print("| skip: cover by " + print_pair(cover, verbose))
|
|
1218
|
+
continue
|
|
1219
|
+
|
|
1220
|
+
# We perform regular top-reduction
|
|
1221
|
+
sgb.append((None, v._positive_lshift_c(1)))
|
|
1222
|
+
tgtval = val + 1 if interrupt_red_with_val else prec
|
|
1223
|
+
v = regular_reduce(sgb, s, v, tgtval)
|
|
1224
|
+
terms = v._terms_c()
|
|
1225
|
+
if terms:
|
|
1226
|
+
sv = terms[0]
|
|
1227
|
+
if not sv:
|
|
1228
|
+
v = v.add_bigoh(sv._coeff.precision_absolute())
|
|
1229
|
+
del sgb[-1]
|
|
1230
|
+
|
|
1231
|
+
if v:
|
|
1232
|
+
v = v.monic() << v.valuation()
|
|
1233
|
+
if v.valuation() > val:
|
|
1234
|
+
# We have a new element in (I0:f) whose signature
|
|
1235
|
+
# could be useful to strengthen the syzygy criterium
|
|
1236
|
+
if verbose > 1:
|
|
1237
|
+
print ("| add signature for syzygy criterium: %s" % s)
|
|
1238
|
+
gb0.append(s)
|
|
1239
|
+
if v:
|
|
1240
|
+
heappush(gens, (v.valuation(), v))
|
|
1241
|
+
else:
|
|
1242
|
+
# We update the current strong Grobner basis
|
|
1243
|
+
# and the J-pairs accordingly
|
|
1244
|
+
p = (s,v)
|
|
1245
|
+
if verbose > 1:
|
|
1246
|
+
print("| new element is SGB: " + print_pair(p, verbose))
|
|
1247
|
+
count = 0
|
|
1248
|
+
for P in sgb:
|
|
1249
|
+
sig_check()
|
|
1250
|
+
J = Jpair(p, P)
|
|
1251
|
+
if J is not None:
|
|
1252
|
+
count += 1
|
|
1253
|
+
if verbose > 2:
|
|
1254
|
+
print("| add J-pair: " + print_pair(J, verbose))
|
|
1255
|
+
heappush(Jpairs, J)
|
|
1256
|
+
if verbose > 1:
|
|
1257
|
+
print("| add %s J-pairs" % count)
|
|
1258
|
+
sgb.append(p)
|
|
1259
|
+
|
|
1260
|
+
# We forget signatures
|
|
1261
|
+
# gb = [ v.monic() for (s,v) in sgb ]
|
|
1262
|
+
gb = [ v for (s,v) in sgb ]
|
|
1263
|
+
if verbose > 1:
|
|
1264
|
+
print("%s elements in GB before minimization" % len(gb))
|
|
1265
|
+
if verbose > 3:
|
|
1266
|
+
for g in gb:
|
|
1267
|
+
print("| %s" % g)
|
|
1268
|
+
# we minimize the Grobner basis
|
|
1269
|
+
i = 0
|
|
1270
|
+
while i < len(gb):
|
|
1271
|
+
ti = (<TateAlgebraElement>gb[i])._terms_c()[0]
|
|
1272
|
+
for j in range(len(gb)):
|
|
1273
|
+
sig_check()
|
|
1274
|
+
tj = (<TateAlgebraElement>gb[j])._terms_c()[0]
|
|
1275
|
+
if j != i and tj._divides_c(ti, integral):
|
|
1276
|
+
del gb[i]
|
|
1277
|
+
break
|
|
1278
|
+
else:
|
|
1279
|
+
i += 1
|
|
1280
|
+
if verbose > 0:
|
|
1281
|
+
if verbose > 1:
|
|
1282
|
+
aft = " after minimization"
|
|
1283
|
+
else:
|
|
1284
|
+
aft = ""
|
|
1285
|
+
print("%s elements in GB%s" % (len(gb), aft))
|
|
1286
|
+
if verbose > 3:
|
|
1287
|
+
for g in gb:
|
|
1288
|
+
print("| %s" % g)
|
|
1289
|
+
# and reduce it
|
|
1290
|
+
do_reduce = True
|
|
1291
|
+
|
|
1292
|
+
# We normalize the final Gröbner basis
|
|
1293
|
+
for i in range(len(gb)-1, -1, -1):
|
|
1294
|
+
sig_check()
|
|
1295
|
+
g = gb[i]
|
|
1296
|
+
gb[i] = g._positive_lshift_c(1)
|
|
1297
|
+
gb[i] = reduce(gb, g, prec)
|
|
1298
|
+
if verbose > 1:
|
|
1299
|
+
print("grobner basis reduced")
|
|
1300
|
+
if verbose > 3:
|
|
1301
|
+
for g in gb:
|
|
1302
|
+
print("| %s" % g)
|
|
1303
|
+
if not integral:
|
|
1304
|
+
gb = [ f.monic() for f in gb ]
|
|
1305
|
+
gb.sort(reverse=True)
|
|
1306
|
+
|
|
1307
|
+
return gb
|