passagemath-singular 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-singular might be problematic. Click here for more details.
- PySingular.cpython-314-x86_64-linux-musl.so +0 -0
- passagemath_singular-10.6.31rc3.dist-info/METADATA +183 -0
- passagemath_singular-10.6.31rc3.dist-info/RECORD +493 -0
- passagemath_singular-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_singular-10.6.31rc3.dist-info/top_level.txt +3 -0
- passagemath_singular.libs/libSingular-4-67059f19.4.1.so +0 -0
- passagemath_singular.libs/libcddgmp-30166d29.so.0.1.3 +0 -0
- passagemath_singular.libs/libfactory-4-9d37bcf4.4.1.so +0 -0
- passagemath_singular.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
- passagemath_singular.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_singular.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
- passagemath_singular.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_singular.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_singular.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_singular.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_singular.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
- passagemath_singular.libs/libntl-26885ca2.so.44.0.1 +0 -0
- passagemath_singular.libs/libomalloc-0-e9ff96db.9.6.so +0 -0
- passagemath_singular.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_singular.libs/libpolys-4-8bcf8e7d.4.1.so +0 -0
- passagemath_singular.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
- passagemath_singular.libs/libreadline-06542304.so.8.2 +0 -0
- passagemath_singular.libs/libsingular_resources-4-73bf7623.4.1.so +0 -0
- passagemath_singular.libs/libstdc++-5d72f927.so.6.0.33 +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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.so +0 -0
- sage/algebras/quatalg/quaternion_algebra_cython.pyx +261 -0
- sage/algebras/quatalg/quaternion_algebra_element.cpython-314-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.so +0 -0
- sage/libs/singular/option.pyx +671 -0
- sage/libs/singular/polynomial.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/singular/polynomial.pxd +39 -0
- sage/libs/singular/polynomial.pyx +661 -0
- sage/libs/singular/ring.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/singular/ring.pxd +58 -0
- sage/libs/singular/ring.pyx +893 -0
- sage/libs/singular/singular.cpython-314-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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-x86_64-linux-musl.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,2835 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-singular
|
|
2
|
+
r"""
|
|
3
|
+
Interface to Singular
|
|
4
|
+
|
|
5
|
+
Introduction
|
|
6
|
+
------------
|
|
7
|
+
|
|
8
|
+
This interface is extremely flexible, since it's exactly like
|
|
9
|
+
typing into the Singular interpreter, and anything that works there
|
|
10
|
+
should work here.
|
|
11
|
+
|
|
12
|
+
The Singular interface will only work if Singular is installed on
|
|
13
|
+
your computer; this should be the case, since Singular is included
|
|
14
|
+
with Sage. The interface offers three pieces of functionality:
|
|
15
|
+
|
|
16
|
+
#. ``singular_console()`` -- a function that dumps you
|
|
17
|
+
into an interactive command-line Singular session.
|
|
18
|
+
|
|
19
|
+
#. ``singular(expr, type='def')`` -- creation of a
|
|
20
|
+
Singular object. This provides a Pythonic interface to Singular.
|
|
21
|
+
For example, if ``f=singular(10)``, then
|
|
22
|
+
``f.factorize()`` returns the factorization of
|
|
23
|
+
`10` computed using Singular.
|
|
24
|
+
|
|
25
|
+
#. ``singular.eval(expr)`` -- evaluation of arbitrary
|
|
26
|
+
Singular expressions, with the result returned as a string.
|
|
27
|
+
|
|
28
|
+
Of course, there are polynomial rings and ideals in Sage as well
|
|
29
|
+
(often based on a C-library interface to Singular). One can convert
|
|
30
|
+
an object in the Singular interpreter interface to Sage by the
|
|
31
|
+
method ``sage()``.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
Tutorial
|
|
35
|
+
--------
|
|
36
|
+
|
|
37
|
+
EXAMPLES: First we illustrate multivariate polynomial
|
|
38
|
+
factorization::
|
|
39
|
+
|
|
40
|
+
sage: R1 = singular.ring(0, '(x,y)', 'dp')
|
|
41
|
+
sage: R1
|
|
42
|
+
polynomial ring, over a field, global ordering
|
|
43
|
+
// coefficients: QQ...
|
|
44
|
+
// number of vars : 2
|
|
45
|
+
// block 1 : ordering dp
|
|
46
|
+
// : names x y
|
|
47
|
+
// block 2 : ordering C
|
|
48
|
+
sage: f = singular('9x16 - 18x13y2 - 9x12y3 + 9x10y4 - 18x11y2 + 36x8y4 + 18x7y5 - 18x5y6 + 9x6y4 - 18x3y6 - 9x2y7 + 9y8')
|
|
49
|
+
sage: f
|
|
50
|
+
9*x^16-18*x^13*y^2-9*x^12*y^3+9*x^10*y^4-18*x^11*y^2+36*x^8*y^4+18*x^7*y^5-18*x^5*y^6+9*x^6*y^4-18*x^3*y^6-9*x^2*y^7+9*y^8
|
|
51
|
+
sage: f.parent()
|
|
52
|
+
Singular
|
|
53
|
+
|
|
54
|
+
::
|
|
55
|
+
|
|
56
|
+
sage: F = f.factorize(); F
|
|
57
|
+
[1]:
|
|
58
|
+
_[1]=9
|
|
59
|
+
_[2]=x^6-2*x^3*y^2-x^2*y^3+y^4
|
|
60
|
+
_[3]=-x^5+y^2
|
|
61
|
+
[2]:
|
|
62
|
+
1,1,2
|
|
63
|
+
|
|
64
|
+
::
|
|
65
|
+
|
|
66
|
+
sage: F[1]
|
|
67
|
+
9,
|
|
68
|
+
x^6-2*x^3*y^2-x^2*y^3+y^4,
|
|
69
|
+
-x^5+y^2
|
|
70
|
+
sage: F[1][2]
|
|
71
|
+
x^6-2*x^3*y^2-x^2*y^3+y^4
|
|
72
|
+
|
|
73
|
+
We can convert `f` and each exponent back to Sage objects
|
|
74
|
+
as well.
|
|
75
|
+
|
|
76
|
+
::
|
|
77
|
+
|
|
78
|
+
sage: g = f.sage(); g
|
|
79
|
+
9*x^16 - 18*x^13*y^2 - 9*x^12*y^3 + 9*x^10*y^4 - 18*x^11*y^2 + 36*x^8*y^4 + 18*x^7*y^5 - 18*x^5*y^6 + 9*x^6*y^4 - 18*x^3*y^6 - 9*x^2*y^7 + 9*y^8
|
|
80
|
+
sage: F[1][2].sage()
|
|
81
|
+
x^6 - 2*x^3*y^2 - x^2*y^3 + y^4
|
|
82
|
+
sage: g.parent()
|
|
83
|
+
Multivariate Polynomial Ring in x, y over Rational Field
|
|
84
|
+
|
|
85
|
+
This example illustrates polynomial GCD's::
|
|
86
|
+
|
|
87
|
+
sage: R2 = singular.ring(0, '(x,y,z)', 'lp')
|
|
88
|
+
sage: a = singular.new('3x2*(x+y)')
|
|
89
|
+
sage: b = singular.new('9x*(y2-x2)')
|
|
90
|
+
sage: g = a.gcd(b)
|
|
91
|
+
sage: g
|
|
92
|
+
x^2+x*y
|
|
93
|
+
|
|
94
|
+
This example illustrates computation of a Groebner basis::
|
|
95
|
+
|
|
96
|
+
sage: R3 = singular.ring(0, '(a,b,c,d)', 'lp')
|
|
97
|
+
sage: I = singular.ideal(['a + b + c + d', 'a*b + a*d + b*c + c*d', 'a*b*c + a*b*d + a*c*d + b*c*d', 'a*b*c*d - 1'])
|
|
98
|
+
sage: I2 = I.groebner()
|
|
99
|
+
sage: I2
|
|
100
|
+
c^2*d^6-c^2*d^2-d^4+1,
|
|
101
|
+
c^3*d^2+c^2*d^3-c-d,
|
|
102
|
+
b*d^4-b+d^5-d,
|
|
103
|
+
b*c-b*d^5+c^2*d^4+c*d-d^6-d^2,
|
|
104
|
+
b^2+2*b*d+d^2,
|
|
105
|
+
a+b+c+d
|
|
106
|
+
|
|
107
|
+
The following example is the same as the one in the Singular - Gap
|
|
108
|
+
interface documentation::
|
|
109
|
+
|
|
110
|
+
sage: R = singular.ring(0, '(x0,x1,x2)', 'lp')
|
|
111
|
+
sage: I1 = singular.ideal(['x0*x1*x2 -x0^2*x2', 'x0^2*x1*x2-x0*x1^2*x2-x0*x1*x2^2', 'x0*x1-x0*x2-x1*x2'])
|
|
112
|
+
sage: I2 = I1.groebner()
|
|
113
|
+
sage: I2
|
|
114
|
+
x1^2*x2^2,
|
|
115
|
+
x0*x2^3-x1^2*x2^2+x1*x2^3,
|
|
116
|
+
x0*x1-x0*x2-x1*x2,
|
|
117
|
+
x0^2*x2-x0*x2^2-x1*x2^2
|
|
118
|
+
sage: I2.sage()
|
|
119
|
+
Ideal (x1^2*x2^2, x0*x2^3 - x1^2*x2^2 + x1*x2^3, x0*x1 - x0*x2 - x1*x2, x0^2*x2 - x0*x2^2 - x1*x2^2) of Multivariate Polynomial Ring in x0, x1, x2 over Rational Field
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
This example illustrates moving a polynomial from one ring to
|
|
123
|
+
another. It also illustrates calling a method of an object with an
|
|
124
|
+
argument.
|
|
125
|
+
|
|
126
|
+
::
|
|
127
|
+
|
|
128
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
129
|
+
sage: f = singular('x3+y3+(x-y)*x2y2+z2')
|
|
130
|
+
sage: f
|
|
131
|
+
x^3*y^2-x^2*y^3+x^3+y^3+z^2
|
|
132
|
+
sage: R1 = singular.ring(0, '(x,y,z)', 'ds')
|
|
133
|
+
sage: f = R.fetch(f)
|
|
134
|
+
sage: f
|
|
135
|
+
z^2+x^3+y^3+x^3*y^2-x^2*y^3
|
|
136
|
+
|
|
137
|
+
We can calculate the Milnor number of `f`::
|
|
138
|
+
|
|
139
|
+
sage: _=singular.LIB('sing.lib') # assign to _ to suppress printing
|
|
140
|
+
sage: f.milnor()
|
|
141
|
+
4
|
|
142
|
+
|
|
143
|
+
The Jacobian applied twice yields the Hessian matrix of
|
|
144
|
+
`f`, with which we can compute.
|
|
145
|
+
|
|
146
|
+
::
|
|
147
|
+
|
|
148
|
+
sage: H = f.jacob().jacob()
|
|
149
|
+
sage: H
|
|
150
|
+
6*x+6*x*y^2-2*y^3,6*x^2*y-6*x*y^2, 0,
|
|
151
|
+
6*x^2*y-6*x*y^2, 6*y+2*x^3-6*x^2*y,0,
|
|
152
|
+
0, 0, 2
|
|
153
|
+
sage: H.sage()
|
|
154
|
+
[6*x + 6*x*y^2 - 2*y^3 6*x^2*y - 6*x*y^2 0]
|
|
155
|
+
[ 6*x^2*y - 6*x*y^2 6*y + 2*x^3 - 6*x^2*y 0]
|
|
156
|
+
[ 0 0 2]
|
|
157
|
+
sage: H.det() # This is a polynomial in Singular
|
|
158
|
+
72*x*y+24*x^4-72*x^3*y+72*x*y^3-24*y^4-48*x^4*y^2+64*x^3*y^3-48*x^2*y^4
|
|
159
|
+
sage: H.det().sage() # This is the corresponding polynomial in Sage
|
|
160
|
+
72*x*y + 24*x^4 - 72*x^3*y + 72*x*y^3 - 24*y^4 - 48*x^4*y^2 + 64*x^3*y^3 - 48*x^2*y^4
|
|
161
|
+
|
|
162
|
+
The 1x1 and 2x2 minors::
|
|
163
|
+
|
|
164
|
+
sage: H.minor(1)
|
|
165
|
+
2,
|
|
166
|
+
6*y+2*x^3-6*x^2*y,
|
|
167
|
+
6*x^2*y-6*x*y^2,
|
|
168
|
+
6*x^2*y-6*x*y^2,
|
|
169
|
+
6*x+6*x*y^2-2*y^3,
|
|
170
|
+
0,
|
|
171
|
+
0,
|
|
172
|
+
0,
|
|
173
|
+
0
|
|
174
|
+
sage: H.minor(2)
|
|
175
|
+
12*y+4*x^3-12*x^2*y,
|
|
176
|
+
12*x^2*y-12*x*y^2,
|
|
177
|
+
12*x^2*y-12*x*y^2,
|
|
178
|
+
12*x+12*x*y^2-4*y^3,
|
|
179
|
+
-36*x*y-12*x^4+36*x^3*y-36*x*y^3+12*y^4+24*x^4*y^2-32*x^3*y^3+24*x^2*y^4,
|
|
180
|
+
0,
|
|
181
|
+
0,
|
|
182
|
+
0,
|
|
183
|
+
0
|
|
184
|
+
|
|
185
|
+
::
|
|
186
|
+
|
|
187
|
+
sage: _=singular.eval('option(redSB)')
|
|
188
|
+
sage: H.minor(1).groebner()
|
|
189
|
+
1
|
|
190
|
+
|
|
191
|
+
Computing the Genus
|
|
192
|
+
-------------------
|
|
193
|
+
|
|
194
|
+
We compute the projective genus of ideals that define curves over
|
|
195
|
+
`\QQ`. It is *very important* to load the
|
|
196
|
+
``normal.lib`` library before calling the
|
|
197
|
+
``genus`` command, or you'll get an error message.
|
|
198
|
+
|
|
199
|
+
EXAMPLES::
|
|
200
|
+
|
|
201
|
+
sage: singular.lib('normal.lib')
|
|
202
|
+
sage: R = singular.ring(0,'(x,y)','dp')
|
|
203
|
+
sage: i2 = singular.ideal('y9 - x2*(x-1)^9 + x')
|
|
204
|
+
sage: i2.genus()
|
|
205
|
+
40
|
|
206
|
+
|
|
207
|
+
Note that the genus can be much smaller than the degree::
|
|
208
|
+
|
|
209
|
+
sage: i = singular.ideal('y9 - x2*(x-1)^9')
|
|
210
|
+
sage: i.genus()
|
|
211
|
+
0
|
|
212
|
+
|
|
213
|
+
An Important Concept
|
|
214
|
+
--------------------
|
|
215
|
+
|
|
216
|
+
The following illustrates an important concept: how Sage interacts
|
|
217
|
+
with the data being used and returned by Singular. Let's compute a
|
|
218
|
+
Groebner basis for some ideal, using Singular through Sage.
|
|
219
|
+
|
|
220
|
+
::
|
|
221
|
+
|
|
222
|
+
sage: singular.lib('polylib.lib')
|
|
223
|
+
sage: singular.ring(32003, '(a,b,c,d,e,f)', 'lp')
|
|
224
|
+
polynomial ring, over a field, global ordering
|
|
225
|
+
// coefficients: ZZ/32003...
|
|
226
|
+
// number of vars : 6
|
|
227
|
+
// block 1 : ordering lp
|
|
228
|
+
// : names a b c d e f
|
|
229
|
+
// block 2 : ordering C
|
|
230
|
+
sage: I = singular.ideal('cyclic(6)')
|
|
231
|
+
sage: g = singular('groebner(I)')
|
|
232
|
+
Traceback (most recent call last):
|
|
233
|
+
...
|
|
234
|
+
TypeError: Singular error:
|
|
235
|
+
...
|
|
236
|
+
|
|
237
|
+
We restart everything and try again, but correctly.
|
|
238
|
+
|
|
239
|
+
::
|
|
240
|
+
|
|
241
|
+
sage: singular.quit()
|
|
242
|
+
sage: singular.lib('polylib.lib'); R = singular.ring(32003, '(a,b,c,d,e,f)', 'lp')
|
|
243
|
+
sage: I = singular.ideal('cyclic(6)')
|
|
244
|
+
sage: I.groebner()
|
|
245
|
+
f^48-2554*f^42-15674*f^36+12326*f^30-12326*f^18+15674*f^12+2554*f^6-1,
|
|
246
|
+
...
|
|
247
|
+
|
|
248
|
+
It's important to understand why the first attempt at computing a
|
|
249
|
+
basis failed. The line where we gave singular the input
|
|
250
|
+
'groebner(I)' was useless because Singular has no idea what 'I' is!
|
|
251
|
+
Although 'I' is an object that we computed with calls to Singular
|
|
252
|
+
functions, it actually lives in Sage. As a consequence, the name
|
|
253
|
+
'I' means nothing to Singular. When we called
|
|
254
|
+
``I.groebner()``, Sage was able to call the groebner
|
|
255
|
+
function on 'I' in Singular, since 'I' actually means something to
|
|
256
|
+
Sage.
|
|
257
|
+
|
|
258
|
+
Long Input
|
|
259
|
+
----------
|
|
260
|
+
|
|
261
|
+
The Singular interface reads in even very long input (using files)
|
|
262
|
+
in a robust manner, as long as you are creating a new object.
|
|
263
|
+
|
|
264
|
+
::
|
|
265
|
+
|
|
266
|
+
sage: t = '"%s"'%10^15000 # 15 thousand character string (note that normal Singular input must be at most 10000)
|
|
267
|
+
sage: a = singular.eval(t)
|
|
268
|
+
sage: a = singular(t)
|
|
269
|
+
|
|
270
|
+
TESTS:
|
|
271
|
+
|
|
272
|
+
We test an automatic coercion::
|
|
273
|
+
|
|
274
|
+
sage: a = 3*singular('2'); a
|
|
275
|
+
6
|
|
276
|
+
sage: type(a)
|
|
277
|
+
<class 'sage.interfaces.singular.SingularElement'>
|
|
278
|
+
sage: a = singular('2')*3; a
|
|
279
|
+
6
|
|
280
|
+
sage: type(a)
|
|
281
|
+
<class 'sage.interfaces.singular.SingularElement'>
|
|
282
|
+
|
|
283
|
+
Create a ring over GF(9) to check that ``gftables`` has been installed,
|
|
284
|
+
see :issue:`11645`::
|
|
285
|
+
|
|
286
|
+
sage: singular.eval("ring testgf9 = (9,x),(a,b,c,d,e,f),(M((1,2,3,0)),wp(2,3),lp);")
|
|
287
|
+
''
|
|
288
|
+
|
|
289
|
+
Verify that :issue:`17720` is fixed::
|
|
290
|
+
|
|
291
|
+
sage: R.<p> = QQ[]
|
|
292
|
+
sage: K.<p> = QQ.extension(p^2 - p - 1)
|
|
293
|
+
sage: r.<x,z> = K[]
|
|
294
|
+
sage: I = r.ideal(z)
|
|
295
|
+
sage: I.primary_decomposition()
|
|
296
|
+
[Ideal (z) of Multivariate Polynomial Ring in x, z over Number Field in p with defining polynomial p^2 - p - 1]
|
|
297
|
+
sage: [ J.gens() for J in I.primary_decomposition("gtz")]
|
|
298
|
+
[[z]]
|
|
299
|
+
|
|
300
|
+
AUTHORS:
|
|
301
|
+
|
|
302
|
+
- David Joyner and William Stein (2005): first version
|
|
303
|
+
|
|
304
|
+
- Neal Harris (unknown): perhaps added "An Important Concept"
|
|
305
|
+
|
|
306
|
+
- Martin Albrecht (2006-03-05): code so singular.[tab] and x =
|
|
307
|
+
singular(...), x.[tab] includes all singular commands.
|
|
308
|
+
|
|
309
|
+
- Martin Albrecht (2006-03-06): This patch adds the equality symbol to
|
|
310
|
+
singular. Also fix a problem in which " " as prompt means comparison
|
|
311
|
+
will break all further communication with Singular.
|
|
312
|
+
|
|
313
|
+
- Martin Albrecht (2006-03-13): added current_ring() and
|
|
314
|
+
current_ring_name()
|
|
315
|
+
|
|
316
|
+
- William Stein (2006-04-10): Fixed problems with ideal constructor
|
|
317
|
+
|
|
318
|
+
- Martin Albrecht (2006-05-18): added sage_poly.
|
|
319
|
+
|
|
320
|
+
- Simon King (2010-11-23): Reduce the overhead caused by waiting for
|
|
321
|
+
the Singular prompt by doing garbage collection differently.
|
|
322
|
+
|
|
323
|
+
- Simon King (2011-06-06): Make conversion from Singular to Sage more flexible.
|
|
324
|
+
|
|
325
|
+
- Simon King (2015): Extend pickling capabilities.
|
|
326
|
+
"""
|
|
327
|
+
|
|
328
|
+
# ****************************************************************************
|
|
329
|
+
# Copyright (C) 2005 David Joyner and William Stein
|
|
330
|
+
#
|
|
331
|
+
# This program is free software: you can redistribute it and/or modify
|
|
332
|
+
# it under the terms of the GNU General Public License as published by
|
|
333
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
334
|
+
# (at your option) any later version.
|
|
335
|
+
# https://www.gnu.org/licenses/
|
|
336
|
+
# ****************************************************************************
|
|
337
|
+
|
|
338
|
+
import os
|
|
339
|
+
import platform
|
|
340
|
+
import re
|
|
341
|
+
import sys
|
|
342
|
+
import pexpect
|
|
343
|
+
import shlex
|
|
344
|
+
import time
|
|
345
|
+
|
|
346
|
+
from .expect import Expect, ExpectElement, FunctionElement, ExpectFunction
|
|
347
|
+
|
|
348
|
+
import sage.interfaces.abc
|
|
349
|
+
|
|
350
|
+
from sage.interfaces.tab_completion import ExtraTabCompletion
|
|
351
|
+
from sage.structure.sequence import Sequence_generic
|
|
352
|
+
from sage.structure.element import RingElement
|
|
353
|
+
import sage.features.singular
|
|
354
|
+
|
|
355
|
+
import sage.rings.integer
|
|
356
|
+
|
|
357
|
+
from sage.misc.verbose import get_verbose
|
|
358
|
+
from sage.misc.instancedoc import instancedoc
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class SingularError(RuntimeError):
|
|
362
|
+
"""
|
|
363
|
+
Raised if Singular printed an error message
|
|
364
|
+
"""
|
|
365
|
+
pass
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class Singular(ExtraTabCompletion, Expect):
|
|
369
|
+
r"""
|
|
370
|
+
Interface to the Singular interpreter.
|
|
371
|
+
|
|
372
|
+
EXAMPLES: A Groebner basis example.
|
|
373
|
+
|
|
374
|
+
::
|
|
375
|
+
|
|
376
|
+
sage: R = singular.ring(0, '(x0,x1,x2)', 'lp')
|
|
377
|
+
sage: I = singular.ideal([ 'x0*x1*x2 -x0^2*x2', 'x0^2*x1*x2-x0*x1^2*x2-x0*x1*x2^2', 'x0*x1-x0*x2-x1*x2'])
|
|
378
|
+
sage: I.groebner()
|
|
379
|
+
x1^2*x2^2,
|
|
380
|
+
x0*x2^3-x1^2*x2^2+x1*x2^3,
|
|
381
|
+
x0*x1-x0*x2-x1*x2,
|
|
382
|
+
x0^2*x2-x0*x2^2-x1*x2^2
|
|
383
|
+
|
|
384
|
+
AUTHORS:
|
|
385
|
+
|
|
386
|
+
- David Joyner and William Stein
|
|
387
|
+
"""
|
|
388
|
+
def __init__(self, maxread=None, script_subdirectory=None,
|
|
389
|
+
logfile=None, server=None, server_tmpdir=None,
|
|
390
|
+
seed=None):
|
|
391
|
+
"""
|
|
392
|
+
EXAMPLES::
|
|
393
|
+
|
|
394
|
+
sage: singular == loads(dumps(singular))
|
|
395
|
+
True
|
|
396
|
+
"""
|
|
397
|
+
prompt = '> '
|
|
398
|
+
Expect.__init__(self,
|
|
399
|
+
terminal_echo=False,
|
|
400
|
+
name='singular',
|
|
401
|
+
prompt=prompt,
|
|
402
|
+
# no tty, fine grained cputime()
|
|
403
|
+
# and do not display CTRL-C prompt
|
|
404
|
+
command="{} -t --ticks-per-sec 1000 --cntrlc=a".format(
|
|
405
|
+
shlex.quote(sage.features.singular.Singular().absolute_filename())),
|
|
406
|
+
server=server,
|
|
407
|
+
server_tmpdir=server_tmpdir,
|
|
408
|
+
script_subdirectory=script_subdirectory,
|
|
409
|
+
restart_on_ctrlc=True,
|
|
410
|
+
verbose_start=False,
|
|
411
|
+
logfile=logfile,
|
|
412
|
+
eval_using_file_cutoff=100 if platform.system() == "SunOS" else 1000)
|
|
413
|
+
self.__libs = []
|
|
414
|
+
self._prompt_wait = prompt
|
|
415
|
+
self.__to_clear = [] # list of variable names that need to be cleared.
|
|
416
|
+
self._seed = seed
|
|
417
|
+
|
|
418
|
+
def set_seed(self, seed=None):
|
|
419
|
+
"""
|
|
420
|
+
Set the seed for singular interpreter.
|
|
421
|
+
|
|
422
|
+
The seed should be an integer at least 1
|
|
423
|
+
and not more than 30 bits.
|
|
424
|
+
See
|
|
425
|
+
http://www.singular.uni-kl.de/Manual/html/sing_19.htm#SEC26
|
|
426
|
+
and
|
|
427
|
+
http://www.singular.uni-kl.de/Manual/html/sing_283.htm#SEC323
|
|
428
|
+
|
|
429
|
+
EXAMPLES::
|
|
430
|
+
|
|
431
|
+
sage: s = Singular()
|
|
432
|
+
sage: s.set_seed(1)
|
|
433
|
+
1
|
|
434
|
+
sage: [s.random(1,10) for i in range(5)]
|
|
435
|
+
[8, 10, 4, 9, 1]
|
|
436
|
+
"""
|
|
437
|
+
if seed is None:
|
|
438
|
+
seed = self.rand_seed()
|
|
439
|
+
self.eval('system("--random",%d)' % seed)
|
|
440
|
+
self._seed = seed
|
|
441
|
+
return seed
|
|
442
|
+
|
|
443
|
+
def _start(self, alt_message=None):
|
|
444
|
+
"""
|
|
445
|
+
EXAMPLES::
|
|
446
|
+
|
|
447
|
+
sage: s = Singular()
|
|
448
|
+
sage: s.is_running()
|
|
449
|
+
False
|
|
450
|
+
sage: s._start()
|
|
451
|
+
sage: s.is_running()
|
|
452
|
+
True
|
|
453
|
+
sage: s.quit()
|
|
454
|
+
"""
|
|
455
|
+
self.__libs = []
|
|
456
|
+
Expect._start(self, alt_message)
|
|
457
|
+
# Load some standard libraries.
|
|
458
|
+
self.lib('general') # assumed loaded by misc/constants.py
|
|
459
|
+
|
|
460
|
+
# these options are required by the new coefficient rings
|
|
461
|
+
# supported by Singular 3-1-0.
|
|
462
|
+
self.option("redTail")
|
|
463
|
+
self.option("redThrough")
|
|
464
|
+
self.option("intStrategy")
|
|
465
|
+
self._saved_options = self.option('get')
|
|
466
|
+
# set random seed
|
|
467
|
+
self.set_seed(self._seed)
|
|
468
|
+
|
|
469
|
+
def __reduce__(self):
|
|
470
|
+
"""
|
|
471
|
+
EXAMPLES::
|
|
472
|
+
|
|
473
|
+
sage: from sage.interfaces.singular import singular
|
|
474
|
+
sage: singular.__reduce__()
|
|
475
|
+
(<function reduce_load_Singular at 0x...>, ())
|
|
476
|
+
"""
|
|
477
|
+
return reduce_load_Singular, ()
|
|
478
|
+
|
|
479
|
+
def _equality_symbol(self):
|
|
480
|
+
"""
|
|
481
|
+
EXAMPLES::
|
|
482
|
+
|
|
483
|
+
sage: singular._equality_symbol()
|
|
484
|
+
'=='
|
|
485
|
+
"""
|
|
486
|
+
return '=='
|
|
487
|
+
|
|
488
|
+
def _true_symbol(self):
|
|
489
|
+
"""
|
|
490
|
+
EXAMPLES::
|
|
491
|
+
|
|
492
|
+
sage: singular._true_symbol()
|
|
493
|
+
'1'
|
|
494
|
+
"""
|
|
495
|
+
return '1'
|
|
496
|
+
|
|
497
|
+
def _false_symbol(self):
|
|
498
|
+
"""
|
|
499
|
+
EXAMPLES::
|
|
500
|
+
|
|
501
|
+
sage: singular._false_symbol()
|
|
502
|
+
'0'
|
|
503
|
+
"""
|
|
504
|
+
return '0'
|
|
505
|
+
|
|
506
|
+
def _quit_string(self):
|
|
507
|
+
"""
|
|
508
|
+
EXAMPLES::
|
|
509
|
+
|
|
510
|
+
sage: singular._quit_string()
|
|
511
|
+
'quit;'
|
|
512
|
+
"""
|
|
513
|
+
return 'quit;'
|
|
514
|
+
|
|
515
|
+
def _send_interrupt(self):
|
|
516
|
+
"""
|
|
517
|
+
Send an interrupt to Singular. If needed, additional
|
|
518
|
+
semi-colons are sent until we get back at the prompt.
|
|
519
|
+
|
|
520
|
+
TESTS:
|
|
521
|
+
|
|
522
|
+
The following works without restarting Singular::
|
|
523
|
+
|
|
524
|
+
sage: a = singular(1)
|
|
525
|
+
sage: _ = singular._expect.sendline('while(1){};')
|
|
526
|
+
sage: singular.interrupt()
|
|
527
|
+
True
|
|
528
|
+
|
|
529
|
+
We can still access a::
|
|
530
|
+
|
|
531
|
+
sage: 2*a
|
|
532
|
+
2
|
|
533
|
+
|
|
534
|
+
Interrupting nothing or unfinished input also works::
|
|
535
|
+
|
|
536
|
+
sage: singular.interrupt()
|
|
537
|
+
True
|
|
538
|
+
sage: _ = singular._expect.sendline('1+')
|
|
539
|
+
sage: singular.interrupt()
|
|
540
|
+
True
|
|
541
|
+
sage: 3*a
|
|
542
|
+
3
|
|
543
|
+
"""
|
|
544
|
+
# Work around for Singular bug
|
|
545
|
+
# http://www.singular.uni-kl.de:8002/trac/ticket/727
|
|
546
|
+
time.sleep(0.1)
|
|
547
|
+
|
|
548
|
+
E = self._expect
|
|
549
|
+
E.sendline(chr(3))
|
|
550
|
+
# The following is needed so interrupt() works even when
|
|
551
|
+
# there is no computation going on.
|
|
552
|
+
for i in range(5):
|
|
553
|
+
try:
|
|
554
|
+
E.expect_upto(self._prompt, timeout=0.1)
|
|
555
|
+
return
|
|
556
|
+
except pexpect.TIMEOUT:
|
|
557
|
+
pass
|
|
558
|
+
E.sendline(";")
|
|
559
|
+
|
|
560
|
+
def _read_in_file_command(self, filename):
|
|
561
|
+
r"""
|
|
562
|
+
EXAMPLES::
|
|
563
|
+
|
|
564
|
+
sage: singular._read_in_file_command('test')
|
|
565
|
+
'< "...";'
|
|
566
|
+
|
|
567
|
+
sage: filename = tmp_filename()
|
|
568
|
+
sage: f = open(filename, 'w')
|
|
569
|
+
sage: _ = f.write('int x = 2;\n')
|
|
570
|
+
sage: f.close()
|
|
571
|
+
sage: singular.read(filename)
|
|
572
|
+
sage: singular.get('x')
|
|
573
|
+
'2'
|
|
574
|
+
"""
|
|
575
|
+
return '< "%s";' % filename
|
|
576
|
+
|
|
577
|
+
def eval(self, x, allow_semicolon=True, strip=True, **kwds):
|
|
578
|
+
r"""
|
|
579
|
+
Send the code x to the Singular interpreter and return the output
|
|
580
|
+
as a string.
|
|
581
|
+
|
|
582
|
+
INPUT:
|
|
583
|
+
|
|
584
|
+
- ``x`` -- string (of code)
|
|
585
|
+
|
|
586
|
+
- ``allow_semicolon`` -- (default: ``False``) if ``False`` then
|
|
587
|
+
raise a :exc:`TypeError` if the input line contains a semicolon
|
|
588
|
+
|
|
589
|
+
- ``strip`` -- ignored
|
|
590
|
+
|
|
591
|
+
EXAMPLES::
|
|
592
|
+
|
|
593
|
+
sage: singular.eval('2 > 1')
|
|
594
|
+
'1'
|
|
595
|
+
sage: singular.eval('2 + 2')
|
|
596
|
+
'4'
|
|
597
|
+
|
|
598
|
+
if the verbosity level is `> 1` comments are also printed
|
|
599
|
+
and not only returned.
|
|
600
|
+
|
|
601
|
+
::
|
|
602
|
+
|
|
603
|
+
sage: r = singular.ring(0,'(x,y,z)','dp')
|
|
604
|
+
sage: i = singular.ideal(['x^2','y^2','z^2'])
|
|
605
|
+
sage: s = i.std()
|
|
606
|
+
sage: singular.eval('hilb(%s)'%(s.name()))
|
|
607
|
+
'...// dimension (affine) = 0\n//
|
|
608
|
+
degree (affine) = 8'
|
|
609
|
+
|
|
610
|
+
::
|
|
611
|
+
|
|
612
|
+
sage: from sage.misc.verbose import set_verbose
|
|
613
|
+
sage: set_verbose(1)
|
|
614
|
+
sage: o = singular.eval('hilb(%s)'%(s.name()))
|
|
615
|
+
...// dimension (affine) = 0
|
|
616
|
+
// degree (affine) = 8
|
|
617
|
+
|
|
618
|
+
This is mainly useful if this method is called implicitly. Because
|
|
619
|
+
then intermediate results, debugging outputs and printed statements
|
|
620
|
+
are printed
|
|
621
|
+
|
|
622
|
+
::
|
|
623
|
+
|
|
624
|
+
sage: o = s.hilb()
|
|
625
|
+
...// dimension (affine) = 0
|
|
626
|
+
// degree (affine) = 8
|
|
627
|
+
// ** right side is not a datum, assignment ignored
|
|
628
|
+
...
|
|
629
|
+
|
|
630
|
+
rather than ignored
|
|
631
|
+
|
|
632
|
+
::
|
|
633
|
+
|
|
634
|
+
sage: set_verbose(0)
|
|
635
|
+
sage: o = s.hilb()
|
|
636
|
+
"""
|
|
637
|
+
# Simon King:
|
|
638
|
+
# In previous versions, the interface was first synchronised and then
|
|
639
|
+
# unused variables were killed. This created a considerable overhead.
|
|
640
|
+
# By github issue #10296, killing unused variables is now done inside
|
|
641
|
+
# singular.set(). Moreover, it is not done by calling a separate _eval_line.
|
|
642
|
+
# In that way, the time spent by waiting for the singular prompt is reduced.
|
|
643
|
+
|
|
644
|
+
# Before #10296, it was possible that garbage collection occurred inside
|
|
645
|
+
# of _eval_line. But collection of the garbage would launch another call
|
|
646
|
+
# to _eval_line. The result would have been a dead lock, that could only
|
|
647
|
+
# be avoided by synchronisation. Since garbage collection is now done
|
|
648
|
+
# without an additional call to _eval_line, synchronisation is not
|
|
649
|
+
# needed anymore, saving even more waiting time for the prompt.
|
|
650
|
+
|
|
651
|
+
# Uncomment the print statements below for low-level debugging of
|
|
652
|
+
# code that involves the singular interfaces. Everything goes
|
|
653
|
+
# through here.
|
|
654
|
+
|
|
655
|
+
x = str(x).rstrip().rstrip(';')
|
|
656
|
+
x = x.replace("> ", ">\t") # don't send a prompt (added by Martin Albrecht)
|
|
657
|
+
if not allow_semicolon and x.find(";") != -1:
|
|
658
|
+
raise TypeError("singular input must not contain any semicolons:\n%s" % x)
|
|
659
|
+
if len(x) == 0 or x[len(x) - 1] != ';':
|
|
660
|
+
x += ';'
|
|
661
|
+
|
|
662
|
+
s = Expect.eval(self, x, **kwds)
|
|
663
|
+
|
|
664
|
+
# "Segment fault" is not a typo:
|
|
665
|
+
# Singular actually does use that string
|
|
666
|
+
if s.find("error occurred") != -1 or s.find("Segment fault") != -1:
|
|
667
|
+
raise SingularError('Singular error:\n%s' % s)
|
|
668
|
+
|
|
669
|
+
if get_verbose() > 0:
|
|
670
|
+
for line in s.splitlines():
|
|
671
|
+
if line.startswith("//"):
|
|
672
|
+
print(line)
|
|
673
|
+
return s
|
|
674
|
+
else:
|
|
675
|
+
return s
|
|
676
|
+
|
|
677
|
+
def set(self, type, name, value):
|
|
678
|
+
"""
|
|
679
|
+
Set the variable with given name to the given value.
|
|
680
|
+
|
|
681
|
+
REMARK:
|
|
682
|
+
|
|
683
|
+
If a variable in the Singular interface was previously marked for
|
|
684
|
+
deletion, the actual deletion is done here, before the new variable
|
|
685
|
+
is created in Singular.
|
|
686
|
+
|
|
687
|
+
EXAMPLES::
|
|
688
|
+
|
|
689
|
+
sage: singular.set('int', 'x', '2')
|
|
690
|
+
sage: singular.get('x')
|
|
691
|
+
'2'
|
|
692
|
+
|
|
693
|
+
We test that an unused variable is only actually deleted if this method
|
|
694
|
+
is called::
|
|
695
|
+
|
|
696
|
+
sage: a = singular(3)
|
|
697
|
+
sage: n = a.name()
|
|
698
|
+
sage: del a
|
|
699
|
+
sage: singular.eval(n)
|
|
700
|
+
'3'
|
|
701
|
+
sage: singular.set('int', 'y', '5')
|
|
702
|
+
sage: singular.eval('defined(%s)'%n)
|
|
703
|
+
'0'
|
|
704
|
+
"""
|
|
705
|
+
cmd = ''.join('if(defined(%s)){kill %s;};' % (v, v)
|
|
706
|
+
for v in self.__to_clear)
|
|
707
|
+
cmd += '%s %s=%s;' % (type, name, value)
|
|
708
|
+
self.__to_clear = []
|
|
709
|
+
self.eval(cmd)
|
|
710
|
+
|
|
711
|
+
def get(self, var):
|
|
712
|
+
"""
|
|
713
|
+
Get string representation of variable named var.
|
|
714
|
+
|
|
715
|
+
EXAMPLES::
|
|
716
|
+
|
|
717
|
+
sage: singular.set('int', 'x', '2')
|
|
718
|
+
sage: singular.get('x')
|
|
719
|
+
'2'
|
|
720
|
+
"""
|
|
721
|
+
return self.eval('print(%s);' % var)
|
|
722
|
+
|
|
723
|
+
def clear(self, var):
|
|
724
|
+
"""
|
|
725
|
+
Clear the variable named ``var``.
|
|
726
|
+
|
|
727
|
+
EXAMPLES::
|
|
728
|
+
|
|
729
|
+
sage: singular.set('int', 'x', '2')
|
|
730
|
+
sage: singular.get('x')
|
|
731
|
+
'2'
|
|
732
|
+
sage: singular.clear('x')
|
|
733
|
+
|
|
734
|
+
"Clearing the variable" means to allow to free the memory
|
|
735
|
+
that it uses in the Singular sub-process. However, the
|
|
736
|
+
actual deletion of the variable is only committed when
|
|
737
|
+
the next element in the Singular interface is created::
|
|
738
|
+
|
|
739
|
+
sage: singular.get('x')
|
|
740
|
+
'2'
|
|
741
|
+
sage: a = singular(3)
|
|
742
|
+
sage: singular.get('x')
|
|
743
|
+
'`x`'
|
|
744
|
+
"""
|
|
745
|
+
# We add the variable to the list of vars to clear when we do an eval.
|
|
746
|
+
# We queue up all the clears and do them at once to avoid synchronizing
|
|
747
|
+
# the interface at the same time we do garbage collection, which can
|
|
748
|
+
# lead to subtle problems. This was Willem Jan's ideas, implemented
|
|
749
|
+
# by William Stein.
|
|
750
|
+
self.__to_clear.append(var)
|
|
751
|
+
|
|
752
|
+
def _create(self, value, type='def'):
|
|
753
|
+
"""
|
|
754
|
+
Create a new variable in the Singular session and returns the name
|
|
755
|
+
of that variable.
|
|
756
|
+
|
|
757
|
+
EXAMPLES::
|
|
758
|
+
|
|
759
|
+
sage: singular._create('2', type='int')
|
|
760
|
+
'sage...'
|
|
761
|
+
sage: singular.get(_)
|
|
762
|
+
'2'
|
|
763
|
+
"""
|
|
764
|
+
name = self._next_var_name()
|
|
765
|
+
self.set(type, name, value)
|
|
766
|
+
return name
|
|
767
|
+
|
|
768
|
+
def __call__(self, x, type='def'):
|
|
769
|
+
"""
|
|
770
|
+
Create a singular object X with given type determined by the string
|
|
771
|
+
x. This returns var, where var is built using the Singular
|
|
772
|
+
statement type var = ... x ... Note that the actual name of var
|
|
773
|
+
could be anything, and can be recovered using X.name().
|
|
774
|
+
|
|
775
|
+
The object X returned can be used like any Sage object, and wraps
|
|
776
|
+
an object in ``self``. The standard arithmetic operators work. Moreover
|
|
777
|
+
if foo is a function then X.foo(y,z,...) calls foo(X, y, z, ...)
|
|
778
|
+
and returns the corresponding object.
|
|
779
|
+
|
|
780
|
+
EXAMPLES::
|
|
781
|
+
|
|
782
|
+
sage: R = singular.ring(0, '(x0,x1,x2)', 'lp')
|
|
783
|
+
sage: I = singular.ideal([ 'x0*x1*x2 -x0^2*x2', 'x0^2*x1*x2-x0*x1^2*x2-x0*x1*x2^2', 'x0*x1-x0*x2-x1*x2'])
|
|
784
|
+
sage: I
|
|
785
|
+
-x0^2*x2+x0*x1*x2,
|
|
786
|
+
x0^2*x1*x2-x0*x1^2*x2-x0*x1*x2^2,
|
|
787
|
+
x0*x1-x0*x2-x1*x2
|
|
788
|
+
sage: type(I)
|
|
789
|
+
<class 'sage.interfaces.singular.SingularElement'>
|
|
790
|
+
sage: I.parent()
|
|
791
|
+
Singular
|
|
792
|
+
"""
|
|
793
|
+
if isinstance(x, SingularElement) and x.parent() is self:
|
|
794
|
+
return x
|
|
795
|
+
elif isinstance(x, ExpectElement):
|
|
796
|
+
return self(x.sage())
|
|
797
|
+
elif not isinstance(x, ExpectElement) and hasattr(x, '_singular_'):
|
|
798
|
+
return x._singular_(self)
|
|
799
|
+
|
|
800
|
+
# some convenient conversions
|
|
801
|
+
if type in ("module", "list") and isinstance(x, (list, tuple, Sequence_generic)):
|
|
802
|
+
x = str(x)[1:-1]
|
|
803
|
+
|
|
804
|
+
return SingularElement(self, type, x, False)
|
|
805
|
+
|
|
806
|
+
def _coerce_map_from_(self, S):
|
|
807
|
+
"""
|
|
808
|
+
Return ``True`` if ``S`` admits a coercion map into the
|
|
809
|
+
Singular interface.
|
|
810
|
+
|
|
811
|
+
EXAMPLES::
|
|
812
|
+
|
|
813
|
+
sage: singular._coerce_map_from_(ZZ)
|
|
814
|
+
True
|
|
815
|
+
sage: singular.coerce_map_from(ZZ)
|
|
816
|
+
Call morphism:
|
|
817
|
+
From: Integer Ring
|
|
818
|
+
To: Singular
|
|
819
|
+
sage: singular.coerce_map_from(float)
|
|
820
|
+
"""
|
|
821
|
+
# we want to implement this without coercing, since singular has state.
|
|
822
|
+
if hasattr(S, 'an_element'):
|
|
823
|
+
if hasattr(S.an_element(), '_singular_'):
|
|
824
|
+
return True
|
|
825
|
+
elif S is int:
|
|
826
|
+
return True
|
|
827
|
+
return None
|
|
828
|
+
|
|
829
|
+
def cputime(self, t=None):
|
|
830
|
+
r"""
|
|
831
|
+
Return the amount of CPU time that the Singular session has used.
|
|
832
|
+
If ``t`` is not None, then it returns the difference
|
|
833
|
+
between the current CPU time and ``t``.
|
|
834
|
+
|
|
835
|
+
EXAMPLES::
|
|
836
|
+
|
|
837
|
+
sage: t = singular.cputime()
|
|
838
|
+
sage: R = singular.ring(0, '(x0,x1,x2)', 'lp')
|
|
839
|
+
sage: I = singular.ideal([ 'x0*x1*x2 -x0^2*x2', 'x0^2*x1*x2-x0*x1^2*x2-x0*x1*x2^2', 'x0*x1-x0*x2-x1*x2'])
|
|
840
|
+
sage: gb = I.groebner()
|
|
841
|
+
sage: singular.cputime(t) #random
|
|
842
|
+
0.02
|
|
843
|
+
"""
|
|
844
|
+
if t:
|
|
845
|
+
return float(self.eval('timer-(%d)' % (int(1000 * t)))) / 1000.0
|
|
846
|
+
else:
|
|
847
|
+
return float(self.eval('timer')) / 1000.0
|
|
848
|
+
|
|
849
|
+
###########################################################
|
|
850
|
+
# Singular libraries
|
|
851
|
+
###########################################################
|
|
852
|
+
def lib(self, lib, reload=False):
|
|
853
|
+
"""
|
|
854
|
+
Load the Singular library named lib.
|
|
855
|
+
|
|
856
|
+
Note that if the library was already loaded during this session it
|
|
857
|
+
is not reloaded unless the optional reload argument is ``True`` (the
|
|
858
|
+
default is ``False``).
|
|
859
|
+
|
|
860
|
+
EXAMPLES::
|
|
861
|
+
|
|
862
|
+
sage: singular.lib('sing.lib')
|
|
863
|
+
sage: singular.lib('sing.lib', reload=True)
|
|
864
|
+
"""
|
|
865
|
+
if lib[-4:] != ".lib":
|
|
866
|
+
lib += ".lib"
|
|
867
|
+
if not reload and lib in self.__libs:
|
|
868
|
+
return
|
|
869
|
+
self.eval('LIB "%s"' % lib)
|
|
870
|
+
self.__libs.append(lib)
|
|
871
|
+
|
|
872
|
+
LIB = lib
|
|
873
|
+
load = lib
|
|
874
|
+
|
|
875
|
+
##########################################################
|
|
876
|
+
# constructors
|
|
877
|
+
##########################################################
|
|
878
|
+
def ideal(self, *gens):
|
|
879
|
+
"""
|
|
880
|
+
Return the ideal generated by gens.
|
|
881
|
+
|
|
882
|
+
INPUT:
|
|
883
|
+
|
|
884
|
+
- ``gens`` -- list or tuple of Singular objects (or
|
|
885
|
+
objects that can be made into Singular objects via evaluation)
|
|
886
|
+
|
|
887
|
+
OUTPUT: the Singular ideal generated by the given list of gens
|
|
888
|
+
|
|
889
|
+
EXAMPLES: A Groebner basis example done in a different way.
|
|
890
|
+
|
|
891
|
+
::
|
|
892
|
+
|
|
893
|
+
sage: _ = singular.eval("ring R=0,(x0,x1,x2),lp")
|
|
894
|
+
sage: i1 = singular.ideal([ 'x0*x1*x2 -x0^2*x2', 'x0^2*x1*x2-x0*x1^2*x2-x0*x1*x2^2', 'x0*x1-x0*x2-x1*x2'])
|
|
895
|
+
sage: i1
|
|
896
|
+
-x0^2*x2+x0*x1*x2,
|
|
897
|
+
x0^2*x1*x2-x0*x1^2*x2-x0*x1*x2^2,
|
|
898
|
+
x0*x1-x0*x2-x1*x2
|
|
899
|
+
|
|
900
|
+
::
|
|
901
|
+
|
|
902
|
+
sage: i2 = singular.ideal('groebner(%s);'%i1.name())
|
|
903
|
+
sage: i2
|
|
904
|
+
x1^2*x2^2,
|
|
905
|
+
x0*x2^3-x1^2*x2^2+x1*x2^3,
|
|
906
|
+
x0*x1-x0*x2-x1*x2,
|
|
907
|
+
x0^2*x2-x0*x2^2-x1*x2^2
|
|
908
|
+
"""
|
|
909
|
+
if isinstance(gens, str):
|
|
910
|
+
gens = self(gens)
|
|
911
|
+
|
|
912
|
+
if isinstance(gens, SingularElement):
|
|
913
|
+
return self(gens.name(), 'ideal')
|
|
914
|
+
|
|
915
|
+
if not isinstance(gens, (list, tuple)):
|
|
916
|
+
raise TypeError("gens (=%s) must be a list, tuple, string, or Singular element" % gens)
|
|
917
|
+
|
|
918
|
+
if len(gens) == 1 and isinstance(gens[0], (list, tuple)):
|
|
919
|
+
gens = gens[0]
|
|
920
|
+
gens2 = []
|
|
921
|
+
for g in gens:
|
|
922
|
+
if not isinstance(g, SingularElement):
|
|
923
|
+
gens2.append(self.new(g))
|
|
924
|
+
else:
|
|
925
|
+
gens2.append(g)
|
|
926
|
+
return self(",".join(g.name() for g in gens2), 'ideal')
|
|
927
|
+
|
|
928
|
+
def list(self, x):
|
|
929
|
+
r"""
|
|
930
|
+
Create a list in Singular from a Sage list ``x``.
|
|
931
|
+
|
|
932
|
+
EXAMPLES::
|
|
933
|
+
|
|
934
|
+
sage: singular.list([1,2])
|
|
935
|
+
[1]:
|
|
936
|
+
1
|
|
937
|
+
[2]:
|
|
938
|
+
2
|
|
939
|
+
|
|
940
|
+
sage: singular.list([1,2,[3,4]])
|
|
941
|
+
[1]:
|
|
942
|
+
1
|
|
943
|
+
[2]:
|
|
944
|
+
2
|
|
945
|
+
[3]:
|
|
946
|
+
[1]:
|
|
947
|
+
3
|
|
948
|
+
[2]:
|
|
949
|
+
4
|
|
950
|
+
|
|
951
|
+
sage: R.<x,y> = QQ[]
|
|
952
|
+
sage: singular.list([1,2,[x,ideal(x,y)]])
|
|
953
|
+
[1]:
|
|
954
|
+
1
|
|
955
|
+
[2]:
|
|
956
|
+
2
|
|
957
|
+
[3]:
|
|
958
|
+
[1]:
|
|
959
|
+
x
|
|
960
|
+
[2]:
|
|
961
|
+
_[1]=x
|
|
962
|
+
_[2]=y
|
|
963
|
+
|
|
964
|
+
Strings have to be escaped before passing them to this method::
|
|
965
|
+
|
|
966
|
+
sage: singular.list([1,2,'"hi"'])
|
|
967
|
+
[1]:
|
|
968
|
+
1
|
|
969
|
+
[2]:
|
|
970
|
+
2
|
|
971
|
+
[3]:
|
|
972
|
+
hi
|
|
973
|
+
|
|
974
|
+
TESTS:
|
|
975
|
+
|
|
976
|
+
Check that a list already converted to Singular can be
|
|
977
|
+
embedded into a list to be converted::
|
|
978
|
+
|
|
979
|
+
sage: singular.list([1, 2, singular.list([3, 4])])
|
|
980
|
+
[1]:
|
|
981
|
+
1
|
|
982
|
+
[2]:
|
|
983
|
+
2
|
|
984
|
+
[3]:
|
|
985
|
+
[1]:
|
|
986
|
+
3
|
|
987
|
+
[2]:
|
|
988
|
+
4
|
|
989
|
+
"""
|
|
990
|
+
|
|
991
|
+
# We have to be careful about object destruction.
|
|
992
|
+
|
|
993
|
+
# If we convert an object to a Singular element, the only
|
|
994
|
+
# thing that goes into the list definition statement is the
|
|
995
|
+
# Singular variable name, so we need to keep the element
|
|
996
|
+
# around long enough to ensure that the variable still exists
|
|
997
|
+
# when we create the list. We ensure this by putting created
|
|
998
|
+
# elements on a list, which gets destroyed when this function
|
|
999
|
+
# returns, by which time the list has been created.
|
|
1000
|
+
|
|
1001
|
+
singular_elements = []
|
|
1002
|
+
|
|
1003
|
+
def strify(x):
|
|
1004
|
+
if isinstance(x, (list, tuple, Sequence_generic)):
|
|
1005
|
+
return 'list(' + ','.join(strify(i) for i in x) + ')'
|
|
1006
|
+
elif isinstance(x, SingularElement):
|
|
1007
|
+
return x.name()
|
|
1008
|
+
elif isinstance(x, (int, sage.rings.integer.Integer)):
|
|
1009
|
+
return repr(x)
|
|
1010
|
+
elif hasattr(x, '_singular_'):
|
|
1011
|
+
e = x._singular_()
|
|
1012
|
+
singular_elements.append(e)
|
|
1013
|
+
return e.name()
|
|
1014
|
+
else:
|
|
1015
|
+
return str(x)
|
|
1016
|
+
|
|
1017
|
+
return self(strify(x), 'list')
|
|
1018
|
+
|
|
1019
|
+
def matrix(self, nrows, ncols, entries=None):
|
|
1020
|
+
"""
|
|
1021
|
+
EXAMPLES::
|
|
1022
|
+
|
|
1023
|
+
sage: singular.lib("matrix")
|
|
1024
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
1025
|
+
sage: A = singular.matrix(3,2,'1,2,3,4,5,6')
|
|
1026
|
+
sage: A
|
|
1027
|
+
1,2,
|
|
1028
|
+
3,4,
|
|
1029
|
+
5,6
|
|
1030
|
+
sage: A.gauss_col()
|
|
1031
|
+
2,-1,
|
|
1032
|
+
1,0,
|
|
1033
|
+
0,1
|
|
1034
|
+
|
|
1035
|
+
AUTHORS:
|
|
1036
|
+
|
|
1037
|
+
- Martin Albrecht (2006-01-14)
|
|
1038
|
+
"""
|
|
1039
|
+
name = self._next_var_name()
|
|
1040
|
+
if entries is None:
|
|
1041
|
+
self.eval('matrix %s[%s][%s]' % (name, nrows, ncols))
|
|
1042
|
+
else:
|
|
1043
|
+
self.eval('matrix %s[%s][%s] = %s' % (name, nrows, ncols, entries))
|
|
1044
|
+
return SingularElement(self, None, name, True)
|
|
1045
|
+
|
|
1046
|
+
def ring(self, char=0, vars='(x)', order='lp', check=None):
|
|
1047
|
+
r"""
|
|
1048
|
+
Create a Singular ring and makes it the current ring.
|
|
1049
|
+
|
|
1050
|
+
INPUT:
|
|
1051
|
+
|
|
1052
|
+
- ``char`` -- string; a string specifying the characteristic
|
|
1053
|
+
of the base ring, in the format accepted by Singular (see
|
|
1054
|
+
examples below)
|
|
1055
|
+
|
|
1056
|
+
- ``vars`` -- tuple or string defining the variable names
|
|
1057
|
+
|
|
1058
|
+
- ``order`` -- string; the monomial order (default: ``'lp'``)
|
|
1059
|
+
|
|
1060
|
+
OUTPUT: a Singular ring
|
|
1061
|
+
|
|
1062
|
+
.. NOTE::
|
|
1063
|
+
|
|
1064
|
+
This function is *not* identical to calling the Singular
|
|
1065
|
+
``ring`` function. In particular, it also attempts to
|
|
1066
|
+
"kill" the variable names, so they can actually be used
|
|
1067
|
+
without getting errors, and it sets printing of elements
|
|
1068
|
+
for this range to short (i.e., with \*'s and carets).
|
|
1069
|
+
|
|
1070
|
+
EXAMPLES: We first declare `\QQ[x,y,z]` with degree reverse
|
|
1071
|
+
lexicographic ordering.
|
|
1072
|
+
|
|
1073
|
+
::
|
|
1074
|
+
|
|
1075
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
1076
|
+
sage: R
|
|
1077
|
+
polynomial ring, over a field, global ordering
|
|
1078
|
+
// coefficients: QQ...
|
|
1079
|
+
// number of vars : 3
|
|
1080
|
+
// block 1 : ordering dp
|
|
1081
|
+
// : names x y z
|
|
1082
|
+
// block 2 : ordering C
|
|
1083
|
+
|
|
1084
|
+
::
|
|
1085
|
+
|
|
1086
|
+
sage: R1 = singular.ring(32003, '(x,y,z)', 'dp')
|
|
1087
|
+
sage: R2 = singular.ring(32003, '(a,b,c,d)', 'lp')
|
|
1088
|
+
|
|
1089
|
+
This is a ring in variables named x(1) through x(10) over the
|
|
1090
|
+
finite field of order `7`::
|
|
1091
|
+
|
|
1092
|
+
sage: R3 = singular.ring(7, '(x(1..10))', 'ds')
|
|
1093
|
+
|
|
1094
|
+
This is a polynomial ring over the transcendental extension
|
|
1095
|
+
`\QQ(a)` of `\QQ`::
|
|
1096
|
+
|
|
1097
|
+
sage: R4 = singular.ring('(0,a)', '(mu,nu)', 'lp')
|
|
1098
|
+
|
|
1099
|
+
This is a ring over the field of single-precision floats::
|
|
1100
|
+
|
|
1101
|
+
sage: R5 = singular.ring('real', '(a,b)', 'lp')
|
|
1102
|
+
|
|
1103
|
+
This is over 50-digit floats::
|
|
1104
|
+
|
|
1105
|
+
sage: R6 = singular.ring('(real,50)', '(a,b)', 'lp')
|
|
1106
|
+
sage: R7 = singular.ring('(complex,50,i)', '(a,b)', 'lp')
|
|
1107
|
+
|
|
1108
|
+
To use a ring that you've defined, use the set_ring() method on
|
|
1109
|
+
the ring. This sets the ring to be the "current ring". For
|
|
1110
|
+
example,
|
|
1111
|
+
|
|
1112
|
+
::
|
|
1113
|
+
|
|
1114
|
+
sage: R = singular.ring(7, '(a,b)', 'ds')
|
|
1115
|
+
sage: S = singular.ring('real', '(a,b)', 'lp')
|
|
1116
|
+
sage: singular.new('10*a')
|
|
1117
|
+
(1.000e+01)*a
|
|
1118
|
+
sage: R.set_ring()
|
|
1119
|
+
sage: singular.new('10*a')
|
|
1120
|
+
3*a
|
|
1121
|
+
"""
|
|
1122
|
+
if len(vars) > 2:
|
|
1123
|
+
s = '; '.join('if(defined(%s)>0){kill %s;};' % (x, x)
|
|
1124
|
+
for x in vars[1:-1].split(','))
|
|
1125
|
+
self.eval(s)
|
|
1126
|
+
|
|
1127
|
+
if check is not None:
|
|
1128
|
+
from sage.misc.superseded import deprecation
|
|
1129
|
+
deprecation(33319, 'The check= keyword argument does nothing.' + f'({check})')
|
|
1130
|
+
|
|
1131
|
+
R = self('%s,%s,%s' % (char, vars, order), 'ring')
|
|
1132
|
+
self.eval('short=0') # make output include *'s for multiplication for *THIS* ring.
|
|
1133
|
+
return R
|
|
1134
|
+
|
|
1135
|
+
def string(self, x):
|
|
1136
|
+
"""
|
|
1137
|
+
Create a Singular string from a Sage string. Note that the Sage
|
|
1138
|
+
string has to be "double-quoted".
|
|
1139
|
+
|
|
1140
|
+
EXAMPLES::
|
|
1141
|
+
|
|
1142
|
+
sage: singular.string('"Sage"')
|
|
1143
|
+
Sage
|
|
1144
|
+
"""
|
|
1145
|
+
return self(x, 'string')
|
|
1146
|
+
|
|
1147
|
+
def set_ring(self, R):
|
|
1148
|
+
"""
|
|
1149
|
+
Set the current Singular ring to `R`.
|
|
1150
|
+
|
|
1151
|
+
EXAMPLES::
|
|
1152
|
+
|
|
1153
|
+
sage: R = singular.ring(7, '(a,b)', 'ds')
|
|
1154
|
+
sage: S = singular.ring('real', '(a,b)', 'lp')
|
|
1155
|
+
sage: singular.current_ring()
|
|
1156
|
+
polynomial ring, over a field, global ordering
|
|
1157
|
+
// coefficients: Float()...
|
|
1158
|
+
// number of vars : 2
|
|
1159
|
+
// block 1 : ordering lp
|
|
1160
|
+
// : names a b
|
|
1161
|
+
// block 2 : ordering C
|
|
1162
|
+
sage: singular.set_ring(R)
|
|
1163
|
+
sage: singular.current_ring()
|
|
1164
|
+
polynomial ring, over a field, local ordering
|
|
1165
|
+
// coefficients: ZZ/7...
|
|
1166
|
+
// number of vars : 2
|
|
1167
|
+
// block 1 : ordering ds
|
|
1168
|
+
// : names a b
|
|
1169
|
+
// block 2 : ordering C
|
|
1170
|
+
"""
|
|
1171
|
+
if not isinstance(R, SingularElement):
|
|
1172
|
+
raise TypeError("R must be a singular ring")
|
|
1173
|
+
self.eval("setring %s; short=0" % R.name(), allow_semicolon=True)
|
|
1174
|
+
|
|
1175
|
+
setring = set_ring
|
|
1176
|
+
|
|
1177
|
+
def current_ring_name(self):
|
|
1178
|
+
"""
|
|
1179
|
+
Return the Singular name of the currently active ring in
|
|
1180
|
+
Singular.
|
|
1181
|
+
|
|
1182
|
+
OUTPUT: currently active ring's name
|
|
1183
|
+
|
|
1184
|
+
EXAMPLES::
|
|
1185
|
+
|
|
1186
|
+
sage: r = PolynomialRing(GF(127),3,'xyz')
|
|
1187
|
+
sage: r._singular_().name() == singular.current_ring_name()
|
|
1188
|
+
True
|
|
1189
|
+
"""
|
|
1190
|
+
ringlist = self.eval("listvar(ring)").splitlines()
|
|
1191
|
+
p = re.compile(r"// ([a-zA-Z0-9_]*).*\[.*\].*\*.*") # do this in constructor?
|
|
1192
|
+
for line in ringlist:
|
|
1193
|
+
m = p.match(line)
|
|
1194
|
+
if m:
|
|
1195
|
+
return m.group(1)
|
|
1196
|
+
return None
|
|
1197
|
+
|
|
1198
|
+
def current_ring(self):
|
|
1199
|
+
"""
|
|
1200
|
+
Return the current ring of the running Singular session.
|
|
1201
|
+
|
|
1202
|
+
EXAMPLES::
|
|
1203
|
+
|
|
1204
|
+
sage: r = PolynomialRing(GF(127),3,'xyz', order='invlex')
|
|
1205
|
+
sage: r._singular_()
|
|
1206
|
+
polynomial ring, over a field, global ordering
|
|
1207
|
+
// coefficients: ZZ/127...
|
|
1208
|
+
// number of vars : 3
|
|
1209
|
+
// block 1 : ordering ip
|
|
1210
|
+
// : names x y z
|
|
1211
|
+
// block 2 : ordering C
|
|
1212
|
+
sage: singular.current_ring()
|
|
1213
|
+
polynomial ring, over a field, global ordering
|
|
1214
|
+
// coefficients: ZZ/127...
|
|
1215
|
+
// number of vars : 3
|
|
1216
|
+
// block 1 : ordering ip
|
|
1217
|
+
// : names x y z
|
|
1218
|
+
// block 2 : ordering C
|
|
1219
|
+
"""
|
|
1220
|
+
name = self.current_ring_name()
|
|
1221
|
+
if name:
|
|
1222
|
+
return self(name)
|
|
1223
|
+
else:
|
|
1224
|
+
return None
|
|
1225
|
+
|
|
1226
|
+
def _tab_completion(self) -> list:
|
|
1227
|
+
"""
|
|
1228
|
+
Return a list of all Singular commands.
|
|
1229
|
+
|
|
1230
|
+
EXAMPLES::
|
|
1231
|
+
|
|
1232
|
+
sage: singular._tab_completion()
|
|
1233
|
+
['exteriorPower',
|
|
1234
|
+
...
|
|
1235
|
+
'crossprod']
|
|
1236
|
+
"""
|
|
1237
|
+
p = re.compile("// *([a-z0-9A-Z_]*).*") # compiles regular expression
|
|
1238
|
+
proclist = self.eval("listvar(proc)").splitlines()
|
|
1239
|
+
return [p.match(line).group(1) for line in proclist]
|
|
1240
|
+
|
|
1241
|
+
def console(self):
|
|
1242
|
+
r"""
|
|
1243
|
+
EXAMPLES::
|
|
1244
|
+
|
|
1245
|
+
sage: singular_console() #not tested
|
|
1246
|
+
SINGULAR / Development
|
|
1247
|
+
A Computer Algebra System for Polynomial Computations / version 3-0-4
|
|
1248
|
+
0<
|
|
1249
|
+
by: G.-M. Greuel, G. Pfister, H. Schoenemann \ Nov 2007
|
|
1250
|
+
FB Mathematik der Universitaet, D-67653 Kaiserslautern \
|
|
1251
|
+
"""
|
|
1252
|
+
singular_console()
|
|
1253
|
+
|
|
1254
|
+
def version(self):
|
|
1255
|
+
"""
|
|
1256
|
+
Return the version of Singular being used.
|
|
1257
|
+
|
|
1258
|
+
EXAMPLES::
|
|
1259
|
+
|
|
1260
|
+
sage: singular.version()
|
|
1261
|
+
"Singular ... version 4...
|
|
1262
|
+
"""
|
|
1263
|
+
return singular_version()
|
|
1264
|
+
|
|
1265
|
+
def _function_class(self):
|
|
1266
|
+
"""
|
|
1267
|
+
EXAMPLES::
|
|
1268
|
+
|
|
1269
|
+
sage: singular._function_class()
|
|
1270
|
+
<class 'sage.interfaces.singular.SingularFunction'>
|
|
1271
|
+
"""
|
|
1272
|
+
return SingularFunction
|
|
1273
|
+
|
|
1274
|
+
def _function_element_class(self):
|
|
1275
|
+
"""
|
|
1276
|
+
EXAMPLES::
|
|
1277
|
+
|
|
1278
|
+
sage: singular._function_element_class()
|
|
1279
|
+
<class 'sage.interfaces.singular.SingularFunctionElement'>
|
|
1280
|
+
"""
|
|
1281
|
+
return SingularFunctionElement
|
|
1282
|
+
|
|
1283
|
+
def option(self, cmd=None, val=None):
|
|
1284
|
+
"""
|
|
1285
|
+
Access to Singular's options as follows:
|
|
1286
|
+
|
|
1287
|
+
Syntax: option() Returns a string of all defined options.
|
|
1288
|
+
|
|
1289
|
+
Syntax: option( 'option_name' ) Sets an option. Note to disable an
|
|
1290
|
+
option, use the prefix no.
|
|
1291
|
+
|
|
1292
|
+
Syntax: option( 'get' ) Returns an intvec of the state of all
|
|
1293
|
+
options.
|
|
1294
|
+
|
|
1295
|
+
Syntax: option( 'set', intvec_expression ) Restores the state of
|
|
1296
|
+
all options from an intvec (produced by option('get')).
|
|
1297
|
+
|
|
1298
|
+
EXAMPLES::
|
|
1299
|
+
|
|
1300
|
+
sage: singular.option()
|
|
1301
|
+
//options: redefine loadLib usage prompt
|
|
1302
|
+
sage: singular.option('get')
|
|
1303
|
+
0,
|
|
1304
|
+
10321
|
|
1305
|
+
sage: old_options = _
|
|
1306
|
+
sage: singular.option('noredefine')
|
|
1307
|
+
sage: singular.option()
|
|
1308
|
+
//options: loadLib usage prompt
|
|
1309
|
+
sage: singular.option('set', old_options)
|
|
1310
|
+
sage: singular.option('get')
|
|
1311
|
+
0,
|
|
1312
|
+
10321
|
|
1313
|
+
"""
|
|
1314
|
+
if cmd is None:
|
|
1315
|
+
return SingularFunction(self, "option")()
|
|
1316
|
+
elif cmd == "get":
|
|
1317
|
+
# return SingularFunction(self, "option")("\"get\"")
|
|
1318
|
+
return self(self.eval("option(get)"), "intvec")
|
|
1319
|
+
elif cmd == "set":
|
|
1320
|
+
if not isinstance(val, SingularElement):
|
|
1321
|
+
raise TypeError("singular.option('set') needs SingularElement as second parameter")
|
|
1322
|
+
# SingularFunction(self,"option")("\"set\"",val)
|
|
1323
|
+
self.eval("option(set,%s)" % val.name())
|
|
1324
|
+
else:
|
|
1325
|
+
SingularFunction(self, "option")(f'"{str(cmd)}"')
|
|
1326
|
+
|
|
1327
|
+
def _keyboard_interrupt(self):
|
|
1328
|
+
print("Interrupting %s..." % self)
|
|
1329
|
+
try:
|
|
1330
|
+
self._expect.sendline(chr(4))
|
|
1331
|
+
except pexpect.ExceptionPexpect as msg:
|
|
1332
|
+
raise pexpect.ExceptionPexpect("THIS IS A BUG -- PLEASE REPORT. This should never happen.\n" + msg)
|
|
1333
|
+
self._start()
|
|
1334
|
+
raise KeyboardInterrupt("Restarting %s (WARNING: all variables defined in previous session are now invalid)" % self)
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
@instancedoc
|
|
1338
|
+
class SingularElement(ExtraTabCompletion, ExpectElement, sage.interfaces.abc.SingularElement):
|
|
1339
|
+
|
|
1340
|
+
def __init__(self, parent, type, value, is_name=False):
|
|
1341
|
+
"""
|
|
1342
|
+
EXAMPLES::
|
|
1343
|
+
|
|
1344
|
+
sage: a = singular(2)
|
|
1345
|
+
sage: loads(dumps(a))
|
|
1346
|
+
2
|
|
1347
|
+
"""
|
|
1348
|
+
RingElement.__init__(self, parent)
|
|
1349
|
+
if parent is None:
|
|
1350
|
+
return
|
|
1351
|
+
if not is_name:
|
|
1352
|
+
try:
|
|
1353
|
+
self._name = parent._create(value, type)
|
|
1354
|
+
# Convert SingularError to TypeError for
|
|
1355
|
+
# coercion to work properly.
|
|
1356
|
+
except SingularError as x:
|
|
1357
|
+
self._session_number = -1
|
|
1358
|
+
raise TypeError(x)
|
|
1359
|
+
except BaseException:
|
|
1360
|
+
self._session_number = -1
|
|
1361
|
+
raise
|
|
1362
|
+
else:
|
|
1363
|
+
self._name = value
|
|
1364
|
+
self._session_number = parent._session_number
|
|
1365
|
+
|
|
1366
|
+
def _repr_(self):
|
|
1367
|
+
r"""
|
|
1368
|
+
Return string representation of ``self``.
|
|
1369
|
+
|
|
1370
|
+
EXAMPLES::
|
|
1371
|
+
|
|
1372
|
+
sage: r = singular.ring(0,'(x,y)','dp')
|
|
1373
|
+
sage: singular(0)
|
|
1374
|
+
0
|
|
1375
|
+
sage: singular('x') # indirect doctest
|
|
1376
|
+
x
|
|
1377
|
+
sage: singular.matrix(2,2)
|
|
1378
|
+
0,0,
|
|
1379
|
+
0,0
|
|
1380
|
+
sage: singular.matrix(2,2,"(25/47*x^2*y^4 + 63/127*x + 27)^3,y,0,1")
|
|
1381
|
+
15625/103823*x^6*y.., y,
|
|
1382
|
+
0, 1
|
|
1383
|
+
|
|
1384
|
+
Note that the output is truncated, and if ``self`` has a custom name then
|
|
1385
|
+
it is used to print the items of the matrix, rather than abbreviating its
|
|
1386
|
+
contents::
|
|
1387
|
+
|
|
1388
|
+
sage: M = singular.matrix(2,2,"(25/47*x^2*y^4 + 63/127*x + 27)^3,y,0,1")
|
|
1389
|
+
sage: M.rename('T')
|
|
1390
|
+
sage: M
|
|
1391
|
+
T[1,1],y,
|
|
1392
|
+
0, 1
|
|
1393
|
+
"""
|
|
1394
|
+
s = super()._repr_()
|
|
1395
|
+
if self._name in s:
|
|
1396
|
+
if self.get_custom_name() is None and self.type() == 'matrix':
|
|
1397
|
+
s = self.parent().eval('pmat(%s,20)' % (self.name()))
|
|
1398
|
+
# compatibility for singular 4.3.2p10 and before
|
|
1399
|
+
if s.startswith("polynomial ring,"):
|
|
1400
|
+
from sage.rings.polynomial.term_order import singular_name_mapping
|
|
1401
|
+
from sage.repl.rich_output import get_display_manager
|
|
1402
|
+
# this is our cue that singular uses `rp` instead of `ip`
|
|
1403
|
+
if singular_name_mapping['invlex'] == 'rp' and 'doctest' in str(get_display_manager()):
|
|
1404
|
+
s = re.sub('^(// .*block.* : ordering )rp$', '\\1ip',
|
|
1405
|
+
s, flags=re.MULTILINE)
|
|
1406
|
+
return s
|
|
1407
|
+
|
|
1408
|
+
def __copy__(self):
|
|
1409
|
+
r"""
|
|
1410
|
+
Return a copy of ``self``.
|
|
1411
|
+
|
|
1412
|
+
EXAMPLES::
|
|
1413
|
+
|
|
1414
|
+
sage: R=singular.ring(0,'(x,y)','dp')
|
|
1415
|
+
sage: M=singular.matrix(3,3,'0,0,-x, 0,y,0, x*y,0,0')
|
|
1416
|
+
sage: N=copy(M)
|
|
1417
|
+
sage: N[1,1]=singular('x+y')
|
|
1418
|
+
sage: N
|
|
1419
|
+
x+y,0,-x,
|
|
1420
|
+
0, y,0,
|
|
1421
|
+
x*y,0,0
|
|
1422
|
+
sage: M
|
|
1423
|
+
0, 0,-x,
|
|
1424
|
+
0, y,0,
|
|
1425
|
+
x*y,0,0
|
|
1426
|
+
sage: L=R.ringlist()
|
|
1427
|
+
sage: L[4]=singular.ideal('x**2-5')
|
|
1428
|
+
sage: Q=L.ring()
|
|
1429
|
+
sage: otherR=singular.ring(5,'(x)','dp')
|
|
1430
|
+
sage: cpQ=copy(Q)
|
|
1431
|
+
sage: cpQ.set_ring()
|
|
1432
|
+
sage: cpQ
|
|
1433
|
+
polynomial ring, over a field, global ordering
|
|
1434
|
+
// coefficients: QQ...
|
|
1435
|
+
// number of vars : 2
|
|
1436
|
+
// block 1 : ordering dp
|
|
1437
|
+
// : names x y
|
|
1438
|
+
// block 2 : ordering C
|
|
1439
|
+
// quotient ring from ideal
|
|
1440
|
+
_[1]=x^2-5
|
|
1441
|
+
sage: R.fetch(M)
|
|
1442
|
+
0, 0,-x,
|
|
1443
|
+
0, y,0,
|
|
1444
|
+
x*y,0,0
|
|
1445
|
+
"""
|
|
1446
|
+
if (self.type() == 'ring') or (self.type() == 'qring'):
|
|
1447
|
+
# Problem: singular has no clean method to produce
|
|
1448
|
+
# a copy of a ring/qring. We use ringlist, but this
|
|
1449
|
+
# is only possible if we make self the active ring,
|
|
1450
|
+
# use ringlist, and switch back to the previous
|
|
1451
|
+
# base ring.
|
|
1452
|
+
br = self.parent().current_ring()
|
|
1453
|
+
self.set_ring()
|
|
1454
|
+
OUT = (self.ringlist()).ring()
|
|
1455
|
+
br.set_ring()
|
|
1456
|
+
return OUT
|
|
1457
|
+
else:
|
|
1458
|
+
return self.parent()(self.name())
|
|
1459
|
+
|
|
1460
|
+
def __len__(self):
|
|
1461
|
+
"""
|
|
1462
|
+
Return the size of this Singular element.
|
|
1463
|
+
|
|
1464
|
+
EXAMPLES::
|
|
1465
|
+
|
|
1466
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
1467
|
+
sage: A = singular.matrix(2,2)
|
|
1468
|
+
sage: len(A)
|
|
1469
|
+
4
|
|
1470
|
+
"""
|
|
1471
|
+
return int(self.size())
|
|
1472
|
+
|
|
1473
|
+
def __setitem__(self, n, value):
|
|
1474
|
+
"""
|
|
1475
|
+
Set the `n`-th element of ``self`` to `x`.
|
|
1476
|
+
|
|
1477
|
+
INPUT:
|
|
1478
|
+
|
|
1479
|
+
- ``n`` -- integer *or* a 2-tuple (for setting
|
|
1480
|
+
matrix elements)
|
|
1481
|
+
|
|
1482
|
+
- ``value`` -- anything (is coerced to a Singular
|
|
1483
|
+
object if it is not one already)
|
|
1484
|
+
|
|
1485
|
+
OUTPUT: changes elements of ``self``
|
|
1486
|
+
|
|
1487
|
+
EXAMPLES::
|
|
1488
|
+
|
|
1489
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
1490
|
+
sage: A = singular.matrix(2,2)
|
|
1491
|
+
sage: A
|
|
1492
|
+
0,0,
|
|
1493
|
+
0,0
|
|
1494
|
+
sage: A[1,1] = 5
|
|
1495
|
+
sage: A
|
|
1496
|
+
5,0,
|
|
1497
|
+
0,0
|
|
1498
|
+
sage: A[1,2] = '5*x + y + z3'
|
|
1499
|
+
sage: A
|
|
1500
|
+
5,z^3+5*x+y,
|
|
1501
|
+
0,0
|
|
1502
|
+
"""
|
|
1503
|
+
P = self.parent()
|
|
1504
|
+
if not isinstance(value, SingularElement):
|
|
1505
|
+
value = P(value)
|
|
1506
|
+
if isinstance(n, tuple):
|
|
1507
|
+
if len(n) != 2:
|
|
1508
|
+
raise ValueError("If n (=%s) is a tuple, it must be a 2-tuple" % n)
|
|
1509
|
+
x, y = n
|
|
1510
|
+
P.eval('%s[%s,%s] = %s' % (self.name(), x, y, value.name()))
|
|
1511
|
+
else:
|
|
1512
|
+
P.eval('%s[%s] = %s' % (self.name(), n, value.name()))
|
|
1513
|
+
|
|
1514
|
+
def __bool__(self):
|
|
1515
|
+
"""
|
|
1516
|
+
Return ``True`` if this Singular element is not zero.
|
|
1517
|
+
|
|
1518
|
+
EXAMPLES::
|
|
1519
|
+
|
|
1520
|
+
sage: bool(singular(0))
|
|
1521
|
+
False
|
|
1522
|
+
sage: bool(singular(1))
|
|
1523
|
+
True
|
|
1524
|
+
"""
|
|
1525
|
+
P = self.parent()
|
|
1526
|
+
return P.eval('%s == 0' % self.name()) == '0'
|
|
1527
|
+
|
|
1528
|
+
def sage_polystring(self):
|
|
1529
|
+
r"""
|
|
1530
|
+
If this Singular element is a polynomial, return a string
|
|
1531
|
+
representation of this polynomial that is suitable for evaluation
|
|
1532
|
+
in Python. Thus \* is used for multiplication and \*\* for
|
|
1533
|
+
exponentiation. This function is primarily used internally.
|
|
1534
|
+
|
|
1535
|
+
The short=0 option *must* be set for the parent ring or this
|
|
1536
|
+
function will not work as expected. This option is set by default
|
|
1537
|
+
for rings created using ``singular.ring`` or set using
|
|
1538
|
+
``ring_name.set_ring()``.
|
|
1539
|
+
|
|
1540
|
+
EXAMPLES::
|
|
1541
|
+
|
|
1542
|
+
sage: R = singular.ring(0,'(x,y)')
|
|
1543
|
+
sage: f = singular('x^3 + 3*y^11 + 5')
|
|
1544
|
+
sage: f
|
|
1545
|
+
x^3+3*y^11+5
|
|
1546
|
+
sage: f.sage_polystring()
|
|
1547
|
+
'x**3+3*y**11+5'
|
|
1548
|
+
"""
|
|
1549
|
+
return str(self).replace('^', '**')
|
|
1550
|
+
|
|
1551
|
+
def sage_global_ring(self):
|
|
1552
|
+
"""
|
|
1553
|
+
Return the current basering in Singular as a polynomial ring or quotient ring.
|
|
1554
|
+
|
|
1555
|
+
EXAMPLES::
|
|
1556
|
+
|
|
1557
|
+
sage: singular.eval('ring r1 = (9,x),(a,b,c,d,e,f),(M((1,2,3,0)),wp(2,3),lp)')
|
|
1558
|
+
''
|
|
1559
|
+
sage: R = singular('r1').sage_global_ring()
|
|
1560
|
+
sage: R
|
|
1561
|
+
Multivariate Polynomial Ring in a, b, c, d, e, f over Finite Field in x of size 3^2
|
|
1562
|
+
sage: R.term_order()
|
|
1563
|
+
Block term order with blocks:
|
|
1564
|
+
(Matrix term order with matrix
|
|
1565
|
+
[1 2]
|
|
1566
|
+
[3 0],
|
|
1567
|
+
Weighted degree reverse lexicographic term order with weights (2, 3),
|
|
1568
|
+
Lexicographic term order of length 2)
|
|
1569
|
+
|
|
1570
|
+
::
|
|
1571
|
+
|
|
1572
|
+
sage: singular.eval('ring r2 = (0,x),(a,b,c),dp')
|
|
1573
|
+
''
|
|
1574
|
+
sage: singular('r2').sage_global_ring()
|
|
1575
|
+
Multivariate Polynomial Ring in a, b, c over Fraction Field of Univariate Polynomial Ring in x over Rational Field
|
|
1576
|
+
|
|
1577
|
+
::
|
|
1578
|
+
|
|
1579
|
+
sage: singular.eval('ring r3 = (3,z),(a,b,c),dp')
|
|
1580
|
+
''
|
|
1581
|
+
sage: singular.eval('minpoly = 1+z+z2+z3+z4')
|
|
1582
|
+
''
|
|
1583
|
+
sage: singular('r3').sage_global_ring()
|
|
1584
|
+
Multivariate Polynomial Ring in a, b, c over Finite Field in z of size 3^4
|
|
1585
|
+
|
|
1586
|
+
Real and complex fields in both Singular and Sage are defined with a precision.
|
|
1587
|
+
The precision in Singular is given in terms of digits, but in Sage it is given
|
|
1588
|
+
in terms of bits. So, the digit precision is internally converted to a reasonable
|
|
1589
|
+
bit precision::
|
|
1590
|
+
|
|
1591
|
+
sage: singular.eval('ring r4 = (real,20),(a,b,c),dp')
|
|
1592
|
+
''
|
|
1593
|
+
sage: singular('r4').sage_global_ring()
|
|
1594
|
+
Multivariate Polynomial Ring in a, b, c over Real Field with 70 bits of precision
|
|
1595
|
+
|
|
1596
|
+
The case of complex coefficients is not fully supported, yet, since
|
|
1597
|
+
the generator of a complex field in Sage is always called "I"::
|
|
1598
|
+
|
|
1599
|
+
sage: singular.eval('ring r5 = (complex,15,j),(a,b,c),dp')
|
|
1600
|
+
''
|
|
1601
|
+
sage: R = singular('r5').sage_global_ring(); R
|
|
1602
|
+
Multivariate Polynomial Ring in a, b, c over Complex Field with 54 bits of precision
|
|
1603
|
+
sage: R.base_ring()('k')
|
|
1604
|
+
Traceback (most recent call last):
|
|
1605
|
+
...
|
|
1606
|
+
ValueError: given string 'k' is not a complex number
|
|
1607
|
+
sage: R.base_ring()('I')
|
|
1608
|
+
1.00000000000000*I
|
|
1609
|
+
|
|
1610
|
+
An example where the base ring is a polynomial ring over an extension of the rational field::
|
|
1611
|
+
|
|
1612
|
+
sage: singular.eval('ring r7 = (0,a), (x,y), dp')
|
|
1613
|
+
''
|
|
1614
|
+
sage: singular.eval('minpoly = a2 + 1')
|
|
1615
|
+
''
|
|
1616
|
+
sage: singular('r7').sage_global_ring()
|
|
1617
|
+
Multivariate Polynomial Ring in x, y over Number Field in a with defining polynomial a^2 + 1
|
|
1618
|
+
|
|
1619
|
+
In our last example, the base ring is a quotient ring::
|
|
1620
|
+
|
|
1621
|
+
sage: singular.eval('ring r6 = (9,a), (x,y,z),lp')
|
|
1622
|
+
''
|
|
1623
|
+
sage: Q = singular('std(ideal(x^2,x+y^2+z^3))', type='qring')
|
|
1624
|
+
sage: Q.sage_global_ring()
|
|
1625
|
+
Quotient of Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2 by the ideal (y^4 - y^2*z^3 + z^6, x + y^2 + z^3)
|
|
1626
|
+
|
|
1627
|
+
AUTHOR:
|
|
1628
|
+
|
|
1629
|
+
- Simon King (2011-06-06)
|
|
1630
|
+
"""
|
|
1631
|
+
# extract the ring of coefficients
|
|
1632
|
+
singular = self.parent()
|
|
1633
|
+
charstr = singular.eval('charstr(basering)').split(',', 1)
|
|
1634
|
+
from sage.rings.integer_ring import ZZ
|
|
1635
|
+
is_extension = len(charstr) == 2
|
|
1636
|
+
if charstr[0] in ['integer', 'ZZ']:
|
|
1637
|
+
br = ZZ
|
|
1638
|
+
is_extension = False
|
|
1639
|
+
elif charstr[0] in ['0', 'QQ']:
|
|
1640
|
+
from sage.rings.rational_field import QQ
|
|
1641
|
+
br = QQ
|
|
1642
|
+
elif charstr[0].startswith('Float'):
|
|
1643
|
+
from sage.rings.real_mpfr import RealField
|
|
1644
|
+
from sage.functions.other import ceil
|
|
1645
|
+
from sage.misc.functional import log
|
|
1646
|
+
prec = singular.eval('ringlist(basering)[1][2][1]')
|
|
1647
|
+
br = RealField(ceil((ZZ(prec) + 1) / log(2, 10)))
|
|
1648
|
+
is_extension = False
|
|
1649
|
+
elif charstr[0] == 'complex':
|
|
1650
|
+
from sage.rings.complex_mpfr import ComplexField
|
|
1651
|
+
from sage.functions.other import ceil
|
|
1652
|
+
from sage.misc.functional import log
|
|
1653
|
+
prec = singular.eval('ringlist(basering)[1][2][1]')
|
|
1654
|
+
br = ComplexField(ceil((ZZ(prec) + 1) / log(2, 10)))
|
|
1655
|
+
is_extension = False
|
|
1656
|
+
else:
|
|
1657
|
+
# it ought to be a finite field
|
|
1658
|
+
q = ZZ(charstr[0].lstrip('ZZ/'))
|
|
1659
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
1660
|
+
if q.is_prime():
|
|
1661
|
+
br = GF(q)
|
|
1662
|
+
else:
|
|
1663
|
+
br = GF(q, charstr[1])
|
|
1664
|
+
# Singular has no extension of a non-prime field
|
|
1665
|
+
is_extension = False
|
|
1666
|
+
|
|
1667
|
+
# We have the base ring of the base ring. But is it
|
|
1668
|
+
# an extension?
|
|
1669
|
+
if is_extension:
|
|
1670
|
+
minpoly = singular.eval('minpoly')
|
|
1671
|
+
if minpoly == '0':
|
|
1672
|
+
from sage.rings.fraction_field import FractionField as Frac
|
|
1673
|
+
BR = Frac(br[charstr[1]])
|
|
1674
|
+
else:
|
|
1675
|
+
is_short = singular.eval('short')
|
|
1676
|
+
if is_short != '0':
|
|
1677
|
+
singular.eval('short=0')
|
|
1678
|
+
minpoly = ZZ[charstr[1]](singular.eval('minpoly'))
|
|
1679
|
+
singular.eval('short=%s' % is_short)
|
|
1680
|
+
else:
|
|
1681
|
+
minpoly = ZZ[charstr[1]](minpoly)
|
|
1682
|
+
BR = br.extension(minpoly, names=charstr[1])
|
|
1683
|
+
else:
|
|
1684
|
+
BR = br
|
|
1685
|
+
|
|
1686
|
+
# Now, we form the polynomial ring over BR with the given variables,
|
|
1687
|
+
# using Singular's term order
|
|
1688
|
+
from sage.rings.polynomial.term_order import termorder_from_singular
|
|
1689
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
1690
|
+
# Meanwhile Singulars quotient rings are also of 'ring' type, not 'qring' as it was in the past.
|
|
1691
|
+
# To find out if a singular ring is a quotient ring or not checking for ring type does not help
|
|
1692
|
+
# and instead of that we check if the quotient ring is zero or not:
|
|
1693
|
+
if (singular.eval('ideal(basering)==0') == '1'):
|
|
1694
|
+
return PolynomialRing(BR, names=singular.eval('varstr(basering)'), order=termorder_from_singular(singular))
|
|
1695
|
+
P = PolynomialRing(BR, names=singular.eval('varstr(basering)'), order=termorder_from_singular(singular))
|
|
1696
|
+
return P.quotient(singular('ringlist(basering)[4]')._sage_(P), names=singular.eval('varstr(basering)'))
|
|
1697
|
+
|
|
1698
|
+
def sage_poly(self, R=None, kcache=None):
|
|
1699
|
+
"""
|
|
1700
|
+
Return a Sage polynomial in the ring r matching the provided poly
|
|
1701
|
+
which is a singular polynomial.
|
|
1702
|
+
|
|
1703
|
+
INPUT:
|
|
1704
|
+
|
|
1705
|
+
- ``R`` -- (default: ``None``) an optional polynomial ring.
|
|
1706
|
+
If it is provided, then you have to make sure that it
|
|
1707
|
+
matches the current singular ring as, e.g., returned by
|
|
1708
|
+
``singular.current_ring()``. By default, the output of
|
|
1709
|
+
:meth:`sage_global_ring` is used.
|
|
1710
|
+
|
|
1711
|
+
- ``kcache`` -- (default: ``None``) an optional dictionary
|
|
1712
|
+
for faster finite field lookups, this is mainly useful for finite
|
|
1713
|
+
extension fields
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
OUTPUT: MPolynomial
|
|
1717
|
+
|
|
1718
|
+
EXAMPLES::
|
|
1719
|
+
|
|
1720
|
+
sage: R = PolynomialRing(GF(2^8,'a'), 'x,y')
|
|
1721
|
+
sage: f = R('a^20*x^2*y+a^10+x')
|
|
1722
|
+
sage: f._singular_().sage_poly(R) == f
|
|
1723
|
+
True
|
|
1724
|
+
sage: R = PolynomialRing(GF(2^8,'a'), 'x', implementation='singular')
|
|
1725
|
+
sage: f = R('a^20*x^3+x^2+a^10')
|
|
1726
|
+
sage: f._singular_().sage_poly(R) == f
|
|
1727
|
+
True
|
|
1728
|
+
|
|
1729
|
+
::
|
|
1730
|
+
|
|
1731
|
+
sage: P.<x,y> = PolynomialRing(QQ, 2)
|
|
1732
|
+
sage: f = x*y**3 - 1/9 * x + 1; f
|
|
1733
|
+
x*y^3 - 1/9*x + 1
|
|
1734
|
+
sage: singular(f)
|
|
1735
|
+
x*y^3-1/9*x+1
|
|
1736
|
+
sage: P(singular(f))
|
|
1737
|
+
x*y^3 - 1/9*x + 1
|
|
1738
|
+
|
|
1739
|
+
TESTS::
|
|
1740
|
+
|
|
1741
|
+
sage: singular.eval('ring r = (3,z),(a,b,c),dp')
|
|
1742
|
+
''
|
|
1743
|
+
sage: singular.eval('minpoly = 1+z+z2+z3+z4')
|
|
1744
|
+
''
|
|
1745
|
+
sage: p = singular('z^4*a^3+z^2*a*b*c')
|
|
1746
|
+
sage: p.sage_poly()
|
|
1747
|
+
(-z^3 - z^2 - z - 1)*a^3 + (z^2)*a*b*c
|
|
1748
|
+
sage: singular('z^4')
|
|
1749
|
+
(-z3-z2-z-1)
|
|
1750
|
+
|
|
1751
|
+
Test that :issue:`25297` is fixed::
|
|
1752
|
+
|
|
1753
|
+
sage: R.<x,y> = QQ[]
|
|
1754
|
+
sage: SE.<xbar,ybar> = R.quotient(x^2 + y^2 - 1)
|
|
1755
|
+
sage: P = ideal(xbar,ybar)
|
|
1756
|
+
sage: P2 = P._singular_().sage()
|
|
1757
|
+
sage: P2.0.lift().parent()
|
|
1758
|
+
Multivariate Polynomial Ring in x, y over Rational Field
|
|
1759
|
+
|
|
1760
|
+
Test that :issue:`29396` is fixed::
|
|
1761
|
+
|
|
1762
|
+
sage: Rxz.<x,z> = RR[]
|
|
1763
|
+
sage: f = x**3 + x*z + 1
|
|
1764
|
+
sage: f.discriminant(x)
|
|
1765
|
+
-4.00000000000000*z^3 - 27.0000000000000
|
|
1766
|
+
sage: Rx.<x> = RR[]
|
|
1767
|
+
sage: Rx("x + 7.5")._singular_().sage_poly()
|
|
1768
|
+
x + 7.50000
|
|
1769
|
+
sage: Rx("x + 7.5")._singular_().sage_poly(Rx)
|
|
1770
|
+
x + 7.50000000000000
|
|
1771
|
+
|
|
1772
|
+
AUTHORS:
|
|
1773
|
+
|
|
1774
|
+
- Martin Albrecht (2006-05-18)
|
|
1775
|
+
- Simon King (2011-06-06): Deal with Singular's short polynomial representation,
|
|
1776
|
+
automatic construction of a polynomial ring, if it is not explicitly given.
|
|
1777
|
+
|
|
1778
|
+
.. NOTE::
|
|
1779
|
+
|
|
1780
|
+
For very simple polynomials
|
|
1781
|
+
``eval(SingularElement.sage_polystring())`` is faster than
|
|
1782
|
+
SingularElement.sage_poly(R), maybe we should detect the
|
|
1783
|
+
crossover point (in dependence of the string length) and
|
|
1784
|
+
choose an appropriate conversion strategy
|
|
1785
|
+
"""
|
|
1786
|
+
# TODO: Refactor imports to move this to the top
|
|
1787
|
+
from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict
|
|
1788
|
+
from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular
|
|
1789
|
+
from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
|
|
1790
|
+
from sage.rings.polynomial.polydict import ETuple
|
|
1791
|
+
from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular
|
|
1792
|
+
from sage.rings.quotient_ring import QuotientRing_generic
|
|
1793
|
+
|
|
1794
|
+
ring_is_fine = False
|
|
1795
|
+
if R is None:
|
|
1796
|
+
ring_is_fine = True
|
|
1797
|
+
R = self.sage_global_ring()
|
|
1798
|
+
|
|
1799
|
+
if isinstance(R, QuotientRing_generic) and (ring_is_fine or can_convert_to_singular(R)):
|
|
1800
|
+
p = self.sage_poly(R.ambient(), kcache)
|
|
1801
|
+
return R(p)
|
|
1802
|
+
|
|
1803
|
+
sage_repr = {}
|
|
1804
|
+
k = R.base_ring()
|
|
1805
|
+
|
|
1806
|
+
variable_str = "*".join(R.variable_names())
|
|
1807
|
+
|
|
1808
|
+
# This returns a string which looks like a list where the first
|
|
1809
|
+
# half of the list is filled with monomials occurring in the
|
|
1810
|
+
# Singular polynomial and the second half filled with the matching
|
|
1811
|
+
# coefficients.
|
|
1812
|
+
#
|
|
1813
|
+
# Our strategy is to split the monomials at "*" to get the powers
|
|
1814
|
+
# in the single variables and then to split the result to get
|
|
1815
|
+
# actual exponent.
|
|
1816
|
+
#
|
|
1817
|
+
# So e.g. ['x^3*y^3','a'] get's split to
|
|
1818
|
+
# [[['x','3'],['y','3']],'a']. We may do this quickly,
|
|
1819
|
+
# as we know what to expect.
|
|
1820
|
+
|
|
1821
|
+
is_short = self.parent().eval('short')
|
|
1822
|
+
if is_short != '0':
|
|
1823
|
+
self.parent().eval('short=0')
|
|
1824
|
+
if isinstance(R, MPolynomialRing_libsingular):
|
|
1825
|
+
out = R(self)
|
|
1826
|
+
self.parent().eval('short=%s' % is_short)
|
|
1827
|
+
return out
|
|
1828
|
+
singular_poly_list = self.parent().eval("string(coef(%s,%s))" % (
|
|
1829
|
+
self.name(), variable_str)).split(",")
|
|
1830
|
+
self.parent().eval('short=%s' % is_short)
|
|
1831
|
+
else:
|
|
1832
|
+
if isinstance(R, MPolynomialRing_libsingular):
|
|
1833
|
+
return R(self)
|
|
1834
|
+
singular_poly_list = self.parent().eval("string(coef(%s,%s))" % (
|
|
1835
|
+
self.name(), variable_str)).split(",")
|
|
1836
|
+
|
|
1837
|
+
# Directly treat constants
|
|
1838
|
+
if singular_poly_list[0] in ['1', '(1.000e+00)']:
|
|
1839
|
+
return R(singular_poly_list[1])
|
|
1840
|
+
|
|
1841
|
+
coeff_start = len(singular_poly_list) // 2
|
|
1842
|
+
|
|
1843
|
+
# Singular 4 puts parentheses around floats and sign outside them
|
|
1844
|
+
charstr = self.parent().eval('charstr(basering)').split(',', 1)
|
|
1845
|
+
if charstr[0].startswith('Float') or charstr[0] == 'complex':
|
|
1846
|
+
for i in range(coeff_start, 2 * coeff_start):
|
|
1847
|
+
singular_poly_list[i] = singular_poly_list[i].replace('(', '').replace(')', '')
|
|
1848
|
+
|
|
1849
|
+
if isinstance(R, MPolynomialRing_polydict) and (ring_is_fine or can_convert_to_singular(R)):
|
|
1850
|
+
# we need to lookup the index of a given variable represented
|
|
1851
|
+
# through a string
|
|
1852
|
+
var_dict = dict(zip(R.variable_names(), range(R.ngens())))
|
|
1853
|
+
|
|
1854
|
+
ngens = R.ngens()
|
|
1855
|
+
|
|
1856
|
+
for i in range(coeff_start):
|
|
1857
|
+
exp = dict()
|
|
1858
|
+
monomial = singular_poly_list[i]
|
|
1859
|
+
|
|
1860
|
+
if monomial not in ['1', '(1.000e+00)']:
|
|
1861
|
+
variables = [var.split("^") for var in monomial.split("*")]
|
|
1862
|
+
for e in variables:
|
|
1863
|
+
var = e[0]
|
|
1864
|
+
if len(e) == 2:
|
|
1865
|
+
power = int(e[1])
|
|
1866
|
+
else:
|
|
1867
|
+
power = 1
|
|
1868
|
+
exp[var_dict[var]] = power
|
|
1869
|
+
|
|
1870
|
+
if kcache is None:
|
|
1871
|
+
sage_repr[ETuple(exp, ngens)] = k(singular_poly_list[coeff_start + i])
|
|
1872
|
+
else:
|
|
1873
|
+
elem = singular_poly_list[coeff_start + i]
|
|
1874
|
+
if elem not in kcache:
|
|
1875
|
+
kcache[elem] = k(elem)
|
|
1876
|
+
sage_repr[ETuple(exp, ngens)] = kcache[elem]
|
|
1877
|
+
|
|
1878
|
+
return R(sage_repr)
|
|
1879
|
+
|
|
1880
|
+
elif isinstance(R, PolynomialRing_generic) and (ring_is_fine or can_convert_to_singular(R)):
|
|
1881
|
+
|
|
1882
|
+
sage_repr = [0] * int(self.deg() + 1)
|
|
1883
|
+
|
|
1884
|
+
for i in range(coeff_start):
|
|
1885
|
+
monomial = singular_poly_list[i]
|
|
1886
|
+
exp = 0
|
|
1887
|
+
|
|
1888
|
+
if monomial not in ['1', '(1.000e+00)']:
|
|
1889
|
+
term = monomial.split("^")
|
|
1890
|
+
if len(term) == 2:
|
|
1891
|
+
exp = int(term[1])
|
|
1892
|
+
else:
|
|
1893
|
+
exp = 1
|
|
1894
|
+
|
|
1895
|
+
if kcache is None:
|
|
1896
|
+
sage_repr[exp] = k(singular_poly_list[coeff_start + i])
|
|
1897
|
+
else:
|
|
1898
|
+
elem = singular_poly_list[coeff_start + i]
|
|
1899
|
+
if elem not in kcache:
|
|
1900
|
+
kcache[elem] = k(elem)
|
|
1901
|
+
sage_repr[exp] = kcache[elem]
|
|
1902
|
+
|
|
1903
|
+
return R(sage_repr)
|
|
1904
|
+
|
|
1905
|
+
else:
|
|
1906
|
+
raise TypeError("Cannot coerce %s into %s" % (self, R))
|
|
1907
|
+
|
|
1908
|
+
def sage_matrix(self, R, sparse=True):
|
|
1909
|
+
"""
|
|
1910
|
+
Return Sage matrix for ``self``.
|
|
1911
|
+
|
|
1912
|
+
INPUT:
|
|
1913
|
+
|
|
1914
|
+
- ``R`` -- (default: ``None``) an optional ring, over which
|
|
1915
|
+
the resulting matrix is going to be defined.
|
|
1916
|
+
By default, the output of :meth:`sage_global_ring` is used.
|
|
1917
|
+
|
|
1918
|
+
- ``sparse`` -- boolean (default: ``True``); whether the
|
|
1919
|
+
resulting matrix is sparse or not
|
|
1920
|
+
|
|
1921
|
+
EXAMPLES::
|
|
1922
|
+
|
|
1923
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
1924
|
+
sage: A = singular.matrix(2,2)
|
|
1925
|
+
sage: A.sage_matrix(ZZ)
|
|
1926
|
+
[0 0]
|
|
1927
|
+
[0 0]
|
|
1928
|
+
sage: A.sage_matrix(RDF)
|
|
1929
|
+
[0.0 0.0]
|
|
1930
|
+
[0.0 0.0]
|
|
1931
|
+
"""
|
|
1932
|
+
from sage.matrix.constructor import matrix
|
|
1933
|
+
nrows, ncols = int(self.nrows()), int(self.ncols())
|
|
1934
|
+
|
|
1935
|
+
if R is None:
|
|
1936
|
+
R = self.sage_global_ring()
|
|
1937
|
+
A = matrix(R, nrows, ncols, sparse=sparse)
|
|
1938
|
+
# this is slow
|
|
1939
|
+
for x in range(nrows):
|
|
1940
|
+
for y in range(ncols):
|
|
1941
|
+
A[x, y] = self[x + 1, y + 1].sage_poly(R)
|
|
1942
|
+
return A
|
|
1943
|
+
|
|
1944
|
+
A = matrix(R, nrows, ncols, sparse=sparse)
|
|
1945
|
+
# this is slow
|
|
1946
|
+
for x in range(nrows):
|
|
1947
|
+
for y in range(ncols):
|
|
1948
|
+
A[x, y] = R(self[x + 1, y + 1])
|
|
1949
|
+
|
|
1950
|
+
return A
|
|
1951
|
+
|
|
1952
|
+
def _sage_(self, R=None):
|
|
1953
|
+
r"""
|
|
1954
|
+
Convert ``self`` to Sage.
|
|
1955
|
+
|
|
1956
|
+
EXAMPLES::
|
|
1957
|
+
|
|
1958
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
1959
|
+
sage: A = singular.matrix(2,2)
|
|
1960
|
+
sage: A.sage(ZZ) # indirect doctest
|
|
1961
|
+
[0 0]
|
|
1962
|
+
[0 0]
|
|
1963
|
+
sage: A = random_matrix(ZZ,3,3); A # random
|
|
1964
|
+
[ -8 2 0]
|
|
1965
|
+
[ 0 1 -1]
|
|
1966
|
+
[ 2 1 -95]
|
|
1967
|
+
sage: As = singular(A); As # random
|
|
1968
|
+
-8 2 0
|
|
1969
|
+
0 1 -1
|
|
1970
|
+
2 1 -95
|
|
1971
|
+
sage: As.sage() == A
|
|
1972
|
+
True
|
|
1973
|
+
|
|
1974
|
+
::
|
|
1975
|
+
|
|
1976
|
+
sage: singular.eval('ring R = integer, (x,y,z),lp')
|
|
1977
|
+
'// ** redefining R (ring R = integer, (x,y,z),lp;)'
|
|
1978
|
+
sage: I = singular.ideal(['x^2','y*z','z+x'])
|
|
1979
|
+
sage: I.sage()
|
|
1980
|
+
Ideal (x^2, y*z, x + z) of Multivariate Polynomial Ring in x, y, z over Integer Ring
|
|
1981
|
+
|
|
1982
|
+
::
|
|
1983
|
+
|
|
1984
|
+
sage: singular('ringlist(basering)').sage()
|
|
1985
|
+
[['integer'], ['x', 'y', 'z'], [['lp', (1, 1, 1)], ['C', (0)]], Ideal (0) of Multivariate Polynomial Ring in x, y, z over Integer Ring]
|
|
1986
|
+
|
|
1987
|
+
::
|
|
1988
|
+
|
|
1989
|
+
sage: singular.eval('ring r10 = (9,a), (x,y,z),lp')
|
|
1990
|
+
''
|
|
1991
|
+
sage: singular.eval('setring R')
|
|
1992
|
+
''
|
|
1993
|
+
sage: singular('r10').sage()
|
|
1994
|
+
Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2
|
|
1995
|
+
|
|
1996
|
+
Note that the current base ring has not been changed by asking for another ring::
|
|
1997
|
+
|
|
1998
|
+
sage: singular('basering')
|
|
1999
|
+
polynomial ring, over a domain, global ordering
|
|
2000
|
+
// coefficients: ZZ...
|
|
2001
|
+
// number of vars : 3
|
|
2002
|
+
// block 1 : ordering lp
|
|
2003
|
+
// : names x y z
|
|
2004
|
+
// block 2 : ordering C
|
|
2005
|
+
|
|
2006
|
+
::
|
|
2007
|
+
|
|
2008
|
+
sage: singular.eval('setring r10')
|
|
2009
|
+
''
|
|
2010
|
+
sage: Q = singular('std(ideal(x^2,x+y^2+z^3))', type='qring')
|
|
2011
|
+
sage: Q.sage()
|
|
2012
|
+
Quotient of Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2 by the ideal (y^4 - y^2*z^3 + z^6, x + y^2 + z^3)
|
|
2013
|
+
sage: singular('x^2+y').sage()
|
|
2014
|
+
y
|
|
2015
|
+
sage: singular('x^2+y').sage().parent()
|
|
2016
|
+
Quotient of Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 3^2 by the ideal (y^4 - y^2*z^3 + z^6, x + y^2 + z^3)
|
|
2017
|
+
|
|
2018
|
+
Test that :issue:`18848` is fixed::
|
|
2019
|
+
|
|
2020
|
+
sage: singular(5).sage()
|
|
2021
|
+
5
|
|
2022
|
+
sage: type(singular(int(5)).sage())
|
|
2023
|
+
<class 'sage.rings.integer.Integer'>
|
|
2024
|
+
|
|
2025
|
+
Test that bigintvec can be coerced::
|
|
2026
|
+
|
|
2027
|
+
sage: singular('hilb((ideal(x)), 1)').sage()
|
|
2028
|
+
(1, -1, 0, 0, -1, 1, 0)
|
|
2029
|
+
"""
|
|
2030
|
+
typ = self.type()
|
|
2031
|
+
if typ == 'poly':
|
|
2032
|
+
return self.sage_poly(R)
|
|
2033
|
+
elif typ == 'int':
|
|
2034
|
+
return sage.rings.integer.Integer(repr(self))
|
|
2035
|
+
elif typ == 'module':
|
|
2036
|
+
return self.sage_matrix(R, sparse=True)
|
|
2037
|
+
elif typ == 'matrix':
|
|
2038
|
+
return self.sage_matrix(R, sparse=False)
|
|
2039
|
+
elif typ == 'list':
|
|
2040
|
+
return [f._sage_(R) for f in self]
|
|
2041
|
+
elif typ == 'intvec':
|
|
2042
|
+
from sage.modules.free_module_element import vector
|
|
2043
|
+
return vector([sage.rings.integer.Integer(str(e)) for e in self])
|
|
2044
|
+
elif typ == 'bigintvec':
|
|
2045
|
+
from sage.modules.free_module_element import vector
|
|
2046
|
+
return vector([sage.rings.rational.Rational(str(e)) for e in self])
|
|
2047
|
+
elif typ == 'intmat':
|
|
2048
|
+
from sage.matrix.constructor import matrix
|
|
2049
|
+
from sage.rings.integer_ring import ZZ
|
|
2050
|
+
A = matrix(ZZ, int(self.nrows()), int(self.ncols()))
|
|
2051
|
+
for i in range(A.nrows()):
|
|
2052
|
+
for j in range(A.ncols()):
|
|
2053
|
+
A[i, j] = sage.rings.integer.Integer(str(self[i + 1, j + 1]))
|
|
2054
|
+
return A
|
|
2055
|
+
elif typ == 'string':
|
|
2056
|
+
return repr(self)
|
|
2057
|
+
elif typ == 'ideal':
|
|
2058
|
+
R = R or self.sage_global_ring()
|
|
2059
|
+
return R.ideal([p.sage_poly(R) for p in self])
|
|
2060
|
+
elif typ in ['ring', 'qring']:
|
|
2061
|
+
br = singular('basering')
|
|
2062
|
+
self.set_ring()
|
|
2063
|
+
R = self.sage_global_ring()
|
|
2064
|
+
br.set_ring()
|
|
2065
|
+
return R
|
|
2066
|
+
raise NotImplementedError("Coercion of this datatype not implemented yet")
|
|
2067
|
+
|
|
2068
|
+
def is_string(self):
|
|
2069
|
+
"""
|
|
2070
|
+
Tell whether this element is a string.
|
|
2071
|
+
|
|
2072
|
+
EXAMPLES::
|
|
2073
|
+
|
|
2074
|
+
sage: singular('"abc"').is_string()
|
|
2075
|
+
True
|
|
2076
|
+
sage: singular('1').is_string()
|
|
2077
|
+
False
|
|
2078
|
+
"""
|
|
2079
|
+
return self.type() == 'string'
|
|
2080
|
+
|
|
2081
|
+
def set_ring(self):
|
|
2082
|
+
"""
|
|
2083
|
+
Set the current ring in Singular to be ``self``.
|
|
2084
|
+
|
|
2085
|
+
EXAMPLES::
|
|
2086
|
+
|
|
2087
|
+
sage: R = singular.ring(7, '(a,b)', 'ds')
|
|
2088
|
+
sage: S = singular.ring('real', '(a,b)', 'lp')
|
|
2089
|
+
sage: singular.current_ring()
|
|
2090
|
+
polynomial ring, over a field, global ordering
|
|
2091
|
+
// coefficients: Float()...
|
|
2092
|
+
// number of vars : 2
|
|
2093
|
+
// block 1 : ordering lp
|
|
2094
|
+
// : names a b
|
|
2095
|
+
// block 2 : ordering C
|
|
2096
|
+
sage: R.set_ring()
|
|
2097
|
+
sage: singular.current_ring()
|
|
2098
|
+
polynomial ring, over a field, local ordering
|
|
2099
|
+
// coefficients: ZZ/7...
|
|
2100
|
+
// number of vars : 2
|
|
2101
|
+
// block 1 : ordering ds
|
|
2102
|
+
// : names a b
|
|
2103
|
+
// block 2 : ordering C
|
|
2104
|
+
"""
|
|
2105
|
+
self.parent().set_ring(self)
|
|
2106
|
+
|
|
2107
|
+
def sage_flattened_str_list(self):
|
|
2108
|
+
"""
|
|
2109
|
+
EXAMPLES::
|
|
2110
|
+
|
|
2111
|
+
sage: R=singular.ring(0,'(x,y)','dp')
|
|
2112
|
+
sage: RL = R.ringlist()
|
|
2113
|
+
sage: RL.sage_flattened_str_list()
|
|
2114
|
+
['0', 'x', 'y', 'dp', '1,1', 'C', '0', '_[1]=0']
|
|
2115
|
+
"""
|
|
2116
|
+
s = str(self)
|
|
2117
|
+
c = r'\[[0-9]*\]:'
|
|
2118
|
+
r = re.compile(c)
|
|
2119
|
+
s = r.sub('', s).strip()
|
|
2120
|
+
return s.split()
|
|
2121
|
+
|
|
2122
|
+
def sage_structured_str_list(self):
|
|
2123
|
+
r"""
|
|
2124
|
+
If ``self`` is a Singular list of lists of Singular elements, return
|
|
2125
|
+
corresponding Sage list of lists of strings.
|
|
2126
|
+
|
|
2127
|
+
EXAMPLES::
|
|
2128
|
+
|
|
2129
|
+
sage: R=singular.ring(0,'(x,y)','dp')
|
|
2130
|
+
sage: RL=R.ringlist()
|
|
2131
|
+
sage: RL
|
|
2132
|
+
[1]:
|
|
2133
|
+
0
|
|
2134
|
+
[2]:
|
|
2135
|
+
[1]:
|
|
2136
|
+
x
|
|
2137
|
+
[2]:
|
|
2138
|
+
y
|
|
2139
|
+
[3]:
|
|
2140
|
+
[1]:
|
|
2141
|
+
[1]:
|
|
2142
|
+
dp
|
|
2143
|
+
[2]:
|
|
2144
|
+
1,1
|
|
2145
|
+
[2]:
|
|
2146
|
+
[1]:
|
|
2147
|
+
C
|
|
2148
|
+
[2]:
|
|
2149
|
+
0
|
|
2150
|
+
[4]:
|
|
2151
|
+
_[1]=0
|
|
2152
|
+
sage: RL.sage_structured_str_list()
|
|
2153
|
+
['0', ['x', 'y'], [['dp', '1,\n1'], ['C', '0']], '0']
|
|
2154
|
+
"""
|
|
2155
|
+
if self.type() != 'list':
|
|
2156
|
+
return str(self)
|
|
2157
|
+
return [X.sage_structured_str_list() for X in self]
|
|
2158
|
+
|
|
2159
|
+
def _tab_completion(self) -> list:
|
|
2160
|
+
"""
|
|
2161
|
+
Return the possible tab-completions for ``self``.
|
|
2162
|
+
|
|
2163
|
+
In this case, we just return all the :kbd:`Tab` completions
|
|
2164
|
+
for the Singular object.
|
|
2165
|
+
|
|
2166
|
+
EXAMPLES::
|
|
2167
|
+
|
|
2168
|
+
sage: R = singular.ring(0,'(x,y)','dp')
|
|
2169
|
+
sage: R._tab_completion()
|
|
2170
|
+
['exteriorPower',
|
|
2171
|
+
...
|
|
2172
|
+
'crossprod']
|
|
2173
|
+
"""
|
|
2174
|
+
return self.parent()._tab_completion()
|
|
2175
|
+
|
|
2176
|
+
def type(self):
|
|
2177
|
+
"""
|
|
2178
|
+
Return the internal type of this element.
|
|
2179
|
+
|
|
2180
|
+
EXAMPLES::
|
|
2181
|
+
|
|
2182
|
+
sage: R = PolynomialRing(GF(2^8,'a'),2,'x')
|
|
2183
|
+
sage: R._singular_().type()
|
|
2184
|
+
'ring'
|
|
2185
|
+
sage: fs = singular('x0^2','poly')
|
|
2186
|
+
sage: fs.type()
|
|
2187
|
+
'poly'
|
|
2188
|
+
"""
|
|
2189
|
+
# singular reports // $varname $type $stuff
|
|
2190
|
+
p = re.compile(r"// [\w]+ (\w+) [\w]*")
|
|
2191
|
+
m = p.match(self.parent().eval("type(%s)" % self.name()))
|
|
2192
|
+
return m.group(1)
|
|
2193
|
+
|
|
2194
|
+
def __iter__(self):
|
|
2195
|
+
"""
|
|
2196
|
+
EXAMPLES::
|
|
2197
|
+
|
|
2198
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
2199
|
+
sage: A = singular.matrix(2,2)
|
|
2200
|
+
sage: list(iter(A))
|
|
2201
|
+
[[0], [0]]
|
|
2202
|
+
sage: A[1,1] = 1; A[1,2] = 2
|
|
2203
|
+
sage: A[2,1] = 3; A[2,2] = 4
|
|
2204
|
+
sage: list(iter(A))
|
|
2205
|
+
[[1,3], [2,4]]
|
|
2206
|
+
"""
|
|
2207
|
+
if self.type() == 'matrix':
|
|
2208
|
+
l = self.ncols()
|
|
2209
|
+
else:
|
|
2210
|
+
l = len(self)
|
|
2211
|
+
|
|
2212
|
+
for i in range(1, int(l + 1)):
|
|
2213
|
+
yield self[i]
|
|
2214
|
+
|
|
2215
|
+
def _singular_(self):
|
|
2216
|
+
"""
|
|
2217
|
+
EXAMPLES::
|
|
2218
|
+
|
|
2219
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
2220
|
+
sage: A = singular.matrix(2,2)
|
|
2221
|
+
sage: A._singular_() is A
|
|
2222
|
+
True
|
|
2223
|
+
"""
|
|
2224
|
+
return self
|
|
2225
|
+
|
|
2226
|
+
def attrib(self, name, value=None):
|
|
2227
|
+
"""
|
|
2228
|
+
Get and set attributes for ``self``.
|
|
2229
|
+
|
|
2230
|
+
INPUT:
|
|
2231
|
+
|
|
2232
|
+
- ``name`` -- string to choose the attribute
|
|
2233
|
+
|
|
2234
|
+
- ``value`` -- boolean value or ``None`` for reading,
|
|
2235
|
+
(default: ``None``)
|
|
2236
|
+
|
|
2237
|
+
VALUES: isSB - the standard basis property is set by all commands
|
|
2238
|
+
computing a standard basis like groebner, std, stdhilb etc.; used
|
|
2239
|
+
by lift, dim, degree, mult, hilb, vdim, kbase isHomog - the weight
|
|
2240
|
+
vector for homogeneous or quasihomogeneous ideals/modules isCI -
|
|
2241
|
+
complete intersection property isCM - Cohen-Macaulay property rank
|
|
2242
|
+
- set the rank of a module (see nrows) withSB - value of type
|
|
2243
|
+
ideal, resp. module, is std withHilb - value of type intvec is
|
|
2244
|
+
hilb(_,1) (see hilb) withRes - value of type list is a free
|
|
2245
|
+
resolution withDim - value of type int is the dimension (see dim)
|
|
2246
|
+
withMult - value of type int is the multiplicity (see mult)
|
|
2247
|
+
|
|
2248
|
+
EXAMPLES::
|
|
2249
|
+
|
|
2250
|
+
sage: P.<x,y,z> = PolynomialRing(QQ)
|
|
2251
|
+
sage: I = Ideal([z^2, y*z, y^2, x*z, x*y, x^2])
|
|
2252
|
+
sage: Ibar = I._singular_()
|
|
2253
|
+
sage: Ibar.attrib('isSB')
|
|
2254
|
+
0
|
|
2255
|
+
sage: singular.eval('vdim(%s)'%Ibar.name()) # sage7 name is random
|
|
2256
|
+
// ** sage7 is no standard basis
|
|
2257
|
+
4
|
|
2258
|
+
sage: Ibar.attrib('isSB',1)
|
|
2259
|
+
sage: singular.eval('vdim(%s)'%Ibar.name())
|
|
2260
|
+
'4'
|
|
2261
|
+
"""
|
|
2262
|
+
if value is None:
|
|
2263
|
+
return int(self.parent().eval('attrib(%s,"%s")' % (self.name(), name)))
|
|
2264
|
+
else:
|
|
2265
|
+
self.parent().eval('attrib(%s,"%s",%d)' % (self.name(), name, value))
|
|
2266
|
+
|
|
2267
|
+
|
|
2268
|
+
@instancedoc
|
|
2269
|
+
class SingularFunction(ExpectFunction):
|
|
2270
|
+
def _instancedoc_(self):
|
|
2271
|
+
"""
|
|
2272
|
+
EXAMPLES::
|
|
2273
|
+
|
|
2274
|
+
sage: 'groebner' in singular.groebner.__doc__ # needs info
|
|
2275
|
+
True
|
|
2276
|
+
"""
|
|
2277
|
+
|
|
2278
|
+
prefix = """
|
|
2279
|
+
This function is an automatically generated pexpect wrapper around the Singular
|
|
2280
|
+
function '%s'.
|
|
2281
|
+
|
|
2282
|
+
EXAMPLES::
|
|
2283
|
+
|
|
2284
|
+
sage: groebner = singular.groebner
|
|
2285
|
+
sage: P.<x, y> = PolynomialRing(QQ)
|
|
2286
|
+
sage: I = P.ideal(x^2-y, y+x)
|
|
2287
|
+
sage: groebner(singular(I))
|
|
2288
|
+
x+y,
|
|
2289
|
+
y^2-y
|
|
2290
|
+
""" % (self._name,)
|
|
2291
|
+
return prefix + get_docstring(self._name,
|
|
2292
|
+
prefix=True,
|
|
2293
|
+
code=True)
|
|
2294
|
+
|
|
2295
|
+
|
|
2296
|
+
@instancedoc
|
|
2297
|
+
class SingularFunctionElement(FunctionElement):
|
|
2298
|
+
def _instancedoc_(self):
|
|
2299
|
+
r"""
|
|
2300
|
+
EXAMPLES::
|
|
2301
|
+
|
|
2302
|
+
sage: R = singular.ring(0, '(x,y,z)', 'dp')
|
|
2303
|
+
sage: A = singular.matrix(2,2)
|
|
2304
|
+
sage: 'matrix_expression' in A.nrows.__doc__ # needs info
|
|
2305
|
+
True
|
|
2306
|
+
"""
|
|
2307
|
+
return get_docstring(self._name, code=True)
|
|
2308
|
+
|
|
2309
|
+
|
|
2310
|
+
def is_SingularElement(x):
|
|
2311
|
+
r"""
|
|
2312
|
+
Return ``True`` if ``x`` is of type :class:`SingularElement`.
|
|
2313
|
+
|
|
2314
|
+
This function is deprecated; use :func:`isinstance`
|
|
2315
|
+
(of :class:`sage.interfaces.abc.SingularElement`) instead.
|
|
2316
|
+
|
|
2317
|
+
EXAMPLES::
|
|
2318
|
+
|
|
2319
|
+
sage: from sage.interfaces.singular import is_SingularElement
|
|
2320
|
+
sage: is_SingularElement(singular(2))
|
|
2321
|
+
doctest:...: DeprecationWarning: the function is_SingularElement is deprecated; use isinstance(x, sage.interfaces.abc.SingularElement) instead
|
|
2322
|
+
See https://github.com/sagemath/sage/issues/34804 for details.
|
|
2323
|
+
True
|
|
2324
|
+
sage: is_SingularElement(2)
|
|
2325
|
+
False
|
|
2326
|
+
"""
|
|
2327
|
+
from sage.misc.superseded import deprecation
|
|
2328
|
+
deprecation(34804, "the function is_SingularElement is deprecated; use isinstance(x, sage.interfaces.abc.SingularElement) instead")
|
|
2329
|
+
|
|
2330
|
+
return isinstance(x, SingularElement)
|
|
2331
|
+
|
|
2332
|
+
|
|
2333
|
+
def get_docstring(name, prefix=False, code=False):
|
|
2334
|
+
"""
|
|
2335
|
+
Return the docstring for the function ``name``.
|
|
2336
|
+
|
|
2337
|
+
INPUT:
|
|
2338
|
+
|
|
2339
|
+
- ``name`` -- a Singular function name
|
|
2340
|
+
- ``prefix`` -- boolean (default: ``False``); whether or not to
|
|
2341
|
+
include the prefix stating that what follows is from the
|
|
2342
|
+
Singular documentation.
|
|
2343
|
+
- ``code`` -- boolean (default: ``False``); whether or not to
|
|
2344
|
+
format the result as a reStructuredText code block. This is
|
|
2345
|
+
intended to support the feature requested in :issue:`11268`.
|
|
2346
|
+
|
|
2347
|
+
OUTPUT:
|
|
2348
|
+
|
|
2349
|
+
A string describing the Singular function ``name``. A
|
|
2350
|
+
:class:`KeyError` is raised if the function was not found in the
|
|
2351
|
+
Singular documentation. If the "info" is not on the user's
|
|
2352
|
+
``PATH``, an :class:`OSError` will be raised. If "info" was found
|
|
2353
|
+
but failed to execute, a :class:`subprocess.CalledProcessError`
|
|
2354
|
+
will be raised instead.
|
|
2355
|
+
|
|
2356
|
+
EXAMPLES::
|
|
2357
|
+
|
|
2358
|
+
sage: from sage.interfaces.singular import get_docstring
|
|
2359
|
+
sage: 'groebner' in get_docstring('groebner') # needs_info
|
|
2360
|
+
True
|
|
2361
|
+
sage: 'standard.lib' in get_docstring('groebner') # needs info
|
|
2362
|
+
True
|
|
2363
|
+
|
|
2364
|
+
The ``prefix=True`` form is used in Sage's generated docstrings::
|
|
2365
|
+
|
|
2366
|
+
sage: from sage.interfaces.singular import get_docstring
|
|
2367
|
+
sage: print(get_docstring("factorize", prefix=True)) # needs info
|
|
2368
|
+
The Singular documentation for "factorize" is given below.
|
|
2369
|
+
...
|
|
2370
|
+
|
|
2371
|
+
TESTS:
|
|
2372
|
+
|
|
2373
|
+
Non-existent functions raise a :class:`KeyError`::
|
|
2374
|
+
|
|
2375
|
+
sage: from sage.interfaces.singular import get_docstring
|
|
2376
|
+
sage: get_docstring("mysql_real_escape_string") # needs info
|
|
2377
|
+
Traceback (most recent call last):
|
|
2378
|
+
...
|
|
2379
|
+
KeyError: 'mysql_real_escape_string'
|
|
2380
|
+
|
|
2381
|
+
This is true also for nodes that exist in the documentation but
|
|
2382
|
+
are not function nodes::
|
|
2383
|
+
|
|
2384
|
+
sage: from sage.interfaces.singular import get_docstring
|
|
2385
|
+
sage: get_docstring("Preface") # needs info
|
|
2386
|
+
Traceback (most recent call last):
|
|
2387
|
+
...
|
|
2388
|
+
KeyError: 'Preface'
|
|
2389
|
+
|
|
2390
|
+
If GNU Info is not installed, we politely decline to do anything::
|
|
2391
|
+
|
|
2392
|
+
sage: from sage.interfaces.singular import get_docstring
|
|
2393
|
+
sage: from sage.features.info import Info
|
|
2394
|
+
sage: Info().hide()
|
|
2395
|
+
sage: get_docstring('groebner')
|
|
2396
|
+
Traceback (most recent call last):
|
|
2397
|
+
...
|
|
2398
|
+
OSError: GNU Info is not installed. Singular's documentation
|
|
2399
|
+
will not be available.
|
|
2400
|
+
sage: Info().unhide()
|
|
2401
|
+
"""
|
|
2402
|
+
from sage.features.info import Info
|
|
2403
|
+
|
|
2404
|
+
if not Info().is_present():
|
|
2405
|
+
raise OSError("GNU Info is not installed. Singular's "
|
|
2406
|
+
"documentation will not be available.")
|
|
2407
|
+
import subprocess
|
|
2408
|
+
cmd_and_args = ["info", f"--node={name}", "singular"]
|
|
2409
|
+
try:
|
|
2410
|
+
result = subprocess.run(cmd_and_args,
|
|
2411
|
+
capture_output=True,
|
|
2412
|
+
check=True,
|
|
2413
|
+
text=True)
|
|
2414
|
+
except subprocess.CalledProcessError as e:
|
|
2415
|
+
# Before Texinfo v7.0.0, the "info" program would exit
|
|
2416
|
+
# successfully even if the desired node was not found.
|
|
2417
|
+
if e.returncode == 1:
|
|
2418
|
+
raise KeyError(name) from e
|
|
2419
|
+
else:
|
|
2420
|
+
# Something else bad happened
|
|
2421
|
+
raise e
|
|
2422
|
+
|
|
2423
|
+
# The subprocess call can succeed if the given node exists but is
|
|
2424
|
+
# not a function node (example: "Preface"). All function nodes
|
|
2425
|
+
# should live in the "Functions" section, and we can determine the
|
|
2426
|
+
# current section by the presence of "Up: <section>" on the first
|
|
2427
|
+
# line of the output, in the navigation header.
|
|
2428
|
+
#
|
|
2429
|
+
# There is a small risk of ambiguity here if there are two
|
|
2430
|
+
# sections with the same name, but it's a trade-off: specifying
|
|
2431
|
+
# the full path down to the intended function would be much more
|
|
2432
|
+
# fragile; it would break whenever a subsection name was tweaked
|
|
2433
|
+
# upstream.
|
|
2434
|
+
offset = result.stdout.find("\n")
|
|
2435
|
+
line0 = result.stdout[:offset]
|
|
2436
|
+
if "Up: Functions" not in line0:
|
|
2437
|
+
raise KeyError(name)
|
|
2438
|
+
|
|
2439
|
+
# If the first line was the navigation header, the second line should
|
|
2440
|
+
# be blank; by incrementing the offset by two, we're skipping over it.
|
|
2441
|
+
offset += 2
|
|
2442
|
+
result = result.stdout[offset:]
|
|
2443
|
+
|
|
2444
|
+
if code:
|
|
2445
|
+
result = "::\n\n " + "\n ".join(result.split('\n'))
|
|
2446
|
+
|
|
2447
|
+
if prefix:
|
|
2448
|
+
result = (f'The Singular documentation for "{name}" is given below.'
|
|
2449
|
+
+ "\n\n" + result)
|
|
2450
|
+
|
|
2451
|
+
return result
|
|
2452
|
+
|
|
2453
|
+
|
|
2454
|
+
singular = Singular()
|
|
2455
|
+
|
|
2456
|
+
|
|
2457
|
+
def reduce_load_Singular():
|
|
2458
|
+
"""
|
|
2459
|
+
EXAMPLES::
|
|
2460
|
+
|
|
2461
|
+
sage: from sage.interfaces.singular import reduce_load_Singular
|
|
2462
|
+
sage: reduce_load_Singular()
|
|
2463
|
+
Singular
|
|
2464
|
+
"""
|
|
2465
|
+
return singular
|
|
2466
|
+
|
|
2467
|
+
|
|
2468
|
+
def singular_console():
|
|
2469
|
+
r"""
|
|
2470
|
+
Spawn a new Singular command-line session.
|
|
2471
|
+
|
|
2472
|
+
EXAMPLES::
|
|
2473
|
+
|
|
2474
|
+
sage: singular_console() #not tested
|
|
2475
|
+
SINGULAR / Development
|
|
2476
|
+
A Computer Algebra System for Polynomial Computations / version 3-0-4
|
|
2477
|
+
0<
|
|
2478
|
+
by: G.-M. Greuel, G. Pfister, H. Schoenemann \ Nov 2007
|
|
2479
|
+
FB Mathematik der Universitaet, D-67653 Kaiserslautern \
|
|
2480
|
+
"""
|
|
2481
|
+
from sage.repl.rich_output.display_manager import get_display_manager
|
|
2482
|
+
if not get_display_manager().is_in_terminal():
|
|
2483
|
+
raise RuntimeError('Can use the console only in the terminal. Try %%singular magics instead.')
|
|
2484
|
+
os.system(sage.features.singular.Singular().absolute_filename())
|
|
2485
|
+
|
|
2486
|
+
|
|
2487
|
+
def singular_version():
|
|
2488
|
+
"""
|
|
2489
|
+
Return the version of Singular being used.
|
|
2490
|
+
|
|
2491
|
+
EXAMPLES::
|
|
2492
|
+
|
|
2493
|
+
sage: singular.version()
|
|
2494
|
+
"Singular ... version 4...
|
|
2495
|
+
"""
|
|
2496
|
+
return singular.eval('system("--version");')
|
|
2497
|
+
|
|
2498
|
+
|
|
2499
|
+
class SingularGBLogPrettyPrinter:
|
|
2500
|
+
"""
|
|
2501
|
+
A device which prints Singular Groebner basis computation logs
|
|
2502
|
+
more verbatim.
|
|
2503
|
+
"""
|
|
2504
|
+
rng_chng = re.compile(r"\[\d+:\d+\]")
|
|
2505
|
+
# [m:n] internal ring change to
|
|
2506
|
+
# poly representation with
|
|
2507
|
+
# exponent bound m and n words in
|
|
2508
|
+
# exponent vector
|
|
2509
|
+
|
|
2510
|
+
new_elem = re.compile("s") # found a new element of the standard basis
|
|
2511
|
+
red_zero = re.compile("-") # reduced a pair/S-polynomial to 0
|
|
2512
|
+
red_post = re.compile(r"\.") # postponed a reduction of a pair/S-polynomial
|
|
2513
|
+
cri_hilb = re.compile("h") # used Hilbert series criterion
|
|
2514
|
+
hig_corn = re.compile(r"H\(\d+\)") # found a 'highest corner' of degree d, no need to consider higher degrees
|
|
2515
|
+
num_crit = re.compile(r"\(\d+\)") # n critical pairs are still to be reduced
|
|
2516
|
+
red_num = re.compile(r"\(S:\d+\)") # doing complete reduction of n elements
|
|
2517
|
+
deg_lead = re.compile(r"\d+") # the degree of the leading terms is currently d
|
|
2518
|
+
|
|
2519
|
+
# SlimGB
|
|
2520
|
+
red_para = re.compile(r"M\[(\d+),(\d+)\]") # parallel reduction of n elements with m nonzero output elements
|
|
2521
|
+
red_betr = re.compile("b") # exchange of a reductor by a 'better' one
|
|
2522
|
+
non_mini = re.compile("e") # a new reductor with non-minimal leading term
|
|
2523
|
+
|
|
2524
|
+
crt_lne1 = re.compile(r"product criterion:(\d+) chain criterion:(\d+)")
|
|
2525
|
+
crt_lne2 = re.compile(r"NF:(\d+) product criterion:(\d+), ext_product criterion:(\d+)")
|
|
2526
|
+
|
|
2527
|
+
pat_sync = re.compile(r"1\+(\d+);")
|
|
2528
|
+
|
|
2529
|
+
global_pattern = re.compile(r"(\[\d+:\d+\]|s|-|\.|h|H\(\d+\)|\(\d+\)|\(S:\d+\)|\d+|M\[\d+,[b,e]*\d+\]|b|e).*")
|
|
2530
|
+
|
|
2531
|
+
def __init__(self, verbosity=1):
|
|
2532
|
+
"""
|
|
2533
|
+
Construct a new Singular Groebner Basis log pretty printer.
|
|
2534
|
+
|
|
2535
|
+
INPUT:
|
|
2536
|
+
|
|
2537
|
+
- ``verbosity`` -- how much information should be printed
|
|
2538
|
+
(between 0 and 3)
|
|
2539
|
+
|
|
2540
|
+
EXAMPLES::
|
|
2541
|
+
|
|
2542
|
+
sage: from sage.interfaces.singular import SingularGBLogPrettyPrinter
|
|
2543
|
+
sage: s0 = SingularGBLogPrettyPrinter(verbosity=0)
|
|
2544
|
+
sage: s1 = SingularGBLogPrettyPrinter(verbosity=1)
|
|
2545
|
+
sage: s0.write("[1:2]12")
|
|
2546
|
+
|
|
2547
|
+
sage: s1.write("[1:2]12")
|
|
2548
|
+
Leading term degree: 12.
|
|
2549
|
+
"""
|
|
2550
|
+
self.verbosity = verbosity
|
|
2551
|
+
|
|
2552
|
+
self.curr_deg = 0 # current degree
|
|
2553
|
+
self.max_deg = 0 # maximal degree in total
|
|
2554
|
+
|
|
2555
|
+
self.nf = 0 # number of normal forms computed (SlimGB only)
|
|
2556
|
+
self.prod = 0 # number of S-polynomials discarded using product criterion
|
|
2557
|
+
self.ext_prod = 0 # number of S-polynomials discarded using extended product criterion
|
|
2558
|
+
self.chain = 0 # number of S-polynomials discarded using chain criterion
|
|
2559
|
+
|
|
2560
|
+
self.storage = "" # stores incomplete strings
|
|
2561
|
+
self.sync = None # should we expect a sync integer?
|
|
2562
|
+
|
|
2563
|
+
def write(self, s):
|
|
2564
|
+
"""
|
|
2565
|
+
EXAMPLES::
|
|
2566
|
+
|
|
2567
|
+
sage: from sage.interfaces.singular import SingularGBLogPrettyPrinter
|
|
2568
|
+
sage: s3 = SingularGBLogPrettyPrinter(verbosity=3)
|
|
2569
|
+
sage: s3.write("(S:1337)")
|
|
2570
|
+
Performing complete reduction of 1337 elements.
|
|
2571
|
+
sage: s3.write("M[389,12]")
|
|
2572
|
+
Parallel reduction of 389 elements with 12 nonzero output elements.
|
|
2573
|
+
"""
|
|
2574
|
+
verbosity = self.verbosity
|
|
2575
|
+
|
|
2576
|
+
if self.storage:
|
|
2577
|
+
s = self.storage + s
|
|
2578
|
+
self.storage = ""
|
|
2579
|
+
|
|
2580
|
+
for line in s.splitlines():
|
|
2581
|
+
# deal with the Sage <-> Singular syncing code
|
|
2582
|
+
match = re.match(SingularGBLogPrettyPrinter.pat_sync, line)
|
|
2583
|
+
if match:
|
|
2584
|
+
self.sync = int(match.groups()[0])
|
|
2585
|
+
continue
|
|
2586
|
+
|
|
2587
|
+
if self.sync and line == "%d" % (self.sync + 1):
|
|
2588
|
+
self.sync = None
|
|
2589
|
+
continue
|
|
2590
|
+
|
|
2591
|
+
if line.endswith(";"):
|
|
2592
|
+
continue
|
|
2593
|
+
if line.startswith(">"):
|
|
2594
|
+
continue
|
|
2595
|
+
|
|
2596
|
+
if line.startswith("std") or line.startswith("slimgb"):
|
|
2597
|
+
continue
|
|
2598
|
+
|
|
2599
|
+
# collect stats returned about avoided reductions to zero
|
|
2600
|
+
match = re.match(SingularGBLogPrettyPrinter.crt_lne1, line)
|
|
2601
|
+
if match:
|
|
2602
|
+
self.prod, self.chain = map(int, re.match(SingularGBLogPrettyPrinter.crt_lne1, line).groups())
|
|
2603
|
+
self.storage = ""
|
|
2604
|
+
continue
|
|
2605
|
+
match = re.match(SingularGBLogPrettyPrinter.crt_lne2, line)
|
|
2606
|
+
if match:
|
|
2607
|
+
self.nf, self.prod, self.ext_prod = map(int, re.match(SingularGBLogPrettyPrinter.crt_lne2, line).groups())
|
|
2608
|
+
self.storage = ""
|
|
2609
|
+
continue
|
|
2610
|
+
|
|
2611
|
+
while line:
|
|
2612
|
+
match = re.match(SingularGBLogPrettyPrinter.global_pattern, line)
|
|
2613
|
+
if not match:
|
|
2614
|
+
self.storage = line
|
|
2615
|
+
line = None
|
|
2616
|
+
continue
|
|
2617
|
+
|
|
2618
|
+
token, = match.groups()
|
|
2619
|
+
line = line[len(token):]
|
|
2620
|
+
|
|
2621
|
+
if re.match(SingularGBLogPrettyPrinter.rng_chng, token):
|
|
2622
|
+
continue
|
|
2623
|
+
|
|
2624
|
+
elif re.match(SingularGBLogPrettyPrinter.new_elem, token) and verbosity >= 3:
|
|
2625
|
+
print("New element found.")
|
|
2626
|
+
|
|
2627
|
+
elif re.match(SingularGBLogPrettyPrinter.red_zero, token) and verbosity >= 2:
|
|
2628
|
+
print("Reduction to zero.")
|
|
2629
|
+
|
|
2630
|
+
elif re.match(SingularGBLogPrettyPrinter.red_post, token) and verbosity >= 2:
|
|
2631
|
+
print("Reduction postponed.")
|
|
2632
|
+
|
|
2633
|
+
elif re.match(SingularGBLogPrettyPrinter.cri_hilb, token) and verbosity >= 2:
|
|
2634
|
+
print("Hilber series criterion applied.")
|
|
2635
|
+
|
|
2636
|
+
elif re.match(SingularGBLogPrettyPrinter.hig_corn, token) and verbosity >= 1:
|
|
2637
|
+
print("Maximal degree found: %s" % token)
|
|
2638
|
+
|
|
2639
|
+
elif re.match(SingularGBLogPrettyPrinter.num_crit, token) and verbosity >= 1:
|
|
2640
|
+
print("Leading term degree: %2d. Critical pairs: %s." % (self.curr_deg, token[1:-1]))
|
|
2641
|
+
|
|
2642
|
+
elif re.match(SingularGBLogPrettyPrinter.red_num, token) and verbosity >= 3:
|
|
2643
|
+
print("Performing complete reduction of %s elements." % token[3:-1])
|
|
2644
|
+
|
|
2645
|
+
elif re.match(SingularGBLogPrettyPrinter.deg_lead, token):
|
|
2646
|
+
if verbosity >= 1:
|
|
2647
|
+
print("Leading term degree: %2d." % int(token))
|
|
2648
|
+
self.curr_deg = int(token)
|
|
2649
|
+
self.max_deg = max(self.max_deg, self.curr_deg)
|
|
2650
|
+
|
|
2651
|
+
elif re.match(SingularGBLogPrettyPrinter.red_para, token) and verbosity >= 3:
|
|
2652
|
+
m, n = re.match(SingularGBLogPrettyPrinter.red_para, token).groups()
|
|
2653
|
+
print("Parallel reduction of %s elements with %s nonzero output elements." % (m, n))
|
|
2654
|
+
|
|
2655
|
+
elif re.match(SingularGBLogPrettyPrinter.red_betr, token) and verbosity >= 3:
|
|
2656
|
+
print("Replaced reductor by 'better' one.")
|
|
2657
|
+
|
|
2658
|
+
elif re.match(SingularGBLogPrettyPrinter.non_mini, token) and verbosity >= 2:
|
|
2659
|
+
print("New reductor with non-minimal leading term found.")
|
|
2660
|
+
|
|
2661
|
+
def flush(self):
|
|
2662
|
+
"""
|
|
2663
|
+
EXAMPLES::
|
|
2664
|
+
|
|
2665
|
+
sage: from sage.interfaces.singular import SingularGBLogPrettyPrinter
|
|
2666
|
+
sage: s3 = SingularGBLogPrettyPrinter(verbosity=3)
|
|
2667
|
+
sage: s3.flush()
|
|
2668
|
+
"""
|
|
2669
|
+
sys.stdout.flush()
|
|
2670
|
+
|
|
2671
|
+
|
|
2672
|
+
class SingularGBDefaultContext:
|
|
2673
|
+
"""
|
|
2674
|
+
Within this context all Singular Groebner basis calculations are
|
|
2675
|
+
reduced automatically.
|
|
2676
|
+
|
|
2677
|
+
AUTHORS:
|
|
2678
|
+
|
|
2679
|
+
- Martin Albrecht
|
|
2680
|
+
- Simon King
|
|
2681
|
+
"""
|
|
2682
|
+
def __init__(self, singular=None):
|
|
2683
|
+
"""
|
|
2684
|
+
Within this context all Singular Groebner basis calculations
|
|
2685
|
+
are reduced automatically.
|
|
2686
|
+
|
|
2687
|
+
INPUT:
|
|
2688
|
+
|
|
2689
|
+
- ``singular`` -- Singular instance (default: default instance)
|
|
2690
|
+
|
|
2691
|
+
EXAMPLES::
|
|
2692
|
+
|
|
2693
|
+
sage: from sage.interfaces.singular import SingularGBDefaultContext
|
|
2694
|
+
sage: P.<a,b,c> = PolynomialRing(QQ,3, order='lex')
|
|
2695
|
+
sage: I = sage.rings.ideal.Katsura(P,3)
|
|
2696
|
+
sage: singular.option('noredTail')
|
|
2697
|
+
sage: singular.option('noredThrough')
|
|
2698
|
+
sage: Is = I._singular_()
|
|
2699
|
+
sage: gb = Is.groebner()
|
|
2700
|
+
sage: gb
|
|
2701
|
+
84*c^4-40*c^3+c^2+c,
|
|
2702
|
+
7*b+210*c^3-79*c^2+3*c,
|
|
2703
|
+
a+2*b+2*c-1
|
|
2704
|
+
|
|
2705
|
+
::
|
|
2706
|
+
|
|
2707
|
+
sage: with SingularGBDefaultContext(): rgb = Is.groebner()
|
|
2708
|
+
sage: rgb
|
|
2709
|
+
84*c^4-40*c^3+c^2+c,
|
|
2710
|
+
7*b+210*c^3-79*c^2+3*c,
|
|
2711
|
+
7*a-420*c^3+158*c^2+8*c-7
|
|
2712
|
+
|
|
2713
|
+
Note that both bases are Groebner bases because they have
|
|
2714
|
+
pairwise prime leading monomials but that the monic version of
|
|
2715
|
+
the last element in ``rgb`` is smaller than the last element
|
|
2716
|
+
of ``gb`` with respect to the lexicographical term ordering. ::
|
|
2717
|
+
|
|
2718
|
+
sage: (7*a-420*c^3+158*c^2+8*c-7)/7 < (a+2*b+2*c-1)
|
|
2719
|
+
True
|
|
2720
|
+
|
|
2721
|
+
.. NOTE::
|
|
2722
|
+
|
|
2723
|
+
This context is used automatically internally whenever a
|
|
2724
|
+
Groebner basis is computed so the user does not need to use
|
|
2725
|
+
it manually.
|
|
2726
|
+
"""
|
|
2727
|
+
if singular is None:
|
|
2728
|
+
from sage.interfaces.singular import singular as singular_default
|
|
2729
|
+
singular = singular_default
|
|
2730
|
+
self.singular = singular
|
|
2731
|
+
|
|
2732
|
+
def __enter__(self):
|
|
2733
|
+
"""
|
|
2734
|
+
EXAMPLES::
|
|
2735
|
+
|
|
2736
|
+
sage: from sage.interfaces.singular import SingularGBDefaultContext
|
|
2737
|
+
sage: P.<a,b,c> = PolynomialRing(QQ,3, order='lex')
|
|
2738
|
+
sage: I = sage.rings.ideal.Katsura(P,3)
|
|
2739
|
+
sage: singular.option('noredTail')
|
|
2740
|
+
sage: singular.option('noredThrough')
|
|
2741
|
+
sage: Is = I._singular_()
|
|
2742
|
+
sage: with SingularGBDefaultContext(): rgb = Is.groebner()
|
|
2743
|
+
sage: rgb
|
|
2744
|
+
84*c^4-40*c^3+c^2+c,
|
|
2745
|
+
7*b+210*c^3-79*c^2+3*c,
|
|
2746
|
+
7*a-420*c^3+158*c^2+8*c-7
|
|
2747
|
+
"""
|
|
2748
|
+
try:
|
|
2749
|
+
self.bck_degBound = int(self.singular.eval('degBound'))
|
|
2750
|
+
except SingularError:
|
|
2751
|
+
self.bck_degBound = 0
|
|
2752
|
+
try:
|
|
2753
|
+
self.bck_multBound = int(self.singular.eval('multBound'))
|
|
2754
|
+
except SingularError:
|
|
2755
|
+
self.bck_multBound = 0
|
|
2756
|
+
self.o = self.singular.option("get")
|
|
2757
|
+
self.singular.option('set', self.singular._saved_options)
|
|
2758
|
+
self.singular.option("redSB")
|
|
2759
|
+
self.singular.option("redTail")
|
|
2760
|
+
try:
|
|
2761
|
+
self.singular.eval('degBound=0')
|
|
2762
|
+
except SingularError:
|
|
2763
|
+
pass
|
|
2764
|
+
try:
|
|
2765
|
+
self.singular.eval('multBound=0')
|
|
2766
|
+
except SingularError:
|
|
2767
|
+
pass
|
|
2768
|
+
|
|
2769
|
+
def __exit__(self, typ, value, tb):
|
|
2770
|
+
"""
|
|
2771
|
+
EXAMPLES::
|
|
2772
|
+
|
|
2773
|
+
sage: from sage.interfaces.singular import SingularGBDefaultContext
|
|
2774
|
+
sage: P.<a,b,c> = PolynomialRing(QQ,3, order='lex')
|
|
2775
|
+
sage: I = sage.rings.ideal.Katsura(P,3)
|
|
2776
|
+
sage: singular.option('noredTail')
|
|
2777
|
+
sage: singular.option('noredThrough')
|
|
2778
|
+
sage: Is = I._singular_()
|
|
2779
|
+
sage: with SingularGBDefaultContext(): rgb = Is.groebner()
|
|
2780
|
+
sage: rgb
|
|
2781
|
+
84*c^4-40*c^3+c^2+c,
|
|
2782
|
+
7*b+210*c^3-79*c^2+3*c,
|
|
2783
|
+
7*a-420*c^3+158*c^2+8*c-7
|
|
2784
|
+
"""
|
|
2785
|
+
self.singular.option("set", self.o)
|
|
2786
|
+
try:
|
|
2787
|
+
self.singular.eval('degBound=%d' % self.bck_degBound)
|
|
2788
|
+
except SingularError:
|
|
2789
|
+
pass
|
|
2790
|
+
try:
|
|
2791
|
+
self.singular.eval('multBound=%d' % self.bck_multBound)
|
|
2792
|
+
except SingularError:
|
|
2793
|
+
pass
|
|
2794
|
+
|
|
2795
|
+
|
|
2796
|
+
def singular_gb_standard_options(func):
|
|
2797
|
+
r"""
|
|
2798
|
+
Decorator to force a reduced Singular groebner basis.
|
|
2799
|
+
|
|
2800
|
+
TESTS::
|
|
2801
|
+
|
|
2802
|
+
sage: P.<a,b,c,d,e> = PolynomialRing(GF(127))
|
|
2803
|
+
sage: J = sage.rings.ideal.Cyclic(P).homogenize()
|
|
2804
|
+
sage: from sage.misc.sageinspect import sage_getsource
|
|
2805
|
+
sage: "basis" in sage_getsource(J.interreduced_basis) #indirect doctest
|
|
2806
|
+
True
|
|
2807
|
+
|
|
2808
|
+
The following tests against a bug that was fixed in :issue:`11298`::
|
|
2809
|
+
|
|
2810
|
+
sage: from sage.misc.sageinspect import sage_getsourcelines, sage_getargspec
|
|
2811
|
+
sage: P.<x,y> = QQ[]
|
|
2812
|
+
sage: I = P*[x,y]
|
|
2813
|
+
sage: sage_getargspec(I.interreduced_basis)
|
|
2814
|
+
FullArgSpec(args=['self'], varargs=None, varkw=None, defaults=None,
|
|
2815
|
+
kwonlyargs=[], kwonlydefaults=None, annotations={})
|
|
2816
|
+
sage: sage_getsourcelines(I.interreduced_basis)
|
|
2817
|
+
([' @handle_AA_and_QQbar\n',
|
|
2818
|
+
' @singular_gb_standard_options\n',
|
|
2819
|
+
' @libsingular_gb_standard_options\n',
|
|
2820
|
+
' def interreduced_basis(self):\n', '
|
|
2821
|
+
...
|
|
2822
|
+
' return self.basis.reduced()\n'], ...)
|
|
2823
|
+
|
|
2824
|
+
.. NOTE::
|
|
2825
|
+
|
|
2826
|
+
This decorator is used automatically internally so the user
|
|
2827
|
+
does not need to use it manually.
|
|
2828
|
+
"""
|
|
2829
|
+
from sage.misc.decorators import sage_wraps
|
|
2830
|
+
|
|
2831
|
+
@sage_wraps(func)
|
|
2832
|
+
def wrapper(*args, **kwds):
|
|
2833
|
+
with SingularGBDefaultContext():
|
|
2834
|
+
return func(*args, **kwds)
|
|
2835
|
+
return wrapper
|