passagemath-singular 10.6.31rc3__cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-singular might be problematic. Click here for more details.
- PySingular.cpython-314-aarch64-linux-gnu.so +0 -0
- passagemath_singular-10.6.31rc3.dist-info/METADATA +183 -0
- passagemath_singular-10.6.31rc3.dist-info/RECORD +490 -0
- passagemath_singular-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_singular-10.6.31rc3.dist-info/top_level.txt +3 -0
- passagemath_singular.libs/libSingular-4-6a2a8666.4.1.so +0 -0
- passagemath_singular.libs/libcddgmp-ac579979.so.0.1.3 +0 -0
- passagemath_singular.libs/libfactory-4-66e33516.4.1.so +0 -0
- passagemath_singular.libs/libflint-81de1160.so.21.0.0 +0 -0
- passagemath_singular.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
- passagemath_singular.libs/libgfortran-e1b7dfc8.so.5.0.0 +0 -0
- passagemath_singular.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
- passagemath_singular.libs/libgsl-e3525837.so.28.0.0 +0 -0
- passagemath_singular.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
- passagemath_singular.libs/libntl-0043a3a2.so.44.0.1 +0 -0
- passagemath_singular.libs/libomalloc-0-06512335.9.6.so +0 -0
- passagemath_singular.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
- passagemath_singular.libs/libpolys-4-cb7246b5.4.1.so +0 -0
- passagemath_singular.libs/libreadline-28330744.so.8.2 +0 -0
- passagemath_singular.libs/libsingular_resources-4-8c425241.4.1.so +0 -0
- passagemath_singular.libs/libtinfo-f81c2d16.so.6.3 +0 -0
- sage/algebras/all__sagemath_singular.py +3 -0
- sage/algebras/fusion_rings/all.py +19 -0
- sage/algebras/fusion_rings/f_matrix.py +2448 -0
- sage/algebras/fusion_rings/fast_parallel_fmats_methods.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/fast_parallel_fmats_methods.pxd +5 -0
- sage/algebras/fusion_rings/fast_parallel_fmats_methods.pyx +538 -0
- sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pxd +3 -0
- sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pyx +331 -0
- sage/algebras/fusion_rings/fusion_double.py +899 -0
- sage/algebras/fusion_rings/fusion_ring.py +1580 -0
- sage/algebras/fusion_rings/poly_tup_engine.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/poly_tup_engine.pxd +24 -0
- sage/algebras/fusion_rings/poly_tup_engine.pyx +579 -0
- sage/algebras/fusion_rings/shm_managers.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/fusion_rings/shm_managers.pxd +24 -0
- sage/algebras/fusion_rings/shm_managers.pyx +780 -0
- sage/algebras/letterplace/all.py +1 -0
- sage/algebras/letterplace/free_algebra_element_letterplace.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/letterplace/free_algebra_element_letterplace.pxd +18 -0
- sage/algebras/letterplace/free_algebra_element_letterplace.pyx +755 -0
- sage/algebras/letterplace/free_algebra_letterplace.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/letterplace/free_algebra_letterplace.pxd +35 -0
- sage/algebras/letterplace/free_algebra_letterplace.pyx +914 -0
- sage/algebras/letterplace/letterplace_ideal.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/letterplace/letterplace_ideal.pyx +408 -0
- sage/algebras/quatalg/all.py +2 -0
- sage/algebras/quatalg/quaternion_algebra.py +4778 -0
- sage/algebras/quatalg/quaternion_algebra_cython.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/quatalg/quaternion_algebra_cython.pyx +261 -0
- sage/algebras/quatalg/quaternion_algebra_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/algebras/quatalg/quaternion_algebra_element.pxd +29 -0
- sage/algebras/quatalg/quaternion_algebra_element.pyx +2176 -0
- sage/all__sagemath_singular.py +11 -0
- sage/ext_data/all__sagemath_singular.py +1 -0
- sage/ext_data/singular/function_field/core.lib +98 -0
- sage/interfaces/all__sagemath_singular.py +1 -0
- sage/interfaces/singular.py +2835 -0
- sage/libs/all__sagemath_singular.py +1 -0
- sage/libs/singular/__init__.py +1 -0
- sage/libs/singular/decl.pxd +1168 -0
- sage/libs/singular/function.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/singular/function.pxd +87 -0
- sage/libs/singular/function.pyx +1901 -0
- sage/libs/singular/function_factory.py +61 -0
- sage/libs/singular/groebner_strategy.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/singular/groebner_strategy.pxd +22 -0
- sage/libs/singular/groebner_strategy.pyx +582 -0
- sage/libs/singular/option.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/singular/option.pyx +671 -0
- sage/libs/singular/polynomial.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/singular/polynomial.pxd +39 -0
- sage/libs/singular/polynomial.pyx +661 -0
- sage/libs/singular/ring.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/singular/ring.pxd +58 -0
- sage/libs/singular/ring.pyx +893 -0
- sage/libs/singular/singular.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/singular/singular.pxd +72 -0
- sage/libs/singular/singular.pyx +1944 -0
- sage/libs/singular/standard_options.py +145 -0
- sage/matrix/all__sagemath_singular.py +1 -0
- sage/matrix/matrix_mpolynomial_dense.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/matrix/matrix_mpolynomial_dense.pxd +7 -0
- sage/matrix/matrix_mpolynomial_dense.pyx +615 -0
- sage/rings/all__sagemath_singular.py +1 -0
- sage/rings/function_field/all__sagemath_singular.py +1 -0
- sage/rings/function_field/derivations_polymod.py +911 -0
- sage/rings/function_field/element_polymod.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/function_field/element_polymod.pyx +406 -0
- sage/rings/function_field/function_field_polymod.py +2611 -0
- sage/rings/function_field/ideal_polymod.py +1775 -0
- sage/rings/function_field/order_polymod.py +1475 -0
- sage/rings/function_field/place_polymod.py +681 -0
- sage/rings/polynomial/all__sagemath_singular.py +1 -0
- sage/rings/polynomial/multi_polynomial_ideal_libsingular.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/multi_polynomial_ideal_libsingular.pxd +5 -0
- sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx +339 -0
- sage/rings/polynomial/multi_polynomial_libsingular.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/multi_polynomial_libsingular.pxd +30 -0
- sage/rings/polynomial/multi_polynomial_libsingular.pyx +6277 -0
- sage/rings/polynomial/plural.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/plural.pxd +48 -0
- sage/rings/polynomial/plural.pyx +3171 -0
- sage/symbolic/all__sagemath_singular.py +1 -0
- sage/symbolic/comparison_impl.pxi +428 -0
- sage/symbolic/constants_c_impl.pxi +178 -0
- sage/symbolic/expression.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/symbolic/expression.pxd +7 -0
- sage/symbolic/expression.pyx +14200 -0
- sage/symbolic/getitem_impl.pxi +202 -0
- sage/symbolic/pynac.pxi +572 -0
- sage/symbolic/pynac_constant_impl.pxi +133 -0
- sage/symbolic/pynac_function_impl.pxi +206 -0
- sage/symbolic/pynac_impl.pxi +2576 -0
- sage/symbolic/pynac_wrap.h +124 -0
- sage/symbolic/series_impl.pxi +272 -0
- sage/symbolic/substitution_map_impl.pxi +94 -0
- sage_wheels/bin/ESingular +0 -0
- sage_wheels/bin/Singular +0 -0
- sage_wheels/bin/TSingular +0 -0
- sage_wheels/lib/singular/MOD/cohomo.la +41 -0
- sage_wheels/lib/singular/MOD/cohomo.so +0 -0
- sage_wheels/lib/singular/MOD/customstd.la +41 -0
- sage_wheels/lib/singular/MOD/customstd.so +0 -0
- sage_wheels/lib/singular/MOD/freealgebra.la +41 -0
- sage_wheels/lib/singular/MOD/freealgebra.so +0 -0
- sage_wheels/lib/singular/MOD/gfanlib.la +41 -0
- sage_wheels/lib/singular/MOD/gfanlib.so +0 -0
- sage_wheels/lib/singular/MOD/gitfan.la +41 -0
- sage_wheels/lib/singular/MOD/gitfan.so +0 -0
- sage_wheels/lib/singular/MOD/interval.la +41 -0
- sage_wheels/lib/singular/MOD/interval.so +0 -0
- sage_wheels/lib/singular/MOD/loctriv.la +41 -0
- sage_wheels/lib/singular/MOD/loctriv.so +0 -0
- sage_wheels/lib/singular/MOD/machinelearning.la +41 -0
- sage_wheels/lib/singular/MOD/machinelearning.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldQ.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldQ.so +0 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldZp.la +41 -0
- sage_wheels/lib/singular/MOD/p_Procs_FieldZp.so +0 -0
- sage_wheels/lib/singular/MOD/partialgb.la +41 -0
- sage_wheels/lib/singular/MOD/partialgb.so +0 -0
- sage_wheels/lib/singular/MOD/pyobject.la +41 -0
- sage_wheels/lib/singular/MOD/pyobject.so +0 -0
- sage_wheels/lib/singular/MOD/singmathic.la +41 -0
- sage_wheels/lib/singular/MOD/singmathic.so +0 -0
- sage_wheels/lib/singular/MOD/sispasm.la +41 -0
- sage_wheels/lib/singular/MOD/sispasm.so +0 -0
- sage_wheels/lib/singular/MOD/subsets.la +41 -0
- sage_wheels/lib/singular/MOD/subsets.so +0 -0
- sage_wheels/lib/singular/MOD/systhreads.la +41 -0
- sage_wheels/lib/singular/MOD/systhreads.so +0 -0
- sage_wheels/lib/singular/MOD/syzextra.la +41 -0
- sage_wheels/lib/singular/MOD/syzextra.so +0 -0
- sage_wheels/libexec/singular/MOD/change_cost +0 -0
- sage_wheels/libexec/singular/MOD/singularsurf +11 -0
- sage_wheels/libexec/singular/MOD/singularsurf_jupyter +9 -0
- sage_wheels/libexec/singular/MOD/singularsurf_win +10 -0
- sage_wheels/libexec/singular/MOD/solve_IP +0 -0
- sage_wheels/libexec/singular/MOD/surfex +16 -0
- sage_wheels/libexec/singular/MOD/toric_ideal +0 -0
- sage_wheels/share/factory/gftables/10201 +342 -0
- sage_wheels/share/factory/gftables/1024 +37 -0
- sage_wheels/share/factory/gftables/10609 +356 -0
- sage_wheels/share/factory/gftables/11449 +384 -0
- sage_wheels/share/factory/gftables/11881 +398 -0
- sage_wheels/share/factory/gftables/121 +6 -0
- sage_wheels/share/factory/gftables/12167 +408 -0
- sage_wheels/share/factory/gftables/125 +7 -0
- sage_wheels/share/factory/gftables/12769 +428 -0
- sage_wheels/share/factory/gftables/128 +7 -0
- sage_wheels/share/factory/gftables/1331 +47 -0
- sage_wheels/share/factory/gftables/1369 +48 -0
- sage_wheels/share/factory/gftables/14641 +490 -0
- sage_wheels/share/factory/gftables/15625 +523 -0
- sage_wheels/share/factory/gftables/16 +3 -0
- sage_wheels/share/factory/gftables/16129 +540 -0
- sage_wheels/share/factory/gftables/16384 +549 -0
- sage_wheels/share/factory/gftables/16807 +563 -0
- sage_wheels/share/factory/gftables/1681 +58 -0
- sage_wheels/share/factory/gftables/169 +8 -0
- sage_wheels/share/factory/gftables/17161 +574 -0
- sage_wheels/share/factory/gftables/1849 +64 -0
- sage_wheels/share/factory/gftables/18769 +628 -0
- sage_wheels/share/factory/gftables/19321 +646 -0
- sage_wheels/share/factory/gftables/19683 +659 -0
- sage_wheels/share/factory/gftables/2048 +71 -0
- sage_wheels/share/factory/gftables/2187 +75 -0
- sage_wheels/share/factory/gftables/2197 +76 -0
- sage_wheels/share/factory/gftables/2209 +76 -0
- sage_wheels/share/factory/gftables/22201 +742 -0
- sage_wheels/share/factory/gftables/22801 +762 -0
- sage_wheels/share/factory/gftables/2401 +82 -0
- sage_wheels/share/factory/gftables/243 +11 -0
- sage_wheels/share/factory/gftables/24389 +815 -0
- sage_wheels/share/factory/gftables/24649 +824 -0
- sage_wheels/share/factory/gftables/25 +3 -0
- sage_wheels/share/factory/gftables/256 +11 -0
- sage_wheels/share/factory/gftables/26569 +888 -0
- sage_wheels/share/factory/gftables/27 +3 -0
- sage_wheels/share/factory/gftables/27889 +932 -0
- sage_wheels/share/factory/gftables/2809 +96 -0
- sage_wheels/share/factory/gftables/28561 +954 -0
- sage_wheels/share/factory/gftables/289 +12 -0
- sage_wheels/share/factory/gftables/29791 +995 -0
- sage_wheels/share/factory/gftables/29929 +1000 -0
- sage_wheels/share/factory/gftables/3125 +107 -0
- sage_wheels/share/factory/gftables/32 +4 -0
- sage_wheels/share/factory/gftables/32041 +1070 -0
- sage_wheels/share/factory/gftables/32761 +1094 -0
- sage_wheels/share/factory/gftables/32768 +1095 -0
- sage_wheels/share/factory/gftables/343 +14 -0
- sage_wheels/share/factory/gftables/3481 +118 -0
- sage_wheels/share/factory/gftables/361 +14 -0
- sage_wheels/share/factory/gftables/36481 +1218 -0
- sage_wheels/share/factory/gftables/3721 +126 -0
- sage_wheels/share/factory/gftables/37249 +1244 -0
- sage_wheels/share/factory/gftables/38809 +1296 -0
- sage_wheels/share/factory/gftables/39601 +1322 -0
- sage_wheels/share/factory/gftables/4 +3 -0
- sage_wheels/share/factory/gftables/4096 +139 -0
- sage_wheels/share/factory/gftables/44521 +1486 -0
- sage_wheels/share/factory/gftables/4489 +152 -0
- sage_wheels/share/factory/gftables/49 +4 -0
- sage_wheels/share/factory/gftables/4913 +166 -0
- sage_wheels/share/factory/gftables/49729 +1660 -0
- sage_wheels/share/factory/gftables/5041 +170 -0
- sage_wheels/share/factory/gftables/50653 +1691 -0
- sage_wheels/share/factory/gftables/512 +20 -0
- sage_wheels/share/factory/gftables/51529 +1720 -0
- sage_wheels/share/factory/gftables/52441 +1750 -0
- sage_wheels/share/factory/gftables/529 +20 -0
- sage_wheels/share/factory/gftables/5329 +180 -0
- sage_wheels/share/factory/gftables/54289 +1812 -0
- sage_wheels/share/factory/gftables/57121 +1906 -0
- sage_wheels/share/factory/gftables/58081 +1938 -0
- sage_wheels/share/factory/gftables/59049 +1971 -0
- sage_wheels/share/factory/gftables/6241 +210 -0
- sage_wheels/share/factory/gftables/625 +23 -0
- sage_wheels/share/factory/gftables/63001 +2102 -0
- sage_wheels/share/factory/gftables/64 +5 -0
- sage_wheels/share/factory/gftables/6561 +221 -0
- sage_wheels/share/factory/gftables/6859 +231 -0
- sage_wheels/share/factory/gftables/6889 +232 -0
- sage_wheels/share/factory/gftables/729 +27 -0
- sage_wheels/share/factory/gftables/7921 +266 -0
- sage_wheels/share/factory/gftables/8 +3 -0
- sage_wheels/share/factory/gftables/81 +5 -0
- sage_wheels/share/factory/gftables/8192 +276 -0
- sage_wheels/share/factory/gftables/841 +30 -0
- sage_wheels/share/factory/gftables/9 +3 -0
- sage_wheels/share/factory/gftables/9409 +316 -0
- sage_wheels/share/factory/gftables/961 +34 -0
- sage_wheels/share/info/singular.info +191898 -0
- sage_wheels/share/singular/LIB/GND.lib +1359 -0
- sage_wheels/share/singular/LIB/JMBTest.lib +976 -0
- sage_wheels/share/singular/LIB/JMSConst.lib +1363 -0
- sage_wheels/share/singular/LIB/KVequiv.lib +699 -0
- sage_wheels/share/singular/LIB/SingularityDBM.lib +491 -0
- sage_wheels/share/singular/LIB/VecField.lib +1542 -0
- sage_wheels/share/singular/LIB/absfact.lib +959 -0
- sage_wheels/share/singular/LIB/ainvar.lib +730 -0
- sage_wheels/share/singular/LIB/aksaka.lib +419 -0
- sage_wheels/share/singular/LIB/alexpoly.lib +2542 -0
- sage_wheels/share/singular/LIB/algebra.lib +1193 -0
- sage_wheels/share/singular/LIB/all.lib +136 -0
- sage_wheels/share/singular/LIB/arcpoint.lib +514 -0
- sage_wheels/share/singular/LIB/arnold.lib +4553 -0
- sage_wheels/share/singular/LIB/arnoldclassify.lib +2058 -0
- sage_wheels/share/singular/LIB/arr.lib +3486 -0
- sage_wheels/share/singular/LIB/assprimeszerodim.lib +755 -0
- sage_wheels/share/singular/LIB/autgradalg.lib +3361 -0
- sage_wheels/share/singular/LIB/bfun.lib +1964 -0
- sage_wheels/share/singular/LIB/bimodules.lib +774 -0
- sage_wheels/share/singular/LIB/brillnoether.lib +226 -0
- sage_wheels/share/singular/LIB/brnoeth.lib +5017 -0
- sage_wheels/share/singular/LIB/central.lib +2169 -0
- sage_wheels/share/singular/LIB/chern.lib +4162 -0
- sage_wheels/share/singular/LIB/cimonom.lib +571 -0
- sage_wheels/share/singular/LIB/cisimplicial.lib +1835 -0
- sage_wheels/share/singular/LIB/classify.lib +3239 -0
- sage_wheels/share/singular/LIB/classify2.lib +1462 -0
- sage_wheels/share/singular/LIB/classifyMapGerms.lib +1515 -0
- sage_wheels/share/singular/LIB/classify_aeq.lib +3253 -0
- sage_wheels/share/singular/LIB/classifyceq.lib +2092 -0
- sage_wheels/share/singular/LIB/classifyci.lib +1133 -0
- sage_wheels/share/singular/LIB/combinat.lib +91 -0
- sage_wheels/share/singular/LIB/compregb.lib +276 -0
- sage_wheels/share/singular/LIB/control.lib +1636 -0
- sage_wheels/share/singular/LIB/crypto.lib +3795 -0
- sage_wheels/share/singular/LIB/curveInv.lib +667 -0
- sage_wheels/share/singular/LIB/curvepar.lib +1817 -0
- sage_wheels/share/singular/LIB/customstd.lib +100 -0
- sage_wheels/share/singular/LIB/deRham.lib +5979 -0
- sage_wheels/share/singular/LIB/decodegb.lib +2134 -0
- sage_wheels/share/singular/LIB/decomp.lib +1655 -0
- sage_wheels/share/singular/LIB/deflation.lib +872 -0
- sage_wheels/share/singular/LIB/deform.lib +925 -0
- sage_wheels/share/singular/LIB/difform.lib +3055 -0
- sage_wheels/share/singular/LIB/divisors.lib +750 -0
- sage_wheels/share/singular/LIB/dmod.lib +5817 -0
- sage_wheels/share/singular/LIB/dmodapp.lib +3269 -0
- sage_wheels/share/singular/LIB/dmodideal.lib +1211 -0
- sage_wheels/share/singular/LIB/dmodloc.lib +2645 -0
- sage_wheels/share/singular/LIB/dmodvar.lib +818 -0
- sage_wheels/share/singular/LIB/dummy.lib +17 -0
- sage_wheels/share/singular/LIB/elim.lib +1009 -0
- sage_wheels/share/singular/LIB/ellipticcovers.lib +548 -0
- sage_wheels/share/singular/LIB/enumpoints.lib +146 -0
- sage_wheels/share/singular/LIB/equising.lib +2127 -0
- sage_wheels/share/singular/LIB/ffmodstd.lib +2384 -0
- sage_wheels/share/singular/LIB/ffsolve.lib +1289 -0
- sage_wheels/share/singular/LIB/findifs.lib +778 -0
- sage_wheels/share/singular/LIB/finitediff.lib +1768 -0
- sage_wheels/share/singular/LIB/finvar.lib +7989 -0
- sage_wheels/share/singular/LIB/fpadim.lib +2429 -0
- sage_wheels/share/singular/LIB/fpalgebras.lib +1666 -0
- sage_wheels/share/singular/LIB/fpaprops.lib +1462 -0
- sage_wheels/share/singular/LIB/freegb.lib +3853 -0
- sage_wheels/share/singular/LIB/general.lib +1350 -0
- sage_wheels/share/singular/LIB/gfan.lib +1768 -0
- sage_wheels/share/singular/LIB/gitfan.lib +3130 -0
- sage_wheels/share/singular/LIB/gkdim.lib +99 -0
- sage_wheels/share/singular/LIB/gmspoly.lib +589 -0
- sage_wheels/share/singular/LIB/gmssing.lib +1739 -0
- sage_wheels/share/singular/LIB/goettsche.lib +909 -0
- sage_wheels/share/singular/LIB/graal.lib +1366 -0
- sage_wheels/share/singular/LIB/gradedModules.lib +2541 -0
- sage_wheels/share/singular/LIB/graphics.lib +360 -0
- sage_wheels/share/singular/LIB/grobcov.lib +7706 -0
- sage_wheels/share/singular/LIB/groups.lib +1123 -0
- sage_wheels/share/singular/LIB/grwalk.lib +507 -0
- sage_wheels/share/singular/LIB/hdepth.lib +194 -0
- sage_wheels/share/singular/LIB/help.cnf +57 -0
- sage_wheels/share/singular/LIB/hess.lib +1946 -0
- sage_wheels/share/singular/LIB/hnoether.lib +4292 -0
- sage_wheels/share/singular/LIB/hodge.lib +400 -0
- sage_wheels/share/singular/LIB/homolog.lib +1965 -0
- sage_wheels/share/singular/LIB/hyperel.lib +975 -0
- sage_wheels/share/singular/LIB/inout.lib +679 -0
- sage_wheels/share/singular/LIB/integralbasis.lib +6224 -0
- sage_wheels/share/singular/LIB/interval.lib +1418 -0
- sage_wheels/share/singular/LIB/intprog.lib +778 -0
- sage_wheels/share/singular/LIB/invar.lib +443 -0
- sage_wheels/share/singular/LIB/involut.lib +980 -0
- sage_wheels/share/singular/LIB/jacobson.lib +1215 -0
- sage_wheels/share/singular/LIB/kskernel.lib +534 -0
- sage_wheels/share/singular/LIB/latex.lib +3146 -0
- sage_wheels/share/singular/LIB/lejeune.lib +651 -0
- sage_wheels/share/singular/LIB/linalg.lib +2040 -0
- sage_wheels/share/singular/LIB/locnormal.lib +212 -0
- sage_wheels/share/singular/LIB/lrcalc.lib +526 -0
- sage_wheels/share/singular/LIB/makedbm.lib +294 -0
- sage_wheels/share/singular/LIB/mathml.lib +813 -0
- sage_wheels/share/singular/LIB/matrix.lib +1372 -0
- sage_wheels/share/singular/LIB/maxlike.lib +1132 -0
- sage_wheels/share/singular/LIB/methods.lib +212 -0
- sage_wheels/share/singular/LIB/moddiq.lib +322 -0
- sage_wheels/share/singular/LIB/modfinduni.lib +181 -0
- sage_wheels/share/singular/LIB/modnormal.lib +218 -0
- sage_wheels/share/singular/LIB/modprimdec.lib +1278 -0
- sage_wheels/share/singular/LIB/modquotient.lib +269 -0
- sage_wheels/share/singular/LIB/modstd.lib +1024 -0
- sage_wheels/share/singular/LIB/modular.lib +545 -0
- sage_wheels/share/singular/LIB/modules.lib +2561 -0
- sage_wheels/share/singular/LIB/modwalk.lib +609 -0
- sage_wheels/share/singular/LIB/mondromy.lib +1016 -0
- sage_wheels/share/singular/LIB/monomialideal.lib +3851 -0
- sage_wheels/share/singular/LIB/mprimdec.lib +2353 -0
- sage_wheels/share/singular/LIB/mregular.lib +1863 -0
- sage_wheels/share/singular/LIB/multigrading.lib +5629 -0
- sage_wheels/share/singular/LIB/ncHilb.lib +777 -0
- sage_wheels/share/singular/LIB/ncModslimgb.lib +791 -0
- sage_wheels/share/singular/LIB/ncalg.lib +16311 -0
- sage_wheels/share/singular/LIB/ncall.lib +31 -0
- sage_wheels/share/singular/LIB/ncdecomp.lib +468 -0
- sage_wheels/share/singular/LIB/ncfactor.lib +13371 -0
- sage_wheels/share/singular/LIB/ncfrac.lib +1023 -0
- sage_wheels/share/singular/LIB/nchilbert.lib +448 -0
- sage_wheels/share/singular/LIB/nchomolog.lib +759 -0
- sage_wheels/share/singular/LIB/ncloc.lib +361 -0
- sage_wheels/share/singular/LIB/ncpreim.lib +795 -0
- sage_wheels/share/singular/LIB/ncrat.lib +2849 -0
- sage_wheels/share/singular/LIB/nctools.lib +1887 -0
- sage_wheels/share/singular/LIB/nets.lib +1456 -0
- sage_wheels/share/singular/LIB/nfmodstd.lib +1000 -0
- sage_wheels/share/singular/LIB/nfmodsyz.lib +732 -0
- sage_wheels/share/singular/LIB/noether.lib +1106 -0
- sage_wheels/share/singular/LIB/normal.lib +8700 -0
- sage_wheels/share/singular/LIB/normaliz.lib +2226 -0
- sage_wheels/share/singular/LIB/ntsolve.lib +362 -0
- sage_wheels/share/singular/LIB/numerAlg.lib +560 -0
- sage_wheels/share/singular/LIB/numerDecom.lib +2261 -0
- sage_wheels/share/singular/LIB/olga.lib +1933 -0
- sage_wheels/share/singular/LIB/orbitparam.lib +351 -0
- sage_wheels/share/singular/LIB/parallel.lib +319 -0
- sage_wheels/share/singular/LIB/paraplanecurves.lib +3110 -0
- sage_wheels/share/singular/LIB/perron.lib +202 -0
- sage_wheels/share/singular/LIB/pfd.lib +2223 -0
- sage_wheels/share/singular/LIB/phindex.lib +642 -0
- sage_wheels/share/singular/LIB/pointid.lib +673 -0
- sage_wheels/share/singular/LIB/polybori.lib +1430 -0
- sage_wheels/share/singular/LIB/polyclass.lib +525 -0
- sage_wheels/share/singular/LIB/polylib.lib +1174 -0
- sage_wheels/share/singular/LIB/polymake.lib +1902 -0
- sage_wheels/share/singular/LIB/presolve.lib +1533 -0
- sage_wheels/share/singular/LIB/primdec.lib +9576 -0
- sage_wheels/share/singular/LIB/primdecint.lib +1782 -0
- sage_wheels/share/singular/LIB/primitiv.lib +401 -0
- sage_wheels/share/singular/LIB/puiseuxexpansions.lib +1631 -0
- sage_wheels/share/singular/LIB/purityfiltration.lib +960 -0
- sage_wheels/share/singular/LIB/qhmoduli.lib +1561 -0
- sage_wheels/share/singular/LIB/qmatrix.lib +293 -0
- sage_wheels/share/singular/LIB/random.lib +455 -0
- sage_wheels/share/singular/LIB/ratgb.lib +489 -0
- sage_wheels/share/singular/LIB/realclassify.lib +5759 -0
- sage_wheels/share/singular/LIB/realizationMatroids.lib +772 -0
- sage_wheels/share/singular/LIB/realrad.lib +1197 -0
- sage_wheels/share/singular/LIB/recover.lib +2628 -0
- sage_wheels/share/singular/LIB/redcgs.lib +3984 -0
- sage_wheels/share/singular/LIB/reesclos.lib +465 -0
- sage_wheels/share/singular/LIB/resbinomial.lib +2802 -0
- sage_wheels/share/singular/LIB/resgraph.lib +789 -0
- sage_wheels/share/singular/LIB/resjung.lib +820 -0
- sage_wheels/share/singular/LIB/resolve.lib +5110 -0
- sage_wheels/share/singular/LIB/resources.lib +170 -0
- sage_wheels/share/singular/LIB/reszeta.lib +5473 -0
- sage_wheels/share/singular/LIB/ring.lib +1328 -0
- sage_wheels/share/singular/LIB/ringgb.lib +343 -0
- sage_wheels/share/singular/LIB/rinvar.lib +1153 -0
- sage_wheels/share/singular/LIB/rootisolation.lib +1481 -0
- sage_wheels/share/singular/LIB/rootsmr.lib +709 -0
- sage_wheels/share/singular/LIB/rootsur.lib +886 -0
- sage_wheels/share/singular/LIB/rstandard.lib +607 -0
- sage_wheels/share/singular/LIB/rwalk.lib +336 -0
- sage_wheels/share/singular/LIB/sagbi.lib +1353 -0
- sage_wheels/share/singular/LIB/sagbiNormaliz.lib +1622 -0
- sage_wheels/share/singular/LIB/sagbiNormaliz0.lib +1498 -0
- sage_wheels/share/singular/LIB/sagbigrob.lib +449 -0
- sage_wheels/share/singular/LIB/schreyer.lib +321 -0
- sage_wheels/share/singular/LIB/schubert.lib +2551 -0
- sage_wheels/share/singular/LIB/sets.lib +524 -0
- sage_wheels/share/singular/LIB/sheafcoh.lib +1663 -0
- sage_wheels/share/singular/LIB/signcond.lib +437 -0
- sage_wheels/share/singular/LIB/sing.lib +1094 -0
- sage_wheels/share/singular/LIB/sing4ti2.lib +419 -0
- sage_wheels/share/singular/LIB/solve.lib +2243 -0
- sage_wheels/share/singular/LIB/spcurve.lib +1077 -0
- sage_wheels/share/singular/LIB/spectrum.lib +62 -0
- sage_wheels/share/singular/LIB/sresext.lib +757 -0
- sage_wheels/share/singular/LIB/ssi.lib +143 -0
- sage_wheels/share/singular/LIB/standard.lib +2769 -0
- sage_wheels/share/singular/LIB/stanleyreisner.lib +473 -0
- sage_wheels/share/singular/LIB/stdmodule.lib +547 -0
- sage_wheels/share/singular/LIB/stratify.lib +1070 -0
- sage_wheels/share/singular/LIB/surf.lib +506 -0
- sage_wheels/share/singular/LIB/surf_jupyter.lib +223 -0
- sage_wheels/share/singular/LIB/surfacesignature.lib +522 -0
- sage_wheels/share/singular/LIB/surfex.lib +1462 -0
- sage_wheels/share/singular/LIB/swalk.lib +877 -0
- sage_wheels/share/singular/LIB/symodstd.lib +1570 -0
- sage_wheels/share/singular/LIB/systhreads.lib +74 -0
- sage_wheels/share/singular/LIB/tasks.lib +1324 -0
- sage_wheels/share/singular/LIB/tateProdCplxNegGrad.lib +2412 -0
- sage_wheels/share/singular/LIB/teachstd.lib +858 -0
- sage_wheels/share/singular/LIB/template.lib +116 -0
- sage_wheels/share/singular/LIB/toric.lib +1119 -0
- sage_wheels/share/singular/LIB/transformation.lib +116 -0
- sage_wheels/share/singular/LIB/triang.lib +1197 -0
- sage_wheels/share/singular/LIB/tropical.lib +8741 -0
- sage_wheels/share/singular/LIB/tropicalEllipticCovers.lib +2922 -0
- sage_wheels/share/singular/LIB/tropicalNewton.lib +1128 -0
- sage_wheels/share/singular/LIB/tst.lib +1108 -0
- sage_wheels/share/singular/LIB/weierstr.lib +241 -0
- sage_wheels/share/singular/LIB/zeroset.lib +1478 -0
- sage_wheels/share/singular/emacs/.emacs-general +184 -0
- sage_wheels/share/singular/emacs/.emacs-singular +234 -0
- sage_wheels/share/singular/emacs/COPYING +44 -0
- sage_wheels/share/singular/emacs/cmd-cmpl.el +241 -0
- sage_wheels/share/singular/emacs/ex-cmpl.el +1681 -0
- sage_wheels/share/singular/emacs/hlp-cmpl.el +4318 -0
- sage_wheels/share/singular/emacs/lib-cmpl.el +179 -0
- sage_wheels/share/singular/emacs/singular.el +4273 -0
- sage_wheels/share/singular/emacs/singular.xpm +39 -0
- sage_wheels/share/singular/singular.idx +5002 -0
|
@@ -0,0 +1,2611 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-singular
|
|
2
|
+
# sage.doctest: needs sage.rings.function_field
|
|
3
|
+
r"""
|
|
4
|
+
Function Fields: extension
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# *****************************************************************************
|
|
8
|
+
# Copyright (C) 2010 William Stein <wstein@gmail.com>
|
|
9
|
+
# 2010 Robert Bradshaw <robertwb@math.washington.edu>
|
|
10
|
+
# 2011-2018 Julian Rüth <julian.rueth@gmail.com>
|
|
11
|
+
# 2011 Maarten Derickx <m.derickx.student@gmail.com>
|
|
12
|
+
# 2011 Syed Ahmad Lavasani
|
|
13
|
+
# 2013-2014 Simon King
|
|
14
|
+
# 2017 Dean Bisogno
|
|
15
|
+
# 2017 Alyson Deines
|
|
16
|
+
# 2017-2019 David Roe
|
|
17
|
+
# 2017-2022 Kwankyu Lee
|
|
18
|
+
# 2018 Marc Mezzarobba
|
|
19
|
+
# 2018 Wilfried Luebbe
|
|
20
|
+
# 2019 Brent Baccala
|
|
21
|
+
# 2022 Frédéric Chapoton
|
|
22
|
+
# 2022 Gonzalo Tornaría
|
|
23
|
+
#
|
|
24
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
25
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
26
|
+
# the License, or (at your option) any later version.
|
|
27
|
+
# http://www.gnu.org/licenses/
|
|
28
|
+
# *****************************************************************************
|
|
29
|
+
|
|
30
|
+
from sage.arith.functions import lcm
|
|
31
|
+
from sage.misc.cachefunc import cached_method
|
|
32
|
+
from sage.misc.lazy_import import LazyImport
|
|
33
|
+
from sage.rings.qqbar_decorators import handle_AA_and_QQbar
|
|
34
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
35
|
+
from sage.rings.integer import Integer
|
|
36
|
+
from sage.categories.homset import Hom
|
|
37
|
+
from sage.categories.function_fields import FunctionFields
|
|
38
|
+
from sage.categories.number_fields import NumberFields
|
|
39
|
+
|
|
40
|
+
from .element import FunctionFieldElement
|
|
41
|
+
from .element_polymod import FunctionFieldElement_polymod
|
|
42
|
+
from .function_field import FunctionField
|
|
43
|
+
from .function_field_rational import RationalFunctionField
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class FunctionField_polymod(FunctionField):
|
|
47
|
+
"""
|
|
48
|
+
Function fields defined by a univariate polynomial, as an extension of the
|
|
49
|
+
base field.
|
|
50
|
+
|
|
51
|
+
INPUT:
|
|
52
|
+
|
|
53
|
+
- ``polynomial`` -- univariate polynomial over a function field
|
|
54
|
+
|
|
55
|
+
- ``names`` -- tuple of length 1 or string; variable names
|
|
56
|
+
|
|
57
|
+
- ``category`` -- category (default: category of function fields)
|
|
58
|
+
|
|
59
|
+
EXAMPLES:
|
|
60
|
+
|
|
61
|
+
We make a function field defined by a degree 5 polynomial over the
|
|
62
|
+
rational function field over the rational numbers::
|
|
63
|
+
|
|
64
|
+
sage: K.<x> = FunctionField(QQ)
|
|
65
|
+
sage: R.<y> = K[]
|
|
66
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
|
|
67
|
+
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
68
|
+
|
|
69
|
+
We next make a function field over the above nontrivial function
|
|
70
|
+
field L::
|
|
71
|
+
|
|
72
|
+
sage: S.<z> = L[]
|
|
73
|
+
sage: M.<z> = L.extension(z^2 + y*z + y); M
|
|
74
|
+
Function field in z defined by z^2 + y*z + y
|
|
75
|
+
sage: 1/z
|
|
76
|
+
((-x/(x^4 + 1))*y^4 + 2*x^2/(x^4 + 1))*z - 1
|
|
77
|
+
sage: z * (1/z)
|
|
78
|
+
1
|
|
79
|
+
|
|
80
|
+
We drill down the tower of function fields::
|
|
81
|
+
|
|
82
|
+
sage: M.base_field()
|
|
83
|
+
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
84
|
+
sage: M.base_field().base_field()
|
|
85
|
+
Rational function field in x over Rational Field
|
|
86
|
+
sage: M.base_field().base_field().constant_field()
|
|
87
|
+
Rational Field
|
|
88
|
+
sage: M.constant_base_field()
|
|
89
|
+
Rational Field
|
|
90
|
+
|
|
91
|
+
.. WARNING::
|
|
92
|
+
|
|
93
|
+
It is not checked if the polynomial used to define the function field is irreducible
|
|
94
|
+
Hence it is not guaranteed that this object really is a field!
|
|
95
|
+
This is illustrated below.
|
|
96
|
+
|
|
97
|
+
::
|
|
98
|
+
|
|
99
|
+
sage: K.<x> = FunctionField(QQ)
|
|
100
|
+
sage: R.<y> = K[]
|
|
101
|
+
sage: L.<y> = K.extension(x^2 - y^2)
|
|
102
|
+
sage: (y - x)*(y + x)
|
|
103
|
+
0
|
|
104
|
+
sage: 1/(y - x)
|
|
105
|
+
1
|
|
106
|
+
sage: y - x == 0; y + x == 0
|
|
107
|
+
False
|
|
108
|
+
False
|
|
109
|
+
"""
|
|
110
|
+
Element = FunctionFieldElement_polymod
|
|
111
|
+
|
|
112
|
+
def __init__(self, polynomial, names, category=None):
|
|
113
|
+
"""
|
|
114
|
+
Create a function field defined as an extension of another function
|
|
115
|
+
field by adjoining a root of a univariate polynomial.
|
|
116
|
+
|
|
117
|
+
EXAMPLES:
|
|
118
|
+
|
|
119
|
+
We create an extension of a function field::
|
|
120
|
+
|
|
121
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
122
|
+
sage: L = K.extension(y^5 - x^3 - 3*x + x*y); L
|
|
123
|
+
Function field in y defined by y^5 + x*y - x^3 - 3*x
|
|
124
|
+
sage: TestSuite(L).run(max_runs=512) # long time (15s)
|
|
125
|
+
|
|
126
|
+
We can set the variable name, which doesn't have to be y::
|
|
127
|
+
|
|
128
|
+
sage: L.<w> = K.extension(y^5 - x^3 - 3*x + x*y); L
|
|
129
|
+
Function field in w defined by w^5 + x*w - x^3 - 3*x
|
|
130
|
+
|
|
131
|
+
TESTS:
|
|
132
|
+
|
|
133
|
+
Test that :issue:`17033` is fixed::
|
|
134
|
+
|
|
135
|
+
sage: K.<t> = FunctionField(QQ)
|
|
136
|
+
sage: R.<x> = QQ[]
|
|
137
|
+
sage: M.<z> = K.extension(x^7 - x - t)
|
|
138
|
+
sage: M(x)
|
|
139
|
+
z
|
|
140
|
+
sage: M('z')
|
|
141
|
+
z
|
|
142
|
+
sage: M('x')
|
|
143
|
+
Traceback (most recent call last):
|
|
144
|
+
...
|
|
145
|
+
TypeError: unable to evaluate 'x' in Fraction Field of Univariate
|
|
146
|
+
Polynomial Ring in t over Rational Field
|
|
147
|
+
"""
|
|
148
|
+
from sage.rings.polynomial.polynomial_element import Polynomial
|
|
149
|
+
if polynomial.parent().ngens() > 1 or not isinstance(polynomial, Polynomial):
|
|
150
|
+
raise TypeError("polynomial must be univariate a polynomial")
|
|
151
|
+
if names is None:
|
|
152
|
+
names = (polynomial.variable_name(), )
|
|
153
|
+
elif names != polynomial.variable_name():
|
|
154
|
+
polynomial = polynomial.change_variable_name(names)
|
|
155
|
+
if polynomial.degree() <= 0:
|
|
156
|
+
raise ValueError("polynomial must have positive degree")
|
|
157
|
+
base_field = polynomial.base_ring()
|
|
158
|
+
if not isinstance(base_field, FunctionField):
|
|
159
|
+
raise TypeError("polynomial must be over a FunctionField")
|
|
160
|
+
|
|
161
|
+
self._base_field = base_field
|
|
162
|
+
self._polynomial = polynomial
|
|
163
|
+
|
|
164
|
+
FunctionField.__init__(self, base_field, names=names,
|
|
165
|
+
category=FunctionFields().or_subcategory(category))
|
|
166
|
+
|
|
167
|
+
from .place_polymod import FunctionFieldPlace_polymod
|
|
168
|
+
self._place_class = FunctionFieldPlace_polymod
|
|
169
|
+
|
|
170
|
+
self._hash = hash(polynomial)
|
|
171
|
+
self._ring = self._polynomial.parent()
|
|
172
|
+
|
|
173
|
+
self._populate_coercion_lists_(coerce_list=[base_field, self._ring])
|
|
174
|
+
self._gen = self(self._ring.gen())
|
|
175
|
+
|
|
176
|
+
def __hash__(self):
|
|
177
|
+
"""
|
|
178
|
+
Return hash of the function field.
|
|
179
|
+
|
|
180
|
+
The hash value is equal to the hash of the defining polynomial.
|
|
181
|
+
|
|
182
|
+
EXAMPLES::
|
|
183
|
+
|
|
184
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
185
|
+
sage: L = K.extension(y^5 - x^3 - 3*x + x*y)
|
|
186
|
+
sage: hash(L) == hash(L.polynomial())
|
|
187
|
+
True
|
|
188
|
+
"""
|
|
189
|
+
return self._hash
|
|
190
|
+
|
|
191
|
+
def _element_constructor_(self, x):
|
|
192
|
+
r"""
|
|
193
|
+
Make ``x`` into an element of the function field, possibly not canonically.
|
|
194
|
+
|
|
195
|
+
INPUT:
|
|
196
|
+
|
|
197
|
+
- ``x`` -- element
|
|
198
|
+
|
|
199
|
+
TESTS::
|
|
200
|
+
|
|
201
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
202
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
203
|
+
sage: L._element_constructor_(L.polynomial_ring().gen())
|
|
204
|
+
y
|
|
205
|
+
"""
|
|
206
|
+
if isinstance(x, FunctionFieldElement):
|
|
207
|
+
return self.element_class(self, self._ring(x.element()))
|
|
208
|
+
return self.element_class(self, self._ring(x))
|
|
209
|
+
|
|
210
|
+
def gen(self, n=0):
|
|
211
|
+
"""
|
|
212
|
+
Return the `n`-th generator of the function field. By default, `n` is 0; any other
|
|
213
|
+
value of `n` leads to an error. The generator is the class of `y`, if we view
|
|
214
|
+
the function field as being presented as `K[y]/(f(y))`.
|
|
215
|
+
|
|
216
|
+
EXAMPLES::
|
|
217
|
+
|
|
218
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
219
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
220
|
+
sage: L.gen()
|
|
221
|
+
y
|
|
222
|
+
sage: L.gen(1)
|
|
223
|
+
Traceback (most recent call last):
|
|
224
|
+
...
|
|
225
|
+
IndexError: there is only one generator
|
|
226
|
+
"""
|
|
227
|
+
if n != 0:
|
|
228
|
+
raise IndexError("there is only one generator")
|
|
229
|
+
return self._gen
|
|
230
|
+
|
|
231
|
+
def ngens(self):
|
|
232
|
+
"""
|
|
233
|
+
Return the number of generators of the function field over its base
|
|
234
|
+
field. This is by definition 1.
|
|
235
|
+
|
|
236
|
+
EXAMPLES::
|
|
237
|
+
|
|
238
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
239
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
240
|
+
sage: L.ngens()
|
|
241
|
+
1
|
|
242
|
+
"""
|
|
243
|
+
return 1
|
|
244
|
+
|
|
245
|
+
def _to_base_field(self, f):
|
|
246
|
+
r"""
|
|
247
|
+
Return ``f`` as an element of the :meth:`base_field`.
|
|
248
|
+
|
|
249
|
+
INPUT:
|
|
250
|
+
|
|
251
|
+
- ``f`` -- element of the function field which lies in the base field
|
|
252
|
+
|
|
253
|
+
EXAMPLES::
|
|
254
|
+
|
|
255
|
+
sage: K.<x> = FunctionField(QQ)
|
|
256
|
+
sage: R.<y> = K[]
|
|
257
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
258
|
+
sage: L._to_base_field(L(x))
|
|
259
|
+
x
|
|
260
|
+
sage: L._to_base_field(y)
|
|
261
|
+
Traceback (most recent call last):
|
|
262
|
+
...
|
|
263
|
+
ValueError: y is not an element of the base field
|
|
264
|
+
|
|
265
|
+
TESTS:
|
|
266
|
+
|
|
267
|
+
Verify that :issue:`21872` has been resolved::
|
|
268
|
+
|
|
269
|
+
sage: R.<z> = L[]
|
|
270
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
271
|
+
|
|
272
|
+
sage: M(1) in QQ
|
|
273
|
+
True
|
|
274
|
+
sage: M(y) in L
|
|
275
|
+
True
|
|
276
|
+
sage: M(x) in K
|
|
277
|
+
True
|
|
278
|
+
sage: z in K
|
|
279
|
+
False
|
|
280
|
+
"""
|
|
281
|
+
K = self.base_field()
|
|
282
|
+
if f.element().is_constant():
|
|
283
|
+
return K(f.element())
|
|
284
|
+
raise ValueError("%r is not an element of the base field" % (f,))
|
|
285
|
+
|
|
286
|
+
def _to_constant_base_field(self, f):
|
|
287
|
+
"""
|
|
288
|
+
Return ``f`` as an element of the :meth:`constant_base_field`.
|
|
289
|
+
|
|
290
|
+
INPUT:
|
|
291
|
+
|
|
292
|
+
- ``f`` -- element of the rational function field which is a
|
|
293
|
+
constant
|
|
294
|
+
|
|
295
|
+
EXAMPLES::
|
|
296
|
+
|
|
297
|
+
sage: K.<x> = FunctionField(QQ)
|
|
298
|
+
sage: R.<y> = K[]
|
|
299
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
300
|
+
sage: L._to_constant_base_field(L(1))
|
|
301
|
+
1
|
|
302
|
+
sage: L._to_constant_base_field(y)
|
|
303
|
+
Traceback (most recent call last):
|
|
304
|
+
...
|
|
305
|
+
ValueError: y is not an element of the base field
|
|
306
|
+
|
|
307
|
+
TESTS:
|
|
308
|
+
|
|
309
|
+
Verify that :issue:`21872` has been resolved::
|
|
310
|
+
|
|
311
|
+
sage: L(1) in QQ
|
|
312
|
+
True
|
|
313
|
+
sage: y in QQ
|
|
314
|
+
False
|
|
315
|
+
"""
|
|
316
|
+
return self.base_field()._to_constant_base_field(self._to_base_field(f))
|
|
317
|
+
|
|
318
|
+
def monic_integral_model(self, names=None):
|
|
319
|
+
"""
|
|
320
|
+
Return a function field isomorphic to this field but which is an
|
|
321
|
+
extension of a rational function field with defining polynomial that is
|
|
322
|
+
monic and integral over the constant base field.
|
|
323
|
+
|
|
324
|
+
INPUT:
|
|
325
|
+
|
|
326
|
+
- ``names`` -- string or tuple of up to two strings (default:
|
|
327
|
+
``None``); the name of the generator of the field, and the name of
|
|
328
|
+
the generator of the underlying rational function field (if a tuple).
|
|
329
|
+
If not given, then the names are chosen automatically.
|
|
330
|
+
|
|
331
|
+
OUTPUT:
|
|
332
|
+
|
|
333
|
+
A triple ``(F,f,t)`` where ``F`` is a function field, ``f`` is an
|
|
334
|
+
isomorphism from ``F`` to this field, and ``t`` is the inverse of
|
|
335
|
+
``f``.
|
|
336
|
+
|
|
337
|
+
EXAMPLES::
|
|
338
|
+
|
|
339
|
+
sage: K.<x> = FunctionField(QQ)
|
|
340
|
+
sage: R.<y> = K[]
|
|
341
|
+
sage: L.<y> = K.extension(x^2*y^5 - 1/x); L
|
|
342
|
+
Function field in y defined by x^2*y^5 - 1/x
|
|
343
|
+
sage: A, from_A, to_A = L.monic_integral_model('z')
|
|
344
|
+
sage: A
|
|
345
|
+
Function field in z defined by z^5 - x^12
|
|
346
|
+
sage: from_A
|
|
347
|
+
Function Field morphism:
|
|
348
|
+
From: Function field in z defined by z^5 - x^12
|
|
349
|
+
To: Function field in y defined by x^2*y^5 - 1/x
|
|
350
|
+
Defn: z |--> x^3*y
|
|
351
|
+
x |--> x
|
|
352
|
+
sage: to_A
|
|
353
|
+
Function Field morphism:
|
|
354
|
+
From: Function field in y defined by x^2*y^5 - 1/x
|
|
355
|
+
To: Function field in z defined by z^5 - x^12
|
|
356
|
+
Defn: y |--> 1/x^3*z
|
|
357
|
+
x |--> x
|
|
358
|
+
sage: to_A(y)
|
|
359
|
+
1/x^3*z
|
|
360
|
+
sage: from_A(to_A(y))
|
|
361
|
+
y
|
|
362
|
+
sage: from_A(to_A(1/y))
|
|
363
|
+
x^3*y^4
|
|
364
|
+
sage: from_A(to_A(1/y)) == 1/y
|
|
365
|
+
True
|
|
366
|
+
|
|
367
|
+
This also works for towers of function fields::
|
|
368
|
+
|
|
369
|
+
sage: R.<z> = L[]
|
|
370
|
+
sage: M.<z> = L.extension(z^2*y - 1/x)
|
|
371
|
+
sage: M.monic_integral_model()
|
|
372
|
+
(Function field in z_ defined by z_^10 - x^18,
|
|
373
|
+
Function Field morphism:
|
|
374
|
+
From: Function field in z_ defined by z_^10 - x^18
|
|
375
|
+
To: Function field in z defined by y*z^2 - 1/x
|
|
376
|
+
Defn: z_ |--> x^2*z
|
|
377
|
+
x |--> x, Function Field morphism:
|
|
378
|
+
From: Function field in z defined by y*z^2 - 1/x
|
|
379
|
+
To: Function field in z_ defined by z_^10 - x^18
|
|
380
|
+
Defn: z |--> 1/x^2*z_
|
|
381
|
+
y |--> 1/x^15*z_^8
|
|
382
|
+
x |--> x)
|
|
383
|
+
|
|
384
|
+
TESTS:
|
|
385
|
+
|
|
386
|
+
If the field is already a monic integral extension, then it is returned
|
|
387
|
+
unchanged::
|
|
388
|
+
|
|
389
|
+
sage: K.<x> = FunctionField(QQ)
|
|
390
|
+
sage: R.<y> = K[]
|
|
391
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
392
|
+
sage: L.monic_integral_model()
|
|
393
|
+
(Function field in y defined by y^2 - x,
|
|
394
|
+
Function Field endomorphism of Function field in y defined by y^2 - x
|
|
395
|
+
Defn: y |--> y
|
|
396
|
+
x |--> x, Function Field endomorphism of Function field in y defined by y^2 - x
|
|
397
|
+
Defn: y |--> y
|
|
398
|
+
x |--> x)
|
|
399
|
+
|
|
400
|
+
unless ``names`` does not match with the current names::
|
|
401
|
+
|
|
402
|
+
sage: L.monic_integral_model(names=('yy','xx'))
|
|
403
|
+
(Function field in yy defined by yy^2 - xx,
|
|
404
|
+
Function Field morphism:
|
|
405
|
+
From: Function field in yy defined by yy^2 - xx
|
|
406
|
+
To: Function field in y defined by y^2 - x
|
|
407
|
+
Defn: yy |--> y
|
|
408
|
+
xx |--> x, Function Field morphism:
|
|
409
|
+
From: Function field in y defined by y^2 - x
|
|
410
|
+
To: Function field in yy defined by yy^2 - xx
|
|
411
|
+
Defn: y |--> yy
|
|
412
|
+
x |--> xx)
|
|
413
|
+
"""
|
|
414
|
+
if names:
|
|
415
|
+
if not isinstance(names, tuple):
|
|
416
|
+
names = (names,)
|
|
417
|
+
if len(names) > 2:
|
|
418
|
+
raise ValueError("names must contain at most 2 entries")
|
|
419
|
+
|
|
420
|
+
if self.base_field() is not self.rational_function_field():
|
|
421
|
+
L, from_L, to_L = self.simple_model()
|
|
422
|
+
ret, ret_to_L, L_to_ret = L.monic_integral_model(names)
|
|
423
|
+
from_ret = ret.hom([from_L(ret_to_L(ret.gen())),
|
|
424
|
+
from_L(ret_to_L(ret.base_field().gen()))])
|
|
425
|
+
to_ret = self.hom([L_to_ret(to_L(k.gen())) for k in self._intermediate_fields(self.rational_function_field())])
|
|
426
|
+
return ret, from_ret, to_ret
|
|
427
|
+
else:
|
|
428
|
+
if self.polynomial().is_monic() and all(c.denominator().is_one() for c in self.polynomial()):
|
|
429
|
+
# self is already monic and integral
|
|
430
|
+
if names is None or names == ():
|
|
431
|
+
names = (self.variable_name(),)
|
|
432
|
+
return self.change_variable_name(names)
|
|
433
|
+
else:
|
|
434
|
+
if not names:
|
|
435
|
+
names = (self.variable_name() + "_",)
|
|
436
|
+
if len(names) == 1:
|
|
437
|
+
names = (names[0], self.rational_function_field().variable_name())
|
|
438
|
+
|
|
439
|
+
g, d = self._make_monic_integral(self.polynomial())
|
|
440
|
+
K, from_K, to_K = self.base_field().change_variable_name(names[1])
|
|
441
|
+
g = g.map_coefficients(to_K)
|
|
442
|
+
ret = K.extension(g, names=names[0])
|
|
443
|
+
from_ret = ret.hom([self.gen() * d, self.base_field().gen()])
|
|
444
|
+
to_ret = self.hom([ret.gen() / d, ret.base_field().gen()])
|
|
445
|
+
return ret, from_ret, to_ret
|
|
446
|
+
|
|
447
|
+
def _make_monic_integral(self, f):
|
|
448
|
+
"""
|
|
449
|
+
Return a monic integral polynomial `g` and an element `d` of the base
|
|
450
|
+
field such that `g(y*d)=0` where `y` is a root of `f`.
|
|
451
|
+
|
|
452
|
+
INPUT:
|
|
453
|
+
|
|
454
|
+
- ``f`` -- polynomial
|
|
455
|
+
|
|
456
|
+
EXAMPLES::
|
|
457
|
+
|
|
458
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
459
|
+
sage: L.<y> = K.extension(x^2*y^5 - 1/x)
|
|
460
|
+
sage: g, d = L._make_monic_integral(L.polynomial()); g,d
|
|
461
|
+
(y^5 - x^12, x^3)
|
|
462
|
+
sage: (y*d).is_integral()
|
|
463
|
+
True
|
|
464
|
+
sage: g.is_monic()
|
|
465
|
+
True
|
|
466
|
+
sage: g(y*d)
|
|
467
|
+
0
|
|
468
|
+
"""
|
|
469
|
+
R = f.base_ring()
|
|
470
|
+
if not isinstance(R, RationalFunctionField):
|
|
471
|
+
raise NotImplementedError
|
|
472
|
+
|
|
473
|
+
# make f monic
|
|
474
|
+
n = f.degree()
|
|
475
|
+
c = f.leading_coefficient()
|
|
476
|
+
if c != 1:
|
|
477
|
+
f = f / c
|
|
478
|
+
|
|
479
|
+
# find lcm of denominators
|
|
480
|
+
# would be good to replace this by minimal...
|
|
481
|
+
d = lcm([b.denominator() for b in f.list() if b])
|
|
482
|
+
if d != 1:
|
|
483
|
+
x = f.parent().gen()
|
|
484
|
+
g = (d**n) * f(x/d)
|
|
485
|
+
else:
|
|
486
|
+
g = f
|
|
487
|
+
return g, d
|
|
488
|
+
|
|
489
|
+
def constant_field(self):
|
|
490
|
+
"""
|
|
491
|
+
Return the algebraic closure of the constant field of the function field.
|
|
492
|
+
|
|
493
|
+
EXAMPLES::
|
|
494
|
+
|
|
495
|
+
sage: K.<x> = FunctionField(GF(5)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
496
|
+
sage: L.<y> = K.extension(Y^5 - x) # needs sage.rings.finite_rings
|
|
497
|
+
sage: L.constant_field() # needs sage.rings.finite_rings
|
|
498
|
+
Traceback (most recent call last):
|
|
499
|
+
...
|
|
500
|
+
NotImplementedError
|
|
501
|
+
"""
|
|
502
|
+
raise NotImplementedError
|
|
503
|
+
|
|
504
|
+
def constant_base_field(self):
|
|
505
|
+
"""
|
|
506
|
+
Return the base constant field of the function field.
|
|
507
|
+
|
|
508
|
+
EXAMPLES::
|
|
509
|
+
|
|
510
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
511
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
|
|
512
|
+
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
513
|
+
sage: L.constant_base_field()
|
|
514
|
+
Rational Field
|
|
515
|
+
sage: S.<z> = L[]
|
|
516
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
517
|
+
sage: M.constant_base_field()
|
|
518
|
+
Rational Field
|
|
519
|
+
"""
|
|
520
|
+
return self.base_field().constant_base_field()
|
|
521
|
+
|
|
522
|
+
@cached_method(key=lambda self, base: self.base_field() if base is None else base)
|
|
523
|
+
def degree(self, base=None):
|
|
524
|
+
"""
|
|
525
|
+
Return the degree of the function field over the function field ``base``.
|
|
526
|
+
|
|
527
|
+
INPUT:
|
|
528
|
+
|
|
529
|
+
- ``base`` -- a function field (default: ``None``), a function field
|
|
530
|
+
from which this field has been constructed as a finite extension
|
|
531
|
+
|
|
532
|
+
EXAMPLES::
|
|
533
|
+
|
|
534
|
+
sage: K.<x> = FunctionField(QQ)
|
|
535
|
+
sage: R.<y> = K[]
|
|
536
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
|
|
537
|
+
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
538
|
+
sage: L.degree()
|
|
539
|
+
5
|
|
540
|
+
sage: L.degree(L)
|
|
541
|
+
1
|
|
542
|
+
|
|
543
|
+
sage: R.<z> = L[]
|
|
544
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
545
|
+
sage: M.degree(L)
|
|
546
|
+
2
|
|
547
|
+
sage: M.degree(K)
|
|
548
|
+
10
|
|
549
|
+
|
|
550
|
+
TESTS::
|
|
551
|
+
|
|
552
|
+
sage: L.degree(M)
|
|
553
|
+
Traceback (most recent call last):
|
|
554
|
+
...
|
|
555
|
+
ValueError: base must be the rational function field itself
|
|
556
|
+
"""
|
|
557
|
+
if base is None:
|
|
558
|
+
base = self.base_field()
|
|
559
|
+
if base is self:
|
|
560
|
+
from sage.rings.integer_ring import ZZ
|
|
561
|
+
return ZZ(1)
|
|
562
|
+
return self._polynomial.degree() * self.base_field().degree(base)
|
|
563
|
+
|
|
564
|
+
def _repr_(self):
|
|
565
|
+
"""
|
|
566
|
+
Return the string representation of the function field.
|
|
567
|
+
|
|
568
|
+
EXAMPLES::
|
|
569
|
+
|
|
570
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
571
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
572
|
+
sage: L._repr_()
|
|
573
|
+
'Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x'
|
|
574
|
+
"""
|
|
575
|
+
return f"Function field in {self.variable_name()} defined by {self._polynomial}"
|
|
576
|
+
|
|
577
|
+
def _latex_(self):
|
|
578
|
+
r"""
|
|
579
|
+
Return the LaTeX representation of the function field.
|
|
580
|
+
|
|
581
|
+
EXAMPLES::
|
|
582
|
+
|
|
583
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
584
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
585
|
+
sage: latex(L)
|
|
586
|
+
\text{Function field in } y \text{ defined by } y^{5} - 2 x y + \frac{-x^{4} - 1}{x}
|
|
587
|
+
"""
|
|
588
|
+
return (fr"\text{{Function field in }} {self.variable_name()} "
|
|
589
|
+
fr"\text{{ defined by }} {self._polynomial._latex_()}")
|
|
590
|
+
|
|
591
|
+
def base_field(self):
|
|
592
|
+
"""
|
|
593
|
+
Return the base field of the function field. This function field is
|
|
594
|
+
presented as `L = K[y]/(f(y))`, and the base field is by definition the
|
|
595
|
+
field `K`.
|
|
596
|
+
|
|
597
|
+
EXAMPLES::
|
|
598
|
+
|
|
599
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
600
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
601
|
+
sage: L.base_field()
|
|
602
|
+
Rational function field in x over Rational Field
|
|
603
|
+
"""
|
|
604
|
+
return self._base_field
|
|
605
|
+
|
|
606
|
+
def random_element(self, *args, **kwds):
|
|
607
|
+
"""
|
|
608
|
+
Create a random element of the function field. Parameters are passed
|
|
609
|
+
onto the random_element method of the base_field.
|
|
610
|
+
|
|
611
|
+
EXAMPLES::
|
|
612
|
+
|
|
613
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
614
|
+
sage: L.<y> = K.extension(y^2 - (x^2 + x))
|
|
615
|
+
sage: L.random_element() # random
|
|
616
|
+
((x^2 - x + 2/3)/(x^2 + 1/3*x - 1))*y^2 + ((-1/4*x^2 + 1/2*x - 1)/(-5/2*x + 2/3))*y
|
|
617
|
+
+ (-1/2*x^2 - 4)/(-12*x^2 + 1/2*x - 1/95)
|
|
618
|
+
"""
|
|
619
|
+
return self(self._ring.random_element(degree=self.degree(), *args, **kwds))
|
|
620
|
+
|
|
621
|
+
def polynomial(self):
|
|
622
|
+
"""
|
|
623
|
+
Return the univariate polynomial that defines the function field, that
|
|
624
|
+
is, the polynomial `f(y)` so that the function field is of the form
|
|
625
|
+
`K[y]/(f(y))`.
|
|
626
|
+
|
|
627
|
+
EXAMPLES::
|
|
628
|
+
|
|
629
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
630
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
631
|
+
sage: L.polynomial()
|
|
632
|
+
y^5 - 2*x*y + (-x^4 - 1)/x
|
|
633
|
+
"""
|
|
634
|
+
return self._polynomial
|
|
635
|
+
|
|
636
|
+
def is_separable(self, base=None):
|
|
637
|
+
r"""
|
|
638
|
+
Return whether this is a separable extension of ``base``.
|
|
639
|
+
|
|
640
|
+
INPUT:
|
|
641
|
+
|
|
642
|
+
- ``base`` -- a function field from which this field has been created
|
|
643
|
+
as an extension or ``None`` (default: ``None``); if ``None``, then
|
|
644
|
+
return whether this is a separable extension over its base field.
|
|
645
|
+
|
|
646
|
+
EXAMPLES::
|
|
647
|
+
|
|
648
|
+
sage: # needs sage.rings.finite_rings
|
|
649
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
650
|
+
sage: R.<y> = K[]
|
|
651
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
652
|
+
sage: L.is_separable()
|
|
653
|
+
False
|
|
654
|
+
sage: R.<z> = L[]
|
|
655
|
+
sage: M.<z> = L.extension(z^3 - y)
|
|
656
|
+
sage: M.is_separable()
|
|
657
|
+
True
|
|
658
|
+
sage: M.is_separable(K)
|
|
659
|
+
False
|
|
660
|
+
|
|
661
|
+
sage: # needs sage.rings.finite_rings
|
|
662
|
+
sage: K.<x> = FunctionField(GF(5))
|
|
663
|
+
sage: R.<y> = K[]
|
|
664
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
665
|
+
sage: L.is_separable()
|
|
666
|
+
True
|
|
667
|
+
|
|
668
|
+
sage: # needs sage.rings.finite_rings
|
|
669
|
+
sage: K.<x> = FunctionField(GF(5))
|
|
670
|
+
sage: R.<y> = K[]
|
|
671
|
+
sage: L.<y> = K.extension(y^5 - 1)
|
|
672
|
+
sage: L.is_separable()
|
|
673
|
+
False
|
|
674
|
+
"""
|
|
675
|
+
if base is None:
|
|
676
|
+
base = self.base_field()
|
|
677
|
+
for k in self._intermediate_fields(base)[:-1]:
|
|
678
|
+
f = k.polynomial()
|
|
679
|
+
g = f.derivative()
|
|
680
|
+
if f.gcd(g).degree() != 0:
|
|
681
|
+
return False
|
|
682
|
+
return True
|
|
683
|
+
|
|
684
|
+
def polynomial_ring(self):
|
|
685
|
+
"""
|
|
686
|
+
Return the polynomial ring used to represent elements of the
|
|
687
|
+
function field. If we view the function field as being presented
|
|
688
|
+
as `K[y]/(f(y))`, then this function returns the ring `K[y]`.
|
|
689
|
+
|
|
690
|
+
EXAMPLES::
|
|
691
|
+
|
|
692
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
693
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
694
|
+
sage: L.polynomial_ring()
|
|
695
|
+
Univariate Polynomial Ring in y over Rational function field in x over Rational Field
|
|
696
|
+
"""
|
|
697
|
+
return self._ring
|
|
698
|
+
|
|
699
|
+
@cached_method(key=lambda self, base, basis, map: (self.base_field() if base is None else base, basis, map))
|
|
700
|
+
def free_module(self, base=None, basis=None, map=True):
|
|
701
|
+
"""
|
|
702
|
+
Return a vector space and isomorphisms from the field to and from the
|
|
703
|
+
vector space.
|
|
704
|
+
|
|
705
|
+
This function allows us to identify the elements of this field with
|
|
706
|
+
elements of a vector space over the base field, which is useful for
|
|
707
|
+
representation and arithmetic with orders, ideals, etc.
|
|
708
|
+
|
|
709
|
+
INPUT:
|
|
710
|
+
|
|
711
|
+
- ``base`` -- a function field (default: ``None``), the returned vector
|
|
712
|
+
space is over this subfield `R`, which defaults to the base field of this
|
|
713
|
+
function field.
|
|
714
|
+
|
|
715
|
+
- ``basis`` -- a basis for this field over the base
|
|
716
|
+
|
|
717
|
+
- ``maps`` -- boolean (default: ``True``); whether to return
|
|
718
|
+
`R`-linear maps to and from `V`
|
|
719
|
+
|
|
720
|
+
OUTPUT:
|
|
721
|
+
|
|
722
|
+
- a vector space over the base function field
|
|
723
|
+
|
|
724
|
+
- an isomorphism from the vector space to the field (if requested)
|
|
725
|
+
|
|
726
|
+
- an isomorphism from the field to the vector space (if requested)
|
|
727
|
+
|
|
728
|
+
EXAMPLES:
|
|
729
|
+
|
|
730
|
+
We define a function field::
|
|
731
|
+
|
|
732
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
733
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)); L
|
|
734
|
+
Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
735
|
+
|
|
736
|
+
We get the vector spaces, and maps back and forth::
|
|
737
|
+
|
|
738
|
+
sage: # needs sage.modules
|
|
739
|
+
sage: V, from_V, to_V = L.free_module()
|
|
740
|
+
sage: V
|
|
741
|
+
Vector space of dimension 5 over Rational function field in x over Rational Field
|
|
742
|
+
sage: from_V
|
|
743
|
+
Isomorphism:
|
|
744
|
+
From: Vector space of dimension 5 over Rational function field in x over Rational Field
|
|
745
|
+
To: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
746
|
+
sage: to_V
|
|
747
|
+
Isomorphism:
|
|
748
|
+
From: Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
749
|
+
To: Vector space of dimension 5 over Rational function field in x over Rational Field
|
|
750
|
+
|
|
751
|
+
We convert an element of the vector space back to the function field::
|
|
752
|
+
|
|
753
|
+
sage: from_V(V.1) # needs sage.modules
|
|
754
|
+
y
|
|
755
|
+
|
|
756
|
+
We define an interesting element of the function field::
|
|
757
|
+
|
|
758
|
+
sage: a = 1/L.0; a # needs sage.modules
|
|
759
|
+
(x/(x^4 + 1))*y^4 - 2*x^2/(x^4 + 1)
|
|
760
|
+
|
|
761
|
+
We convert it to the vector space, and get a vector over the base field::
|
|
762
|
+
|
|
763
|
+
sage: to_V(a) # needs sage.modules
|
|
764
|
+
(-2*x^2/(x^4 + 1), 0, 0, 0, x/(x^4 + 1))
|
|
765
|
+
|
|
766
|
+
We convert to and back, and get the same element::
|
|
767
|
+
|
|
768
|
+
sage: from_V(to_V(a)) == a # needs sage.modules
|
|
769
|
+
True
|
|
770
|
+
|
|
771
|
+
In the other direction::
|
|
772
|
+
|
|
773
|
+
sage: v = x*V.0 + (1/x)*V.1 # needs sage.modules
|
|
774
|
+
sage: to_V(from_V(v)) == v # needs sage.modules
|
|
775
|
+
True
|
|
776
|
+
|
|
777
|
+
And we show how it works over an extension of an extension field::
|
|
778
|
+
|
|
779
|
+
sage: R2.<z> = L[]; M.<z> = L.extension(z^2 - y)
|
|
780
|
+
sage: M.free_module() # needs sage.modules
|
|
781
|
+
(Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x,
|
|
782
|
+
Isomorphism:
|
|
783
|
+
From: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
784
|
+
To: Function field in z defined by z^2 - y,
|
|
785
|
+
Isomorphism:
|
|
786
|
+
From: Function field in z defined by z^2 - y
|
|
787
|
+
To: Vector space of dimension 2 over Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x)
|
|
788
|
+
|
|
789
|
+
We can also get the vector space of ``M`` over ``K``::
|
|
790
|
+
|
|
791
|
+
sage: M.free_module(K) # needs sage.modules
|
|
792
|
+
(Vector space of dimension 10 over Rational function field in x over Rational Field,
|
|
793
|
+
Isomorphism:
|
|
794
|
+
From: Vector space of dimension 10 over Rational function field in x over Rational Field
|
|
795
|
+
To: Function field in z defined by z^2 - y,
|
|
796
|
+
Isomorphism:
|
|
797
|
+
From: Function field in z defined by z^2 - y
|
|
798
|
+
To: Vector space of dimension 10 over Rational function field in x over Rational Field)
|
|
799
|
+
"""
|
|
800
|
+
if basis is not None:
|
|
801
|
+
raise NotImplementedError
|
|
802
|
+
from .maps import MapVectorSpaceToFunctionField, MapFunctionFieldToVectorSpace
|
|
803
|
+
if base is None:
|
|
804
|
+
base = self.base_field()
|
|
805
|
+
degree = self.degree(base)
|
|
806
|
+
V = base**degree
|
|
807
|
+
if not map:
|
|
808
|
+
return V
|
|
809
|
+
from_V = MapVectorSpaceToFunctionField(V, self)
|
|
810
|
+
to_V = MapFunctionFieldToVectorSpace(self, V)
|
|
811
|
+
return (V, from_V, to_V)
|
|
812
|
+
|
|
813
|
+
def maximal_order(self):
|
|
814
|
+
"""
|
|
815
|
+
Return the maximal order of the function field.
|
|
816
|
+
|
|
817
|
+
EXAMPLES::
|
|
818
|
+
|
|
819
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
820
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
821
|
+
sage: L.maximal_order()
|
|
822
|
+
Maximal order of Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
823
|
+
"""
|
|
824
|
+
from .order_polymod import FunctionFieldMaximalOrder_polymod
|
|
825
|
+
return FunctionFieldMaximalOrder_polymod(self)
|
|
826
|
+
|
|
827
|
+
def maximal_order_infinite(self):
|
|
828
|
+
"""
|
|
829
|
+
Return the maximal infinite order of the function field.
|
|
830
|
+
|
|
831
|
+
EXAMPLES::
|
|
832
|
+
|
|
833
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
834
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
835
|
+
sage: L.maximal_order_infinite()
|
|
836
|
+
Maximal infinite order of Function field in y defined by y^5 - 2*x*y + (-x^4 - 1)/x
|
|
837
|
+
|
|
838
|
+
sage: K.<x> = FunctionField(GF(2)); _.<t> = K[] # needs sage.rings.finite_rings
|
|
839
|
+
sage: F.<y> = K.extension(t^3 - x^2*(x^2 + x + 1)^2) # needs sage.rings.finite_rings
|
|
840
|
+
sage: F.maximal_order_infinite() # needs sage.rings.finite_rings
|
|
841
|
+
Maximal infinite order of Function field in y defined by y^3 + x^6 + x^4 + x^2
|
|
842
|
+
|
|
843
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
844
|
+
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings
|
|
845
|
+
sage: L.maximal_order_infinite() # needs sage.rings.finite_rings
|
|
846
|
+
Maximal infinite order of Function field in y defined by y^2 + y + (x^2 + 1)/x
|
|
847
|
+
"""
|
|
848
|
+
from .order_polymod import FunctionFieldMaximalOrderInfinite_polymod
|
|
849
|
+
return FunctionFieldMaximalOrderInfinite_polymod(self)
|
|
850
|
+
|
|
851
|
+
def different(self):
|
|
852
|
+
"""
|
|
853
|
+
Return the different of the function field.
|
|
854
|
+
|
|
855
|
+
EXAMPLES::
|
|
856
|
+
|
|
857
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
858
|
+
sage: F.<y> = K.extension(Y^3 - x^2*(x^2 + x + 1)^2) # needs sage.rings.finite_rings
|
|
859
|
+
sage: F.different() # needs sage.rings.finite_rings
|
|
860
|
+
2*Place (x, (1/(x^3 + x^2 + x))*y^2)
|
|
861
|
+
+ 2*Place (x^2 + x + 1, (1/(x^3 + x^2 + x))*y^2)
|
|
862
|
+
"""
|
|
863
|
+
O = self.maximal_order()
|
|
864
|
+
Oinf = self.maximal_order_infinite()
|
|
865
|
+
return O.different().divisor() + Oinf.different().divisor()
|
|
866
|
+
|
|
867
|
+
def equation_order(self):
|
|
868
|
+
"""
|
|
869
|
+
Return the equation order of the function field.
|
|
870
|
+
|
|
871
|
+
If we view the function field as being presented as `K[y]/(f(y))`, then
|
|
872
|
+
the order generated by the class of `y` is returned. If `f`
|
|
873
|
+
is not monic, then :meth:`_make_monic_integral` is called, and instead
|
|
874
|
+
we get the order generated by some integral multiple of a root of `f`.
|
|
875
|
+
|
|
876
|
+
EXAMPLES::
|
|
877
|
+
|
|
878
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
879
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x))
|
|
880
|
+
sage: O = L.equation_order()
|
|
881
|
+
sage: O.basis()
|
|
882
|
+
(1, x*y, x^2*y^2, x^3*y^3, x^4*y^4)
|
|
883
|
+
|
|
884
|
+
We try an example, in which the defining polynomial is not
|
|
885
|
+
monic and is not integral::
|
|
886
|
+
|
|
887
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
888
|
+
sage: L.<y> = K.extension(x^2*y^5 - 1/x); L
|
|
889
|
+
Function field in y defined by x^2*y^5 - 1/x
|
|
890
|
+
sage: O = L.equation_order()
|
|
891
|
+
sage: O.basis()
|
|
892
|
+
(1, x^3*y, x^6*y^2, x^9*y^3, x^12*y^4)
|
|
893
|
+
"""
|
|
894
|
+
d = self._make_monic_integral(self.polynomial())[1]
|
|
895
|
+
return self.order(d*self.gen(), check=False)
|
|
896
|
+
|
|
897
|
+
def hom(self, im_gens, base_morphism=None):
|
|
898
|
+
"""
|
|
899
|
+
Create a homomorphism from the function field to another function field.
|
|
900
|
+
|
|
901
|
+
INPUT:
|
|
902
|
+
|
|
903
|
+
- ``im_gens`` -- list of images of the generators of the function field
|
|
904
|
+
and of successive base rings
|
|
905
|
+
|
|
906
|
+
- ``base_morphism`` -- homomorphism of the base ring, after the
|
|
907
|
+
``im_gens`` are used. Thus if ``im_gens`` has length 2, then
|
|
908
|
+
``base_morphism`` should be a morphism from the base ring of the base
|
|
909
|
+
ring of the function field.
|
|
910
|
+
|
|
911
|
+
EXAMPLES:
|
|
912
|
+
|
|
913
|
+
We create a rational function field, and a quadratic extension of it::
|
|
914
|
+
|
|
915
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
916
|
+
sage: L.<y> = K.extension(y^2 - x^3 - 1)
|
|
917
|
+
|
|
918
|
+
We make the field automorphism that sends y to -y::
|
|
919
|
+
|
|
920
|
+
sage: f = L.hom(-y); f
|
|
921
|
+
Function Field endomorphism of Function field in y defined by y^2 - x^3 - 1
|
|
922
|
+
Defn: y |--> -y
|
|
923
|
+
|
|
924
|
+
Evaluation works::
|
|
925
|
+
|
|
926
|
+
sage: f(y*x - 1/x)
|
|
927
|
+
-x*y - 1/x
|
|
928
|
+
|
|
929
|
+
We try to define an invalid morphism::
|
|
930
|
+
|
|
931
|
+
sage: f = L.hom(y + 1)
|
|
932
|
+
Traceback (most recent call last):
|
|
933
|
+
...
|
|
934
|
+
ValueError: invalid morphism
|
|
935
|
+
|
|
936
|
+
We make a morphism of the base rational function field::
|
|
937
|
+
|
|
938
|
+
sage: phi = K.hom(x + 1); phi
|
|
939
|
+
Function Field endomorphism of Rational function field in x over Rational Field
|
|
940
|
+
Defn: x |--> x + 1
|
|
941
|
+
sage: phi(x^3 - 3)
|
|
942
|
+
x^3 + 3*x^2 + 3*x - 2
|
|
943
|
+
sage: (x+1)^3 - 3
|
|
944
|
+
x^3 + 3*x^2 + 3*x - 2
|
|
945
|
+
|
|
946
|
+
We make a morphism by specifying where the generators and the
|
|
947
|
+
base generators go::
|
|
948
|
+
|
|
949
|
+
sage: L.hom([-y, x])
|
|
950
|
+
Function Field endomorphism of Function field in y defined by y^2 - x^3 - 1
|
|
951
|
+
Defn: y |--> -y
|
|
952
|
+
x |--> x
|
|
953
|
+
|
|
954
|
+
You can also specify a morphism on the base::
|
|
955
|
+
|
|
956
|
+
sage: R1.<q> = K[]
|
|
957
|
+
sage: L1.<q> = K.extension(q^2 - (x+1)^3 - 1)
|
|
958
|
+
sage: L.hom(q, base_morphism=phi)
|
|
959
|
+
Function Field morphism:
|
|
960
|
+
From: Function field in y defined by y^2 - x^3 - 1
|
|
961
|
+
To: Function field in q defined by q^2 - x^3 - 3*x^2 - 3*x - 2
|
|
962
|
+
Defn: y |--> q
|
|
963
|
+
x |--> x + 1
|
|
964
|
+
|
|
965
|
+
We make another extension of a rational function field::
|
|
966
|
+
|
|
967
|
+
sage: K2.<t> = FunctionField(QQ); R2.<w> = K2[]
|
|
968
|
+
sage: L2.<w> = K2.extension((4*w)^2 - (t+1)^3 - 1)
|
|
969
|
+
|
|
970
|
+
We define a morphism, by giving the images of generators::
|
|
971
|
+
|
|
972
|
+
sage: f = L.hom([4*w, t + 1]); f
|
|
973
|
+
Function Field morphism:
|
|
974
|
+
From: Function field in y defined by y^2 - x^3 - 1
|
|
975
|
+
To: Function field in w defined by 16*w^2 - t^3 - 3*t^2 - 3*t - 2
|
|
976
|
+
Defn: y |--> 4*w
|
|
977
|
+
x |--> t + 1
|
|
978
|
+
|
|
979
|
+
Evaluation works, as expected::
|
|
980
|
+
|
|
981
|
+
sage: f(y+x)
|
|
982
|
+
4*w + t + 1
|
|
983
|
+
sage: f(x*y + x/(x^2+1))
|
|
984
|
+
(4*t + 4)*w + (t + 1)/(t^2 + 2*t + 2)
|
|
985
|
+
|
|
986
|
+
We make another extension of a rational function field::
|
|
987
|
+
|
|
988
|
+
sage: K3.<yy> = FunctionField(QQ); R3.<xx> = K3[]
|
|
989
|
+
sage: L3.<xx> = K3.extension(yy^2 - xx^3 - 1)
|
|
990
|
+
|
|
991
|
+
This is the function field L with the generators exchanged. We define a morphism to L::
|
|
992
|
+
|
|
993
|
+
sage: g = L3.hom([x,y]); g
|
|
994
|
+
Function Field morphism:
|
|
995
|
+
From: Function field in xx defined by -xx^3 + yy^2 - 1
|
|
996
|
+
To: Function field in y defined by y^2 - x^3 - 1
|
|
997
|
+
Defn: xx |--> x
|
|
998
|
+
yy |--> y
|
|
999
|
+
"""
|
|
1000
|
+
if not isinstance(im_gens, (list, tuple)):
|
|
1001
|
+
im_gens = [im_gens]
|
|
1002
|
+
if len(im_gens) == 0:
|
|
1003
|
+
raise ValueError("no images specified")
|
|
1004
|
+
|
|
1005
|
+
if len(im_gens) > 1:
|
|
1006
|
+
base_morphism = self.base_field().hom(im_gens[1:], base_morphism)
|
|
1007
|
+
|
|
1008
|
+
# the codomain of this morphism is the field containing all the im_gens
|
|
1009
|
+
codomain = im_gens[0].parent()
|
|
1010
|
+
if base_morphism is not None:
|
|
1011
|
+
from sage.categories.pushout import pushout
|
|
1012
|
+
codomain = pushout(codomain, base_morphism.codomain())
|
|
1013
|
+
|
|
1014
|
+
from .maps import FunctionFieldMorphism_polymod
|
|
1015
|
+
return FunctionFieldMorphism_polymod(self.Hom(codomain), im_gens[0], base_morphism)
|
|
1016
|
+
|
|
1017
|
+
@cached_method
|
|
1018
|
+
def genus(self):
|
|
1019
|
+
"""
|
|
1020
|
+
Return the genus of the function field.
|
|
1021
|
+
|
|
1022
|
+
For now, the genus is computed using Singular.
|
|
1023
|
+
|
|
1024
|
+
EXAMPLES::
|
|
1025
|
+
|
|
1026
|
+
sage: K.<x> = FunctionField(QQ); R.<y> = K[]
|
|
1027
|
+
sage: L.<y> = K.extension(y^3 - (x^3 + 2*x*y + 1/x))
|
|
1028
|
+
sage: L.genus()
|
|
1029
|
+
3
|
|
1030
|
+
"""
|
|
1031
|
+
# Unfortunately Singular can not compute the genus with the
|
|
1032
|
+
# polynomial_ring()._singular_ object because genus method only accepts
|
|
1033
|
+
# a ring of transcendental degree 2 over a prime field not a ring of
|
|
1034
|
+
# transcendental degree 1 over a rational function field of one variable
|
|
1035
|
+
|
|
1036
|
+
if (isinstance(self._base_field, RationalFunctionField) and
|
|
1037
|
+
self._base_field.constant_field().is_prime_field()):
|
|
1038
|
+
from sage.interfaces.singular import singular
|
|
1039
|
+
|
|
1040
|
+
# making the auxiliary ring which only has polynomials
|
|
1041
|
+
# with integral coefficients.
|
|
1042
|
+
tmpAuxRing = PolynomialRing(self._base_field.constant_field(),
|
|
1043
|
+
str(self._base_field.gen()) + ',' + str(self._ring.gen()))
|
|
1044
|
+
intMinPoly, d = self._make_monic_integral(self._polynomial)
|
|
1045
|
+
curveIdeal = tmpAuxRing.ideal(intMinPoly)
|
|
1046
|
+
|
|
1047
|
+
singular.lib('normal.lib') # loading genus method in Singular
|
|
1048
|
+
return int(curveIdeal._singular_().genus())
|
|
1049
|
+
|
|
1050
|
+
else:
|
|
1051
|
+
raise NotImplementedError("computation of genus over non-prime "
|
|
1052
|
+
"constant fields not implemented yet")
|
|
1053
|
+
|
|
1054
|
+
def _simple_model(self, name='v'):
|
|
1055
|
+
r"""
|
|
1056
|
+
Return a finite extension `N/K(x)` isomorphic to the tower of
|
|
1057
|
+
extensions `M/L/K(x)` with `K` perfect.
|
|
1058
|
+
|
|
1059
|
+
Helper method for :meth:`simple_model`.
|
|
1060
|
+
|
|
1061
|
+
INPUT:
|
|
1062
|
+
|
|
1063
|
+
- ``name`` -- string; the name of the generator of `N`
|
|
1064
|
+
|
|
1065
|
+
ALGORITHM:
|
|
1066
|
+
|
|
1067
|
+
Since `K` is perfect, the extension `M/K(x)` is simple, i.e., generated
|
|
1068
|
+
by a single element [BM1940]_. Therefore, there are only finitely many
|
|
1069
|
+
intermediate fields (Exercise 3.6.7 in [Bo2009]_).
|
|
1070
|
+
Let `a` be a generator of `M/L` and let `b` be a generator of `L/K(x)`.
|
|
1071
|
+
For some `i` the field `N_i=K(x)(a+x^ib)` is isomorphic to `M` and so
|
|
1072
|
+
it is enough to test for all terms of the form `a+x^ib` whether they
|
|
1073
|
+
generate a field of the right degree.
|
|
1074
|
+
Indeed, suppose for contradiction that for all `i` we had `N_i\neq M`.
|
|
1075
|
+
Then `N_i=N_j` for some `i,j`. Thus `(a+x^ib)-(a+x^jb)=b(x^i-x^j)\in
|
|
1076
|
+
N_j` and so `b\in N_j`. Similarly,
|
|
1077
|
+
`a+x^ib-x^{i-j}(a+x^jb)=a(1+x^{i-j})\in N_j` and so `a\in N_j`.
|
|
1078
|
+
Therefore, `N_j=M`.
|
|
1079
|
+
|
|
1080
|
+
TESTS::
|
|
1081
|
+
|
|
1082
|
+
sage: K.<x> = FunctionField(QQ)
|
|
1083
|
+
sage: R.<y> = K[]
|
|
1084
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
1085
|
+
sage: R.<z> = L[]
|
|
1086
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
1087
|
+
sage: M._simple_model()
|
|
1088
|
+
(Function field in v defined by v^4 - x,
|
|
1089
|
+
Function Field morphism:
|
|
1090
|
+
From: Function field in v defined by v^4 - x
|
|
1091
|
+
To: Function field in z defined by z^2 - y
|
|
1092
|
+
Defn: v |--> z,
|
|
1093
|
+
Function Field morphism:
|
|
1094
|
+
From: Function field in z defined by z^2 - y
|
|
1095
|
+
To: Function field in v defined by v^4 - x
|
|
1096
|
+
Defn: z |--> v
|
|
1097
|
+
y |--> v^2)
|
|
1098
|
+
|
|
1099
|
+
Check that this also works for inseparable extensions::
|
|
1100
|
+
|
|
1101
|
+
sage: # needs sage.rings.finite_rings
|
|
1102
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
1103
|
+
sage: R.<y> = K[]
|
|
1104
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
1105
|
+
sage: R.<z> = L[]
|
|
1106
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
1107
|
+
sage: M._simple_model()
|
|
1108
|
+
(Function field in v defined by v^4 + x,
|
|
1109
|
+
Function Field morphism:
|
|
1110
|
+
From: Function field in v defined by v^4 + x
|
|
1111
|
+
To: Function field in z defined by z^2 + y
|
|
1112
|
+
Defn: v |--> z,
|
|
1113
|
+
Function Field morphism:
|
|
1114
|
+
From: Function field in z defined by z^2 + y
|
|
1115
|
+
To: Function field in v defined by v^4 + x
|
|
1116
|
+
Defn: z |--> v
|
|
1117
|
+
y |--> v^2)
|
|
1118
|
+
|
|
1119
|
+
An example where the generator of the last extension does not generate
|
|
1120
|
+
the extension of the rational function field::
|
|
1121
|
+
|
|
1122
|
+
sage: # needs sage.rings.finite_rings
|
|
1123
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
1124
|
+
sage: R.<y> = K[]
|
|
1125
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
1126
|
+
sage: R.<z> = L[]
|
|
1127
|
+
sage: M.<z> = L.extension(z^3 - 1)
|
|
1128
|
+
sage: M._simple_model()
|
|
1129
|
+
(Function field in v defined by v^6 + x*v^4 + x^2*v^2 + x^3 + 1,
|
|
1130
|
+
Function Field morphism:
|
|
1131
|
+
From: Function field in v defined by v^6 + x*v^4 + x^2*v^2 + x^3 + 1
|
|
1132
|
+
To: Function field in z defined by z^3 + 1
|
|
1133
|
+
Defn: v |--> z + y,
|
|
1134
|
+
Function Field morphism:
|
|
1135
|
+
From: Function field in z defined by z^3 + 1
|
|
1136
|
+
To: Function field in v defined by v^6 + x*v^4 + x^2*v^2 + x^3 + 1
|
|
1137
|
+
Defn: z |--> v^4 + x^2
|
|
1138
|
+
y |--> v^4 + v + x^2)
|
|
1139
|
+
"""
|
|
1140
|
+
M = self
|
|
1141
|
+
L = M.base_field()
|
|
1142
|
+
K = L.base_field()
|
|
1143
|
+
|
|
1144
|
+
assert (isinstance(K, RationalFunctionField))
|
|
1145
|
+
assert (K is not L)
|
|
1146
|
+
assert (L is not M)
|
|
1147
|
+
|
|
1148
|
+
if not K.constant_field().is_perfect():
|
|
1149
|
+
raise NotImplementedError("simple_model() only implemented over perfect constant fields")
|
|
1150
|
+
|
|
1151
|
+
x = K.gen()
|
|
1152
|
+
b = L.gen()
|
|
1153
|
+
a = M.gen()
|
|
1154
|
+
|
|
1155
|
+
# using a+x^i*b tends to lead to huge powers of x in the minimal
|
|
1156
|
+
# polynomial of the resulting field; it is better to try terms of
|
|
1157
|
+
# the form a+i*b first (but in characteristic p>0 there are only
|
|
1158
|
+
# finitely many of these)
|
|
1159
|
+
# We systematically try elements of the form a+b*factor*x^exponent
|
|
1160
|
+
factor = self.constant_base_field().zero()
|
|
1161
|
+
exponent = 0
|
|
1162
|
+
while True:
|
|
1163
|
+
v = M(a+b*factor*x**exponent)
|
|
1164
|
+
minpoly = v.matrix(K).minpoly()
|
|
1165
|
+
if minpoly.degree() == M.degree()*L.degree():
|
|
1166
|
+
break
|
|
1167
|
+
factor += 1
|
|
1168
|
+
if factor == 0:
|
|
1169
|
+
factor = self.constant_base_field().one()
|
|
1170
|
+
exponent += 1
|
|
1171
|
+
|
|
1172
|
+
N = K.extension(minpoly, names=(name,))
|
|
1173
|
+
|
|
1174
|
+
# the morphism N -> M, v |-> v
|
|
1175
|
+
N_to_M = N.hom(v)
|
|
1176
|
+
|
|
1177
|
+
# the morphism M -> N, b |-> M_b, a |-> M_a
|
|
1178
|
+
V, V_to_M, M_to_V = M.free_module(K)
|
|
1179
|
+
V, V_to_N, N_to_V = N.free_module(K)
|
|
1180
|
+
from sage.matrix.matrix_space import MatrixSpace
|
|
1181
|
+
MS = MatrixSpace(V.base_field(), V.dimension())
|
|
1182
|
+
# the power basis of v over K
|
|
1183
|
+
B = [M_to_V(v**i) for i in range(V.dimension())]
|
|
1184
|
+
B = MS(B)
|
|
1185
|
+
M_b = V_to_N(B.solve_left(M_to_V(b)))
|
|
1186
|
+
M_a = V_to_N(B.solve_left(M_to_V(a)))
|
|
1187
|
+
M_to_N = M.hom([M_a, M_b])
|
|
1188
|
+
|
|
1189
|
+
return N, N_to_M, M_to_N
|
|
1190
|
+
|
|
1191
|
+
@cached_method
|
|
1192
|
+
def simple_model(self, name=None):
|
|
1193
|
+
"""
|
|
1194
|
+
Return a function field isomorphic to this field which is a simple
|
|
1195
|
+
extension of a rational function field.
|
|
1196
|
+
|
|
1197
|
+
INPUT:
|
|
1198
|
+
|
|
1199
|
+
- ``name`` -- string (default: ``None``); the name of generator of
|
|
1200
|
+
the simple extension. If ``None``, then the name of the generator
|
|
1201
|
+
will be the same as the name of the generator of this function field.
|
|
1202
|
+
|
|
1203
|
+
OUTPUT:
|
|
1204
|
+
|
|
1205
|
+
A triple ``(F,f,t)`` where ``F`` is a field isomorphic to this field,
|
|
1206
|
+
``f`` is an isomorphism from ``F`` to this function field and ``t`` is
|
|
1207
|
+
the inverse of ``f``.
|
|
1208
|
+
|
|
1209
|
+
EXAMPLES:
|
|
1210
|
+
|
|
1211
|
+
A tower of four function fields::
|
|
1212
|
+
|
|
1213
|
+
sage: K.<x> = FunctionField(QQ); R.<z> = K[]
|
|
1214
|
+
sage: L.<z> = K.extension(z^2 - x); R.<u> = L[]
|
|
1215
|
+
sage: M.<u> = L.extension(u^2 - z); R.<v> = M[]
|
|
1216
|
+
sage: N.<v> = M.extension(v^2 - u)
|
|
1217
|
+
|
|
1218
|
+
The fields N and M as simple extensions of K::
|
|
1219
|
+
|
|
1220
|
+
sage: N.simple_model()
|
|
1221
|
+
(Function field in v defined by v^8 - x,
|
|
1222
|
+
Function Field morphism:
|
|
1223
|
+
From: Function field in v defined by v^8 - x
|
|
1224
|
+
To: Function field in v defined by v^2 - u
|
|
1225
|
+
Defn: v |--> v,
|
|
1226
|
+
Function Field morphism:
|
|
1227
|
+
From: Function field in v defined by v^2 - u
|
|
1228
|
+
To: Function field in v defined by v^8 - x
|
|
1229
|
+
Defn: v |--> v
|
|
1230
|
+
u |--> v^2
|
|
1231
|
+
z |--> v^4
|
|
1232
|
+
x |--> x)
|
|
1233
|
+
sage: M.simple_model()
|
|
1234
|
+
(Function field in u defined by u^4 - x,
|
|
1235
|
+
Function Field morphism:
|
|
1236
|
+
From: Function field in u defined by u^4 - x
|
|
1237
|
+
To: Function field in u defined by u^2 - z
|
|
1238
|
+
Defn: u |--> u,
|
|
1239
|
+
Function Field morphism:
|
|
1240
|
+
From: Function field in u defined by u^2 - z
|
|
1241
|
+
To: Function field in u defined by u^4 - x
|
|
1242
|
+
Defn: u |--> u
|
|
1243
|
+
z |--> u^2
|
|
1244
|
+
x |--> x)
|
|
1245
|
+
|
|
1246
|
+
An optional parameter ``name`` can be used to set the name of the
|
|
1247
|
+
generator of the simple extension::
|
|
1248
|
+
|
|
1249
|
+
sage: M.simple_model(name='t')
|
|
1250
|
+
(Function field in t defined by t^4 - x, Function Field morphism:
|
|
1251
|
+
From: Function field in t defined by t^4 - x
|
|
1252
|
+
To: Function field in u defined by u^2 - z
|
|
1253
|
+
Defn: t |--> u, Function Field morphism:
|
|
1254
|
+
From: Function field in u defined by u^2 - z
|
|
1255
|
+
To: Function field in t defined by t^4 - x
|
|
1256
|
+
Defn: u |--> t
|
|
1257
|
+
z |--> t^2
|
|
1258
|
+
x |--> x)
|
|
1259
|
+
|
|
1260
|
+
An example with higher degrees::
|
|
1261
|
+
|
|
1262
|
+
sage: # needs sage.rings.finite_rings
|
|
1263
|
+
sage: K.<x> = FunctionField(GF(3)); R.<y> = K[]
|
|
1264
|
+
sage: L.<y> = K.extension(y^5 - x); R.<z> = L[]
|
|
1265
|
+
sage: M.<z> = L.extension(z^3 - x)
|
|
1266
|
+
sage: M.simple_model()
|
|
1267
|
+
(Function field in z defined by z^15 + x*z^12 + x^2*z^9 + 2*x^3*z^6 + 2*x^4*z^3 + 2*x^5 + 2*x^3,
|
|
1268
|
+
Function Field morphism:
|
|
1269
|
+
From: Function field in z defined by z^15 + x*z^12 + x^2*z^9 + 2*x^3*z^6 + 2*x^4*z^3 + 2*x^5 + 2*x^3
|
|
1270
|
+
To: Function field in z defined by z^3 + 2*x
|
|
1271
|
+
Defn: z |--> z + y,
|
|
1272
|
+
Function Field morphism:
|
|
1273
|
+
From: Function field in z defined by z^3 + 2*x
|
|
1274
|
+
To: Function field in z defined by z^15 + x*z^12 + x^2*z^9 + 2*x^3*z^6 + 2*x^4*z^3 + 2*x^5 + 2*x^3
|
|
1275
|
+
Defn: z |--> 2/x*z^6 + 2*z^3 + z + 2*x
|
|
1276
|
+
y |--> 1/x*z^6 + z^3 + x
|
|
1277
|
+
x |--> x)
|
|
1278
|
+
|
|
1279
|
+
This also works for inseparable extensions::
|
|
1280
|
+
|
|
1281
|
+
sage: # needs sage.rings.finite_rings
|
|
1282
|
+
sage: K.<x> = FunctionField(GF(2)); R.<y> = K[]
|
|
1283
|
+
sage: L.<y> = K.extension(y^2 - x); R.<z> = L[]
|
|
1284
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
1285
|
+
sage: M.simple_model()
|
|
1286
|
+
(Function field in z defined by z^4 + x,
|
|
1287
|
+
Function Field morphism:
|
|
1288
|
+
From: Function field in z defined by z^4 + x
|
|
1289
|
+
To: Function field in z defined by z^2 + y
|
|
1290
|
+
Defn: z |--> z,
|
|
1291
|
+
Function Field morphism:
|
|
1292
|
+
From: Function field in z defined by z^2 + y
|
|
1293
|
+
To: Function field in z defined by z^4 + x
|
|
1294
|
+
Defn: z |--> z
|
|
1295
|
+
y |--> z^2
|
|
1296
|
+
x |--> x)
|
|
1297
|
+
"""
|
|
1298
|
+
if name is None:
|
|
1299
|
+
name = self.variable_name()
|
|
1300
|
+
|
|
1301
|
+
if isinstance(self.base_field(), RationalFunctionField):
|
|
1302
|
+
# the extension is simple already
|
|
1303
|
+
if name == self.variable_name():
|
|
1304
|
+
id = Hom(self, self).identity()
|
|
1305
|
+
return self, id, id
|
|
1306
|
+
else:
|
|
1307
|
+
ret = self.base_field().extension(self.polynomial(), names=(name,))
|
|
1308
|
+
f = ret.hom(self.gen())
|
|
1309
|
+
t = self.hom(ret.gen())
|
|
1310
|
+
return ret, f, t
|
|
1311
|
+
else:
|
|
1312
|
+
# recursively collapse the tower of fields
|
|
1313
|
+
base = self.base_field()
|
|
1314
|
+
base_, from_base_, to_base_ = base.simple_model()
|
|
1315
|
+
self_ = base_.extension(self.polynomial().map_coefficients(to_base_), names=(name,))
|
|
1316
|
+
gens_in_base_ = [to_base_(k.gen())
|
|
1317
|
+
for k in base._intermediate_fields(base.rational_function_field())]
|
|
1318
|
+
to_self_ = self.hom([self_.gen()] + gens_in_base_)
|
|
1319
|
+
from_self_ = self_.hom([self.gen(), from_base_(base_.gen())])
|
|
1320
|
+
|
|
1321
|
+
# now collapse self_/base_/K(x)
|
|
1322
|
+
ret, ret_to_self_, self__to_ret = self_._simple_model(name)
|
|
1323
|
+
ret_to_self = ret.hom(from_self_(ret_to_self_(ret.gen())))
|
|
1324
|
+
gens_in_ret = [self__to_ret(to_self_(k.gen()))
|
|
1325
|
+
for k in self._intermediate_fields(self.rational_function_field())]
|
|
1326
|
+
self_to_ret = self.hom(gens_in_ret)
|
|
1327
|
+
return ret, ret_to_self, self_to_ret
|
|
1328
|
+
|
|
1329
|
+
@cached_method
|
|
1330
|
+
def primitive_element(self):
|
|
1331
|
+
r"""
|
|
1332
|
+
Return a primitive element over the underlying rational function field.
|
|
1333
|
+
|
|
1334
|
+
If this is a finite extension of a rational function field `K(x)` with
|
|
1335
|
+
`K` perfect, then this is a simple extension of `K(x)`, i.e., there is
|
|
1336
|
+
a primitive element `y` which generates this field over `K(x)`. This
|
|
1337
|
+
method returns such an element `y`.
|
|
1338
|
+
|
|
1339
|
+
EXAMPLES::
|
|
1340
|
+
|
|
1341
|
+
sage: K.<x> = FunctionField(QQ)
|
|
1342
|
+
sage: R.<y> = K[]
|
|
1343
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
1344
|
+
sage: R.<z> = L[]
|
|
1345
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
1346
|
+
sage: R.<z> = L[]
|
|
1347
|
+
sage: N.<u> = L.extension(z^2 - x - 1)
|
|
1348
|
+
sage: N.primitive_element()
|
|
1349
|
+
u + y
|
|
1350
|
+
sage: M.primitive_element()
|
|
1351
|
+
z
|
|
1352
|
+
sage: L.primitive_element()
|
|
1353
|
+
y
|
|
1354
|
+
|
|
1355
|
+
This also works for inseparable extensions::
|
|
1356
|
+
|
|
1357
|
+
sage: # needs sage.rings.finite_rings
|
|
1358
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
1359
|
+
sage: R.<Y> = K[]
|
|
1360
|
+
sage: L.<y> = K.extension(Y^2 - x)
|
|
1361
|
+
sage: R.<Z> = L[]
|
|
1362
|
+
sage: M.<z> = L.extension(Z^2 - y)
|
|
1363
|
+
sage: M.primitive_element()
|
|
1364
|
+
z
|
|
1365
|
+
"""
|
|
1366
|
+
N, f, t = self.simple_model()
|
|
1367
|
+
return f(N.gen())
|
|
1368
|
+
|
|
1369
|
+
@cached_method
|
|
1370
|
+
def separable_model(self, names=None):
|
|
1371
|
+
r"""
|
|
1372
|
+
Return a function field isomorphic to this field which is a separable
|
|
1373
|
+
extension of a rational function field.
|
|
1374
|
+
|
|
1375
|
+
INPUT:
|
|
1376
|
+
|
|
1377
|
+
- ``names`` -- tuple of two strings or ``None`` (default: ``None``);
|
|
1378
|
+
the second entry will be used as the variable name of the rational
|
|
1379
|
+
function field, the first entry will be used as the variable name of
|
|
1380
|
+
its separable extension. If ``None``, then the variable names will be
|
|
1381
|
+
chosen automatically.
|
|
1382
|
+
|
|
1383
|
+
OUTPUT:
|
|
1384
|
+
|
|
1385
|
+
A triple ``(F,f,t)`` where ``F`` is a function field, ``f`` is an
|
|
1386
|
+
isomorphism from ``F`` to this function field, and ``t`` is the inverse
|
|
1387
|
+
of ``f``.
|
|
1388
|
+
|
|
1389
|
+
ALGORITHM:
|
|
1390
|
+
|
|
1391
|
+
Suppose that the constant base field is perfect. If this is a monic
|
|
1392
|
+
integral inseparable extension of a rational function field, then the
|
|
1393
|
+
defining polynomial is separable if we swap the variables (Proposition
|
|
1394
|
+
4.8 in Chapter VIII of [Lan2002]_.)
|
|
1395
|
+
The algorithm reduces to this case with :meth:`monic_integral_model`.
|
|
1396
|
+
|
|
1397
|
+
EXAMPLES::
|
|
1398
|
+
|
|
1399
|
+
sage: # needs sage.rings.finite_rings
|
|
1400
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
1401
|
+
sage: R.<y> = K[]
|
|
1402
|
+
sage: L.<y> = K.extension(y^2 - x^3)
|
|
1403
|
+
sage: L.separable_model(('t','w'))
|
|
1404
|
+
(Function field in t defined by t^3 + w^2,
|
|
1405
|
+
Function Field morphism:
|
|
1406
|
+
From: Function field in t defined by t^3 + w^2
|
|
1407
|
+
To: Function field in y defined by y^2 + x^3
|
|
1408
|
+
Defn: t |--> x
|
|
1409
|
+
w |--> y,
|
|
1410
|
+
Function Field morphism:
|
|
1411
|
+
From: Function field in y defined by y^2 + x^3
|
|
1412
|
+
To: Function field in t defined by t^3 + w^2
|
|
1413
|
+
Defn: y |--> w
|
|
1414
|
+
x |--> t)
|
|
1415
|
+
|
|
1416
|
+
This also works for non-integral polynomials::
|
|
1417
|
+
|
|
1418
|
+
sage: # needs sage.rings.finite_rings
|
|
1419
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
1420
|
+
sage: R.<y> = K[]
|
|
1421
|
+
sage: L.<y> = K.extension(y^2/x - x^2)
|
|
1422
|
+
sage: L.separable_model()
|
|
1423
|
+
(Function field in y_ defined by y_^3 + x_^2,
|
|
1424
|
+
Function Field morphism:
|
|
1425
|
+
From: Function field in y_ defined by y_^3 + x_^2
|
|
1426
|
+
To: Function field in y defined by 1/x*y^2 + x^2
|
|
1427
|
+
Defn: y_ |--> x
|
|
1428
|
+
x_ |--> y,
|
|
1429
|
+
Function Field morphism:
|
|
1430
|
+
From: Function field in y defined by 1/x*y^2 + x^2
|
|
1431
|
+
To: Function field in y_ defined by y_^3 + x_^2
|
|
1432
|
+
Defn: y |--> x_
|
|
1433
|
+
x |--> y_)
|
|
1434
|
+
|
|
1435
|
+
If the base field is not perfect this is only implemented in trivial cases::
|
|
1436
|
+
|
|
1437
|
+
sage: # needs sage.rings.finite_rings
|
|
1438
|
+
sage: k.<t> = FunctionField(GF(2))
|
|
1439
|
+
sage: k.is_perfect()
|
|
1440
|
+
False
|
|
1441
|
+
sage: K.<x> = FunctionField(k)
|
|
1442
|
+
sage: R.<y> = K[]
|
|
1443
|
+
sage: L.<y> = K.extension(y^3 - t)
|
|
1444
|
+
sage: L.separable_model()
|
|
1445
|
+
(Function field in y defined by y^3 + t,
|
|
1446
|
+
Function Field endomorphism of Function field in y defined by y^3 + t
|
|
1447
|
+
Defn: y |--> y
|
|
1448
|
+
x |--> x,
|
|
1449
|
+
Function Field endomorphism of Function field in y defined by y^3 + t
|
|
1450
|
+
Defn: y |--> y
|
|
1451
|
+
x |--> x)
|
|
1452
|
+
|
|
1453
|
+
Some other cases for which a separable model could be constructed are
|
|
1454
|
+
not supported yet::
|
|
1455
|
+
|
|
1456
|
+
sage: R.<y> = K[] # needs sage.rings.finite_rings
|
|
1457
|
+
sage: L.<y> = K.extension(y^2 - t) # needs sage.rings.finite_rings
|
|
1458
|
+
sage: L.separable_model() # needs sage.rings.finite_rings
|
|
1459
|
+
Traceback (most recent call last):
|
|
1460
|
+
...
|
|
1461
|
+
NotImplementedError: constructing a separable model is only implemented
|
|
1462
|
+
for function fields over a perfect constant base field
|
|
1463
|
+
|
|
1464
|
+
TESTS:
|
|
1465
|
+
|
|
1466
|
+
Check that this also works in characteristic zero::
|
|
1467
|
+
|
|
1468
|
+
sage: K.<x> = FunctionField(QQ)
|
|
1469
|
+
sage: R.<y> = K[]
|
|
1470
|
+
sage: L.<y> = K.extension(y^2 - x^3)
|
|
1471
|
+
sage: L.separable_model()
|
|
1472
|
+
(Function field in y defined by y^2 - x^3,
|
|
1473
|
+
Function Field endomorphism of Function field in y defined by y^2 - x^3
|
|
1474
|
+
Defn: y |--> y
|
|
1475
|
+
x |--> x,
|
|
1476
|
+
Function Field endomorphism of Function field in y defined by y^2 - x^3
|
|
1477
|
+
Defn: y |--> y
|
|
1478
|
+
x |--> x)
|
|
1479
|
+
|
|
1480
|
+
Check that this works for towers of inseparable extensions::
|
|
1481
|
+
|
|
1482
|
+
sage: # needs sage.rings.finite_rings
|
|
1483
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
1484
|
+
sage: R.<y> = K[]
|
|
1485
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
1486
|
+
sage: R.<z> = L[]
|
|
1487
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
1488
|
+
sage: M.separable_model()
|
|
1489
|
+
(Function field in z_ defined by z_ + x_^4,
|
|
1490
|
+
Function Field morphism:
|
|
1491
|
+
From: Function field in z_ defined by z_ + x_^4
|
|
1492
|
+
To: Function field in z defined by z^2 + y
|
|
1493
|
+
Defn: z_ |--> x
|
|
1494
|
+
x_ |--> z,
|
|
1495
|
+
Function Field morphism:
|
|
1496
|
+
From: Function field in z defined by z^2 + y
|
|
1497
|
+
To: Function field in z_ defined by z_ + x_^4
|
|
1498
|
+
Defn: z |--> x_
|
|
1499
|
+
y |--> x_^2
|
|
1500
|
+
x |--> x_^4)
|
|
1501
|
+
|
|
1502
|
+
Check that this also works if only the first extension is inseparable::
|
|
1503
|
+
|
|
1504
|
+
sage: # needs sage.rings.finite_rings
|
|
1505
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
1506
|
+
sage: R.<y> = K[]
|
|
1507
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
1508
|
+
sage: R.<z> = L[]
|
|
1509
|
+
sage: M.<z> = L.extension(z^3 - y)
|
|
1510
|
+
sage: M.separable_model()
|
|
1511
|
+
(Function field in z_ defined by z_ + x_^6,
|
|
1512
|
+
Function Field morphism:
|
|
1513
|
+
From: Function field in z_ defined by z_ + x_^6
|
|
1514
|
+
To: Function field in z defined by z^3 + y
|
|
1515
|
+
Defn: z_ |--> x
|
|
1516
|
+
x_ |--> z,
|
|
1517
|
+
Function Field morphism:
|
|
1518
|
+
From: Function field in z defined by z^3 + y
|
|
1519
|
+
To: Function field in z_ defined by z_ + x_^6
|
|
1520
|
+
Defn: z |--> x_
|
|
1521
|
+
y |--> x_^3
|
|
1522
|
+
x |--> x_^6)
|
|
1523
|
+
"""
|
|
1524
|
+
if names is None:
|
|
1525
|
+
pass
|
|
1526
|
+
elif not isinstance(names, tuple):
|
|
1527
|
+
raise TypeError("names must be a tuple consisting of two strings")
|
|
1528
|
+
elif len(names) != 2:
|
|
1529
|
+
raise ValueError("must provide exactly two variable names")
|
|
1530
|
+
|
|
1531
|
+
if self.base_ring() is not self.rational_function_field():
|
|
1532
|
+
L, from_L, to_L = self.simple_model()
|
|
1533
|
+
K, from_K, to_K = L.separable_model(names=names)
|
|
1534
|
+
f = K.hom([from_L(from_K(K.gen())), from_L(from_K(K.base_field().gen()))])
|
|
1535
|
+
t = self.hom([to_K(to_L(k.gen())) for k in self._intermediate_fields(self.rational_function_field())])
|
|
1536
|
+
return K, f, t
|
|
1537
|
+
|
|
1538
|
+
if self.polynomial().gcd(self.polynomial().derivative()).is_one():
|
|
1539
|
+
# the model is already separable
|
|
1540
|
+
if names is None:
|
|
1541
|
+
names = self.variable_name(), self.base_field().variable_name()
|
|
1542
|
+
return self.change_variable_name(names)
|
|
1543
|
+
|
|
1544
|
+
if not self.constant_base_field().is_perfect():
|
|
1545
|
+
raise NotImplementedError("constructing a separable model is only implemented for function fields over a perfect constant base field")
|
|
1546
|
+
|
|
1547
|
+
if names is None:
|
|
1548
|
+
names = (self.variable_name()+"_", self.rational_function_field().variable_name()+"_")
|
|
1549
|
+
|
|
1550
|
+
L, from_L, to_L = self.monic_integral_model()
|
|
1551
|
+
|
|
1552
|
+
if L.polynomial().gcd(L.polynomial().derivative()).is_one():
|
|
1553
|
+
# L is separable
|
|
1554
|
+
ret, ret_to_L, L_to_ret = L.change_variable_name(names)
|
|
1555
|
+
f = ret.hom([from_L(ret_to_L(ret.gen())), from_L(ret_to_L(ret.base_field().gen()))])
|
|
1556
|
+
t = self.hom([L_to_ret(to_L(self.gen())), L_to_ret(to_L(self.base_field().gen()))])
|
|
1557
|
+
return ret, f, t
|
|
1558
|
+
else:
|
|
1559
|
+
# otherwise, the polynomial of L must be separable in the other variable
|
|
1560
|
+
from .constructor import FunctionField
|
|
1561
|
+
K = FunctionField(self.constant_base_field(), names=(names[1],))
|
|
1562
|
+
# construct a field isomorphic to L on top of K
|
|
1563
|
+
|
|
1564
|
+
# turn the minpoly of K into a bivariate polynomial
|
|
1565
|
+
if names[0] == names[1]:
|
|
1566
|
+
raise ValueError("names of generators must be distinct")
|
|
1567
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
1568
|
+
R = PolynomialRing(self.constant_base_field(), names=names)
|
|
1569
|
+
S = R.remove_var(names[1])
|
|
1570
|
+
f = R(L.polynomial().change_variable_name(names[1]).map_coefficients(
|
|
1571
|
+
lambda c: c.numerator().change_variable_name(names[0]), S))
|
|
1572
|
+
f = f.polynomial(R.gen(0)).change_ring(K)
|
|
1573
|
+
f /= f.leading_coefficient()
|
|
1574
|
+
# f must be separable in the other variable (otherwise it would factor)
|
|
1575
|
+
assert f.gcd(f.derivative()).is_one()
|
|
1576
|
+
|
|
1577
|
+
ret = K.extension(f, names=(names[0],))
|
|
1578
|
+
# isomorphisms between L and ret are given by swapping generators
|
|
1579
|
+
ret_to_L = ret.hom([L(L.base_field().gen()), L.gen()])
|
|
1580
|
+
L_to_ret = L.hom([ret(K.gen()), ret.gen()])
|
|
1581
|
+
# compose with from_L and to_L to get the desired isomorphisms between self and ret
|
|
1582
|
+
f = ret.hom([from_L(ret_to_L(ret.gen())), from_L(ret_to_L(ret.base_field().gen()))])
|
|
1583
|
+
t = self.hom([L_to_ret(to_L(self.gen())), L_to_ret(to_L(self.base_field().gen()))])
|
|
1584
|
+
return ret, f, t
|
|
1585
|
+
|
|
1586
|
+
def change_variable_name(self, name):
|
|
1587
|
+
r"""
|
|
1588
|
+
Return a field isomorphic to this field with variable(s) ``name``.
|
|
1589
|
+
|
|
1590
|
+
INPUT:
|
|
1591
|
+
|
|
1592
|
+
- ``name`` -- string or tuple consisting of a strings; the names of
|
|
1593
|
+
the new variables starting with a generator of this field and going
|
|
1594
|
+
down to the rational function field
|
|
1595
|
+
|
|
1596
|
+
OUTPUT:
|
|
1597
|
+
|
|
1598
|
+
A triple ``F,f,t`` where ``F`` is a function field, ``f`` is an
|
|
1599
|
+
isomorphism from ``F`` to this field, and ``t`` is the inverse of
|
|
1600
|
+
``f``.
|
|
1601
|
+
|
|
1602
|
+
EXAMPLES::
|
|
1603
|
+
|
|
1604
|
+
sage: K.<x> = FunctionField(QQ)
|
|
1605
|
+
sage: R.<y> = K[]
|
|
1606
|
+
sage: L.<y> = K.extension(y^2 - x)
|
|
1607
|
+
sage: R.<z> = L[]
|
|
1608
|
+
sage: M.<z> = L.extension(z^2 - y)
|
|
1609
|
+
|
|
1610
|
+
sage: M.change_variable_name('zz')
|
|
1611
|
+
(Function field in zz defined by zz^2 - y,
|
|
1612
|
+
Function Field morphism:
|
|
1613
|
+
From: Function field in zz defined by zz^2 - y
|
|
1614
|
+
To: Function field in z defined by z^2 - y
|
|
1615
|
+
Defn: zz |--> z
|
|
1616
|
+
y |--> y
|
|
1617
|
+
x |--> x,
|
|
1618
|
+
Function Field morphism:
|
|
1619
|
+
From: Function field in z defined by z^2 - y
|
|
1620
|
+
To: Function field in zz defined by zz^2 - y
|
|
1621
|
+
Defn: z |--> zz
|
|
1622
|
+
y |--> y
|
|
1623
|
+
x |--> x)
|
|
1624
|
+
sage: M.change_variable_name(('zz','yy'))
|
|
1625
|
+
(Function field in zz defined by zz^2 - yy,
|
|
1626
|
+
Function Field morphism:
|
|
1627
|
+
From: Function field in zz defined by zz^2 - yy
|
|
1628
|
+
To: Function field in z defined by z^2 - y
|
|
1629
|
+
Defn: zz |--> z
|
|
1630
|
+
yy |--> y
|
|
1631
|
+
x |--> x,
|
|
1632
|
+
Function Field morphism:
|
|
1633
|
+
From: Function field in z defined by z^2 - y
|
|
1634
|
+
To: Function field in zz defined by zz^2 - yy
|
|
1635
|
+
Defn: z |--> zz
|
|
1636
|
+
y |--> yy
|
|
1637
|
+
x |--> x)
|
|
1638
|
+
sage: M.change_variable_name(('zz','yy','xx'))
|
|
1639
|
+
(Function field in zz defined by zz^2 - yy,
|
|
1640
|
+
Function Field morphism:
|
|
1641
|
+
From: Function field in zz defined by zz^2 - yy
|
|
1642
|
+
To: Function field in z defined by z^2 - y
|
|
1643
|
+
Defn: zz |--> z
|
|
1644
|
+
yy |--> y
|
|
1645
|
+
xx |--> x,
|
|
1646
|
+
Function Field morphism:
|
|
1647
|
+
From: Function field in z defined by z^2 - y
|
|
1648
|
+
To: Function field in zz defined by zz^2 - yy
|
|
1649
|
+
Defn: z |--> zz
|
|
1650
|
+
y |--> yy
|
|
1651
|
+
x |--> xx)
|
|
1652
|
+
"""
|
|
1653
|
+
if not isinstance(name, tuple):
|
|
1654
|
+
name = (name,)
|
|
1655
|
+
if len(name) == 0:
|
|
1656
|
+
raise ValueError("name must contain at least one string")
|
|
1657
|
+
elif len(name) == 1:
|
|
1658
|
+
base = self.base_field()
|
|
1659
|
+
from_base = to_base = Hom(base, base).identity()
|
|
1660
|
+
else:
|
|
1661
|
+
base, from_base, to_base = self.base_field().change_variable_name(name[1:])
|
|
1662
|
+
|
|
1663
|
+
ret = base.extension(self.polynomial().map_coefficients(to_base), names=(name[0],))
|
|
1664
|
+
f = ret.hom([k.gen() for k in self._intermediate_fields(self.rational_function_field())])
|
|
1665
|
+
t = self.hom([k.gen() for k in ret._intermediate_fields(ret.rational_function_field())])
|
|
1666
|
+
return ret, f, t
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
class FunctionField_simple(FunctionField_polymod):
|
|
1670
|
+
"""
|
|
1671
|
+
Function fields defined by irreducible and separable polynomials
|
|
1672
|
+
over rational function fields.
|
|
1673
|
+
"""
|
|
1674
|
+
@cached_method
|
|
1675
|
+
def _inversion_isomorphism(self):
|
|
1676
|
+
r"""
|
|
1677
|
+
Return an inverted function field isomorphic to ``self`` and isomorphisms
|
|
1678
|
+
between them.
|
|
1679
|
+
|
|
1680
|
+
An *inverted* function field `M` is an extension of the base rational
|
|
1681
|
+
function field `k(x)` of ``self``, and isomorphic to ``self`` by an
|
|
1682
|
+
isomorphism sending `x` to `1/x`, which we call an *inversion*
|
|
1683
|
+
isomorphism. Also the defining polynomial of the function field `M` is
|
|
1684
|
+
required to be monic and integral.
|
|
1685
|
+
|
|
1686
|
+
The inversion isomorphism is for internal use to reposition infinite
|
|
1687
|
+
places to finite places.
|
|
1688
|
+
|
|
1689
|
+
EXAMPLES::
|
|
1690
|
+
|
|
1691
|
+
sage: K.<x> = FunctionField(GF(2)); _.<t> = K[] # needs sage.rings.finite_rings
|
|
1692
|
+
sage: F.<y> = K.extension(t^3 - x^2*(x^2 + x + 1)^2) # needs sage.rings.finite_rings
|
|
1693
|
+
sage: F._inversion_isomorphism() # needs sage.rings.finite_rings
|
|
1694
|
+
(Function field in s defined by s^3 + x^16 + x^14 + x^12, Composite map:
|
|
1695
|
+
From: Function field in s defined by s^3 + x^16 + x^14 + x^12
|
|
1696
|
+
To: Function field in y defined by y^3 + x^6 + x^4 + x^2
|
|
1697
|
+
Defn: Function Field morphism:
|
|
1698
|
+
From: Function field in s defined by s^3 + x^16 + x^14 + x^12
|
|
1699
|
+
To: Function field in T defined by T^3 + (x^4 + x^2 + 1)/x^6
|
|
1700
|
+
Defn: s |--> x^6*T
|
|
1701
|
+
x |--> x
|
|
1702
|
+
then
|
|
1703
|
+
Function Field morphism:
|
|
1704
|
+
From: Function field in T defined by T^3 + (x^4 + x^2 + 1)/x^6
|
|
1705
|
+
To: Function field in y defined by y^3 + x^6 + x^4 + x^2
|
|
1706
|
+
Defn: T |--> y
|
|
1707
|
+
x |--> 1/x,
|
|
1708
|
+
Composite map:
|
|
1709
|
+
From: Function field in y defined by y^3 + x^6 + x^4 + x^2
|
|
1710
|
+
To: Function field in s defined by s^3 + x^16 + x^14 + x^12
|
|
1711
|
+
Defn: Function Field morphism:
|
|
1712
|
+
From: Function field in y defined by y^3 + x^6 + x^4 + x^2
|
|
1713
|
+
To: Function field in T defined by T^3 + (x^4 + x^2 + 1)/x^6
|
|
1714
|
+
Defn: y |--> T
|
|
1715
|
+
x |--> 1/x
|
|
1716
|
+
then
|
|
1717
|
+
Function Field morphism:
|
|
1718
|
+
From: Function field in T defined by T^3 + (x^4 + x^2 + 1)/x^6
|
|
1719
|
+
To: Function field in s defined by s^3 + x^16 + x^14 + x^12
|
|
1720
|
+
Defn: T |--> 1/x^6*s
|
|
1721
|
+
x |--> x)
|
|
1722
|
+
"""
|
|
1723
|
+
K = self.base_field()
|
|
1724
|
+
R = PolynomialRing(K, 'T')
|
|
1725
|
+
x = K.gen()
|
|
1726
|
+
xinv = 1/x
|
|
1727
|
+
|
|
1728
|
+
h = K.hom(xinv)
|
|
1729
|
+
F_poly = R([h(c) for c in self.polynomial().list()])
|
|
1730
|
+
F = K.extension(F_poly)
|
|
1731
|
+
|
|
1732
|
+
self2F = self.hom([F.gen(), xinv])
|
|
1733
|
+
F2self = F.hom([self.gen(), xinv])
|
|
1734
|
+
|
|
1735
|
+
M, M2F, F2M = F.monic_integral_model('s')
|
|
1736
|
+
|
|
1737
|
+
return M, F2self*M2F, F2M*self2F
|
|
1738
|
+
|
|
1739
|
+
def places_above(self, p):
|
|
1740
|
+
"""
|
|
1741
|
+
Return places lying above ``p``.
|
|
1742
|
+
|
|
1743
|
+
INPUT:
|
|
1744
|
+
|
|
1745
|
+
- ``p`` -- place of the base rational function field
|
|
1746
|
+
|
|
1747
|
+
EXAMPLES::
|
|
1748
|
+
|
|
1749
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
1750
|
+
sage: F.<y> = K.extension(Y^3 - x^2*(x^2 + x + 1)^2) # needs sage.rings.finite_rings
|
|
1751
|
+
sage: all(q.place_below() == p # needs sage.rings.finite_rings
|
|
1752
|
+
....: for p in K.places() for q in F.places_above(p))
|
|
1753
|
+
True
|
|
1754
|
+
|
|
1755
|
+
sage: K.<x> = FunctionField(QQ); _.<Y> = K[]
|
|
1756
|
+
sage: F.<y> = K.extension(Y^3 - x^2*(x^2 + x + 1)^2)
|
|
1757
|
+
sage: O = K.maximal_order()
|
|
1758
|
+
sage: pls = [O.ideal(x - c).place() for c in [-2, -1, 0, 1, 2]]
|
|
1759
|
+
sage: all(q.place_below() == p
|
|
1760
|
+
....: for p in pls for q in F.places_above(p))
|
|
1761
|
+
True
|
|
1762
|
+
|
|
1763
|
+
sage: # needs sage.rings.number_field sage.symbolic
|
|
1764
|
+
sage: K.<x> = FunctionField(QQbar); _.<Y> = K[]
|
|
1765
|
+
sage: F.<y> = K.extension(Y^3 - x^2*(x^2 + x + 1)^2)
|
|
1766
|
+
sage: O = K.maximal_order()
|
|
1767
|
+
sage: pls = [O.ideal(x - QQbar(sqrt(c))).place()
|
|
1768
|
+
....: for c in [-2, -1, 0, 1, 2]]
|
|
1769
|
+
sage: all(q.place_below() == p # long time (4s)
|
|
1770
|
+
....: for p in pls for q in F.places_above(p))
|
|
1771
|
+
True
|
|
1772
|
+
"""
|
|
1773
|
+
R = self.base_field()
|
|
1774
|
+
|
|
1775
|
+
if p not in R.place_set():
|
|
1776
|
+
raise TypeError("not a place of the base rational function field")
|
|
1777
|
+
|
|
1778
|
+
if p.is_infinite_place():
|
|
1779
|
+
dec = self.maximal_order_infinite().decomposition()
|
|
1780
|
+
else:
|
|
1781
|
+
dec = self.maximal_order().decomposition(p.prime_ideal())
|
|
1782
|
+
|
|
1783
|
+
return tuple([q.place() for q, deg, exp in dec])
|
|
1784
|
+
|
|
1785
|
+
def constant_field(self):
|
|
1786
|
+
"""
|
|
1787
|
+
Return the algebraic closure of the base constant field in the function
|
|
1788
|
+
field.
|
|
1789
|
+
|
|
1790
|
+
EXAMPLES::
|
|
1791
|
+
|
|
1792
|
+
sage: K.<x> = FunctionField(GF(3)); _.<y> = K[] # needs sage.rings.finite_rings
|
|
1793
|
+
sage: L.<y> = K.extension(y^5 - (x^3 + 2*x*y + 1/x)) # needs sage.rings.finite_rings
|
|
1794
|
+
sage: L.constant_field() # needs sage.rings.finite_rings
|
|
1795
|
+
Finite Field of size 3
|
|
1796
|
+
"""
|
|
1797
|
+
return self.exact_constant_field()[0]
|
|
1798
|
+
|
|
1799
|
+
def exact_constant_field(self, name='t'):
|
|
1800
|
+
"""
|
|
1801
|
+
Return the exact constant field and its embedding into the function field.
|
|
1802
|
+
|
|
1803
|
+
INPUT:
|
|
1804
|
+
|
|
1805
|
+
- ``name`` -- name (default: `t`) of the generator of the exact constant field
|
|
1806
|
+
|
|
1807
|
+
EXAMPLES::
|
|
1808
|
+
|
|
1809
|
+
sage: # needs sage.rings.finite_rings
|
|
1810
|
+
sage: K.<x> = FunctionField(GF(3)); _.<Y> = K[]
|
|
1811
|
+
sage: f = Y^2 - x*Y + x^2 + 1 # irreducible but not absolutely irreducible
|
|
1812
|
+
sage: L.<y> = K.extension(f)
|
|
1813
|
+
sage: L.genus()
|
|
1814
|
+
0
|
|
1815
|
+
sage: L.exact_constant_field()
|
|
1816
|
+
(Finite Field in t of size 3^2, Ring morphism:
|
|
1817
|
+
From: Finite Field in t of size 3^2
|
|
1818
|
+
To: Function field in y defined by y^2 + 2*x*y + x^2 + 1
|
|
1819
|
+
Defn: t |--> y + x)
|
|
1820
|
+
sage: (y+x).divisor()
|
|
1821
|
+
0
|
|
1822
|
+
"""
|
|
1823
|
+
# A basis of the full constant field is obtained from
|
|
1824
|
+
# computing a Riemann-Roch basis of zero divisor.
|
|
1825
|
+
basis = self.divisor_group().zero().basis_function_space()
|
|
1826
|
+
|
|
1827
|
+
dim = len(basis)
|
|
1828
|
+
|
|
1829
|
+
for e in basis:
|
|
1830
|
+
_min_poly = e.minimal_polynomial(name)
|
|
1831
|
+
if _min_poly.degree() == dim:
|
|
1832
|
+
break
|
|
1833
|
+
k = self.constant_base_field()
|
|
1834
|
+
R = k[name]
|
|
1835
|
+
min_poly = R([k(c) for c in _min_poly.list()])
|
|
1836
|
+
|
|
1837
|
+
k_ext = k.extension(min_poly, name)
|
|
1838
|
+
|
|
1839
|
+
if k_ext.is_prime_field():
|
|
1840
|
+
# The cover of the quotient ring k_ext is the integer ring
|
|
1841
|
+
# whose generator is 1. This is different from the generator
|
|
1842
|
+
# of k_ext.
|
|
1843
|
+
embedding = k_ext.hom([self(1)], self)
|
|
1844
|
+
else:
|
|
1845
|
+
embedding = k_ext.hom([e], self)
|
|
1846
|
+
|
|
1847
|
+
return k_ext, embedding
|
|
1848
|
+
|
|
1849
|
+
def genus(self):
|
|
1850
|
+
"""
|
|
1851
|
+
Return the genus of the function field.
|
|
1852
|
+
|
|
1853
|
+
EXAMPLES::
|
|
1854
|
+
|
|
1855
|
+
sage: # needs sage.rings.finite_rings
|
|
1856
|
+
sage: F.<a> = GF(16)
|
|
1857
|
+
sage: K.<x> = FunctionField(F); K
|
|
1858
|
+
Rational function field in x over Finite Field in a of size 2^4
|
|
1859
|
+
sage: R.<t> = PolynomialRing(K)
|
|
1860
|
+
sage: L.<y> = K.extension(t^4 + t - x^5)
|
|
1861
|
+
sage: L.genus()
|
|
1862
|
+
6
|
|
1863
|
+
|
|
1864
|
+
sage: # needs sage.rings.number_field
|
|
1865
|
+
sage: R.<T> = QQ[]
|
|
1866
|
+
sage: N.<a> = NumberField(T^2 + 1)
|
|
1867
|
+
sage: K.<x> = FunctionField(N); K
|
|
1868
|
+
Rational function field in x over Number Field in a with defining polynomial T^2 + 1
|
|
1869
|
+
sage: K.genus()
|
|
1870
|
+
0
|
|
1871
|
+
sage: S.<t> = PolynomialRing(K)
|
|
1872
|
+
sage: L.<y> = K.extension(t^2 - x^3 + x)
|
|
1873
|
+
sage: L.genus()
|
|
1874
|
+
1
|
|
1875
|
+
|
|
1876
|
+
The genus is computed by the Hurwitz genus formula.
|
|
1877
|
+
"""
|
|
1878
|
+
k, _ = self.exact_constant_field()
|
|
1879
|
+
if k in NumberFields():
|
|
1880
|
+
k_degree = k.relative_degree()
|
|
1881
|
+
else:
|
|
1882
|
+
k_degree = k.degree()
|
|
1883
|
+
different_degree = self.different().degree() # must be even
|
|
1884
|
+
return Integer(different_degree // 2 - self.degree() / k_degree) + 1
|
|
1885
|
+
|
|
1886
|
+
def residue_field(self, place, name=None):
|
|
1887
|
+
"""
|
|
1888
|
+
Return the residue field associated with the place along with the maps
|
|
1889
|
+
from and to the residue field.
|
|
1890
|
+
|
|
1891
|
+
INPUT:
|
|
1892
|
+
|
|
1893
|
+
- ``place`` -- place of the function field
|
|
1894
|
+
|
|
1895
|
+
- ``name`` -- string; name of the generator of the residue field
|
|
1896
|
+
|
|
1897
|
+
The domain of the map to the residue field is the discrete valuation
|
|
1898
|
+
ring associated with the place.
|
|
1899
|
+
|
|
1900
|
+
The discrete valuation ring is defined as the ring of all elements of
|
|
1901
|
+
the function field with nonnegative valuation at the place. The maximal
|
|
1902
|
+
ideal is the set of elements of positive valuation. The residue field
|
|
1903
|
+
is then the quotient of the discrete valuation ring by its maximal
|
|
1904
|
+
ideal.
|
|
1905
|
+
|
|
1906
|
+
If an element not in the valuation ring is applied to the map, an
|
|
1907
|
+
exception :exc:`TypeError` is raised.
|
|
1908
|
+
|
|
1909
|
+
EXAMPLES::
|
|
1910
|
+
|
|
1911
|
+
sage: # needs sage.rings.finite_rings
|
|
1912
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
|
1913
|
+
sage: L.<y> = K.extension(Y^2 + Y + x + 1/x)
|
|
1914
|
+
sage: p = L.places_finite()[0]
|
|
1915
|
+
sage: R, fr_R, to_R = L.residue_field(p)
|
|
1916
|
+
sage: R
|
|
1917
|
+
Finite Field of size 2
|
|
1918
|
+
sage: f = 1 + y
|
|
1919
|
+
sage: f.valuation(p)
|
|
1920
|
+
-1
|
|
1921
|
+
sage: to_R(f)
|
|
1922
|
+
Traceback (most recent call last):
|
|
1923
|
+
...
|
|
1924
|
+
TypeError: ...
|
|
1925
|
+
sage: (1+1/f).valuation(p)
|
|
1926
|
+
0
|
|
1927
|
+
sage: to_R(1 + 1/f)
|
|
1928
|
+
1
|
|
1929
|
+
sage: [fr_R(e) for e in R]
|
|
1930
|
+
[0, 1]
|
|
1931
|
+
"""
|
|
1932
|
+
return place.residue_field(name=name)
|
|
1933
|
+
|
|
1934
|
+
def places_infinite(self, degree=1):
|
|
1935
|
+
"""
|
|
1936
|
+
Return a list of the infinite places with ``degree``.
|
|
1937
|
+
|
|
1938
|
+
INPUT:
|
|
1939
|
+
|
|
1940
|
+
- ``degree`` -- positive integer (default: `1`)
|
|
1941
|
+
|
|
1942
|
+
EXAMPLES::
|
|
1943
|
+
|
|
1944
|
+
sage: # needs sage.rings.finite_rings
|
|
1945
|
+
sage: F.<a> = GF(2)
|
|
1946
|
+
sage: K.<x> = FunctionField(F)
|
|
1947
|
+
sage: R.<t> = PolynomialRing(K)
|
|
1948
|
+
sage: L.<y> = K.extension(t^4 + t - x^5)
|
|
1949
|
+
sage: L.places_infinite(1)
|
|
1950
|
+
[Place (1/x, 1/x^4*y^3)]
|
|
1951
|
+
"""
|
|
1952
|
+
return list(self._places_infinite(degree))
|
|
1953
|
+
|
|
1954
|
+
def _places_infinite(self, degree):
|
|
1955
|
+
"""
|
|
1956
|
+
Return a generator of *infinite* places with ``degree``.
|
|
1957
|
+
|
|
1958
|
+
INPUT:
|
|
1959
|
+
|
|
1960
|
+
- ``degree`` -- positive integer
|
|
1961
|
+
|
|
1962
|
+
EXAMPLES::
|
|
1963
|
+
|
|
1964
|
+
sage: # needs sage.rings.finite_rings
|
|
1965
|
+
sage: F.<a> = GF(2)
|
|
1966
|
+
sage: K.<x> = FunctionField(F)
|
|
1967
|
+
sage: R.<t> = PolynomialRing(K)
|
|
1968
|
+
sage: L.<y> = K.extension(t^4 + t - x^5)
|
|
1969
|
+
sage: L._places_infinite(1)
|
|
1970
|
+
<generator object ...>
|
|
1971
|
+
"""
|
|
1972
|
+
Oinf = self.maximal_order_infinite()
|
|
1973
|
+
for prime, _, _ in Oinf.decomposition():
|
|
1974
|
+
place = prime.place()
|
|
1975
|
+
if place.degree() == degree:
|
|
1976
|
+
yield place
|
|
1977
|
+
|
|
1978
|
+
|
|
1979
|
+
class FunctionField_char_zero(FunctionField_simple):
|
|
1980
|
+
"""
|
|
1981
|
+
Function fields of characteristic zero.
|
|
1982
|
+
|
|
1983
|
+
EXAMPLES::
|
|
1984
|
+
|
|
1985
|
+
sage: K.<x> = FunctionField(QQ); _.<Y> = K[]
|
|
1986
|
+
sage: L.<y> = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2))
|
|
1987
|
+
sage: L
|
|
1988
|
+
Function field in y defined by y^3 + (-x^3 + 1)/(x^3 - 2)
|
|
1989
|
+
sage: L.characteristic()
|
|
1990
|
+
0
|
|
1991
|
+
"""
|
|
1992
|
+
@cached_method
|
|
1993
|
+
def higher_derivation(self):
|
|
1994
|
+
"""
|
|
1995
|
+
Return the higher derivation (also called the Hasse-Schmidt derivation)
|
|
1996
|
+
for the function field.
|
|
1997
|
+
|
|
1998
|
+
The higher derivation of the function field is uniquely determined with
|
|
1999
|
+
respect to the separating element `x` of the base rational function
|
|
2000
|
+
field `k(x)`.
|
|
2001
|
+
|
|
2002
|
+
EXAMPLES::
|
|
2003
|
+
|
|
2004
|
+
sage: K.<x> = FunctionField(QQ); _.<Y> = K[]
|
|
2005
|
+
sage: L.<y> = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2))
|
|
2006
|
+
sage: L.higher_derivation() # needs sage.modules
|
|
2007
|
+
Higher derivation map:
|
|
2008
|
+
From: Function field in y defined by y^3 + (-x^3 + 1)/(x^3 - 2)
|
|
2009
|
+
To: Function field in y defined by y^3 + (-x^3 + 1)/(x^3 - 2)
|
|
2010
|
+
"""
|
|
2011
|
+
from .derivations_polymod import FunctionFieldHigherDerivation_char_zero
|
|
2012
|
+
return FunctionFieldHigherDerivation_char_zero(self)
|
|
2013
|
+
|
|
2014
|
+
|
|
2015
|
+
class FunctionField_global(FunctionField_simple):
|
|
2016
|
+
"""
|
|
2017
|
+
Global function fields.
|
|
2018
|
+
|
|
2019
|
+
INPUT:
|
|
2020
|
+
|
|
2021
|
+
- ``polynomial`` -- monic irreducible and separable polynomial
|
|
2022
|
+
|
|
2023
|
+
- ``names`` -- name of the generator of the function field
|
|
2024
|
+
|
|
2025
|
+
EXAMPLES::
|
|
2026
|
+
|
|
2027
|
+
sage: K.<x> = FunctionField(GF(5)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2028
|
+
sage: L.<y> = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2)) # needs sage.rings.finite_rings
|
|
2029
|
+
sage: L # needs sage.rings.finite_rings
|
|
2030
|
+
Function field in y defined by y^3 + (4*x^3 + 1)/(x^3 + 3)
|
|
2031
|
+
|
|
2032
|
+
The defining equation needs not be monic::
|
|
2033
|
+
|
|
2034
|
+
sage: K.<x> = FunctionField(GF(4)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2035
|
+
sage: L.<y> = K.extension((1 - x)*Y^7 - x^3) # needs sage.rings.finite_rings
|
|
2036
|
+
sage: L.gaps() # long time (6s) # needs sage.rings.finite_rings
|
|
2037
|
+
[1, 2, 3]
|
|
2038
|
+
|
|
2039
|
+
or may define a trivial extension::
|
|
2040
|
+
|
|
2041
|
+
sage: K.<x> = FunctionField(GF(5)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2042
|
+
sage: L.<y> = K.extension(Y-1) # needs sage.rings.finite_rings
|
|
2043
|
+
sage: L.genus() # needs sage.rings.finite_rings
|
|
2044
|
+
0
|
|
2045
|
+
"""
|
|
2046
|
+
_differentials_space = LazyImport('sage.rings.function_field.differential', 'DifferentialsSpace_global')
|
|
2047
|
+
|
|
2048
|
+
def __init__(self, polynomial, names):
|
|
2049
|
+
"""
|
|
2050
|
+
Initialize.
|
|
2051
|
+
|
|
2052
|
+
TESTS::
|
|
2053
|
+
|
|
2054
|
+
sage: K.<x> = FunctionField(GF(5)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2055
|
+
sage: L.<y> = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2)) # needs sage.rings.finite_rings
|
|
2056
|
+
sage: TestSuite(L).run() # long time (7s) # needs sage.rings.finite_rings
|
|
2057
|
+
"""
|
|
2058
|
+
FunctionField_polymod.__init__(self, polynomial, names)
|
|
2059
|
+
|
|
2060
|
+
def maximal_order(self):
|
|
2061
|
+
"""
|
|
2062
|
+
Return the maximal order of the function field.
|
|
2063
|
+
|
|
2064
|
+
EXAMPLES::
|
|
2065
|
+
|
|
2066
|
+
sage: # needs sage.rings.finite_rings
|
|
2067
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
2068
|
+
sage: R.<t> = PolynomialRing(K)
|
|
2069
|
+
sage: F.<y> = K.extension(t^4 + x^12*t^2 + x^18*t + x^21 + x^18)
|
|
2070
|
+
sage: O = F.maximal_order()
|
|
2071
|
+
sage: O.basis()
|
|
2072
|
+
(1, 1/x^4*y, 1/x^11*y^2 + 1/x^2, 1/x^15*y^3 + 1/x^6*y)
|
|
2073
|
+
"""
|
|
2074
|
+
from .order_polymod import FunctionFieldMaximalOrder_global
|
|
2075
|
+
return FunctionFieldMaximalOrder_global(self)
|
|
2076
|
+
|
|
2077
|
+
@cached_method
|
|
2078
|
+
def higher_derivation(self):
|
|
2079
|
+
"""
|
|
2080
|
+
Return the higher derivation (also called the Hasse-Schmidt derivation)
|
|
2081
|
+
for the function field.
|
|
2082
|
+
|
|
2083
|
+
The higher derivation of the function field is uniquely determined with
|
|
2084
|
+
respect to the separating element `x` of the base rational function
|
|
2085
|
+
field `k(x)`.
|
|
2086
|
+
|
|
2087
|
+
EXAMPLES::
|
|
2088
|
+
|
|
2089
|
+
sage: K.<x> = FunctionField(GF(5)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2090
|
+
sage: L.<y> = K.extension(Y^3 - (x^3 - 1)/(x^3 - 2)) # needs sage.rings.finite_rings
|
|
2091
|
+
sage: L.higher_derivation() # needs sage.modules sage.rings.finite_rings
|
|
2092
|
+
Higher derivation map:
|
|
2093
|
+
From: Function field in y defined by y^3 + (4*x^3 + 1)/(x^3 + 3)
|
|
2094
|
+
To: Function field in y defined by y^3 + (4*x^3 + 1)/(x^3 + 3)
|
|
2095
|
+
"""
|
|
2096
|
+
from .derivations_polymod import FunctionFieldHigherDerivation_global
|
|
2097
|
+
return FunctionFieldHigherDerivation_global(self)
|
|
2098
|
+
|
|
2099
|
+
def get_place(self, degree):
|
|
2100
|
+
"""
|
|
2101
|
+
Return a place of ``degree``.
|
|
2102
|
+
|
|
2103
|
+
INPUT:
|
|
2104
|
+
|
|
2105
|
+
- ``degree`` -- positive integer
|
|
2106
|
+
|
|
2107
|
+
OUTPUT: a place of ``degree`` if any exists; otherwise ``None``
|
|
2108
|
+
|
|
2109
|
+
EXAMPLES::
|
|
2110
|
+
|
|
2111
|
+
sage: # needs sage.rings.finite_rings
|
|
2112
|
+
sage: F.<a> = GF(2)
|
|
2113
|
+
sage: K.<x> = FunctionField(F)
|
|
2114
|
+
sage: R.<Y> = PolynomialRing(K)
|
|
2115
|
+
sage: L.<y> = K.extension(Y^4 + Y - x^5)
|
|
2116
|
+
sage: L.get_place(1)
|
|
2117
|
+
Place (x, y)
|
|
2118
|
+
sage: L.get_place(2)
|
|
2119
|
+
Place (x, y^2 + y + 1)
|
|
2120
|
+
sage: L.get_place(3)
|
|
2121
|
+
Place (x^3 + x^2 + 1, y + x^2 + x)
|
|
2122
|
+
sage: L.get_place(4)
|
|
2123
|
+
Place (x + 1, x^5 + 1)
|
|
2124
|
+
sage: L.get_place(5)
|
|
2125
|
+
Place (x^5 + x^3 + x^2 + x + 1, y + x^4 + 1)
|
|
2126
|
+
sage: L.get_place(6)
|
|
2127
|
+
Place (x^3 + x^2 + 1, y^2 + y + x^2)
|
|
2128
|
+
sage: L.get_place(7)
|
|
2129
|
+
Place (x^7 + x + 1, y + x^6 + x^5 + x^4 + x^3 + x)
|
|
2130
|
+
sage: L.get_place(8)
|
|
2131
|
+
"""
|
|
2132
|
+
for p in self._places_finite(degree):
|
|
2133
|
+
return p
|
|
2134
|
+
|
|
2135
|
+
for p in self._places_infinite(degree):
|
|
2136
|
+
return p
|
|
2137
|
+
|
|
2138
|
+
return None
|
|
2139
|
+
|
|
2140
|
+
def places(self, degree=1):
|
|
2141
|
+
"""
|
|
2142
|
+
Return a list of the places with ``degree``.
|
|
2143
|
+
|
|
2144
|
+
INPUT:
|
|
2145
|
+
|
|
2146
|
+
- ``degree`` -- positive integer (default: `1`)
|
|
2147
|
+
|
|
2148
|
+
EXAMPLES::
|
|
2149
|
+
|
|
2150
|
+
sage: # needs sage.rings.finite_rings
|
|
2151
|
+
sage: F.<a> = GF(2)
|
|
2152
|
+
sage: K.<x> = FunctionField(F)
|
|
2153
|
+
sage: R.<t> = PolynomialRing(K)
|
|
2154
|
+
sage: L.<y> = K.extension(t^4 + t - x^5)
|
|
2155
|
+
sage: L.places(1)
|
|
2156
|
+
[Place (1/x, 1/x^4*y^3), Place (x, y), Place (x, y + 1)]
|
|
2157
|
+
"""
|
|
2158
|
+
return self.places_infinite(degree) + self.places_finite(degree)
|
|
2159
|
+
|
|
2160
|
+
def places_finite(self, degree=1):
|
|
2161
|
+
"""
|
|
2162
|
+
Return a list of the finite places with ``degree``.
|
|
2163
|
+
|
|
2164
|
+
INPUT:
|
|
2165
|
+
|
|
2166
|
+
- ``degree`` -- positive integer (default: `1`)
|
|
2167
|
+
|
|
2168
|
+
EXAMPLES::
|
|
2169
|
+
|
|
2170
|
+
sage: # needs sage.rings.finite_rings
|
|
2171
|
+
sage: F.<a> = GF(2)
|
|
2172
|
+
sage: K.<x> = FunctionField(F)
|
|
2173
|
+
sage: R.<t> = PolynomialRing(K)
|
|
2174
|
+
sage: L.<y> = K.extension(t^4 + t - x^5)
|
|
2175
|
+
sage: L.places_finite(1)
|
|
2176
|
+
[Place (x, y), Place (x, y + 1)]
|
|
2177
|
+
"""
|
|
2178
|
+
return list(self._places_finite(degree))
|
|
2179
|
+
|
|
2180
|
+
def _places_finite(self, degree):
|
|
2181
|
+
"""
|
|
2182
|
+
Return a generator of finite places with ``degree``.
|
|
2183
|
+
|
|
2184
|
+
INPUT:
|
|
2185
|
+
|
|
2186
|
+
- ``degree`` -- positive integer
|
|
2187
|
+
|
|
2188
|
+
EXAMPLES::
|
|
2189
|
+
|
|
2190
|
+
sage: # needs sage.rings.finite_rings
|
|
2191
|
+
sage: F.<a> = GF(2)
|
|
2192
|
+
sage: K.<x> = FunctionField(F)
|
|
2193
|
+
sage: R.<t> = PolynomialRing(K)
|
|
2194
|
+
sage: L.<y> = K.extension(t^4 + t - x^5)
|
|
2195
|
+
sage: L._places_finite(1)
|
|
2196
|
+
<generator object ...>
|
|
2197
|
+
"""
|
|
2198
|
+
O = self.maximal_order()
|
|
2199
|
+
K = self.base_field()
|
|
2200
|
+
|
|
2201
|
+
degree = Integer(degree)
|
|
2202
|
+
|
|
2203
|
+
for d in degree.divisors():
|
|
2204
|
+
for p in K._places_finite(degree=d):
|
|
2205
|
+
for prime, _, _ in O.decomposition(p.prime_ideal()):
|
|
2206
|
+
place = prime.place()
|
|
2207
|
+
if place.degree() == degree:
|
|
2208
|
+
yield place
|
|
2209
|
+
|
|
2210
|
+
def gaps(self):
|
|
2211
|
+
"""
|
|
2212
|
+
Return the gaps of the function field.
|
|
2213
|
+
|
|
2214
|
+
These are the gaps at the ordinary places, that is, places which are
|
|
2215
|
+
not Weierstrass places.
|
|
2216
|
+
|
|
2217
|
+
EXAMPLES::
|
|
2218
|
+
|
|
2219
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2220
|
+
sage: L.<y> = K.extension(Y^3 + x^3 * Y + x) # needs sage.rings.finite_rings
|
|
2221
|
+
sage: L.gaps() # needs sage.modules sage.rings.finite_rings
|
|
2222
|
+
[1, 2, 3]
|
|
2223
|
+
"""
|
|
2224
|
+
return self._weierstrass_places()[1]
|
|
2225
|
+
|
|
2226
|
+
def weierstrass_places(self):
|
|
2227
|
+
"""
|
|
2228
|
+
Return all Weierstrass places of the function field.
|
|
2229
|
+
|
|
2230
|
+
EXAMPLES::
|
|
2231
|
+
|
|
2232
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2233
|
+
sage: L.<y> = K.extension(Y^3 + x^3 * Y + x) # needs sage.rings.finite_rings
|
|
2234
|
+
sage: L.weierstrass_places() # needs sage.modules sage.rings.finite_rings
|
|
2235
|
+
[Place (1/x, 1/x^3*y^2 + 1/x),
|
|
2236
|
+
Place (1/x, 1/x^3*y^2 + 1/x^2*y + 1),
|
|
2237
|
+
Place (x, y),
|
|
2238
|
+
Place (x + 1, (x^3 + 1)*y + x + 1),
|
|
2239
|
+
Place (x^3 + x + 1, y + 1),
|
|
2240
|
+
Place (x^3 + x + 1, y + x^2),
|
|
2241
|
+
Place (x^3 + x + 1, y + x^2 + 1),
|
|
2242
|
+
Place (x^3 + x^2 + 1, y + x),
|
|
2243
|
+
Place (x^3 + x^2 + 1, y + x^2 + 1),
|
|
2244
|
+
Place (x^3 + x^2 + 1, y + x^2 + x + 1)]
|
|
2245
|
+
"""
|
|
2246
|
+
return self._weierstrass_places()[0].support()
|
|
2247
|
+
|
|
2248
|
+
@cached_method
|
|
2249
|
+
def _weierstrass_places(self):
|
|
2250
|
+
"""
|
|
2251
|
+
Return the Weierstrass places together with the gap sequence for
|
|
2252
|
+
ordinary places.
|
|
2253
|
+
|
|
2254
|
+
EXAMPLES::
|
|
2255
|
+
|
|
2256
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2257
|
+
sage: L.<y> = K.extension(Y^3 + x^3 * Y + x) # needs sage.rings.finite_rings
|
|
2258
|
+
sage: len(L.weierstrass_places()) # indirect doctest # needs sage.modules sage.rings.finite_rings
|
|
2259
|
+
10
|
|
2260
|
+
|
|
2261
|
+
This method implements Algorithm 30 in [Hes2002b]_.
|
|
2262
|
+
"""
|
|
2263
|
+
from sage.matrix.constructor import matrix
|
|
2264
|
+
from sage.modules.free_module_element import vector
|
|
2265
|
+
|
|
2266
|
+
W = self(self.base_field().gen()).differential().divisor()
|
|
2267
|
+
basis = W._basis()
|
|
2268
|
+
|
|
2269
|
+
if not basis:
|
|
2270
|
+
return [], []
|
|
2271
|
+
d = len(basis)
|
|
2272
|
+
|
|
2273
|
+
der = self.higher_derivation()
|
|
2274
|
+
M = matrix([basis])
|
|
2275
|
+
e = 1
|
|
2276
|
+
gaps = [1]
|
|
2277
|
+
while M.nrows() < d:
|
|
2278
|
+
row = vector([der._derive(basis[i], e) for i in range(d)])
|
|
2279
|
+
if row not in M.row_space():
|
|
2280
|
+
M = matrix(M.rows() + [row])
|
|
2281
|
+
gaps.append(e + 1)
|
|
2282
|
+
e += 1
|
|
2283
|
+
|
|
2284
|
+
# This is faster than M.determinant(). Note that Mx
|
|
2285
|
+
# is a matrix over univariate polynomial ring.
|
|
2286
|
+
Mx = matrix(M.nrows(), [c._x for c in M.list()])
|
|
2287
|
+
detM = self(Mx.determinant() % self._polynomial)
|
|
2288
|
+
|
|
2289
|
+
R = detM.divisor() + sum(gaps)*W # ramification divisor
|
|
2290
|
+
|
|
2291
|
+
return R, gaps
|
|
2292
|
+
|
|
2293
|
+
@cached_method
|
|
2294
|
+
def L_polynomial(self, name='t'):
|
|
2295
|
+
"""
|
|
2296
|
+
Return the L-polynomial of the function field.
|
|
2297
|
+
|
|
2298
|
+
INPUT:
|
|
2299
|
+
|
|
2300
|
+
- ``name`` -- (default: ``t``) name of the variable of the polynomial
|
|
2301
|
+
|
|
2302
|
+
EXAMPLES::
|
|
2303
|
+
|
|
2304
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[] # needs sage.rings.finite_rings
|
|
2305
|
+
sage: F.<y> = K.extension(Y^2 + Y + x + 1/x) # needs sage.rings.finite_rings
|
|
2306
|
+
sage: F.L_polynomial() # needs sage.rings.finite_rings
|
|
2307
|
+
2*t^2 + t + 1
|
|
2308
|
+
"""
|
|
2309
|
+
from sage.rings.integer_ring import ZZ
|
|
2310
|
+
q = self.constant_field().order()
|
|
2311
|
+
g = self.genus()
|
|
2312
|
+
|
|
2313
|
+
B = [len(self.places(i+1)) for i in range(g)]
|
|
2314
|
+
N = [sum(d * B[d-1] for d in ZZ(i+1).divisors()) for i in range(g)]
|
|
2315
|
+
S = [N[i] - q**(i+1) - 1 for i in range(g)]
|
|
2316
|
+
|
|
2317
|
+
a = [1]
|
|
2318
|
+
for i in range(1, g+1):
|
|
2319
|
+
a.append(sum(S[j] * a[i-j-1] for j in range(i)) / i)
|
|
2320
|
+
for j in range(1, g+1):
|
|
2321
|
+
a.append(q**j * a[g-j])
|
|
2322
|
+
|
|
2323
|
+
return ZZ[name](a)
|
|
2324
|
+
|
|
2325
|
+
def number_of_rational_places(self, r=1):
|
|
2326
|
+
"""
|
|
2327
|
+
Return the number of rational places of the function field whose
|
|
2328
|
+
constant field extended by degree ``r``.
|
|
2329
|
+
|
|
2330
|
+
INPUT:
|
|
2331
|
+
|
|
2332
|
+
- ``r`` -- positive integer (default: `1`)
|
|
2333
|
+
|
|
2334
|
+
EXAMPLES::
|
|
2335
|
+
|
|
2336
|
+
sage: # needs sage.rings.finite_rings
|
|
2337
|
+
sage: K.<x> = FunctionField(GF(2)); _.<Y> = K[]
|
|
2338
|
+
sage: F.<y> = K.extension(Y^2 + Y + x + 1/x)
|
|
2339
|
+
sage: F.number_of_rational_places()
|
|
2340
|
+
4
|
|
2341
|
+
sage: [F.number_of_rational_places(r) for r in [1..10]]
|
|
2342
|
+
[4, 8, 4, 16, 44, 56, 116, 288, 508, 968]
|
|
2343
|
+
"""
|
|
2344
|
+
from sage.rings.integer_ring import IntegerRing
|
|
2345
|
+
|
|
2346
|
+
q = self.constant_field().order()
|
|
2347
|
+
L = self.L_polynomial()
|
|
2348
|
+
Lp = L.derivative()
|
|
2349
|
+
|
|
2350
|
+
R = IntegerRing()[[L.parent().gen()]] # power series ring
|
|
2351
|
+
|
|
2352
|
+
f = R(Lp / L, prec=r)
|
|
2353
|
+
n = f[r-1] + q**r + 1
|
|
2354
|
+
|
|
2355
|
+
return n
|
|
2356
|
+
|
|
2357
|
+
|
|
2358
|
+
@handle_AA_and_QQbar
|
|
2359
|
+
def _singular_normal(ideal):
|
|
2360
|
+
r"""
|
|
2361
|
+
Compute the normalization of the affine algebra defined by ``ideal`` using
|
|
2362
|
+
Singular.
|
|
2363
|
+
|
|
2364
|
+
The affine algebra is the quotient algebra of a multivariate polynomial
|
|
2365
|
+
ring `R` by the ideal. The normalization is by definition the integral
|
|
2366
|
+
closure of the algebra in its total ring of fractions.
|
|
2367
|
+
|
|
2368
|
+
INPUT:
|
|
2369
|
+
|
|
2370
|
+
- ``ideal`` -- a radical ideal in a multivariate polynomial ring
|
|
2371
|
+
|
|
2372
|
+
OUTPUT:
|
|
2373
|
+
|
|
2374
|
+
a list of lists, one list for each ideal in the equidimensional
|
|
2375
|
+
decomposition of the ``ideal``, each list giving a set of generators of the
|
|
2376
|
+
normalization of each ideal as an R-module by dividing all elements of the
|
|
2377
|
+
list by the final element. Thus the list ``[x, y]`` means that `\{x/y, 1\}`
|
|
2378
|
+
is the set of generators of the normalization of `R/(x,y)`.
|
|
2379
|
+
|
|
2380
|
+
ALGORITHM:
|
|
2381
|
+
|
|
2382
|
+
Singular's implementation of the normalization algorithm described in G.-M.
|
|
2383
|
+
Greuel, S. Laplagne, F. Seelisch: Normalization of Rings (2009).
|
|
2384
|
+
|
|
2385
|
+
EXAMPLES::
|
|
2386
|
+
|
|
2387
|
+
sage: from sage.rings.function_field.function_field_polymod import _singular_normal
|
|
2388
|
+
sage: R.<x,y> = QQ[]
|
|
2389
|
+
|
|
2390
|
+
sage: f = (x^2 - y^3) * x
|
|
2391
|
+
sage: _singular_normal(ideal(f))
|
|
2392
|
+
[[x, y], [1]]
|
|
2393
|
+
|
|
2394
|
+
sage: f = y^2 - x
|
|
2395
|
+
sage: _singular_normal(ideal(f))
|
|
2396
|
+
[[1]]
|
|
2397
|
+
"""
|
|
2398
|
+
from sage.libs.singular.function import (singular_function,
|
|
2399
|
+
lib as singular_lib,
|
|
2400
|
+
get_printlevel, set_printlevel)
|
|
2401
|
+
singular_lib('normal.lib')
|
|
2402
|
+
normal = singular_function('normal')
|
|
2403
|
+
|
|
2404
|
+
# verbose unless printlevel is -1.
|
|
2405
|
+
saved_printlevel = get_printlevel()
|
|
2406
|
+
set_printlevel(-1)
|
|
2407
|
+
nor = normal(ideal)
|
|
2408
|
+
set_printlevel(saved_printlevel)
|
|
2409
|
+
|
|
2410
|
+
return nor[1]
|
|
2411
|
+
|
|
2412
|
+
|
|
2413
|
+
class FunctionField_integral(FunctionField_simple):
|
|
2414
|
+
"""
|
|
2415
|
+
Integral function fields.
|
|
2416
|
+
|
|
2417
|
+
A function field is integral if it is defined by an irreducible separable
|
|
2418
|
+
polynomial, which is integral over the maximal order of the base rational
|
|
2419
|
+
function field.
|
|
2420
|
+
"""
|
|
2421
|
+
def _maximal_order_basis(self):
|
|
2422
|
+
"""
|
|
2423
|
+
Return a basis of the maximal order of the function field.
|
|
2424
|
+
|
|
2425
|
+
EXAMPLES::
|
|
2426
|
+
|
|
2427
|
+
sage: # needs sage.rings.finite_rings
|
|
2428
|
+
sage: K.<x> = FunctionField(GF(2))
|
|
2429
|
+
sage: R.<t> = PolynomialRing(K)
|
|
2430
|
+
sage: F.<y> = K.extension(t^4 + x^12*t^2 + x^18*t + x^21 + x^18)
|
|
2431
|
+
sage: F._maximal_order_basis()
|
|
2432
|
+
[1, 1/x^4*y, 1/x^11*y^2 + 1/x^2, 1/x^15*y^3 + 1/x^6*y]
|
|
2433
|
+
|
|
2434
|
+
The basis of the maximal order *always* starts with 1. This is assumed
|
|
2435
|
+
in some algorithms.
|
|
2436
|
+
"""
|
|
2437
|
+
from sage.matrix.constructor import matrix
|
|
2438
|
+
from .hermite_form_polynomial import reversed_hermite_form
|
|
2439
|
+
|
|
2440
|
+
k = self.constant_base_field()
|
|
2441
|
+
K = self.base_field() # rational function field
|
|
2442
|
+
n = self.degree()
|
|
2443
|
+
|
|
2444
|
+
# Construct the defining polynomial of the function field as a
|
|
2445
|
+
# two-variate polynomial g in the ring k[y,x] where k is the constant
|
|
2446
|
+
# base field.
|
|
2447
|
+
S, (y, x) = PolynomialRing(k, names='y,x', order='lex').objgens()
|
|
2448
|
+
v = self.polynomial().list()
|
|
2449
|
+
g = sum([v[i].numerator().subs(x) * y**i for i in range(len(v))])
|
|
2450
|
+
|
|
2451
|
+
if self.is_global():
|
|
2452
|
+
from sage.libs.singular.function import singular_function, lib
|
|
2453
|
+
from sage.env import SAGE_EXTCODE
|
|
2454
|
+
lib(SAGE_EXTCODE + '/singular/function_field/core.lib')
|
|
2455
|
+
normalize = singular_function('core_normalize')
|
|
2456
|
+
|
|
2457
|
+
# Singular "normalP" algorithm assumes affine domain over
|
|
2458
|
+
# a prime field. So we construct gflat lifting g as in
|
|
2459
|
+
# k_prime[yy,xx,zz]/(k_poly) where k = k_prime[zz]/(k_poly)
|
|
2460
|
+
R = PolynomialRing(k.prime_subfield(), names='yy,xx,zz')
|
|
2461
|
+
gflat = R.zero()
|
|
2462
|
+
for m in g.monomials():
|
|
2463
|
+
c = g.monomial_coefficient(m).polynomial('zz')
|
|
2464
|
+
gflat += R(c) * R(m) # R(m) is a monomial in yy and xx
|
|
2465
|
+
|
|
2466
|
+
k_poly = R(k.polynomial('zz'))
|
|
2467
|
+
|
|
2468
|
+
# invoke Singular
|
|
2469
|
+
pols_in_R = normalize(R.ideal([k_poly, gflat]))
|
|
2470
|
+
|
|
2471
|
+
# reconstruct polynomials in S
|
|
2472
|
+
h = R.hom([y, x, k.gen()], S)
|
|
2473
|
+
pols_in_S = [h(f) for f in pols_in_R]
|
|
2474
|
+
else:
|
|
2475
|
+
# Call Singular. Singular's "normal" function returns a basis
|
|
2476
|
+
# of the integral closure of k(x,y)/(g) as a k[x,y]-module.
|
|
2477
|
+
pols_in_S = _singular_normal(S.ideal(g))[0]
|
|
2478
|
+
|
|
2479
|
+
# reconstruct the polynomials in the function field
|
|
2480
|
+
x = K.gen()
|
|
2481
|
+
y = self.gen()
|
|
2482
|
+
pols = []
|
|
2483
|
+
for f in pols_in_S:
|
|
2484
|
+
p = f.polynomial(S.gen(0))
|
|
2485
|
+
s = 0
|
|
2486
|
+
for i in range(p.degree()+1):
|
|
2487
|
+
s += p[i].subs(x) * y**i
|
|
2488
|
+
pols.append(s)
|
|
2489
|
+
|
|
2490
|
+
# Now if pols = [g1,g2,...gn,g0], then the g1/g0,g2/g0,...,gn/g0,
|
|
2491
|
+
# and g0/g0=1 are the module generators of the integral closure
|
|
2492
|
+
# of the equation order Sb = k[xb,yb] in its fraction field,
|
|
2493
|
+
# that is, the function field. The integral closure of k[x]
|
|
2494
|
+
# is then obtained by multiplying these generators with powers of y
|
|
2495
|
+
# as the equation order itself is an integral extension of k[x].
|
|
2496
|
+
d = ~ pols[-1]
|
|
2497
|
+
_basis = []
|
|
2498
|
+
for f in pols:
|
|
2499
|
+
b = d * f
|
|
2500
|
+
for i in range(n):
|
|
2501
|
+
_basis.append(b)
|
|
2502
|
+
b *= y
|
|
2503
|
+
|
|
2504
|
+
# Finally we reduce _basis to get a basis over k[x]. This is done of
|
|
2505
|
+
# course by Hermite normal form computation. Here we apply a trick to
|
|
2506
|
+
# get a basis that starts with 1 and is ordered in increasing
|
|
2507
|
+
# y-degrees. The trick is to use the reversed Hermite normal form.
|
|
2508
|
+
# Note that it is important that the overall denominator l lies in k[x].
|
|
2509
|
+
V, fr_V, to_V = self.free_module()
|
|
2510
|
+
basis_V = [to_V(bvec) for bvec in _basis]
|
|
2511
|
+
l = lcm([vvec.denominator() for vvec in basis_V])
|
|
2512
|
+
|
|
2513
|
+
_mat = matrix([[coeff.numerator() for coeff in l*v] for v in basis_V])
|
|
2514
|
+
reversed_hermite_form(_mat)
|
|
2515
|
+
|
|
2516
|
+
basis = [fr_V(v) / l for v in _mat if not v.is_zero()]
|
|
2517
|
+
return basis
|
|
2518
|
+
|
|
2519
|
+
@cached_method
|
|
2520
|
+
def equation_order(self):
|
|
2521
|
+
"""
|
|
2522
|
+
Return the equation order of the function field.
|
|
2523
|
+
|
|
2524
|
+
EXAMPLES::
|
|
2525
|
+
|
|
2526
|
+
sage: K.<x> = FunctionField(GF(2)); R.<t> = PolynomialRing(K) # needs sage.rings.finite_rings
|
|
2527
|
+
sage: F.<y> = K.extension(t^3 - x^2*(x^2+x+1)^2) # needs sage.rings.finite_rings
|
|
2528
|
+
sage: F.equation_order() # needs sage.rings.finite_rings
|
|
2529
|
+
Order in Function field in y defined by y^3 + x^6 + x^4 + x^2
|
|
2530
|
+
|
|
2531
|
+
sage: K.<x> = FunctionField(QQ); R.<t> = PolynomialRing(K)
|
|
2532
|
+
sage: F.<y> = K.extension(t^3 - x^2*(x^2+x+1)^2)
|
|
2533
|
+
sage: F.equation_order()
|
|
2534
|
+
Order in Function field in y defined by y^3 - x^6 - 2*x^5 - 3*x^4 - 2*x^3 - x^2
|
|
2535
|
+
"""
|
|
2536
|
+
from .order_basis import FunctionFieldOrder_basis
|
|
2537
|
+
a = self.gen()
|
|
2538
|
+
basis = [a**i for i in range(self.degree())]
|
|
2539
|
+
return FunctionFieldOrder_basis(tuple(basis))
|
|
2540
|
+
|
|
2541
|
+
@cached_method
|
|
2542
|
+
def primitive_integal_element_infinite(self):
|
|
2543
|
+
"""
|
|
2544
|
+
Return a primitive integral element over the base maximal infinite order.
|
|
2545
|
+
|
|
2546
|
+
This element is integral over the maximal infinite order of the base
|
|
2547
|
+
rational function field and the function field is a simple extension by
|
|
2548
|
+
this element over the base order.
|
|
2549
|
+
|
|
2550
|
+
EXAMPLES::
|
|
2551
|
+
|
|
2552
|
+
sage: # needs sage.rings.finite_rings
|
|
2553
|
+
sage: K.<x> = FunctionField(GF(2)); R.<t> = PolynomialRing(K)
|
|
2554
|
+
sage: F.<y> = K.extension(t^3 - x^2*(x^2+x+1)^2)
|
|
2555
|
+
sage: b = F.primitive_integal_element_infinite(); b
|
|
2556
|
+
1/x^2*y
|
|
2557
|
+
sage: b.minimal_polynomial('t')
|
|
2558
|
+
t^3 + (x^4 + x^2 + 1)/x^4
|
|
2559
|
+
"""
|
|
2560
|
+
f = self.polynomial()
|
|
2561
|
+
n = f.degree()
|
|
2562
|
+
y = self.gen()
|
|
2563
|
+
x = self.base_field().gen()
|
|
2564
|
+
|
|
2565
|
+
cf = max([(f[i].numerator().degree()/(n-i)).ceil() for i in range(n)
|
|
2566
|
+
if f[i] != 0])
|
|
2567
|
+
return y*x**(-cf)
|
|
2568
|
+
|
|
2569
|
+
@cached_method
|
|
2570
|
+
def equation_order_infinite(self):
|
|
2571
|
+
"""
|
|
2572
|
+
Return the infinite equation order of the function field.
|
|
2573
|
+
|
|
2574
|
+
This is by definition `o[b]` where `b` is the primitive integral
|
|
2575
|
+
element from :meth:`primitive_integal_element_infinite()` and `o` is
|
|
2576
|
+
the maximal infinite order of the base rational function field.
|
|
2577
|
+
|
|
2578
|
+
EXAMPLES::
|
|
2579
|
+
|
|
2580
|
+
sage: K.<x> = FunctionField(GF(2)); R.<t> = PolynomialRing(K) # needs sage.rings.finite_rings
|
|
2581
|
+
sage: F.<y> = K.extension(t^3 - x^2*(x^2+x+1)^2) # needs sage.rings.finite_rings
|
|
2582
|
+
sage: F.equation_order_infinite() # needs sage.rings.finite_rings
|
|
2583
|
+
Infinite order in Function field in y defined by y^3 + x^6 + x^4 + x^2
|
|
2584
|
+
|
|
2585
|
+
sage: K.<x> = FunctionField(QQ); R.<t> = PolynomialRing(K)
|
|
2586
|
+
sage: F.<y> = K.extension(t^3 - x^2*(x^2+x+1)^2)
|
|
2587
|
+
sage: F.equation_order_infinite()
|
|
2588
|
+
Infinite order in Function field in y defined by y^3 - x^6 - 2*x^5 - 3*x^4 - 2*x^3 - x^2
|
|
2589
|
+
"""
|
|
2590
|
+
from .order_basis import FunctionFieldOrderInfinite_basis
|
|
2591
|
+
b = self.primitive_integal_element_infinite()
|
|
2592
|
+
basis = [b**i for i in range(self.degree())]
|
|
2593
|
+
return FunctionFieldOrderInfinite_basis(tuple(basis))
|
|
2594
|
+
|
|
2595
|
+
|
|
2596
|
+
class FunctionField_char_zero_integral(FunctionField_char_zero, FunctionField_integral):
|
|
2597
|
+
"""
|
|
2598
|
+
Function fields of characteristic zero, defined by an irreducible and
|
|
2599
|
+
separable polynomial, integral over the maximal order of the base rational
|
|
2600
|
+
function field with a finite constant field.
|
|
2601
|
+
"""
|
|
2602
|
+
pass
|
|
2603
|
+
|
|
2604
|
+
|
|
2605
|
+
class FunctionField_global_integral(FunctionField_global, FunctionField_integral):
|
|
2606
|
+
"""
|
|
2607
|
+
Global function fields, defined by an irreducible and separable polynomial,
|
|
2608
|
+
integral over the maximal order of the base rational function field with a
|
|
2609
|
+
finite constant field.
|
|
2610
|
+
"""
|
|
2611
|
+
pass
|