passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
|
@@ -0,0 +1,2570 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
"""
|
|
3
|
+
Generic Multivariate Polynomials
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- David Joyner: first version
|
|
8
|
+
|
|
9
|
+
- William Stein: use dict's instead of lists
|
|
10
|
+
|
|
11
|
+
- Martin Albrecht malb@informatik.uni-bremen.de: some functions added
|
|
12
|
+
|
|
13
|
+
- William Stein (2006-02-11): added better __div__ behavior.
|
|
14
|
+
|
|
15
|
+
- Kiran S. Kedlaya (2006-02-12): added Macaulay2 analogues of some
|
|
16
|
+
Singular features
|
|
17
|
+
|
|
18
|
+
- William Stein (2006-04-19): added e.g.,
|
|
19
|
+
``f[1,3]`` to get coeff of `xy^3`; added examples of the new
|
|
20
|
+
``R.x,y = PolynomialRing(QQ,2)`` notation.
|
|
21
|
+
|
|
22
|
+
- Martin Albrecht: improved singular coercions (restructured class
|
|
23
|
+
hierarchy) and added ETuples
|
|
24
|
+
|
|
25
|
+
- Robert Bradshaw (2007-08-14): added support for coercion of
|
|
26
|
+
polynomials in a subset of variables (including multi-level
|
|
27
|
+
univariate rings)
|
|
28
|
+
|
|
29
|
+
- Joel B. Mohler (2008-03): Refactored interactions with ETuples.
|
|
30
|
+
|
|
31
|
+
EXAMPLES:
|
|
32
|
+
|
|
33
|
+
We verify Lagrange's four squares identity::
|
|
34
|
+
|
|
35
|
+
sage: R.<a0,a1,a2,a3,b0,b1,b2,b3> = QQbar[] # needs sage.rings.number_field
|
|
36
|
+
sage: ((a0^2 + a1^2 + a2^2 + a3^2) * (b0^2 + b1^2 + b2^2 + b3^2) == # needs sage.rings.number_field
|
|
37
|
+
....: (a0*b0 - a1*b1 - a2*b2 - a3*b3)^2 + (a0*b1 + a1*b0 + a2*b3 - a3*b2)^2
|
|
38
|
+
....: + (a0*b2 - a1*b3 + a2*b0 + a3*b1)^2 + (a0*b3 + a1*b2 - a2*b1 + a3*b0)^2)
|
|
39
|
+
True
|
|
40
|
+
"""
|
|
41
|
+
# ****************************************************************************
|
|
42
|
+
#
|
|
43
|
+
# Sage: Open Source Mathematical Software
|
|
44
|
+
#
|
|
45
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
46
|
+
# 2022 Vincent Delecroix <20100.delecroix@gmail.com>
|
|
47
|
+
#
|
|
48
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
49
|
+
#
|
|
50
|
+
# This code is distributed in the hope that it will be useful,
|
|
51
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
52
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
53
|
+
# General Public License for more details.
|
|
54
|
+
#
|
|
55
|
+
# The full text of the GPL is available at:
|
|
56
|
+
#
|
|
57
|
+
# https://www.gnu.org/licenses/
|
|
58
|
+
# ****************************************************************************
|
|
59
|
+
|
|
60
|
+
import operator
|
|
61
|
+
|
|
62
|
+
from sage.structure.element import CommutativeRingElement, coerce_binop, get_coercion_model, parent
|
|
63
|
+
from sage.misc.misc_c import prod
|
|
64
|
+
from sage.rings.integer import Integer
|
|
65
|
+
import sage.rings.integer_ring
|
|
66
|
+
from sage.rings.qqbar_decorators import handle_AA_and_QQbar
|
|
67
|
+
from . import polydict
|
|
68
|
+
from sage.structure.factorization import Factorization
|
|
69
|
+
from sage.rings.polynomial.polynomial_singular_interface import Polynomial_singular_repr
|
|
70
|
+
from sage.structure.sequence import Sequence
|
|
71
|
+
from .multi_polynomial import MPolynomial, is_MPolynomial
|
|
72
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
73
|
+
from sage.misc.superseded import deprecated_function_alias
|
|
74
|
+
from sage.rings.rational_field import QQ
|
|
75
|
+
from sage.rings.fraction_field import FractionField
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class MPolynomial_element(MPolynomial):
|
|
79
|
+
r"""
|
|
80
|
+
Generic multivariate polynomial.
|
|
81
|
+
|
|
82
|
+
This implementation is based on the :class:`~sage.rings.polynomial.polydict.PolyDict`.
|
|
83
|
+
|
|
84
|
+
.. TODO::
|
|
85
|
+
|
|
86
|
+
As mentioned in their docstring,
|
|
87
|
+
:class:`~sage.rings.polynomial.polydict.PolyDict` objects never clear
|
|
88
|
+
zeros. In all arithmetic operations on :class:`MPolynomial_element`
|
|
89
|
+
there is an additional call to the method ``remove_zeros`` to clear
|
|
90
|
+
them. This is not ideal because of the presence of inexact zeros, see
|
|
91
|
+
:issue:`35174`.
|
|
92
|
+
"""
|
|
93
|
+
def __init__(self, parent, x):
|
|
94
|
+
"""
|
|
95
|
+
EXAMPLES::
|
|
96
|
+
|
|
97
|
+
sage: # needs sage.rings.number_field
|
|
98
|
+
sage: x = polygen(ZZ, 'x')
|
|
99
|
+
sage: K.<cuberoot2> = NumberField(x^3 - 2)
|
|
100
|
+
sage: L.<cuberoot3> = K.extension(x^3 - 3)
|
|
101
|
+
sage: S.<sqrt2> = L.extension(x^2 - 2)
|
|
102
|
+
sage: S
|
|
103
|
+
Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
|
|
104
|
+
sage: P.<x,y,z> = PolynomialRing(S) # indirect doctest
|
|
105
|
+
"""
|
|
106
|
+
CommutativeRingElement.__init__(self, parent)
|
|
107
|
+
self.__element = x
|
|
108
|
+
|
|
109
|
+
def _repr_(self):
|
|
110
|
+
"""
|
|
111
|
+
EXAMPLES::
|
|
112
|
+
|
|
113
|
+
sage: P.<x,y,z> = PolynomialRing(QQbar) # needs sage.rings.number_field
|
|
114
|
+
sage: x + QQbar(sqrt(2) - 1/2*I) # indirect doctest # needs sage.rings.number_field sage.symbolic
|
|
115
|
+
x + 1.414213562373095? - 0.50000000000000000?*I
|
|
116
|
+
"""
|
|
117
|
+
return "%s" % self.__element
|
|
118
|
+
|
|
119
|
+
####################
|
|
120
|
+
|
|
121
|
+
def __call__(self, *x, **kwds):
|
|
122
|
+
r"""
|
|
123
|
+
Evaluate this multi-variate polynomial at `x`, where
|
|
124
|
+
`x` is either the tuple of values to substitute in, or one
|
|
125
|
+
can use functional notation `f(a_0,a_1,a_2, \ldots)` to
|
|
126
|
+
evaluate `f` with the `i`-th variable replaced by `a_i`.
|
|
127
|
+
|
|
128
|
+
EXAMPLES::
|
|
129
|
+
|
|
130
|
+
sage: # needs sage.rings.real_mpfr
|
|
131
|
+
sage: R.<x,y> = CC[]
|
|
132
|
+
sage: f = x^2 + y^2
|
|
133
|
+
sage: f(1,2)
|
|
134
|
+
5.00000000000000
|
|
135
|
+
sage: f((1,2))
|
|
136
|
+
5.00000000000000
|
|
137
|
+
|
|
138
|
+
::
|
|
139
|
+
|
|
140
|
+
sage: # needs sage.rings.real_mpfr
|
|
141
|
+
sage: x = PolynomialRing(CC, 3, 'x').gens()
|
|
142
|
+
sage: f = x[0] + x[1] - 2*x[1]*x[2]; f
|
|
143
|
+
(-2.00000000000000)*x1*x2 + x0 + x1
|
|
144
|
+
sage: f(1,2,0)
|
|
145
|
+
3.00000000000000
|
|
146
|
+
sage: f(1,2,5)
|
|
147
|
+
-17.0000000000000
|
|
148
|
+
|
|
149
|
+
TESTS:
|
|
150
|
+
|
|
151
|
+
Check :issue:`27446`::
|
|
152
|
+
|
|
153
|
+
sage: P = PolynomialRing(QQ, 't', 0)
|
|
154
|
+
sage: a = P(1)
|
|
155
|
+
sage: a(()).parent()
|
|
156
|
+
Rational Field
|
|
157
|
+
|
|
158
|
+
AUTHORS:
|
|
159
|
+
|
|
160
|
+
- David Kohel (2005-09-27)
|
|
161
|
+
"""
|
|
162
|
+
if len(kwds) > 0:
|
|
163
|
+
f = self.subs(**kwds)
|
|
164
|
+
if len(x) > 0:
|
|
165
|
+
return f(*x)
|
|
166
|
+
else:
|
|
167
|
+
return f
|
|
168
|
+
if len(x) == 1 and isinstance(x[0], (list, tuple)):
|
|
169
|
+
x = x[0]
|
|
170
|
+
n = self.parent().ngens()
|
|
171
|
+
if len(x) != n:
|
|
172
|
+
raise TypeError("x must be of correct length")
|
|
173
|
+
if n == 0:
|
|
174
|
+
return self.constant_coefficient()
|
|
175
|
+
try:
|
|
176
|
+
K = x[0].parent()
|
|
177
|
+
except AttributeError:
|
|
178
|
+
K = self.parent().base_ring()
|
|
179
|
+
try:
|
|
180
|
+
y = K.zero()
|
|
181
|
+
one = K.one()
|
|
182
|
+
except (AttributeError, RuntimeError):
|
|
183
|
+
y = K(0)
|
|
184
|
+
one = K(1)
|
|
185
|
+
for m, c in self.element().dict().items():
|
|
186
|
+
y += c * prod((v ** e for v, e in zip(x, m) if e), one)
|
|
187
|
+
return y
|
|
188
|
+
|
|
189
|
+
def _richcmp_(self, right, op):
|
|
190
|
+
"""
|
|
191
|
+
Compare ``self`` to ``right`` with respect to the term order of
|
|
192
|
+
self.parent().
|
|
193
|
+
|
|
194
|
+
EXAMPLES::
|
|
195
|
+
|
|
196
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, 3, order='lex') # needs sage.rings.number_field
|
|
197
|
+
sage: x^1*y^2 > y^3*z^4 # needs sage.rings.number_field
|
|
198
|
+
True
|
|
199
|
+
sage: x^3*y^2*z^4 < x^3*y^2*z^1 # needs sage.rings.number_field
|
|
200
|
+
False
|
|
201
|
+
|
|
202
|
+
::
|
|
203
|
+
|
|
204
|
+
sage: R.<x,y,z> = PolynomialRing(CC, 3, order='deglex') # needs sage.rings.real_mpfr
|
|
205
|
+
sage: x^1*y^2*z^3 > x^3*y^2*z^0 # needs sage.rings.real_mpfr
|
|
206
|
+
True
|
|
207
|
+
sage: x^1*y^2*z^4 < x^1*y^1*z^5 # needs sage.rings.real_mpfr
|
|
208
|
+
False
|
|
209
|
+
|
|
210
|
+
::
|
|
211
|
+
|
|
212
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, 3, order='degrevlex') # needs sage.rings.number_field
|
|
213
|
+
sage: x^1*y^5*z^2 > x^4*y^1*z^3 # needs sage.rings.number_field
|
|
214
|
+
True
|
|
215
|
+
sage: x^4*y^7*z^1 < x^4*y^2*z^3 # needs sage.rings.number_field
|
|
216
|
+
False
|
|
217
|
+
"""
|
|
218
|
+
return self.__element.rich_compare(right.__element, op,
|
|
219
|
+
self.parent().term_order().sortkey)
|
|
220
|
+
|
|
221
|
+
def _im_gens_(self, codomain, im_gens, base_map=None):
|
|
222
|
+
"""
|
|
223
|
+
EXAMPLES::
|
|
224
|
+
|
|
225
|
+
sage: R.<x,y> = PolynomialRing(QQbar, 2) # needs sage.rings.number_field
|
|
226
|
+
sage: f = R.hom([y, x], R) # needs sage.rings.number_field
|
|
227
|
+
sage: f(x^2 + 3*y^5) # indirect doctest # needs sage.rings.number_field
|
|
228
|
+
3*x^5 + y^2
|
|
229
|
+
|
|
230
|
+
You can specify a map on the base ring::
|
|
231
|
+
|
|
232
|
+
sage: # needs sage.libs.singular
|
|
233
|
+
sage: F.<x,y> = ZZ[]
|
|
234
|
+
sage: F = F.fraction_field(); x,y = F(x),F(y)
|
|
235
|
+
sage: cc = F.hom([y,x])
|
|
236
|
+
sage: R.<z,w> = F[]
|
|
237
|
+
sage: phi = R.hom([w,z], base_map=cc)
|
|
238
|
+
sage: phi(w/x)
|
|
239
|
+
1/y*z
|
|
240
|
+
"""
|
|
241
|
+
n = self.parent().ngens()
|
|
242
|
+
if n == 0:
|
|
243
|
+
return codomain.coerce(self)
|
|
244
|
+
y = codomain(0)
|
|
245
|
+
if base_map is None:
|
|
246
|
+
# Just use conversion
|
|
247
|
+
base_map = codomain
|
|
248
|
+
for (m,c) in self.element().dict().items():
|
|
249
|
+
y += base_map(c)*prod([ im_gens[i]**m[i] for i in range(n) if m[i] ])
|
|
250
|
+
return y
|
|
251
|
+
|
|
252
|
+
def number_of_terms(self):
|
|
253
|
+
"""
|
|
254
|
+
Return the number of nonzero coefficients of this polynomial.
|
|
255
|
+
|
|
256
|
+
This is also called weight, :meth:`hamming_weight` or sparsity.
|
|
257
|
+
|
|
258
|
+
EXAMPLES::
|
|
259
|
+
|
|
260
|
+
sage: # needs sage.rings.real_mpfr
|
|
261
|
+
sage: R.<x, y> = CC[]
|
|
262
|
+
sage: f = x^3 - y
|
|
263
|
+
sage: f.number_of_terms()
|
|
264
|
+
2
|
|
265
|
+
sage: R(0).number_of_terms()
|
|
266
|
+
0
|
|
267
|
+
sage: f = (x+y)^100
|
|
268
|
+
sage: f.number_of_terms()
|
|
269
|
+
101
|
|
270
|
+
|
|
271
|
+
The method :meth:`hamming_weight` is an alias::
|
|
272
|
+
|
|
273
|
+
sage: f.hamming_weight() # needs sage.rings.real_mpfr
|
|
274
|
+
101
|
|
275
|
+
"""
|
|
276
|
+
return len(self.element().dict())
|
|
277
|
+
|
|
278
|
+
hamming_weight = number_of_terms
|
|
279
|
+
|
|
280
|
+
def __neg__(self):
|
|
281
|
+
"""
|
|
282
|
+
Return the negative of ``self``.
|
|
283
|
+
|
|
284
|
+
EXAMPLES::
|
|
285
|
+
|
|
286
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
287
|
+
sage: -x # needs sage.rings.number_field
|
|
288
|
+
-x
|
|
289
|
+
sage: -(y-1) # needs sage.rings.number_field
|
|
290
|
+
-y + 1
|
|
291
|
+
"""
|
|
292
|
+
return self.__class__(self.parent(), -self.__element)
|
|
293
|
+
|
|
294
|
+
def _add_(self, right):
|
|
295
|
+
"""
|
|
296
|
+
Return the sum of ``self`` and ``right``.
|
|
297
|
+
|
|
298
|
+
EXAMPLES::
|
|
299
|
+
|
|
300
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
301
|
+
sage: x + y # needs sage.rings.number_field
|
|
302
|
+
x + y
|
|
303
|
+
"""
|
|
304
|
+
elt = self.__element + right.__element
|
|
305
|
+
elt.remove_zeros()
|
|
306
|
+
return self.__class__(self.parent(), elt)
|
|
307
|
+
|
|
308
|
+
def _sub_(self, right):
|
|
309
|
+
"""
|
|
310
|
+
Return the difference between ``self`` and ``right``.
|
|
311
|
+
|
|
312
|
+
EXAMPLES::
|
|
313
|
+
|
|
314
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
315
|
+
sage: x - y # needs sage.rings.number_field
|
|
316
|
+
x - y
|
|
317
|
+
"""
|
|
318
|
+
elt = self.__element - right.__element
|
|
319
|
+
elt.remove_zeros()
|
|
320
|
+
return self.__class__(self.parent(), elt)
|
|
321
|
+
|
|
322
|
+
def _mul_(self, right):
|
|
323
|
+
"""
|
|
324
|
+
Return the product between ``self`` and ``right``.
|
|
325
|
+
|
|
326
|
+
EXAMPLES::
|
|
327
|
+
|
|
328
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
329
|
+
sage: x * y # needs sage.rings.number_field
|
|
330
|
+
x*y
|
|
331
|
+
"""
|
|
332
|
+
elt = self.__element * right.__element
|
|
333
|
+
elt.remove_zeros()
|
|
334
|
+
return self.__class__(self.parent(), elt)
|
|
335
|
+
|
|
336
|
+
def _lmul_(self, a):
|
|
337
|
+
"""
|
|
338
|
+
Left Scalar Multiplication.
|
|
339
|
+
|
|
340
|
+
EXAMPLES:
|
|
341
|
+
|
|
342
|
+
Note that it is not really possible to do a meaningful
|
|
343
|
+
example since sage mpoly rings refuse to have non-commutative
|
|
344
|
+
bases.
|
|
345
|
+
|
|
346
|
+
::
|
|
347
|
+
|
|
348
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
349
|
+
sage: f = (x + y) # needs sage.rings.number_field
|
|
350
|
+
sage: 3 * f # needs sage.rings.number_field
|
|
351
|
+
3*x + 3*y
|
|
352
|
+
"""
|
|
353
|
+
elt = self.__element.scalar_lmult(a)
|
|
354
|
+
elt.remove_zeros()
|
|
355
|
+
return self.__class__(self.parent(), elt)
|
|
356
|
+
|
|
357
|
+
def _rmul_(self, a):
|
|
358
|
+
"""
|
|
359
|
+
Right Scalar Multiplication.
|
|
360
|
+
|
|
361
|
+
EXAMPLES:
|
|
362
|
+
|
|
363
|
+
Note that it is not really possible to do a meaningful
|
|
364
|
+
example since sage mpoly rings refuse to have non-commutative
|
|
365
|
+
bases.
|
|
366
|
+
|
|
367
|
+
::
|
|
368
|
+
|
|
369
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
370
|
+
sage: f = (x + y) # needs sage.rings.number_field
|
|
371
|
+
sage: f * 3 # needs sage.rings.number_field
|
|
372
|
+
3*x + 3*y
|
|
373
|
+
"""
|
|
374
|
+
elt = self.__element.scalar_rmult(a)
|
|
375
|
+
elt.remove_zeros()
|
|
376
|
+
return self.__class__(self.parent(), elt)
|
|
377
|
+
|
|
378
|
+
def _div_(self, right):
|
|
379
|
+
r"""
|
|
380
|
+
EXAMPLES::
|
|
381
|
+
|
|
382
|
+
sage: R.<x,y> = CC['x,y'] # needs sage.rings.real_mpfr
|
|
383
|
+
sage: f = (x + y)/x; f # needs sage.rings.real_mpfr
|
|
384
|
+
(x + y)/x
|
|
385
|
+
sage: f.parent() # needs sage.rings.real_mpfr
|
|
386
|
+
Fraction Field of Multivariate Polynomial Ring in x, y over
|
|
387
|
+
Complex Field with 53 bits of precision
|
|
388
|
+
|
|
389
|
+
If dividing by a scalar, there is no need to go to the fraction
|
|
390
|
+
field of the polynomial ring::
|
|
391
|
+
|
|
392
|
+
sage: f = (x + y)/2; f # needs sage.rings.real_mpfr
|
|
393
|
+
0.500000000000000*x + 0.500000000000000*y
|
|
394
|
+
sage: f.parent() # needs sage.rings.real_mpfr
|
|
395
|
+
Multivariate Polynomial Ring in x, y over Complex Field with
|
|
396
|
+
53 bits of precision
|
|
397
|
+
|
|
398
|
+
TESTS:
|
|
399
|
+
|
|
400
|
+
Ensure that :issue:`13704` is fixed.::
|
|
401
|
+
|
|
402
|
+
sage: R.<t> = PolynomialRing(QQ)
|
|
403
|
+
sage: S.<x,y> = PolynomialRing(R)
|
|
404
|
+
sage: x/S(2)
|
|
405
|
+
1/2*x
|
|
406
|
+
"""
|
|
407
|
+
if right.is_constant():
|
|
408
|
+
inv = self.base_ring().one() / right.constant_coefficient()
|
|
409
|
+
return inv * self
|
|
410
|
+
return self.parent().fraction_field()(self, right, coerce=False)
|
|
411
|
+
|
|
412
|
+
def __rpow__(self, n):
|
|
413
|
+
if not isinstance(n, (int, Integer)):
|
|
414
|
+
raise TypeError("The exponent must be an integer.")
|
|
415
|
+
return self.parent()(self.__element**n)
|
|
416
|
+
|
|
417
|
+
def element(self):
|
|
418
|
+
return self.__element
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class MPolynomial_polydict(Polynomial_singular_repr, MPolynomial_element):
|
|
422
|
+
r"""
|
|
423
|
+
Multivariate polynomials implemented in pure python using
|
|
424
|
+
polydicts.
|
|
425
|
+
"""
|
|
426
|
+
def __init__(self, parent, x):
|
|
427
|
+
"""
|
|
428
|
+
EXAMPLES::
|
|
429
|
+
|
|
430
|
+
sage: R, x = PolynomialRing(QQbar, 10, 'x').objgens() # needs sage.rings.number_field
|
|
431
|
+
sage: x # needs sage.rings.number_field
|
|
432
|
+
(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
|
433
|
+
sage: loads(dumps(x)) == x # needs sage.rings.number_field
|
|
434
|
+
True
|
|
435
|
+
"""
|
|
436
|
+
if not isinstance(x, polydict.PolyDict):
|
|
437
|
+
x = polydict.PolyDict(x)
|
|
438
|
+
x.remove_zeros()
|
|
439
|
+
MPolynomial_element.__init__(self, parent, x)
|
|
440
|
+
|
|
441
|
+
def _new_constant_poly(self, x, P):
|
|
442
|
+
"""
|
|
443
|
+
Quickly create a new constant polynomial with value x in parent P.
|
|
444
|
+
|
|
445
|
+
ASSUMPTION:
|
|
446
|
+
|
|
447
|
+
x must be an element of the base ring of P. That assumption is
|
|
448
|
+
not verified.
|
|
449
|
+
|
|
450
|
+
EXAMPLES::
|
|
451
|
+
|
|
452
|
+
sage: R.<x,y> = QQ['t'][]
|
|
453
|
+
sage: x._new_constant_poly(R.base_ring()(2),R)
|
|
454
|
+
2
|
|
455
|
+
"""
|
|
456
|
+
return MPolynomial_polydict(P, {P._zero_tuple:x})
|
|
457
|
+
|
|
458
|
+
def _repr_(self):
|
|
459
|
+
"""
|
|
460
|
+
EXAMPLES::
|
|
461
|
+
|
|
462
|
+
sage: # needs sage.rings.number_field
|
|
463
|
+
sage: R.<x,y> = QQbar[]
|
|
464
|
+
sage: repr(-x^2 - y + 1) # indirect doctest
|
|
465
|
+
'-x^2 - y + 1'
|
|
466
|
+
sage: K.<I> = QuadraticField(-1)
|
|
467
|
+
sage: R.<x,y> = K[]
|
|
468
|
+
sage: repr(-I*y - x^2) # indirect doctest
|
|
469
|
+
'-x^2 + (-I)*y'
|
|
470
|
+
"""
|
|
471
|
+
if self.is_gen():
|
|
472
|
+
return self.parent().variable_names()[self.degrees().nonzero_positions()[0]]
|
|
473
|
+
try:
|
|
474
|
+
key = self.parent().term_order().sortkey
|
|
475
|
+
except AttributeError:
|
|
476
|
+
key = None
|
|
477
|
+
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
|
|
478
|
+
return self.element().poly_repr(self.parent().variable_names(),
|
|
479
|
+
atomic_coefficients=atomic,
|
|
480
|
+
sortkey=key)
|
|
481
|
+
|
|
482
|
+
def _latex_(self):
|
|
483
|
+
r"""
|
|
484
|
+
EXAMPLES::
|
|
485
|
+
|
|
486
|
+
sage: # needs sage.rings.number_field
|
|
487
|
+
sage: R.<x,y> = QQbar[]
|
|
488
|
+
sage: latex(-x^2 - y + 1)
|
|
489
|
+
-x^{2} - y + 1
|
|
490
|
+
sage: K.<I> = QuadraticField(-1)
|
|
491
|
+
sage: R.<x,y> = K[]
|
|
492
|
+
sage: latex(-I*y + I*x^2)
|
|
493
|
+
\left(\sqrt{-1}\right) x^{2} + \left(-\sqrt{-1}\right) y
|
|
494
|
+
"""
|
|
495
|
+
try:
|
|
496
|
+
key = self.parent().term_order().sortkey
|
|
497
|
+
except AttributeError:
|
|
498
|
+
key = None
|
|
499
|
+
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
|
|
500
|
+
return self.element().latex(self.parent().latex_variable_names(),
|
|
501
|
+
atomic_coefficients=atomic, sortkey=key)
|
|
502
|
+
|
|
503
|
+
def _repr_with_changed_varnames(self, varnames):
|
|
504
|
+
"""
|
|
505
|
+
EXAMPLES::
|
|
506
|
+
|
|
507
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
508
|
+
sage: f = -x^2 - y + 1 # needs sage.rings.number_field
|
|
509
|
+
sage: f._repr_with_changed_varnames(['jack', 'jill']) # needs sage.rings.number_field
|
|
510
|
+
'-jack^2 - jill + 1'
|
|
511
|
+
"""
|
|
512
|
+
try:
|
|
513
|
+
key = self.parent().term_order().sortkey
|
|
514
|
+
except AttributeError:
|
|
515
|
+
key = None
|
|
516
|
+
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
|
|
517
|
+
return self.element().poly_repr(varnames,
|
|
518
|
+
atomic_coefficients=atomic, sortkey=key)
|
|
519
|
+
|
|
520
|
+
def _macaulay2_(self, macaulay2=None):
|
|
521
|
+
"""
|
|
522
|
+
EXAMPLES::
|
|
523
|
+
|
|
524
|
+
sage: R = GF(13)['a,b']['c,d']
|
|
525
|
+
sage: macaulay2(R('a^2 + c')) # optional - macaulay2
|
|
526
|
+
2
|
|
527
|
+
c + a
|
|
528
|
+
|
|
529
|
+
TESTS:
|
|
530
|
+
|
|
531
|
+
Elements of the base ring are coerced to the polynomial ring
|
|
532
|
+
correctly::
|
|
533
|
+
|
|
534
|
+
sage: macaulay2(R('a^2')).ring()._operator('===', R) # optional - macaulay2
|
|
535
|
+
true
|
|
536
|
+
"""
|
|
537
|
+
if macaulay2 is None:
|
|
538
|
+
from sage.interfaces.macaulay2 import macaulay2 as m2_default
|
|
539
|
+
macaulay2 = m2_default
|
|
540
|
+
m2_parent = macaulay2(self.parent())
|
|
541
|
+
macaulay2.use(m2_parent)
|
|
542
|
+
return macaulay2('substitute(%s,%s)' % (repr(self), m2_parent._name))
|
|
543
|
+
|
|
544
|
+
def degrees(self):
|
|
545
|
+
r"""
|
|
546
|
+
Return a tuple (precisely - an ``ETuple``) with the
|
|
547
|
+
degree of each variable in this polynomial. The list of degrees is,
|
|
548
|
+
of course, ordered by the order of the generators.
|
|
549
|
+
|
|
550
|
+
EXAMPLES::
|
|
551
|
+
|
|
552
|
+
sage: # needs sage.rings.number_field
|
|
553
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar)
|
|
554
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
555
|
+
sage: f.degrees()
|
|
556
|
+
(2, 2, 0)
|
|
557
|
+
sage: f = x^2 + z^2
|
|
558
|
+
sage: f.degrees()
|
|
559
|
+
(2, 0, 2)
|
|
560
|
+
sage: f.total_degree() # this simply illustrates that total degree is not the sum of the degrees
|
|
561
|
+
2
|
|
562
|
+
sage: R.<x,y,z,u> = PolynomialRing(QQbar)
|
|
563
|
+
sage: f = (1-x) * (1+y+z+x^3)^5
|
|
564
|
+
sage: f.degrees()
|
|
565
|
+
(16, 5, 5, 0)
|
|
566
|
+
sage: R(0).degrees()
|
|
567
|
+
(0, 0, 0, 0)
|
|
568
|
+
"""
|
|
569
|
+
if not self:
|
|
570
|
+
return polydict.ETuple({}, self.parent().ngens())
|
|
571
|
+
else:
|
|
572
|
+
return self._MPolynomial_element__element.max_exp()
|
|
573
|
+
|
|
574
|
+
def degree(self, x=None, std_grading=False):
|
|
575
|
+
"""
|
|
576
|
+
Return the degree of ``self`` in ``x``, where ``x`` must be one of the
|
|
577
|
+
generators for the parent of ``self``.
|
|
578
|
+
|
|
579
|
+
INPUT:
|
|
580
|
+
|
|
581
|
+
- ``x`` -- multivariate polynomial (a generator of the parent
|
|
582
|
+
of ``self``). If ``x`` is not specified (or is None), return
|
|
583
|
+
the total degree, which is the maximum degree of any
|
|
584
|
+
monomial. Note that a weighted term ordering alters the
|
|
585
|
+
grading of the generators of the ring; see the tests below.
|
|
586
|
+
To avoid this behavior, set the optional argument ``std_grading=True``.
|
|
587
|
+
|
|
588
|
+
OUTPUT: integer
|
|
589
|
+
|
|
590
|
+
EXAMPLES::
|
|
591
|
+
|
|
592
|
+
sage: R.<x,y> = RR[]
|
|
593
|
+
sage: f = y^2 - x^9 - x
|
|
594
|
+
sage: f.degree(x)
|
|
595
|
+
9
|
|
596
|
+
sage: f.degree(y)
|
|
597
|
+
2
|
|
598
|
+
sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(x)
|
|
599
|
+
3
|
|
600
|
+
sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(y)
|
|
601
|
+
10
|
|
602
|
+
|
|
603
|
+
Note that total degree takes into account if we are working in a polynomial
|
|
604
|
+
ring with a weighted term order.
|
|
605
|
+
|
|
606
|
+
::
|
|
607
|
+
|
|
608
|
+
sage: R = PolynomialRing(QQ, 'x,y', order=TermOrder('wdeglex',(2,3)))
|
|
609
|
+
sage: x,y = R.gens()
|
|
610
|
+
sage: x.degree()
|
|
611
|
+
2
|
|
612
|
+
sage: y.degree()
|
|
613
|
+
3
|
|
614
|
+
sage: x.degree(y), x.degree(x), y.degree(x), y.degree(y)
|
|
615
|
+
(0, 1, 0, 1)
|
|
616
|
+
sage: f = x^2*y + x*y^2
|
|
617
|
+
sage: f.degree(x)
|
|
618
|
+
2
|
|
619
|
+
sage: f.degree(y)
|
|
620
|
+
2
|
|
621
|
+
sage: f.degree()
|
|
622
|
+
8
|
|
623
|
+
sage: f.degree(std_grading=True)
|
|
624
|
+
3
|
|
625
|
+
|
|
626
|
+
Note that if ``x`` is not a generator of the parent of ``self``,
|
|
627
|
+
for example if it is a generator of a polynomial algebra which
|
|
628
|
+
maps naturally to this one, then it is converted to an element
|
|
629
|
+
of this algebra. (This fixes the problem reported in
|
|
630
|
+
:issue:`17366`.)
|
|
631
|
+
|
|
632
|
+
::
|
|
633
|
+
|
|
634
|
+
sage: x, y = ZZ['x','y'].gens()
|
|
635
|
+
sage: GF(3037000453)['x','y'].gen(0).degree(x) # needs sage.rings.finite_rings
|
|
636
|
+
1
|
|
637
|
+
|
|
638
|
+
sage: x0, y0 = QQ['x','y'].gens()
|
|
639
|
+
sage: GF(3037000453)['x','y'].gen(0).degree(x0) # needs sage.rings.finite_rings
|
|
640
|
+
Traceback (most recent call last):
|
|
641
|
+
...
|
|
642
|
+
TypeError: argument is not coercible to the parent
|
|
643
|
+
|
|
644
|
+
sage: GF(3037000453)['x','y'].gen(0).degree(x^2) # needs sage.rings.finite_rings
|
|
645
|
+
Traceback (most recent call last):
|
|
646
|
+
...
|
|
647
|
+
TypeError: argument is not a generator
|
|
648
|
+
|
|
649
|
+
TESTS::
|
|
650
|
+
|
|
651
|
+
sage: R = PolynomialRing(GF(2)['t'], 'x,y',
|
|
652
|
+
....: order=TermOrder('wdeglex', (2,3)))
|
|
653
|
+
sage: x, y = R.gens()
|
|
654
|
+
sage: x.degree()
|
|
655
|
+
2
|
|
656
|
+
sage: y.degree()
|
|
657
|
+
3
|
|
658
|
+
sage: x.degree(y), x.degree(x), y.degree(x), y.degree(y)
|
|
659
|
+
(0, 1, 0, 1)
|
|
660
|
+
sage: f = (x^2*y + x*y^2)
|
|
661
|
+
sage: f.degree(x)
|
|
662
|
+
2
|
|
663
|
+
sage: f.degree(y)
|
|
664
|
+
2
|
|
665
|
+
sage: f.degree()
|
|
666
|
+
8
|
|
667
|
+
sage: f.degree(std_grading=True)
|
|
668
|
+
3
|
|
669
|
+
sage: R(0).degree()
|
|
670
|
+
-1
|
|
671
|
+
|
|
672
|
+
Degree of zero polynomial for other implementation :issue:`20048` ::
|
|
673
|
+
|
|
674
|
+
sage: R.<x,y> = GF(3037000453)[] # needs sage.rings.finite_rings
|
|
675
|
+
sage: R.zero().degree(x)
|
|
676
|
+
-1
|
|
677
|
+
|
|
678
|
+
Ensure that :issue:`37603` is fixed::
|
|
679
|
+
|
|
680
|
+
sage: # needs sage.rings.number_field
|
|
681
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar)
|
|
682
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
683
|
+
sage: type(f.degree())
|
|
684
|
+
<class 'sage.rings.integer.Integer'>
|
|
685
|
+
sage: type(f.degree(x))
|
|
686
|
+
<class 'sage.rings.integer.Integer'>
|
|
687
|
+
sage: type(f.degree(x)) == type(f.degree(y)) == type(f.degree(z))
|
|
688
|
+
True
|
|
689
|
+
"""
|
|
690
|
+
if x is None:
|
|
691
|
+
if std_grading or not self.parent().term_order().is_weighted_degree_order():
|
|
692
|
+
return Integer(self.element().degree(None))
|
|
693
|
+
return self.weighted_degree(self.parent().term_order().weights())
|
|
694
|
+
if isinstance(x, MPolynomial):
|
|
695
|
+
if x.parent() is not self.parent():
|
|
696
|
+
try:
|
|
697
|
+
x = self.parent().coerce(x)
|
|
698
|
+
except TypeError:
|
|
699
|
+
raise TypeError("x must canonically coerce to parent")
|
|
700
|
+
if not x.is_gen():
|
|
701
|
+
raise TypeError("x must be one of the generators of the parent")
|
|
702
|
+
else:
|
|
703
|
+
raise TypeError("x must be one of the generators of the parent")
|
|
704
|
+
return Integer(self.element().degree(x.element()))
|
|
705
|
+
|
|
706
|
+
def total_degree(self):
|
|
707
|
+
"""
|
|
708
|
+
Return the total degree of ``self``, which is the maximum degree of any
|
|
709
|
+
monomial in ``self``.
|
|
710
|
+
|
|
711
|
+
EXAMPLES::
|
|
712
|
+
|
|
713
|
+
sage: # needs sage.rings.number_field
|
|
714
|
+
sage: R.<x,y,z> = QQbar[]
|
|
715
|
+
sage: f = 2*x*y^3*z^2
|
|
716
|
+
sage: f.total_degree()
|
|
717
|
+
6
|
|
718
|
+
sage: f = 4*x^2*y^2*z^3
|
|
719
|
+
sage: f.total_degree()
|
|
720
|
+
7
|
|
721
|
+
sage: f = 99*x^6*y^3*z^9
|
|
722
|
+
sage: f.total_degree()
|
|
723
|
+
18
|
|
724
|
+
sage: f = x*y^3*z^6 + 3*x^2
|
|
725
|
+
sage: f.total_degree()
|
|
726
|
+
10
|
|
727
|
+
sage: f = z^3 + 8*x^4*y^5*z
|
|
728
|
+
sage: f.total_degree()
|
|
729
|
+
10
|
|
730
|
+
sage: f = z^9 + 10*x^4 + y^8*x^2
|
|
731
|
+
sage: f.total_degree()
|
|
732
|
+
10
|
|
733
|
+
|
|
734
|
+
TESTS:
|
|
735
|
+
|
|
736
|
+
Ensure that :issue:`37603` is fixed::
|
|
737
|
+
|
|
738
|
+
sage: # needs sage.rings.number_field
|
|
739
|
+
sage: R.<x,y,z> = QQbar[]
|
|
740
|
+
sage: f = 2*x*y^3*z^2
|
|
741
|
+
sage: f.total_degree()
|
|
742
|
+
6
|
|
743
|
+
sage: type(f.total_degree())
|
|
744
|
+
<class 'sage.rings.integer.Integer'>
|
|
745
|
+
"""
|
|
746
|
+
return self.degree()
|
|
747
|
+
|
|
748
|
+
def monomial_coefficient(self, mon):
|
|
749
|
+
"""
|
|
750
|
+
Return the coefficient in the base ring of the monomial ``mon`` in
|
|
751
|
+
``self``, where ``mon`` must have the same parent as ``self``.
|
|
752
|
+
|
|
753
|
+
This function contrasts with the function
|
|
754
|
+
``coefficient`` which returns the coefficient of a
|
|
755
|
+
monomial viewing this polynomial in a polynomial ring over a base
|
|
756
|
+
ring having fewer variables.
|
|
757
|
+
|
|
758
|
+
INPUT:
|
|
759
|
+
|
|
760
|
+
- ``mon`` -- a monomial
|
|
761
|
+
|
|
762
|
+
OUTPUT: coefficient in base ring
|
|
763
|
+
|
|
764
|
+
.. SEEALSO::
|
|
765
|
+
|
|
766
|
+
For coefficients in a base ring of fewer variables, look
|
|
767
|
+
at :meth:`coefficient`.
|
|
768
|
+
|
|
769
|
+
EXAMPLES:
|
|
770
|
+
|
|
771
|
+
::
|
|
772
|
+
|
|
773
|
+
sage: # needs sage.rings.number_field
|
|
774
|
+
sage: R.<x,y> = QQbar[]
|
|
775
|
+
sage: f = 2 * x * y
|
|
776
|
+
sage: c = f.monomial_coefficient(x*y); c
|
|
777
|
+
2
|
|
778
|
+
sage: c.parent()
|
|
779
|
+
Algebraic Field
|
|
780
|
+
|
|
781
|
+
::
|
|
782
|
+
|
|
783
|
+
sage: # needs sage.rings.number_field
|
|
784
|
+
sage: f = y^2 + y^2*x - x^9 - 7*x + 5*x*y
|
|
785
|
+
sage: f.monomial_coefficient(y^2)
|
|
786
|
+
1
|
|
787
|
+
sage: f.monomial_coefficient(x*y)
|
|
788
|
+
5
|
|
789
|
+
sage: f.monomial_coefficient(x^9)
|
|
790
|
+
-1
|
|
791
|
+
sage: f.monomial_coefficient(x^10)
|
|
792
|
+
0
|
|
793
|
+
|
|
794
|
+
::
|
|
795
|
+
|
|
796
|
+
sage: # needs sage.rings.number_field
|
|
797
|
+
sage: a = polygen(ZZ, 'a')
|
|
798
|
+
sage: K.<a> = NumberField(a^2 + a + 1)
|
|
799
|
+
sage: P.<x,y> = K[]
|
|
800
|
+
sage: f = (a*x - 1) * ((a+1)*y - 1); f
|
|
801
|
+
-x*y + (-a)*x + (-a - 1)*y + 1
|
|
802
|
+
sage: f.monomial_coefficient(x)
|
|
803
|
+
-a
|
|
804
|
+
"""
|
|
805
|
+
if parent(mon) is not self.parent():
|
|
806
|
+
raise TypeError("mon must be a monomial in the parent of self")
|
|
807
|
+
exp = polydict.monomial_exponent(mon.element())
|
|
808
|
+
zero = self.parent().base_ring().zero()
|
|
809
|
+
return self.element().get(exp, zero)
|
|
810
|
+
|
|
811
|
+
def monomial_coefficients(self, copy=None):
|
|
812
|
+
"""
|
|
813
|
+
Return underlying dictionary with keys the exponents and values
|
|
814
|
+
the coefficients of this polynomial.
|
|
815
|
+
|
|
816
|
+
EXAMPLES::
|
|
817
|
+
|
|
818
|
+
sage: # needs sage.rings.number_field
|
|
819
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, order='lex')
|
|
820
|
+
sage: f = (x^1*y^5*z^2 + x^2*z + x^4*y^1*z^3)
|
|
821
|
+
sage: f.monomial_coefficients()
|
|
822
|
+
{(1, 5, 2): 1, (2, 0, 1): 1, (4, 1, 3): 1}
|
|
823
|
+
|
|
824
|
+
``dict`` is an alias::
|
|
825
|
+
|
|
826
|
+
sage: f.dict() # needs sage.rings.number_field
|
|
827
|
+
{(1, 5, 2): 1, (2, 0, 1): 1, (4, 1, 3): 1}
|
|
828
|
+
"""
|
|
829
|
+
return self.element().dict()
|
|
830
|
+
|
|
831
|
+
dict = monomial_coefficients
|
|
832
|
+
|
|
833
|
+
def __iter__(self):
|
|
834
|
+
"""
|
|
835
|
+
Iterate over ``self`` respecting the term order.
|
|
836
|
+
|
|
837
|
+
EXAMPLES::
|
|
838
|
+
|
|
839
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, order='lex') # needs sage.rings.number_field
|
|
840
|
+
sage: f = (x^1*y^5*z^2 + x^2*z + x^4*y^1*z^3) # needs sage.rings.number_field
|
|
841
|
+
sage: list(f) # needs sage.rings.number_field
|
|
842
|
+
[(1, x^4*y*z^3), (1, x^2*z), (1, x*y^5*z^2)]
|
|
843
|
+
|
|
844
|
+
::
|
|
845
|
+
|
|
846
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, order='deglex') # needs sage.rings.number_field
|
|
847
|
+
sage: f = (x^1*y^5*z^2 + x^2*z + x^4*y^1*z^3) # needs sage.rings.number_field
|
|
848
|
+
sage: list(f) # needs sage.rings.number_field
|
|
849
|
+
[(1, x^4*y*z^3), (1, x*y^5*z^2), (1, x^2*z)]
|
|
850
|
+
|
|
851
|
+
::
|
|
852
|
+
|
|
853
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, order='degrevlex') # needs sage.rings.number_field
|
|
854
|
+
sage: f = (x^1*y^5*z^2 + x^2*z + x^4*y^1*z^3) # needs sage.rings.number_field
|
|
855
|
+
sage: list(f) # needs sage.rings.number_field
|
|
856
|
+
[(1, x*y^5*z^2), (1, x^4*y*z^3), (1, x^2*z)]
|
|
857
|
+
|
|
858
|
+
::
|
|
859
|
+
|
|
860
|
+
sage: R = ZZ['t']
|
|
861
|
+
sage: P.<x,y,z> = PolynomialRing(R,3)
|
|
862
|
+
sage: f = 3*x^3*y + 16*x + 7
|
|
863
|
+
sage: [(c,m) for c,m in f]
|
|
864
|
+
[(3, x^3*y), (16, x), (7, 1)]
|
|
865
|
+
sage: f = P.random_element(10,10)
|
|
866
|
+
sage: sum(c*m for c,m in f) == f
|
|
867
|
+
True
|
|
868
|
+
"""
|
|
869
|
+
elt = self.element()
|
|
870
|
+
ring = self.parent()
|
|
871
|
+
one = ring.base_ring().one()
|
|
872
|
+
for exp in self._exponents:
|
|
873
|
+
yield (elt[exp], MPolynomial_polydict(ring, polydict.PolyDict({exp: one}, check=False)))
|
|
874
|
+
|
|
875
|
+
def __getitem__(self, x):
|
|
876
|
+
"""
|
|
877
|
+
Return the coefficient corresponding to ``x``.
|
|
878
|
+
|
|
879
|
+
INPUT:
|
|
880
|
+
|
|
881
|
+
- ``x`` -- tuple or, in case of a single-variable
|
|
882
|
+
MPolynomial ring, ``x`` can also be an integer
|
|
883
|
+
|
|
884
|
+
EXAMPLES::
|
|
885
|
+
|
|
886
|
+
sage: # needs sage.rings.number_field
|
|
887
|
+
sage: R.<x, y> = PolynomialRing(QQbar, 2)
|
|
888
|
+
sage: f = -10*x^3*y + 17*x*y
|
|
889
|
+
sage: f[3,1]
|
|
890
|
+
-10
|
|
891
|
+
sage: f[1,1]
|
|
892
|
+
17
|
|
893
|
+
sage: f[0,1]
|
|
894
|
+
0
|
|
895
|
+
|
|
896
|
+
::
|
|
897
|
+
|
|
898
|
+
sage: R.<x> = PolynomialRing(QQbar, 1); R # needs sage.rings.number_field
|
|
899
|
+
Multivariate Polynomial Ring in x over Algebraic Field
|
|
900
|
+
sage: f = 5*x^2 + 3; f # needs sage.rings.number_field
|
|
901
|
+
5*x^2 + 3
|
|
902
|
+
sage: f[2] # needs sage.rings.number_field
|
|
903
|
+
5
|
|
904
|
+
"""
|
|
905
|
+
if isinstance(x, MPolynomial):
|
|
906
|
+
return self.monomial_coefficient(x)
|
|
907
|
+
if not isinstance(x, tuple):
|
|
908
|
+
try:
|
|
909
|
+
x = tuple(x)
|
|
910
|
+
except TypeError:
|
|
911
|
+
x = (x, )
|
|
912
|
+
try:
|
|
913
|
+
return self.element()[x]
|
|
914
|
+
except KeyError:
|
|
915
|
+
return self.parent().base_ring().zero()
|
|
916
|
+
|
|
917
|
+
def iterator_exp_coeff(self, as_ETuples=True):
|
|
918
|
+
"""
|
|
919
|
+
Iterate over ``self`` as pairs of ((E)Tuple, coefficient).
|
|
920
|
+
|
|
921
|
+
INPUT:
|
|
922
|
+
|
|
923
|
+
- ``as_ETuples`` -- boolean (default: ``True``); if ``True`` iterate
|
|
924
|
+
over pairs whose first element is an ETuple, otherwise as a tuples
|
|
925
|
+
|
|
926
|
+
EXAMPLES::
|
|
927
|
+
|
|
928
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, order='lex') # needs sage.rings.number_field
|
|
929
|
+
sage: f = (x^1*y^5*z^2 + x^2*z + x^4*y^1*z^3) # needs sage.rings.number_field
|
|
930
|
+
sage: list(f.iterator_exp_coeff()) # needs sage.rings.number_field
|
|
931
|
+
[((4, 1, 3), 1), ((2, 0, 1), 1), ((1, 5, 2), 1)]
|
|
932
|
+
|
|
933
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, order='deglex') # needs sage.rings.number_field
|
|
934
|
+
sage: f = (x^1*y^5*z^2 + x^2*z + x^4*y^1*z^3) # needs sage.rings.number_field
|
|
935
|
+
sage: list(f.iterator_exp_coeff(as_ETuples=False)) # needs sage.rings.number_field
|
|
936
|
+
[((4, 1, 3), 1), ((1, 5, 2), 1), ((2, 0, 1), 1)]
|
|
937
|
+
"""
|
|
938
|
+
elt = self.element()
|
|
939
|
+
if as_ETuples:
|
|
940
|
+
for exp in self._exponents:
|
|
941
|
+
yield (exp, elt[exp])
|
|
942
|
+
else:
|
|
943
|
+
for exp in self._exponents:
|
|
944
|
+
yield (tuple(exp), elt[exp])
|
|
945
|
+
|
|
946
|
+
def coefficient(self, degrees):
|
|
947
|
+
"""
|
|
948
|
+
Return the coefficient of the variables with the degrees specified
|
|
949
|
+
in the python dictionary ``degrees``. Mathematically,
|
|
950
|
+
this is the coefficient in the base ring adjoined by the variables
|
|
951
|
+
of this ring not listed in ``degrees``. However, the
|
|
952
|
+
result has the same parent as this polynomial.
|
|
953
|
+
|
|
954
|
+
This function contrasts with the function
|
|
955
|
+
``monomial_coefficient`` which returns the coefficient
|
|
956
|
+
in the base ring of a monomial.
|
|
957
|
+
|
|
958
|
+
INPUT:
|
|
959
|
+
|
|
960
|
+
- ``degrees`` -- can be any of:
|
|
961
|
+
|
|
962
|
+
- a dictionary of degree restrictions
|
|
963
|
+
|
|
964
|
+
- a list of degree restrictions (with ``None`` in
|
|
965
|
+
the unrestricted variables)
|
|
966
|
+
|
|
967
|
+
- a monomial (very fast, but not as flexible)
|
|
968
|
+
|
|
969
|
+
OUTPUT: element of the parent of ``self``
|
|
970
|
+
|
|
971
|
+
.. SEEALSO::
|
|
972
|
+
|
|
973
|
+
For coefficients of specific monomials, look at
|
|
974
|
+
:meth:`monomial_coefficient`.
|
|
975
|
+
|
|
976
|
+
EXAMPLES::
|
|
977
|
+
|
|
978
|
+
sage: # needs sage.rings.number_field
|
|
979
|
+
sage: R.<x, y> = QQbar[]
|
|
980
|
+
sage: f = 2 * x * y
|
|
981
|
+
sage: c = f.coefficient({x: 1, y: 1}); c
|
|
982
|
+
2
|
|
983
|
+
sage: c.parent()
|
|
984
|
+
Multivariate Polynomial Ring in x, y over Algebraic Field
|
|
985
|
+
sage: c in PolynomialRing(QQbar, 2, names=['x', 'y'])
|
|
986
|
+
True
|
|
987
|
+
sage: f = y^2 - x^9 - 7*x + 5*x*y
|
|
988
|
+
sage: f.coefficient({y: 1})
|
|
989
|
+
5*x
|
|
990
|
+
sage: f.coefficient({y: 0})
|
|
991
|
+
-x^9 + (-7)*x
|
|
992
|
+
sage: f.coefficient({x: 0, y: 0})
|
|
993
|
+
0
|
|
994
|
+
sage: f = (1+y+y^2) * (1+x+x^2)
|
|
995
|
+
sage: f.coefficient({x: 0})
|
|
996
|
+
y^2 + y + 1
|
|
997
|
+
sage: f.coefficient([0, None])
|
|
998
|
+
y^2 + y + 1
|
|
999
|
+
sage: f.coefficient(x)
|
|
1000
|
+
y^2 + y + 1
|
|
1001
|
+
sage: # Be aware that this may not be what you think!
|
|
1002
|
+
sage: # The physical appearance of the variable x is deceiving -- particularly if the exponent would be a variable.
|
|
1003
|
+
sage: f.coefficient(x^0) # outputs the full polynomial
|
|
1004
|
+
x^2*y^2 + x^2*y + x*y^2 + x^2 + x*y + y^2 + x + y + 1
|
|
1005
|
+
|
|
1006
|
+
::
|
|
1007
|
+
|
|
1008
|
+
sage: # needs sage.rings.real_mpfr
|
|
1009
|
+
sage: R.<x,y> = RR[]
|
|
1010
|
+
sage: f = x*y + 5
|
|
1011
|
+
sage: c = f.coefficient({x: 0, y: 0}); c
|
|
1012
|
+
5.00000000000000
|
|
1013
|
+
sage: parent(c)
|
|
1014
|
+
Multivariate Polynomial Ring in x, y over Real Field with 53 bits of precision
|
|
1015
|
+
|
|
1016
|
+
AUTHORS:
|
|
1017
|
+
|
|
1018
|
+
- Joel B. Mohler (2007-10-31)
|
|
1019
|
+
"""
|
|
1020
|
+
looking_for = None
|
|
1021
|
+
if isinstance(degrees, MPolynomial) and degrees.parent() == self.parent() and degrees.is_monomial():
|
|
1022
|
+
looking_for = [e if e > 0 else None for e in degrees._exponents[0]]
|
|
1023
|
+
elif isinstance(degrees, list):
|
|
1024
|
+
looking_for = degrees
|
|
1025
|
+
elif isinstance(degrees, dict):
|
|
1026
|
+
poly_vars = self.parent().gens()
|
|
1027
|
+
looking_for = [None] * len(poly_vars)
|
|
1028
|
+
for d, exp in degrees.items():
|
|
1029
|
+
for i in range(len(poly_vars)):
|
|
1030
|
+
if d == poly_vars[i]:
|
|
1031
|
+
looking_for[i] = exp
|
|
1032
|
+
if not looking_for:
|
|
1033
|
+
raise ValueError("You must pass a dictionary list or monomial.")
|
|
1034
|
+
return self.parent()(self.element().polynomial_coefficient(looking_for))
|
|
1035
|
+
|
|
1036
|
+
def global_height(self, prec=None):
|
|
1037
|
+
"""
|
|
1038
|
+
Return the (projective) global height of the polynomial.
|
|
1039
|
+
|
|
1040
|
+
This returns the absolute logarithmic height of the coefficients
|
|
1041
|
+
thought of as a projective point.
|
|
1042
|
+
|
|
1043
|
+
INPUT:
|
|
1044
|
+
|
|
1045
|
+
- ``prec`` -- desired floating point precision (default:
|
|
1046
|
+
default :class:`RealField` precision)
|
|
1047
|
+
|
|
1048
|
+
OUTPUT: a real number
|
|
1049
|
+
|
|
1050
|
+
EXAMPLES::
|
|
1051
|
+
|
|
1052
|
+
sage: R.<x,y> = PolynomialRing(QQbar, 2) # needs sage.rings.number_field
|
|
1053
|
+
sage: f = QQbar(i)*x^2 + 3*x*y # needs sage.rings.number_field
|
|
1054
|
+
sage: f.global_height() # needs sage.rings.number_field
|
|
1055
|
+
1.09861228866811
|
|
1056
|
+
|
|
1057
|
+
Scaling should not change the result::
|
|
1058
|
+
|
|
1059
|
+
sage: # needs sage.rings.number_field sage.symbolic
|
|
1060
|
+
sage: R.<x, y> = PolynomialRing(QQbar, 2)
|
|
1061
|
+
sage: f = 1/25*x^2 + 25/3*x + 1 + QQbar(sqrt(2))*y^2
|
|
1062
|
+
sage: f.global_height()
|
|
1063
|
+
6.43775164973640
|
|
1064
|
+
sage: g = 100 * f
|
|
1065
|
+
sage: g.global_height()
|
|
1066
|
+
6.43775164973640
|
|
1067
|
+
|
|
1068
|
+
::
|
|
1069
|
+
|
|
1070
|
+
sage: # needs sage.rings.number_field
|
|
1071
|
+
sage: R.<x> = QQ[]
|
|
1072
|
+
sage: K.<k> = NumberField(x^2 + 1)
|
|
1073
|
+
sage: Q.<q,r> = PolynomialRing(K, implementation='generic')
|
|
1074
|
+
sage: f = 12 * q
|
|
1075
|
+
sage: f.global_height()
|
|
1076
|
+
0.000000000000000
|
|
1077
|
+
|
|
1078
|
+
::
|
|
1079
|
+
|
|
1080
|
+
sage: R.<x,y> = PolynomialRing(QQ, implementation='generic')
|
|
1081
|
+
sage: f = 1/123*x*y + 12
|
|
1082
|
+
sage: f.global_height(prec=2) # needs sage.symbolic
|
|
1083
|
+
8.0
|
|
1084
|
+
|
|
1085
|
+
::
|
|
1086
|
+
|
|
1087
|
+
sage: R.<x,y> = PolynomialRing(QQ, implementation='generic')
|
|
1088
|
+
sage: f = 0*x*y
|
|
1089
|
+
sage: f.global_height() # needs sage.rings.real_mpfr
|
|
1090
|
+
0.000000000000000
|
|
1091
|
+
"""
|
|
1092
|
+
if prec is None:
|
|
1093
|
+
prec = 53
|
|
1094
|
+
|
|
1095
|
+
if self.is_zero():
|
|
1096
|
+
from sage.rings.real_mpfr import RealField
|
|
1097
|
+
return RealField(prec).zero()
|
|
1098
|
+
|
|
1099
|
+
from sage.categories.number_fields import NumberFields
|
|
1100
|
+
|
|
1101
|
+
K = self.base_ring()
|
|
1102
|
+
if K in NumberFields() or isinstance(K, (sage.rings.abc.Order, sage.rings.integer_ring.IntegerRing_class)):
|
|
1103
|
+
from sage.schemes.projective.projective_space import ProjectiveSpace
|
|
1104
|
+
Pr = ProjectiveSpace(K, self.number_of_terms()-1)
|
|
1105
|
+
return Pr.point(self.coefficients()).global_height(prec=prec)
|
|
1106
|
+
if isinstance(K, sage.rings.abc.AlgebraicField):
|
|
1107
|
+
from sage.rings.qqbar import number_field_elements_from_algebraics
|
|
1108
|
+
|
|
1109
|
+
K_pre, P, phi = number_field_elements_from_algebraics(list(self.coefficients()))
|
|
1110
|
+
from sage.schemes.projective.projective_space import ProjectiveSpace
|
|
1111
|
+
Pr = ProjectiveSpace(K_pre, len(P)-1)
|
|
1112
|
+
return Pr.point(P).global_height(prec=prec)
|
|
1113
|
+
|
|
1114
|
+
raise TypeError("Must be over a Numberfield or a Numberfield Order.")
|
|
1115
|
+
|
|
1116
|
+
def local_height(self, v, prec=None):
|
|
1117
|
+
"""
|
|
1118
|
+
Return the maximum of the local height of the coefficients of
|
|
1119
|
+
this polynomial.
|
|
1120
|
+
|
|
1121
|
+
INPUT:
|
|
1122
|
+
|
|
1123
|
+
- ``v`` -- a prime or prime ideal of the base ring
|
|
1124
|
+
|
|
1125
|
+
- ``prec`` -- desired floating point precision (default:
|
|
1126
|
+
default RealField precision)
|
|
1127
|
+
|
|
1128
|
+
OUTPUT: a real number
|
|
1129
|
+
|
|
1130
|
+
EXAMPLES::
|
|
1131
|
+
|
|
1132
|
+
sage: R.<x,y> = PolynomialRing(QQ, implementation='generic')
|
|
1133
|
+
sage: f = 1/1331*x^2 + 1/4000*y
|
|
1134
|
+
sage: f.local_height(1331) # needs sage.rings.real_mpfr
|
|
1135
|
+
7.19368581839511
|
|
1136
|
+
|
|
1137
|
+
::
|
|
1138
|
+
|
|
1139
|
+
sage: # needs sage.rings.number_field
|
|
1140
|
+
sage: R.<x> = QQ[]
|
|
1141
|
+
sage: K.<k> = NumberField(x^2 - 5)
|
|
1142
|
+
sage: T.<t,w> = PolynomialRing(K, implementation='generic')
|
|
1143
|
+
sage: I = K.ideal(3)
|
|
1144
|
+
sage: f = 1/3*t*w + 3
|
|
1145
|
+
sage: f.local_height(I) # needs sage.symbolic
|
|
1146
|
+
1.09861228866811
|
|
1147
|
+
|
|
1148
|
+
::
|
|
1149
|
+
|
|
1150
|
+
sage: R.<x,y> = PolynomialRing(QQ, implementation='generic')
|
|
1151
|
+
sage: f = 1/2*x*y + 2
|
|
1152
|
+
sage: f.local_height(2, prec=2) # needs sage.rings.real_mpfr
|
|
1153
|
+
0.75
|
|
1154
|
+
"""
|
|
1155
|
+
from sage.categories.number_fields import NumberFields
|
|
1156
|
+
|
|
1157
|
+
if prec is None:
|
|
1158
|
+
prec = 53
|
|
1159
|
+
|
|
1160
|
+
K = FractionField(self.base_ring())
|
|
1161
|
+
if K not in NumberFields():
|
|
1162
|
+
raise TypeError("must be over a Numberfield or a Numberfield order")
|
|
1163
|
+
|
|
1164
|
+
return max([K(c).local_height(v, prec=prec) for c in self.coefficients()])
|
|
1165
|
+
|
|
1166
|
+
def local_height_arch(self, i, prec=None):
|
|
1167
|
+
"""
|
|
1168
|
+
Return the maximum of the local height at the ``i``-th infinite place
|
|
1169
|
+
of the coefficients of this polynomial.
|
|
1170
|
+
|
|
1171
|
+
INPUT:
|
|
1172
|
+
|
|
1173
|
+
- ``i`` -- integer
|
|
1174
|
+
|
|
1175
|
+
- ``prec`` -- desired floating point precision (default:
|
|
1176
|
+
default :class:`RealField` precision)
|
|
1177
|
+
|
|
1178
|
+
OUTPUT: a real number
|
|
1179
|
+
|
|
1180
|
+
EXAMPLES::
|
|
1181
|
+
|
|
1182
|
+
sage: R.<x,y> = PolynomialRing(QQ, implementation='generic')
|
|
1183
|
+
sage: f = 210*x*y
|
|
1184
|
+
sage: f.local_height_arch(0) # needs sage.rings.real_mpfr
|
|
1185
|
+
5.34710753071747
|
|
1186
|
+
|
|
1187
|
+
::
|
|
1188
|
+
|
|
1189
|
+
sage: # needs sage.rings.number_field
|
|
1190
|
+
sage: R.<x> = QQ[]
|
|
1191
|
+
sage: K.<k> = NumberField(x^2 - 5)
|
|
1192
|
+
sage: T.<t,w> = PolynomialRing(K, implementation='generic')
|
|
1193
|
+
sage: f = 1/2*t*w + 3
|
|
1194
|
+
sage: f.local_height_arch(1, prec=52)
|
|
1195
|
+
1.09861228866811
|
|
1196
|
+
|
|
1197
|
+
::
|
|
1198
|
+
|
|
1199
|
+
sage: R.<x,y> = PolynomialRing(QQ, implementation='generic')
|
|
1200
|
+
sage: f = 1/2*x*y + 3
|
|
1201
|
+
sage: f.local_height_arch(0, prec=2) # needs sage.rings.real_mpfr
|
|
1202
|
+
1.0
|
|
1203
|
+
"""
|
|
1204
|
+
from sage.categories.number_fields import NumberFields
|
|
1205
|
+
|
|
1206
|
+
if prec is None:
|
|
1207
|
+
prec = 53
|
|
1208
|
+
|
|
1209
|
+
K = FractionField(self.base_ring())
|
|
1210
|
+
if K not in NumberFields():
|
|
1211
|
+
return TypeError("must be over a Numberfield or a Numberfield Order")
|
|
1212
|
+
|
|
1213
|
+
if K == QQ:
|
|
1214
|
+
return max([K(c).local_height_arch(prec=prec) for c in self.coefficients()])
|
|
1215
|
+
return max([K(c).local_height_arch(i, prec=prec) for c in self.coefficients()])
|
|
1216
|
+
|
|
1217
|
+
@lazy_attribute
|
|
1218
|
+
def _exponents(self):
|
|
1219
|
+
"""
|
|
1220
|
+
Return the exponents of the monomials appearing in ``self`` for
|
|
1221
|
+
internal use only.
|
|
1222
|
+
|
|
1223
|
+
EXAMPLES::
|
|
1224
|
+
|
|
1225
|
+
sage: R.<a,b,c> = PolynomialRing(QQbar, 3) # needs sage.rings.number_field
|
|
1226
|
+
sage: f = a^3 + b + 2*b^2 # needs sage.rings.number_field
|
|
1227
|
+
sage: f._exponents # needs sage.rings.number_field
|
|
1228
|
+
[(3, 0, 0), (0, 2, 0), (0, 1, 0)]
|
|
1229
|
+
"""
|
|
1230
|
+
return sorted(self.element().dict(), key=self.parent().term_order().sortkey, reverse=True)
|
|
1231
|
+
|
|
1232
|
+
def exponents(self, as_ETuples=True):
|
|
1233
|
+
r"""
|
|
1234
|
+
Return the exponents of the monomials appearing in ``self``.
|
|
1235
|
+
|
|
1236
|
+
INPUT:
|
|
1237
|
+
|
|
1238
|
+
- ``as_ETuples`` -- (default: ``True``) return the list of
|
|
1239
|
+
exponents as a list of ETuples
|
|
1240
|
+
|
|
1241
|
+
OUTPUT: the list of exponents as a list of ETuples or tuples
|
|
1242
|
+
|
|
1243
|
+
EXAMPLES::
|
|
1244
|
+
|
|
1245
|
+
sage: R.<a,b,c> = PolynomialRing(QQbar, 3) # needs sage.rings.number_field
|
|
1246
|
+
sage: f = a^3 + b + 2*b^2 # needs sage.rings.number_field
|
|
1247
|
+
sage: f.exponents() # needs sage.rings.number_field
|
|
1248
|
+
[(3, 0, 0), (0, 2, 0), (0, 1, 0)]
|
|
1249
|
+
|
|
1250
|
+
By default the list of exponents is a list of ETuples::
|
|
1251
|
+
|
|
1252
|
+
sage: type(f.exponents()[0]) # needs sage.rings.number_field
|
|
1253
|
+
<class 'sage.rings.polynomial.polydict.ETuple'>
|
|
1254
|
+
sage: type(f.exponents(as_ETuples=False)[0]) # needs sage.rings.number_field
|
|
1255
|
+
<... 'tuple'>
|
|
1256
|
+
|
|
1257
|
+
TESTS:
|
|
1258
|
+
|
|
1259
|
+
Check that we can mutate the list and not change the result::
|
|
1260
|
+
|
|
1261
|
+
sage: # needs sage.rings.number_field
|
|
1262
|
+
sage: R.<a,b,c> = PolynomialRing(QQbar, 3)
|
|
1263
|
+
sage: f = a^3 + b + 2*b^2
|
|
1264
|
+
sage: E = f.exponents(); E
|
|
1265
|
+
[(3, 0, 0), (0, 2, 0), (0, 1, 0)]
|
|
1266
|
+
sage: E.pop()
|
|
1267
|
+
(0, 1, 0)
|
|
1268
|
+
sage: E != f.exponents()
|
|
1269
|
+
True
|
|
1270
|
+
"""
|
|
1271
|
+
if as_ETuples:
|
|
1272
|
+
return list(self._exponents) # Make a shallow copy
|
|
1273
|
+
else:
|
|
1274
|
+
return [tuple(e) for e in self._exponents]
|
|
1275
|
+
|
|
1276
|
+
def inverse_of_unit(self):
|
|
1277
|
+
"""
|
|
1278
|
+
Return the inverse of a unit in a ring.
|
|
1279
|
+
|
|
1280
|
+
TESTS::
|
|
1281
|
+
|
|
1282
|
+
sage: R.<c> = QQ[]
|
|
1283
|
+
sage: l = R(2)
|
|
1284
|
+
sage: l.inverse_of_unit().parent()
|
|
1285
|
+
Univariate Polynomial Ring in c over Rational Field
|
|
1286
|
+
"""
|
|
1287
|
+
if self.is_unit():
|
|
1288
|
+
d = self.element().dict()
|
|
1289
|
+
if len(d) != 1:
|
|
1290
|
+
raise NotImplementedError
|
|
1291
|
+
return list(d.values())[0].inverse_of_unit()
|
|
1292
|
+
raise ArithmeticError("is not a unit")
|
|
1293
|
+
|
|
1294
|
+
def is_homogeneous(self):
|
|
1295
|
+
"""
|
|
1296
|
+
Return ``True`` if ``self`` is a homogeneous polynomial.
|
|
1297
|
+
|
|
1298
|
+
EXAMPLES::
|
|
1299
|
+
|
|
1300
|
+
sage: # needs sage.rings.number_field
|
|
1301
|
+
sage: R.<x,y> = QQbar[]
|
|
1302
|
+
sage: (x + y).is_homogeneous()
|
|
1303
|
+
True
|
|
1304
|
+
sage: (x.parent()(0)).is_homogeneous()
|
|
1305
|
+
True
|
|
1306
|
+
sage: (x + y^2).is_homogeneous()
|
|
1307
|
+
False
|
|
1308
|
+
sage: (x^2 + y^2).is_homogeneous()
|
|
1309
|
+
True
|
|
1310
|
+
sage: (x^2 + y^2*x).is_homogeneous()
|
|
1311
|
+
False
|
|
1312
|
+
sage: (x^2*y + y^2*x).is_homogeneous()
|
|
1313
|
+
True
|
|
1314
|
+
|
|
1315
|
+
The weight of the parent ring is respected::
|
|
1316
|
+
|
|
1317
|
+
sage: # needs sage.rings.finite_rings
|
|
1318
|
+
sage: term_order = TermOrder("wdegrevlex", [1, 3])
|
|
1319
|
+
sage: R.<x, y> = PolynomialRing(Qp(5), order=term_order)
|
|
1320
|
+
sage: (x + y).is_homogeneous()
|
|
1321
|
+
False
|
|
1322
|
+
sage: (x^3 + y).is_homogeneous()
|
|
1323
|
+
True
|
|
1324
|
+
"""
|
|
1325
|
+
return self.element().is_homogeneous(self.parent().term_order().weights())
|
|
1326
|
+
|
|
1327
|
+
def _homogenize(self, var):
|
|
1328
|
+
r"""
|
|
1329
|
+
Return ``self`` if ``self`` is homogeneous.
|
|
1330
|
+
Otherwise return a homogenized polynomial constructed by modifying
|
|
1331
|
+
the degree of the variable with index ``var``.
|
|
1332
|
+
|
|
1333
|
+
INPUT:
|
|
1334
|
+
|
|
1335
|
+
- ``var`` -- integer indicating which variable to
|
|
1336
|
+
use to homogenize (``0 <= var < parent(self).ngens()``)
|
|
1337
|
+
|
|
1338
|
+
OUTPUT: a multivariate polynomial
|
|
1339
|
+
|
|
1340
|
+
EXAMPLES::
|
|
1341
|
+
|
|
1342
|
+
sage: # needs sage.rings.number_field
|
|
1343
|
+
sage: P.<x,y> = QQbar[]
|
|
1344
|
+
sage: f = x^2 + y + 1 + 5*x*y^1
|
|
1345
|
+
sage: g = f.homogenize('z'); g # indirect doctest
|
|
1346
|
+
x^2 + 5*x*y + y*z + z^2
|
|
1347
|
+
sage: g.parent()
|
|
1348
|
+
Multivariate Polynomial Ring in x, y, z over Algebraic Field
|
|
1349
|
+
|
|
1350
|
+
SEE: ``self.homogenize``
|
|
1351
|
+
"""
|
|
1352
|
+
if self.is_homogeneous():
|
|
1353
|
+
return self
|
|
1354
|
+
X = self.element().homogenize(var)
|
|
1355
|
+
X.remove_zeros()
|
|
1356
|
+
R = self.parent()
|
|
1357
|
+
return R(X)
|
|
1358
|
+
|
|
1359
|
+
def is_gen(self) -> bool:
|
|
1360
|
+
"""
|
|
1361
|
+
Return ``True`` if ``self`` is a generator of its parent.
|
|
1362
|
+
|
|
1363
|
+
EXAMPLES::
|
|
1364
|
+
|
|
1365
|
+
sage: # needs sage.rings.number_field
|
|
1366
|
+
sage: R.<x,y> = QQbar[]
|
|
1367
|
+
sage: x.is_gen()
|
|
1368
|
+
True
|
|
1369
|
+
sage: (x + y - y).is_gen()
|
|
1370
|
+
True
|
|
1371
|
+
sage: (x*y).is_gen()
|
|
1372
|
+
False
|
|
1373
|
+
|
|
1374
|
+
TESTS::
|
|
1375
|
+
|
|
1376
|
+
sage: # needs sage.rings.number_field
|
|
1377
|
+
sage: R.<x,y> = QQbar[]
|
|
1378
|
+
sage: x.is_generator()
|
|
1379
|
+
doctest:warning...:
|
|
1380
|
+
DeprecationWarning: is_generator is deprecated. Please use is_gen instead.
|
|
1381
|
+
See https://github.com/sagemath/sage/issues/38942 for details.
|
|
1382
|
+
True
|
|
1383
|
+
"""
|
|
1384
|
+
elt = self.element()
|
|
1385
|
+
if len(elt) == 1:
|
|
1386
|
+
(e, c), = elt.dict().items()
|
|
1387
|
+
return e.nonzero_values() == [1] and c.is_one()
|
|
1388
|
+
return False
|
|
1389
|
+
|
|
1390
|
+
is_generator = deprecated_function_alias(38942, is_gen)
|
|
1391
|
+
|
|
1392
|
+
def is_monomial(self):
|
|
1393
|
+
"""
|
|
1394
|
+
Return ``True`` if ``self`` is a monomial, which we define to be a
|
|
1395
|
+
product of generators with coefficient 1.
|
|
1396
|
+
|
|
1397
|
+
Use :meth:`is_term` to allow the coefficient to not be 1.
|
|
1398
|
+
|
|
1399
|
+
EXAMPLES::
|
|
1400
|
+
|
|
1401
|
+
sage: # needs sage.rings.number_field
|
|
1402
|
+
sage: R.<x,y> = QQbar[]
|
|
1403
|
+
sage: x.is_monomial()
|
|
1404
|
+
True
|
|
1405
|
+
sage: (x + 2*y).is_monomial()
|
|
1406
|
+
False
|
|
1407
|
+
sage: (2*x).is_monomial()
|
|
1408
|
+
False
|
|
1409
|
+
sage: (x*y).is_monomial()
|
|
1410
|
+
True
|
|
1411
|
+
|
|
1412
|
+
To allow a non-1 leading coefficient, use :meth:`is_term`::
|
|
1413
|
+
|
|
1414
|
+
sage: (2*x*y).is_term() # needs sage.rings.number_field
|
|
1415
|
+
True
|
|
1416
|
+
sage: (2*x*y).is_monomial() # needs sage.rings.number_field
|
|
1417
|
+
False
|
|
1418
|
+
"""
|
|
1419
|
+
return len(self.element()) == 1 and self.element().coefficients()[0] == 1
|
|
1420
|
+
|
|
1421
|
+
def is_term(self):
|
|
1422
|
+
"""
|
|
1423
|
+
Return ``True`` if ``self`` is a term, which we define to be a
|
|
1424
|
+
product of generators times some coefficient, which need
|
|
1425
|
+
not be 1.
|
|
1426
|
+
|
|
1427
|
+
Use :meth:`is_monomial` to require that the coefficient be 1.
|
|
1428
|
+
|
|
1429
|
+
EXAMPLES::
|
|
1430
|
+
|
|
1431
|
+
sage: # needs sage.rings.number_field
|
|
1432
|
+
sage: R.<x,y> = QQbar[]
|
|
1433
|
+
sage: x.is_term()
|
|
1434
|
+
True
|
|
1435
|
+
sage: (x + 2*y).is_term()
|
|
1436
|
+
False
|
|
1437
|
+
sage: (2*x).is_term()
|
|
1438
|
+
True
|
|
1439
|
+
sage: (7*x^5*y).is_term()
|
|
1440
|
+
True
|
|
1441
|
+
|
|
1442
|
+
To require leading coefficient 1, use :meth:`is_monomial`::
|
|
1443
|
+
|
|
1444
|
+
sage: (2*x*y).is_monomial() # needs sage.rings.number_field
|
|
1445
|
+
False
|
|
1446
|
+
sage: (2*x*y).is_term() # needs sage.rings.number_field
|
|
1447
|
+
True
|
|
1448
|
+
"""
|
|
1449
|
+
return len(self.element()) == 1
|
|
1450
|
+
|
|
1451
|
+
def subs(self, fixed=None, **kwds):
|
|
1452
|
+
"""
|
|
1453
|
+
Fix some given variables in a given multivariate polynomial and
|
|
1454
|
+
return the changed multivariate polynomials. The polynomial itself
|
|
1455
|
+
is not affected. The variable, value pairs for fixing are to be
|
|
1456
|
+
provided as a dictionary of the form ``{variable: value}``.
|
|
1457
|
+
|
|
1458
|
+
This is a special case of evaluating the polynomial with some of
|
|
1459
|
+
the variables constants and the others the original variables.
|
|
1460
|
+
|
|
1461
|
+
INPUT:
|
|
1462
|
+
|
|
1463
|
+
- ``fixed`` -- (optional) dictionary of inputs
|
|
1464
|
+
|
|
1465
|
+
- ``**kwds`` -- named parameters
|
|
1466
|
+
|
|
1467
|
+
OUTPUT: new :class:`MPolynomial`
|
|
1468
|
+
|
|
1469
|
+
EXAMPLES::
|
|
1470
|
+
|
|
1471
|
+
sage: # needs sage.rings.number_field
|
|
1472
|
+
sage: R.<x,y> = QQbar[]
|
|
1473
|
+
sage: f = x^2 + y + x^2*y^2 + 5
|
|
1474
|
+
sage: f((5, y))
|
|
1475
|
+
25*y^2 + y + 30
|
|
1476
|
+
sage: f.subs({x: 5})
|
|
1477
|
+
25*y^2 + y + 30
|
|
1478
|
+
"""
|
|
1479
|
+
variables = list(self.parent().gens())
|
|
1480
|
+
for i in range(len(variables)):
|
|
1481
|
+
if str(variables[i]) in kwds:
|
|
1482
|
+
variables[i] = kwds[str(variables[i])]
|
|
1483
|
+
elif fixed:
|
|
1484
|
+
if variables[i] in fixed:
|
|
1485
|
+
variables[i] = fixed[variables[i]]
|
|
1486
|
+
elif i in fixed:
|
|
1487
|
+
variables[i] = fixed[i]
|
|
1488
|
+
return self(tuple(variables))
|
|
1489
|
+
|
|
1490
|
+
def monomials(self):
|
|
1491
|
+
"""
|
|
1492
|
+
Return the list of monomials in ``self``. The returned list is
|
|
1493
|
+
decreasingly ordered by the term ordering of ``self.parent()``.
|
|
1494
|
+
|
|
1495
|
+
OUTPUT: list of :class:`MPolynomial` instances, representing monomials
|
|
1496
|
+
|
|
1497
|
+
EXAMPLES::
|
|
1498
|
+
|
|
1499
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
1500
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5 # needs sage.rings.number_field
|
|
1501
|
+
sage: f.monomials() # needs sage.rings.number_field
|
|
1502
|
+
[x^2*y^2, x^2, y, 1]
|
|
1503
|
+
|
|
1504
|
+
::
|
|
1505
|
+
|
|
1506
|
+
sage: # needs sage.rings.number_field
|
|
1507
|
+
sage: R.<fx,fy,gx,gy> = QQbar[]
|
|
1508
|
+
sage: F = (fx*gy - fy*gx)^3; F
|
|
1509
|
+
-fy^3*gx^3 + 3*fx*fy^2*gx^2*gy + (-3)*fx^2*fy*gx*gy^2 + fx^3*gy^3
|
|
1510
|
+
sage: F.monomials()
|
|
1511
|
+
[fy^3*gx^3, fx*fy^2*gx^2*gy, fx^2*fy*gx*gy^2, fx^3*gy^3]
|
|
1512
|
+
sage: F.coefficients()
|
|
1513
|
+
[-1, 3, -3, 1]
|
|
1514
|
+
sage: sum(map(mul, zip(F.coefficients(), F.monomials()))) == F
|
|
1515
|
+
True
|
|
1516
|
+
"""
|
|
1517
|
+
ring = self.parent()
|
|
1518
|
+
one = ring.base_ring().one()
|
|
1519
|
+
return [MPolynomial_polydict(ring, polydict.PolyDict({m: one}, check=False))
|
|
1520
|
+
for m in self._exponents]
|
|
1521
|
+
|
|
1522
|
+
def constant_coefficient(self):
|
|
1523
|
+
"""
|
|
1524
|
+
Return the constant coefficient of this multivariate polynomial.
|
|
1525
|
+
|
|
1526
|
+
EXAMPLES::
|
|
1527
|
+
|
|
1528
|
+
sage: # needs sage.rings.number_field
|
|
1529
|
+
sage: R.<x,y> = QQbar[]
|
|
1530
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
1531
|
+
sage: f.constant_coefficient()
|
|
1532
|
+
5
|
|
1533
|
+
sage: f = 3*x^2
|
|
1534
|
+
sage: f.constant_coefficient()
|
|
1535
|
+
0
|
|
1536
|
+
"""
|
|
1537
|
+
#v = (0,)*int(self.parent().ngens())
|
|
1538
|
+
d = self.element().dict()
|
|
1539
|
+
try:
|
|
1540
|
+
return d[polydict.ETuple({},self.parent().ngens())]
|
|
1541
|
+
except KeyError:
|
|
1542
|
+
return self.parent().base_ring().zero()
|
|
1543
|
+
|
|
1544
|
+
def is_univariate(self):
|
|
1545
|
+
"""
|
|
1546
|
+
Return ``True`` if this multivariate polynomial is univariate and
|
|
1547
|
+
``False`` otherwise.
|
|
1548
|
+
|
|
1549
|
+
EXAMPLES::
|
|
1550
|
+
|
|
1551
|
+
sage: # needs sage.rings.number_field
|
|
1552
|
+
sage: R.<x,y> = QQbar[]
|
|
1553
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
1554
|
+
sage: f.is_univariate()
|
|
1555
|
+
False
|
|
1556
|
+
sage: g = f.subs({x: 10}); g
|
|
1557
|
+
700*y^2 + (-2)*y + 305
|
|
1558
|
+
sage: g.is_univariate()
|
|
1559
|
+
True
|
|
1560
|
+
sage: f = x^0
|
|
1561
|
+
sage: f.is_univariate()
|
|
1562
|
+
True
|
|
1563
|
+
"""
|
|
1564
|
+
mons = self.element().dict()
|
|
1565
|
+
|
|
1566
|
+
found = -1
|
|
1567
|
+
for mon in mons:
|
|
1568
|
+
for i in mon.nonzero_positions():
|
|
1569
|
+
if found != i:
|
|
1570
|
+
if found != -1:
|
|
1571
|
+
return False
|
|
1572
|
+
else:
|
|
1573
|
+
found = i
|
|
1574
|
+
return True
|
|
1575
|
+
|
|
1576
|
+
def univariate_polynomial(self, R=None):
|
|
1577
|
+
"""
|
|
1578
|
+
Return a univariate polynomial associated to this multivariate
|
|
1579
|
+
polynomial.
|
|
1580
|
+
|
|
1581
|
+
INPUT:
|
|
1582
|
+
|
|
1583
|
+
- ``R`` -- (default: ``None``) :class:`PolynomialRing`
|
|
1584
|
+
|
|
1585
|
+
|
|
1586
|
+
If this polynomial is not in at most one variable, then a
|
|
1587
|
+
:exc:`ValueError` exception is raised. This is checked using the
|
|
1588
|
+
method :meth:`is_univariate`. The new :class:`Polynomial` is over the same base
|
|
1589
|
+
ring as the given :class:`MPolynomial`.
|
|
1590
|
+
|
|
1591
|
+
EXAMPLES::
|
|
1592
|
+
|
|
1593
|
+
sage: # needs sage.rings.number_field
|
|
1594
|
+
sage: R.<x,y> = QQbar[]
|
|
1595
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
1596
|
+
sage: f.univariate_polynomial()
|
|
1597
|
+
Traceback (most recent call last):
|
|
1598
|
+
...
|
|
1599
|
+
TypeError: polynomial must involve at most one variable
|
|
1600
|
+
sage: g = f.subs({x: 10}); g
|
|
1601
|
+
700*y^2 + (-2)*y + 305
|
|
1602
|
+
sage: g.univariate_polynomial()
|
|
1603
|
+
700*y^2 - 2*y + 305
|
|
1604
|
+
sage: g.univariate_polynomial(PolynomialRing(QQ, 'z'))
|
|
1605
|
+
700*z^2 - 2*z + 305
|
|
1606
|
+
|
|
1607
|
+
TESTS::
|
|
1608
|
+
|
|
1609
|
+
sage: P = PolynomialRing(QQ, 0, '')
|
|
1610
|
+
sage: P(5).univariate_polynomial()
|
|
1611
|
+
5
|
|
1612
|
+
"""
|
|
1613
|
+
if self.parent().ngens() == 0:
|
|
1614
|
+
if R is None:
|
|
1615
|
+
return self.base_ring()(self)
|
|
1616
|
+
else:
|
|
1617
|
+
return R(self)
|
|
1618
|
+
|
|
1619
|
+
if not self.is_univariate():
|
|
1620
|
+
raise TypeError("polynomial must involve at most one variable")
|
|
1621
|
+
|
|
1622
|
+
#construct ring if None
|
|
1623
|
+
if R is None:
|
|
1624
|
+
# constant, we just pick first variable from parent
|
|
1625
|
+
if self.is_constant():
|
|
1626
|
+
R = self.base_ring()[self.parent().variable_names()[0]]
|
|
1627
|
+
else:
|
|
1628
|
+
R = self.base_ring()[str(self.variables()[0])]
|
|
1629
|
+
|
|
1630
|
+
monomial_coefficients = self._MPolynomial_element__element.dict()
|
|
1631
|
+
|
|
1632
|
+
if not self.is_constant():
|
|
1633
|
+
var_idx = self.degrees().nonzero_positions()[0] #variable
|
|
1634
|
+
else:
|
|
1635
|
+
var_idx = 0 #constant
|
|
1636
|
+
if len(monomial_coefficients) == 0:
|
|
1637
|
+
return R(0)
|
|
1638
|
+
|
|
1639
|
+
#construct list
|
|
1640
|
+
lookup = [0,] * len(next(iter(monomial_coefficients)))
|
|
1641
|
+
coefficients = []
|
|
1642
|
+
for degree in range(max(m[var_idx]
|
|
1643
|
+
for m in monomial_coefficients.keys()) + 1):
|
|
1644
|
+
lookup[var_idx] = int(degree)
|
|
1645
|
+
try:
|
|
1646
|
+
coefficients.append( monomial_coefficients[ polydict.ETuple(lookup) ] ) #if we find something, add the coefficient
|
|
1647
|
+
except KeyError:
|
|
1648
|
+
coefficients.append( 0 ) #else add zero
|
|
1649
|
+
|
|
1650
|
+
#construct polynomial
|
|
1651
|
+
return R(coefficients)
|
|
1652
|
+
|
|
1653
|
+
def variables(self):
|
|
1654
|
+
"""
|
|
1655
|
+
Return the tuple of variables occurring in this polynomial.
|
|
1656
|
+
|
|
1657
|
+
EXAMPLES::
|
|
1658
|
+
|
|
1659
|
+
sage: # needs sage.rings.number_field
|
|
1660
|
+
sage: R.<x,y> = QQbar[]
|
|
1661
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
1662
|
+
sage: f.variables()
|
|
1663
|
+
(x, y)
|
|
1664
|
+
sage: g = f.subs({x: 10}); g
|
|
1665
|
+
700*y^2 + (-2)*y + 305
|
|
1666
|
+
sage: g.variables()
|
|
1667
|
+
(y,)
|
|
1668
|
+
|
|
1669
|
+
TESTS:
|
|
1670
|
+
|
|
1671
|
+
This shows that the issue at :issue:`7077` is fixed::
|
|
1672
|
+
|
|
1673
|
+
sage: x,y,z=polygens(QQ,'x,y,z')
|
|
1674
|
+
sage: (x^2).variables()
|
|
1675
|
+
(x,)
|
|
1676
|
+
"""
|
|
1677
|
+
return tuple([self.parent().gen(index) for index in self.degrees().nonzero_positions()])
|
|
1678
|
+
|
|
1679
|
+
def variable(self, i):
|
|
1680
|
+
"""
|
|
1681
|
+
Return the `i`-th variable occurring in this polynomial.
|
|
1682
|
+
|
|
1683
|
+
EXAMPLES::
|
|
1684
|
+
|
|
1685
|
+
sage: # needs sage.rings.number_field
|
|
1686
|
+
sage: R.<x,y> = QQbar[]
|
|
1687
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
1688
|
+
sage: f.variable(0)
|
|
1689
|
+
x
|
|
1690
|
+
sage: f.variable(1)
|
|
1691
|
+
y
|
|
1692
|
+
"""
|
|
1693
|
+
return self.variables()[int(i)]
|
|
1694
|
+
|
|
1695
|
+
def nvariables(self):
|
|
1696
|
+
"""
|
|
1697
|
+
Return the number of variables in this polynomial.
|
|
1698
|
+
|
|
1699
|
+
EXAMPLES::
|
|
1700
|
+
|
|
1701
|
+
sage: # needs sage.rings.number_field
|
|
1702
|
+
sage: R.<x,y> = QQbar[]
|
|
1703
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
1704
|
+
sage: f.nvariables()
|
|
1705
|
+
2
|
|
1706
|
+
sage: g = f.subs({x: 10}); g
|
|
1707
|
+
700*y^2 + (-2)*y + 305
|
|
1708
|
+
sage: g.nvariables()
|
|
1709
|
+
1
|
|
1710
|
+
"""
|
|
1711
|
+
return len(self.degrees().nonzero_positions())
|
|
1712
|
+
|
|
1713
|
+
def is_constant(self):
|
|
1714
|
+
"""
|
|
1715
|
+
Return ``True`` if ``self`` is a constant and ``False`` otherwise.
|
|
1716
|
+
|
|
1717
|
+
EXAMPLES::
|
|
1718
|
+
|
|
1719
|
+
sage: # needs sage.rings.number_field
|
|
1720
|
+
sage: R.<x,y> = QQbar[]
|
|
1721
|
+
sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5
|
|
1722
|
+
sage: f.is_constant()
|
|
1723
|
+
False
|
|
1724
|
+
sage: g = 10*x^0
|
|
1725
|
+
sage: g.is_constant()
|
|
1726
|
+
True
|
|
1727
|
+
"""
|
|
1728
|
+
return self.element().is_constant()
|
|
1729
|
+
|
|
1730
|
+
def lm(self):
|
|
1731
|
+
"""
|
|
1732
|
+
Return the lead monomial of ``self`` with respect to the term order of
|
|
1733
|
+
``self.parent()``.
|
|
1734
|
+
|
|
1735
|
+
EXAMPLES::
|
|
1736
|
+
|
|
1737
|
+
sage: R.<x,y,z> = PolynomialRing(GF(7), 3, order='lex')
|
|
1738
|
+
sage: (x^1*y^2 + y^3*z^4).lm()
|
|
1739
|
+
x*y^2
|
|
1740
|
+
sage: (x^3*y^2*z^4 + x^3*y^2*z^1).lm()
|
|
1741
|
+
x^3*y^2*z^4
|
|
1742
|
+
|
|
1743
|
+
::
|
|
1744
|
+
|
|
1745
|
+
sage: # needs sage.rings.real_mpfr
|
|
1746
|
+
sage: R.<x,y,z> = PolynomialRing(CC, 3, order='deglex')
|
|
1747
|
+
sage: (x^1*y^2*z^3 + x^3*y^2*z^0).lm()
|
|
1748
|
+
x*y^2*z^3
|
|
1749
|
+
sage: (x^1*y^2*z^4 + x^1*y^1*z^5).lm()
|
|
1750
|
+
x*y^2*z^4
|
|
1751
|
+
|
|
1752
|
+
::
|
|
1753
|
+
|
|
1754
|
+
sage: # needs sage.rings.number_field
|
|
1755
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, 3, order='degrevlex')
|
|
1756
|
+
sage: (x^1*y^5*z^2 + x^4*y^1*z^3).lm()
|
|
1757
|
+
x*y^5*z^2
|
|
1758
|
+
sage: (x^4*y^7*z^1 + x^4*y^2*z^3).lm()
|
|
1759
|
+
x^4*y^7*z
|
|
1760
|
+
|
|
1761
|
+
TESTS::
|
|
1762
|
+
|
|
1763
|
+
sage: from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict
|
|
1764
|
+
sage: R.<x,y> = MPolynomialRing_polydict(GF(2), 2, order='lex')
|
|
1765
|
+
sage: f = x + y
|
|
1766
|
+
sage: f.lm()
|
|
1767
|
+
x
|
|
1768
|
+
"""
|
|
1769
|
+
try:
|
|
1770
|
+
return self.__lm
|
|
1771
|
+
except AttributeError:
|
|
1772
|
+
if self.is_zero():
|
|
1773
|
+
return self
|
|
1774
|
+
R = self.parent()
|
|
1775
|
+
f = self._MPolynomial_element__element.lcmt(R.term_order().greater_tuple)
|
|
1776
|
+
one = R.base_ring().one()
|
|
1777
|
+
self.__lm = MPolynomial_polydict(R,polydict.PolyDict({f: one}, check=False))
|
|
1778
|
+
return self.__lm
|
|
1779
|
+
|
|
1780
|
+
def lc(self):
|
|
1781
|
+
"""
|
|
1782
|
+
Return the leading coefficient of ``self``, i.e.,
|
|
1783
|
+
``self.coefficient(self.lm())``.
|
|
1784
|
+
|
|
1785
|
+
EXAMPLES::
|
|
1786
|
+
|
|
1787
|
+
sage: R.<x,y,z> = QQbar[] # needs sage.rings.number_field
|
|
1788
|
+
sage: f = 3*x^2 - y^2 - x*y # needs sage.rings.number_field
|
|
1789
|
+
sage: f.lc() # needs sage.rings.number_field
|
|
1790
|
+
3
|
|
1791
|
+
"""
|
|
1792
|
+
try:
|
|
1793
|
+
return self.__lc
|
|
1794
|
+
except AttributeError:
|
|
1795
|
+
if self.is_zero():
|
|
1796
|
+
return self.base_ring()._zero_element
|
|
1797
|
+
R = self.parent()
|
|
1798
|
+
f = self._MPolynomial_element__element.dict()
|
|
1799
|
+
self.__lc = f[self._MPolynomial_element__element.lcmt( R.term_order().greater_tuple )]
|
|
1800
|
+
return self.__lc
|
|
1801
|
+
|
|
1802
|
+
def lt(self):
|
|
1803
|
+
r"""
|
|
1804
|
+
Return the leading term of ``self`` i.e., ``self.lc()*self.lm()``. The
|
|
1805
|
+
notion of "leading term" depends on the ordering defined in the
|
|
1806
|
+
parent ring.
|
|
1807
|
+
|
|
1808
|
+
EXAMPLES::
|
|
1809
|
+
|
|
1810
|
+
sage: # needs sage.rings.number_field
|
|
1811
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar)
|
|
1812
|
+
sage: f = 3*x^2 - y^2 - x*y
|
|
1813
|
+
sage: f.lt()
|
|
1814
|
+
3*x^2
|
|
1815
|
+
sage: R.<x,y,z> = PolynomialRing(QQbar, order='invlex')
|
|
1816
|
+
sage: f = 3*x^2 - y^2 - x*y
|
|
1817
|
+
sage: f.lt()
|
|
1818
|
+
-y^2
|
|
1819
|
+
|
|
1820
|
+
TESTS::
|
|
1821
|
+
|
|
1822
|
+
sage: from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict
|
|
1823
|
+
sage: R.<x,y> = MPolynomialRing_polydict(GF(2), 2, order='lex')
|
|
1824
|
+
sage: f = x + y
|
|
1825
|
+
sage: f.lt()
|
|
1826
|
+
x
|
|
1827
|
+
"""
|
|
1828
|
+
try:
|
|
1829
|
+
return self.__lt
|
|
1830
|
+
except AttributeError:
|
|
1831
|
+
if self.is_zero():
|
|
1832
|
+
return self
|
|
1833
|
+
R = self.parent()
|
|
1834
|
+
f = self._MPolynomial_element__element.dict()
|
|
1835
|
+
res = self._MPolynomial_element__element.lcmt(R.term_order().greater_tuple)
|
|
1836
|
+
self.__lt = MPolynomial_polydict(R, polydict.PolyDict({res: f[res]}, check=False))
|
|
1837
|
+
return self.__lt
|
|
1838
|
+
|
|
1839
|
+
def __eq__(self, right):
|
|
1840
|
+
if not isinstance(right, MPolynomial_polydict):
|
|
1841
|
+
# we want comparison with zero to be fast
|
|
1842
|
+
if not right:
|
|
1843
|
+
return not self._MPolynomial_element__element.dict()
|
|
1844
|
+
return CommutativeRingElement.__eq__(self, right)
|
|
1845
|
+
return self._MPolynomial_element__element == right._MPolynomial_element__element
|
|
1846
|
+
|
|
1847
|
+
def __ne__(self, right):
|
|
1848
|
+
if not isinstance(right, MPolynomial_polydict):
|
|
1849
|
+
# we want comparison with zero to be fast
|
|
1850
|
+
if not right:
|
|
1851
|
+
return not not self._MPolynomial_element__element.dict()
|
|
1852
|
+
return CommutativeRingElement.__ne__(self, right)
|
|
1853
|
+
return self._MPolynomial_element__element != right._MPolynomial_element__element
|
|
1854
|
+
|
|
1855
|
+
# required by Python 3
|
|
1856
|
+
__hash__ = MPolynomial_element.__hash__
|
|
1857
|
+
|
|
1858
|
+
def __bool__(self):
|
|
1859
|
+
"""
|
|
1860
|
+
Return ``True`` if ``self != 0``.
|
|
1861
|
+
|
|
1862
|
+
.. NOTE::
|
|
1863
|
+
|
|
1864
|
+
This is much faster than actually writing ``self == 0``.
|
|
1865
|
+
"""
|
|
1866
|
+
return bool(self._MPolynomial_element__element)
|
|
1867
|
+
|
|
1868
|
+
def _floordiv_(self, right):
|
|
1869
|
+
r"""
|
|
1870
|
+
Quotient of division of ``self`` by ``other``. This is denoted ``//``.
|
|
1871
|
+
|
|
1872
|
+
.. NOTE::
|
|
1873
|
+
|
|
1874
|
+
It's not clear to me that this is well-defined if
|
|
1875
|
+
``self`` is not exactly divisible by other.
|
|
1876
|
+
|
|
1877
|
+
EXAMPLES::
|
|
1878
|
+
|
|
1879
|
+
sage: # needs sage.rings.number_field
|
|
1880
|
+
sage: R.<x,y> = QQbar[]
|
|
1881
|
+
sage: 2*x*y//y
|
|
1882
|
+
2*x
|
|
1883
|
+
sage: 2*x//y
|
|
1884
|
+
0
|
|
1885
|
+
sage: 2*x//4
|
|
1886
|
+
1/2*x
|
|
1887
|
+
sage: type(0//y)
|
|
1888
|
+
<class 'sage.rings.polynomial.multi_polynomial_element.MPolynomial_polydict'>
|
|
1889
|
+
"""
|
|
1890
|
+
# handle division by monomials without using Singular
|
|
1891
|
+
if len(right.monomial_coefficients()) == 1:
|
|
1892
|
+
P = self.parent()
|
|
1893
|
+
ret = P(0)
|
|
1894
|
+
denC, denM = next(iter(right))
|
|
1895
|
+
for c, m in self:
|
|
1896
|
+
t = c * m
|
|
1897
|
+
if denC.divides(c) and P.monomial_divides(denM, m):
|
|
1898
|
+
ret += P.monomial_quotient(t, right, coeff=True)
|
|
1899
|
+
return ret
|
|
1900
|
+
|
|
1901
|
+
Q, _ = self.quo_rem(right)
|
|
1902
|
+
return Q
|
|
1903
|
+
|
|
1904
|
+
def _derivative(self, var=None):
|
|
1905
|
+
r"""
|
|
1906
|
+
Differentiates ``self`` with respect to variable ``var``.
|
|
1907
|
+
|
|
1908
|
+
If ``var`` is not one of the generators of this ring, ``_derivative(var)``
|
|
1909
|
+
is called recursively on each coefficient of this polynomial.
|
|
1910
|
+
|
|
1911
|
+
.. SEEALSO::
|
|
1912
|
+
|
|
1913
|
+
:meth:`derivative`
|
|
1914
|
+
|
|
1915
|
+
EXAMPLES::
|
|
1916
|
+
|
|
1917
|
+
sage: # needs sage.rings.number_field
|
|
1918
|
+
sage: R.<t> = PowerSeriesRing(QQbar)
|
|
1919
|
+
sage: S.<x, y> = PolynomialRing(R)
|
|
1920
|
+
sage: f = (t^2 + O(t^3))*x^2*y^3 + (37*t^4 + O(t^5))*x^3
|
|
1921
|
+
sage: f.parent()
|
|
1922
|
+
Multivariate Polynomial Ring in x, y
|
|
1923
|
+
over Power Series Ring in t over Algebraic Field
|
|
1924
|
+
sage: f._derivative(x) # with respect to x
|
|
1925
|
+
(2*t^2 + O(t^3))*x*y^3 + (111*t^4 + O(t^5))*x^2
|
|
1926
|
+
sage: f._derivative(x).parent()
|
|
1927
|
+
Multivariate Polynomial Ring in x, y
|
|
1928
|
+
over Power Series Ring in t over Algebraic Field
|
|
1929
|
+
sage: f._derivative(y) # with respect to y
|
|
1930
|
+
(3*t^2 + O(t^3))*x^2*y^2
|
|
1931
|
+
sage: f._derivative(t) # with respect to t (recurses into base ring)
|
|
1932
|
+
(2*t + O(t^2))*x^2*y^3 + (148*t^3 + O(t^4))*x^3
|
|
1933
|
+
sage: f._derivative(x)._derivative(y) # with respect to x and then y
|
|
1934
|
+
(6*t^2 + O(t^3))*x*y^2
|
|
1935
|
+
sage: f.derivative(y, 3) # with respect to y three times
|
|
1936
|
+
(6*t^2 + O(t^3))*x^2
|
|
1937
|
+
sage: f._derivative() # can't figure out the variable
|
|
1938
|
+
Traceback (most recent call last):
|
|
1939
|
+
...
|
|
1940
|
+
ValueError: must specify which variable to differentiate with respect to
|
|
1941
|
+
"""
|
|
1942
|
+
if var is None:
|
|
1943
|
+
raise ValueError("must specify which variable to differentiate with respect to")
|
|
1944
|
+
|
|
1945
|
+
P = self.parent()
|
|
1946
|
+
|
|
1947
|
+
# check if var is one of the generators
|
|
1948
|
+
index = polydict.gen_index(P(var).element())
|
|
1949
|
+
if index == -1:
|
|
1950
|
+
# var is not a generator; do term-by-term differentiation recursively
|
|
1951
|
+
# var may be, for example, a generator of the base ring
|
|
1952
|
+
d = {e: x._derivative(var)
|
|
1953
|
+
for e, x in self.monomial_coefficients().items()}
|
|
1954
|
+
d = polydict.PolyDict(d, check=False)
|
|
1955
|
+
d.remove_zeros()
|
|
1956
|
+
return MPolynomial_polydict(P, d)
|
|
1957
|
+
|
|
1958
|
+
# differentiate w.r.t. indicated variable
|
|
1959
|
+
elt = self.element().derivative_i(index)
|
|
1960
|
+
elt.remove_zeros()
|
|
1961
|
+
return MPolynomial_polydict(P, elt)
|
|
1962
|
+
|
|
1963
|
+
def integral(self, var=None):
|
|
1964
|
+
r"""
|
|
1965
|
+
Integrate ``self`` with respect to variable ``var``.
|
|
1966
|
+
|
|
1967
|
+
.. NOTE::
|
|
1968
|
+
|
|
1969
|
+
The integral is always chosen so the constant term is 0.
|
|
1970
|
+
|
|
1971
|
+
If ``var`` is not one of the generators of this ring, ``integral(var)``
|
|
1972
|
+
is called recursively on each coefficient of this polynomial.
|
|
1973
|
+
|
|
1974
|
+
EXAMPLES:
|
|
1975
|
+
|
|
1976
|
+
On polynomials with rational coefficients::
|
|
1977
|
+
|
|
1978
|
+
sage: x, y = PolynomialRing(QQ, 'x, y').gens()
|
|
1979
|
+
sage: ex = x*y + x - y
|
|
1980
|
+
sage: it = ex.integral(x); it
|
|
1981
|
+
1/2*x^2*y + 1/2*x^2 - x*y
|
|
1982
|
+
sage: it.parent() == x.parent()
|
|
1983
|
+
True
|
|
1984
|
+
|
|
1985
|
+
sage: R = ZZ['x']['y, z']
|
|
1986
|
+
sage: y, z = R.gens()
|
|
1987
|
+
sage: R.an_element().integral(y).parent()
|
|
1988
|
+
Multivariate Polynomial Ring in y, z
|
|
1989
|
+
over Univariate Polynomial Ring in x over Rational Field
|
|
1990
|
+
|
|
1991
|
+
On polynomials with coefficients in power series::
|
|
1992
|
+
|
|
1993
|
+
sage: # needs sage.rings.number_field
|
|
1994
|
+
sage: R.<t> = PowerSeriesRing(QQbar)
|
|
1995
|
+
sage: S.<x, y> = PolynomialRing(R)
|
|
1996
|
+
sage: f = (t^2 + O(t^3))*x^2*y^3 + (37*t^4 + O(t^5))*x^3
|
|
1997
|
+
sage: f.parent()
|
|
1998
|
+
Multivariate Polynomial Ring in x, y
|
|
1999
|
+
over Power Series Ring in t over Algebraic Field
|
|
2000
|
+
sage: f.integral(x) # with respect to x
|
|
2001
|
+
(1/3*t^2 + O(t^3))*x^3*y^3 + (37/4*t^4 + O(t^5))*x^4
|
|
2002
|
+
sage: f.integral(x).parent()
|
|
2003
|
+
Multivariate Polynomial Ring in x, y
|
|
2004
|
+
over Power Series Ring in t over Algebraic Field
|
|
2005
|
+
sage: f.integral(y) # with respect to y
|
|
2006
|
+
(1/4*t^2 + O(t^3))*x^2*y^4 + (37*t^4 + O(t^5))*x^3*y
|
|
2007
|
+
sage: f.integral(t) # with respect to t (recurses into base ring)
|
|
2008
|
+
(1/3*t^3 + O(t^4))*x^2*y^3 + (37/5*t^5 + O(t^6))*x^3
|
|
2009
|
+
|
|
2010
|
+
TESTS::
|
|
2011
|
+
|
|
2012
|
+
sage: f.integral() # can't figure out the variable # needs sage.rings.number_field
|
|
2013
|
+
Traceback (most recent call last):
|
|
2014
|
+
...
|
|
2015
|
+
ValueError: must specify which variable to integrate with respect to
|
|
2016
|
+
|
|
2017
|
+
:issue:`34000`::
|
|
2018
|
+
|
|
2019
|
+
sage: R = ZZ['x']['y,z']
|
|
2020
|
+
sage: y, z = R.gens()
|
|
2021
|
+
sage: parent(y.integral(y))
|
|
2022
|
+
Multivariate Polynomial Ring in y, z over Univariate Polynomial Ring in x over Rational Field
|
|
2023
|
+
"""
|
|
2024
|
+
if var is None:
|
|
2025
|
+
raise ValueError("must specify which variable to integrate "
|
|
2026
|
+
"with respect to")
|
|
2027
|
+
|
|
2028
|
+
# TODO:
|
|
2029
|
+
# calling the coercion model bin_op is much more accurate than using the
|
|
2030
|
+
# true division (which is bypassed by polynomials). But it does not work
|
|
2031
|
+
# in all cases!!
|
|
2032
|
+
# See similar in polynomial_element.pyx
|
|
2033
|
+
P = self.parent()
|
|
2034
|
+
cm = get_coercion_model()
|
|
2035
|
+
try:
|
|
2036
|
+
S = cm.bin_op(P.one(), sage.rings.integer_ring.ZZ.one(), operator.truediv).parent()
|
|
2037
|
+
except TypeError:
|
|
2038
|
+
Q = (P.base_ring().one() / sage.rings.integer_ring.ZZ.one()).parent()
|
|
2039
|
+
S = P.change_ring(Q)
|
|
2040
|
+
|
|
2041
|
+
if P is not S:
|
|
2042
|
+
return S.coerce(self).integral(var)
|
|
2043
|
+
|
|
2044
|
+
# check if var is one of the generators
|
|
2045
|
+
index = polydict.gen_index(P(var).element())
|
|
2046
|
+
if index == -1:
|
|
2047
|
+
# var is not a generator; do term-by-term integration recursively
|
|
2048
|
+
# var may be, for example, a generator of the base ring
|
|
2049
|
+
d = {e: x.integral(var)
|
|
2050
|
+
for e, x in self.monomial_coefficients().items()}
|
|
2051
|
+
d = polydict.PolyDict(d, check=False)
|
|
2052
|
+
d.remove_zeros()
|
|
2053
|
+
else:
|
|
2054
|
+
# integrate w.r.t. indicated variable
|
|
2055
|
+
d = self.element().integral_i(index)
|
|
2056
|
+
return MPolynomial_polydict(P, d)
|
|
2057
|
+
|
|
2058
|
+
def factor(self, proof=None):
|
|
2059
|
+
r"""
|
|
2060
|
+
Compute the irreducible factorization of this polynomial.
|
|
2061
|
+
|
|
2062
|
+
INPUT:
|
|
2063
|
+
|
|
2064
|
+
- ``proof`` -- insist on provably correct results (default: ``True``
|
|
2065
|
+
unless explicitly disabled for the ``'polynomial'`` subsystem with
|
|
2066
|
+
:class:`sage.structure.proof.proof.WithProof`.)
|
|
2067
|
+
|
|
2068
|
+
TESTS:
|
|
2069
|
+
|
|
2070
|
+
Check if we can handle polynomials with no variables, see :issue:`7950`::
|
|
2071
|
+
|
|
2072
|
+
sage: P = PolynomialRing(ZZ,0,'')
|
|
2073
|
+
sage: res = P(10).factor(); res
|
|
2074
|
+
2 * 5
|
|
2075
|
+
sage: res[0][0].parent()
|
|
2076
|
+
Multivariate Polynomial Ring in no variables over Integer Ring
|
|
2077
|
+
sage: R = PolynomialRing(QQ,0,'')
|
|
2078
|
+
sage: res = R(10).factor(); res
|
|
2079
|
+
10
|
|
2080
|
+
sage: res.unit().parent()
|
|
2081
|
+
Rational Field
|
|
2082
|
+
sage: P(0).factor()
|
|
2083
|
+
Traceback (most recent call last):
|
|
2084
|
+
...
|
|
2085
|
+
ArithmeticError: factorization of 0 is not defined
|
|
2086
|
+
|
|
2087
|
+
Check if we can factor a constant polynomial, see :issue:`8207`::
|
|
2088
|
+
|
|
2089
|
+
sage: R.<x,y> = CC[] # needs sage.rings.real_mpfr
|
|
2090
|
+
sage: R(1).factor() # needs sage.rings.real_mpfr
|
|
2091
|
+
1.00000000000000
|
|
2092
|
+
|
|
2093
|
+
Check that we prohibit too large moduli, :issue:`11829`::
|
|
2094
|
+
|
|
2095
|
+
sage: R.<x,y> = GF(previous_prime(2^31))[] # needs sage.rings.finite_rings
|
|
2096
|
+
sage: factor(x + y + 1) # needs sage.rings.finite_rings
|
|
2097
|
+
Traceback (most recent call last):
|
|
2098
|
+
...
|
|
2099
|
+
NotImplementedError: Factorization of multivariate polynomials
|
|
2100
|
+
over prime fields with characteristic > 2^29 is not implemented.
|
|
2101
|
+
|
|
2102
|
+
Check that we can factor over the algebraic field (:issue:`25390`)::
|
|
2103
|
+
|
|
2104
|
+
sage: # needs sage.libs.singular sage.rings.number_field
|
|
2105
|
+
sage: R.<x,y> = PolynomialRing(QQbar)
|
|
2106
|
+
sage: factor(x^2 + y^2)
|
|
2107
|
+
(x + (-1*I)*y) * (x + 1*I*y)
|
|
2108
|
+
|
|
2109
|
+
Check that the global proof flag for polynomials is honored::
|
|
2110
|
+
|
|
2111
|
+
sage: # needs sage.libs.singular
|
|
2112
|
+
sage: R.<x,y> = PolynomialRing(QQ['z'])
|
|
2113
|
+
sage: f = x^2 + y^2
|
|
2114
|
+
sage: with proof.WithProof('polynomial', True):
|
|
2115
|
+
....: f.factor()
|
|
2116
|
+
Traceback (most recent call last):
|
|
2117
|
+
...
|
|
2118
|
+
NotImplementedError: Provably correct factorization not implemented.
|
|
2119
|
+
Disable this error by wrapping your code in a
|
|
2120
|
+
`with proof.WithProof('polynomial', False):` block.
|
|
2121
|
+
sage: with proof.WithProof('polynomial', False):
|
|
2122
|
+
....: f.factor()
|
|
2123
|
+
Traceback (most recent call last):
|
|
2124
|
+
...
|
|
2125
|
+
TypeError: no conversion of this ring to a Singular ring defined
|
|
2126
|
+
|
|
2127
|
+
We check that the original issue in :issue:`7554` is fixed::
|
|
2128
|
+
|
|
2129
|
+
sage: K.<a> = PolynomialRing(QQ)
|
|
2130
|
+
sage: R.<x,y> = PolynomialRing(FractionField(K))
|
|
2131
|
+
sage: factor(x) # needs sage.libs.pari
|
|
2132
|
+
x
|
|
2133
|
+
|
|
2134
|
+
In the example below, we set the special method
|
|
2135
|
+
``_factor_multivariate_polynomial()`` in the base ring which is called to
|
|
2136
|
+
factor multivariate polynomials. This facility can be used to easily
|
|
2137
|
+
extend polynomial factorization to work over new rings you introduce::
|
|
2138
|
+
|
|
2139
|
+
sage: R.<x, y> = PolynomialRing(QQ['z'])
|
|
2140
|
+
sage: (x*y).factor()
|
|
2141
|
+
Traceback (most recent call last):
|
|
2142
|
+
...
|
|
2143
|
+
NotImplementedError: ...
|
|
2144
|
+
sage: R.base_ring()._factor_multivariate_polynomial = lambda f, **kwargs: f.change_ring(QQ).factor()
|
|
2145
|
+
sage: (x*y).factor() # needs sage.libs.pari
|
|
2146
|
+
y * x
|
|
2147
|
+
sage: del R.base_ring()._factor_multivariate_polynomial # clean up
|
|
2148
|
+
|
|
2149
|
+
Check that a "multivariate" polynomial in one variable is factored
|
|
2150
|
+
correctly::
|
|
2151
|
+
|
|
2152
|
+
sage: R.<z> = PolynomialRing(CC,1) # needs sage.rings.real_mpfr
|
|
2153
|
+
sage: f = z^4 - 6*z + 3 # needs sage.rings.real_mpfr
|
|
2154
|
+
sage: f.factor() # needs sage.libs.pari sage.rings.real_mpfr
|
|
2155
|
+
(z - 1.60443920904349) * (z - 0.511399619393097)
|
|
2156
|
+
* (z + 1.05791941421830 - 1.59281852704435*I)
|
|
2157
|
+
* (z + 1.05791941421830 + 1.59281852704435*I)
|
|
2158
|
+
|
|
2159
|
+
We check a case that failed with an exception at some point::
|
|
2160
|
+
|
|
2161
|
+
sage: # needs sage.rings.finite_rings
|
|
2162
|
+
sage: k.<u> = GF(4)
|
|
2163
|
+
sage: R.<v> = k[]
|
|
2164
|
+
sage: l.<v> = R.quo(v^3 + v + 1)
|
|
2165
|
+
sage: R.<x,y> = l[]
|
|
2166
|
+
sage: f = y^3 + x^3 + (u + 1)*x
|
|
2167
|
+
sage: f.factor()
|
|
2168
|
+
x^3 + y^3 + (u + 1)*x
|
|
2169
|
+
"""
|
|
2170
|
+
R = self.parent()
|
|
2171
|
+
|
|
2172
|
+
# raise error if trying to factor zero
|
|
2173
|
+
if not self:
|
|
2174
|
+
raise ArithmeticError("factorization of {!r} is not defined".format(self))
|
|
2175
|
+
|
|
2176
|
+
# if number of variables is zero ...
|
|
2177
|
+
if R.ngens() == 0:
|
|
2178
|
+
base_ring = self.base_ring()
|
|
2179
|
+
if base_ring.is_field():
|
|
2180
|
+
return Factorization([],unit=self.base_ring()(self))
|
|
2181
|
+
else:
|
|
2182
|
+
F = base_ring(self).factor()
|
|
2183
|
+
return Factorization([(R(f),m) for f,m in F], unit=F.unit())
|
|
2184
|
+
|
|
2185
|
+
base_ring = self.base_ring()
|
|
2186
|
+
if hasattr(base_ring, '_factor_multivariate_polynomial'):
|
|
2187
|
+
return base_ring._factor_multivariate_polynomial(self, proof=proof)
|
|
2188
|
+
|
|
2189
|
+
# try to use univariate factoring
|
|
2190
|
+
try:
|
|
2191
|
+
F = self.univariate_polynomial().factor()
|
|
2192
|
+
return Factorization([(R(f), m) for f, m in F], unit=F.unit())
|
|
2193
|
+
except TypeError:
|
|
2194
|
+
pass
|
|
2195
|
+
|
|
2196
|
+
base_ring = self.base_ring()
|
|
2197
|
+
if base_ring.is_finite():
|
|
2198
|
+
if base_ring.characteristic() > 1 << 29:
|
|
2199
|
+
raise NotImplementedError("Factorization of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented.")
|
|
2200
|
+
|
|
2201
|
+
if proof is None:
|
|
2202
|
+
from sage.structure.proof.proof import get_flag
|
|
2203
|
+
proof = get_flag(subsystem='polynomial')
|
|
2204
|
+
if proof:
|
|
2205
|
+
raise NotImplementedError("Provably correct factorization not implemented. Disable this error by wrapping your code in a `with proof.WithProof('polynomial', False):` block.")
|
|
2206
|
+
|
|
2207
|
+
R._singular_().set_ring()
|
|
2208
|
+
S = self._singular_().factorize()
|
|
2209
|
+
factors = S[1]
|
|
2210
|
+
exponents = S[2]
|
|
2211
|
+
v = sorted([(R(factors[i + 1]), Integer(exponents[i + 1]))
|
|
2212
|
+
for i in range(len(factors))])
|
|
2213
|
+
unit = R(1)
|
|
2214
|
+
for i in range(len(v)):
|
|
2215
|
+
if v[i][0].is_unit():
|
|
2216
|
+
unit = unit * v[i][0]
|
|
2217
|
+
del v[i]
|
|
2218
|
+
break
|
|
2219
|
+
F = sorted(Factorization(v, unit=unit))
|
|
2220
|
+
return F
|
|
2221
|
+
|
|
2222
|
+
@handle_AA_and_QQbar
|
|
2223
|
+
def lift(self, I):
|
|
2224
|
+
"""
|
|
2225
|
+
Given an ideal `I = (f_1,...,f_r)` and some `g` (= ``self``) in `I`, find
|
|
2226
|
+
`s_1,...,s_r` such that `g = s_1 f_1 + ... + s_r f_r`.
|
|
2227
|
+
|
|
2228
|
+
ALGORITHM: Use Singular.
|
|
2229
|
+
|
|
2230
|
+
EXAMPLES::
|
|
2231
|
+
|
|
2232
|
+
sage: # needs sage.rings.real_mpfr
|
|
2233
|
+
sage: A.<x,y> = PolynomialRing(CC, 2, order='degrevlex')
|
|
2234
|
+
sage: I = A.ideal([x^10 + x^9*y^2, y^8 - x^2*y^7])
|
|
2235
|
+
sage: f = x*y^13 + y^12
|
|
2236
|
+
sage: M = f.lift(I); M # needs sage.libs.singular
|
|
2237
|
+
[y^7, x^7*y^2 + x^8 + x^5*y^3 + x^6*y + x^3*y^4 + x^4*y^2 + x*y^5 + x^2*y^3 + y^4]
|
|
2238
|
+
sage: sum(map(mul, zip(M, I.gens()))) == f # needs sage.libs.singular
|
|
2239
|
+
True
|
|
2240
|
+
|
|
2241
|
+
TESTS:
|
|
2242
|
+
|
|
2243
|
+
Check that this method works over ``QQbar`` (:issue:`25351`)::
|
|
2244
|
+
|
|
2245
|
+
sage: # needs sage.rings.number_field
|
|
2246
|
+
sage: A.<x,y> = QQbar[]
|
|
2247
|
+
sage: I = A.ideal([x^2 + y^2 - 1, x^2 - y^2])
|
|
2248
|
+
sage: f = 2*x^2 - 1
|
|
2249
|
+
sage: M = f.lift(I) # needs sage.libs.singular
|
|
2250
|
+
sage: sum(map(mul, zip(M, I.gens()))) == f # needs sage.libs.singular
|
|
2251
|
+
True
|
|
2252
|
+
"""
|
|
2253
|
+
fs = self._singular_()
|
|
2254
|
+
Is = I._singular_()
|
|
2255
|
+
P = I.ring()
|
|
2256
|
+
try:
|
|
2257
|
+
M = Is.lift(fs)._sage_(P)
|
|
2258
|
+
except TypeError:
|
|
2259
|
+
raise ArithmeticError("f is not in I")
|
|
2260
|
+
return Sequence(M.list(), P, check=False, immutable=True)
|
|
2261
|
+
|
|
2262
|
+
@coerce_binop
|
|
2263
|
+
@handle_AA_and_QQbar
|
|
2264
|
+
def quo_rem(self, right):
|
|
2265
|
+
"""
|
|
2266
|
+
Return quotient and remainder of ``self`` and ``right``.
|
|
2267
|
+
|
|
2268
|
+
EXAMPLES::
|
|
2269
|
+
|
|
2270
|
+
sage: R.<x,y> = CC[] # needs sage.rings.real_mpfr
|
|
2271
|
+
sage: f = y*x^2 + x + 1 # needs sage.rings.real_mpfr
|
|
2272
|
+
sage: f.quo_rem(x) # needs sage.libs.singular sage.rings.real_mpfr
|
|
2273
|
+
(x*y + 1.00000000000000, 1.00000000000000)
|
|
2274
|
+
|
|
2275
|
+
sage: R = QQ['a','b']['x','y','z']
|
|
2276
|
+
sage: p1 = R('a + (1+2*b)*x*y + (3-a^2)*z')
|
|
2277
|
+
sage: p2 = R('x-1')
|
|
2278
|
+
sage: p1.quo_rem(p2) # needs sage.libs.singular
|
|
2279
|
+
((2*b + 1)*y, (2*b + 1)*y + (-a^2 + 3)*z + a)
|
|
2280
|
+
|
|
2281
|
+
sage: R.<x,y> = Qp(5)[] # needs sage.rings.padics
|
|
2282
|
+
sage: x.quo_rem(y) # needs sage.libs.singular sage.rings.padics
|
|
2283
|
+
Traceback (most recent call last):
|
|
2284
|
+
...
|
|
2285
|
+
TypeError: no conversion of this ring to a Singular ring defined
|
|
2286
|
+
|
|
2287
|
+
ALGORITHM: Use Singular.
|
|
2288
|
+
|
|
2289
|
+
TESTS:
|
|
2290
|
+
|
|
2291
|
+
Check that this method works over ``QQbar`` (:issue:`25351`)::
|
|
2292
|
+
|
|
2293
|
+
sage: R.<x,y> = QQbar[] # needs sage.rings.number_field
|
|
2294
|
+
sage: f = y*x^2 + x + 1 # needs sage.rings.number_field
|
|
2295
|
+
sage: f.quo_rem(x) # needs sage.libs.singular sage.rings.number_field
|
|
2296
|
+
(x*y + 1, 1)
|
|
2297
|
+
"""
|
|
2298
|
+
R = self.parent()
|
|
2299
|
+
try:
|
|
2300
|
+
R._singular_().set_ring()
|
|
2301
|
+
except (TypeError, ImportError):
|
|
2302
|
+
f = self.parent().flattening_morphism()
|
|
2303
|
+
if f.domain() != f.codomain():
|
|
2304
|
+
g = f.section()
|
|
2305
|
+
q,r = f(self).quo_rem(f(right))
|
|
2306
|
+
return g(q), g(r)
|
|
2307
|
+
else:
|
|
2308
|
+
raise TypeError
|
|
2309
|
+
else:
|
|
2310
|
+
X = self._singular_().division(right._singular_())
|
|
2311
|
+
return R(X[1][1,1]), R(X[2][1])
|
|
2312
|
+
|
|
2313
|
+
@handle_AA_and_QQbar
|
|
2314
|
+
def resultant(self, other, variable=None):
|
|
2315
|
+
"""
|
|
2316
|
+
Compute the resultant of ``self`` and ``other`` with respect
|
|
2317
|
+
to ``variable``.
|
|
2318
|
+
|
|
2319
|
+
If a second argument is not provided, the first variable of
|
|
2320
|
+
``self.parent()`` is chosen.
|
|
2321
|
+
|
|
2322
|
+
For inexact rings or rings not available in Singular,
|
|
2323
|
+
this computes the determinant of the Sylvester matrix.
|
|
2324
|
+
|
|
2325
|
+
INPUT:
|
|
2326
|
+
|
|
2327
|
+
- ``other`` -- polynomial in ``self.parent()``
|
|
2328
|
+
|
|
2329
|
+
- ``variable`` -- (optional) variable (of type polynomial) in
|
|
2330
|
+
``self.parent()``
|
|
2331
|
+
|
|
2332
|
+
EXAMPLES::
|
|
2333
|
+
|
|
2334
|
+
sage: P.<x,y> = PolynomialRing(QQ, 2)
|
|
2335
|
+
sage: a = x + y
|
|
2336
|
+
sage: b = x^3 - y^3
|
|
2337
|
+
sage: a.resultant(b) # needs sage.libs.singular
|
|
2338
|
+
-2*y^3
|
|
2339
|
+
sage: a.resultant(b, y) # needs sage.libs.singular
|
|
2340
|
+
2*x^3
|
|
2341
|
+
|
|
2342
|
+
TESTS::
|
|
2343
|
+
|
|
2344
|
+
sage: from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict_domain
|
|
2345
|
+
sage: P.<x,y> = MPolynomialRing_polydict_domain(QQ, 2, order='degrevlex')
|
|
2346
|
+
sage: a = x + y
|
|
2347
|
+
sage: b = x^3 - y^3
|
|
2348
|
+
sage: a.resultant(b) # needs sage.libs.singular
|
|
2349
|
+
-2*y^3
|
|
2350
|
+
sage: a.resultant(b, y) # needs sage.libs.singular
|
|
2351
|
+
2*x^3
|
|
2352
|
+
|
|
2353
|
+
Check that :issue:`15061` is fixed::
|
|
2354
|
+
|
|
2355
|
+
sage: R.<x, y> = AA[] # needs sage.rings.number_field
|
|
2356
|
+
sage: (x^2 + 1).resultant(x^2 - y) # needs sage.libs.singular sage.rings.number_field
|
|
2357
|
+
y^2 + 2*y + 1
|
|
2358
|
+
|
|
2359
|
+
Test for :issue:`2693`::
|
|
2360
|
+
|
|
2361
|
+
sage: R.<x,y> = RR[]
|
|
2362
|
+
sage: p = x + y
|
|
2363
|
+
sage: q = x*y
|
|
2364
|
+
sage: p.resultant(q) # needs sage.libs.singular sage.modules
|
|
2365
|
+
-y^2
|
|
2366
|
+
|
|
2367
|
+
Check that this method works over QQbar (:issue:`25351`)::
|
|
2368
|
+
|
|
2369
|
+
sage: # needs sage.rings.number_field
|
|
2370
|
+
sage: P.<x,y> = QQbar[]
|
|
2371
|
+
sage: a = x + y
|
|
2372
|
+
sage: b = x^3 - y^3
|
|
2373
|
+
sage: a.resultant(b) # needs sage.libs.singular sage.modules
|
|
2374
|
+
(-2)*y^3
|
|
2375
|
+
sage: a.resultant(b, y) # needs sage.libs.singular sage.modules
|
|
2376
|
+
2*x^3
|
|
2377
|
+
"""
|
|
2378
|
+
R = self.parent()
|
|
2379
|
+
if variable is None:
|
|
2380
|
+
variable = R.gen(0)
|
|
2381
|
+
if R._has_singular and R.is_exact():
|
|
2382
|
+
rt = self._singular_().resultant(other._singular_(), variable._singular_())
|
|
2383
|
+
r = rt.sage_poly(R)
|
|
2384
|
+
else:
|
|
2385
|
+
r = self.sylvester_matrix(other, variable).det()
|
|
2386
|
+
if R.ngens() <= 1 and r.degree() <= 0:
|
|
2387
|
+
return R.base_ring()(r[0])
|
|
2388
|
+
else:
|
|
2389
|
+
return r
|
|
2390
|
+
|
|
2391
|
+
@coerce_binop
|
|
2392
|
+
@handle_AA_and_QQbar
|
|
2393
|
+
def subresultants(self, other, variable=None):
|
|
2394
|
+
r"""
|
|
2395
|
+
Return the nonzero subresultant polynomials of ``self`` and ``other``.
|
|
2396
|
+
|
|
2397
|
+
INPUT:
|
|
2398
|
+
|
|
2399
|
+
- ``other`` -- a polynomial
|
|
2400
|
+
|
|
2401
|
+
OUTPUT: list of polynomials in the same ring as ``self``
|
|
2402
|
+
|
|
2403
|
+
EXAMPLES::
|
|
2404
|
+
|
|
2405
|
+
sage: # needs sage.libs.singular sage.rings.number_field
|
|
2406
|
+
sage: R.<x,y> = QQbar[]
|
|
2407
|
+
sage: p = (y^2 + 6)*(x - 1) - y*(x^2 + 1)
|
|
2408
|
+
sage: q = (x^2 + 6)*(y - 1) - x*(y^2 + 1)
|
|
2409
|
+
sage: p.subresultants(q, y)
|
|
2410
|
+
[2*x^6 + (-22)*x^5 + 102*x^4 + (-274)*x^3 + 488*x^2 + (-552)*x + 288,
|
|
2411
|
+
-x^3 - x^2*y + 6*x^2 + 5*x*y + (-11)*x + (-6)*y + 6]
|
|
2412
|
+
sage: p.subresultants(q, x)
|
|
2413
|
+
[2*y^6 + (-22)*y^5 + 102*y^4 + (-274)*y^3 + 488*y^2 + (-552)*y + 288,
|
|
2414
|
+
x*y^2 + y^3 + (-5)*x*y + (-6)*y^2 + 6*x + 11*y - 6]
|
|
2415
|
+
"""
|
|
2416
|
+
R = self.parent()
|
|
2417
|
+
if variable is None:
|
|
2418
|
+
x = R.gen(0)
|
|
2419
|
+
else:
|
|
2420
|
+
x = variable
|
|
2421
|
+
p = self.polynomial(x)
|
|
2422
|
+
q = other.polynomial(x)
|
|
2423
|
+
return [R(f) for f in p.subresultants(q)]
|
|
2424
|
+
|
|
2425
|
+
def reduce(self, I):
|
|
2426
|
+
"""
|
|
2427
|
+
Reduce this polynomial by the polynomials in `I`.
|
|
2428
|
+
|
|
2429
|
+
INPUT:
|
|
2430
|
+
|
|
2431
|
+
- ``I`` -- list of polynomials or an ideal
|
|
2432
|
+
|
|
2433
|
+
EXAMPLES::
|
|
2434
|
+
|
|
2435
|
+
sage: # needs sage.rings.number_field
|
|
2436
|
+
sage: P.<x,y,z> = QQbar[]
|
|
2437
|
+
sage: f1 = -2 * x^2 + x^3
|
|
2438
|
+
sage: f2 = -2 * y + x * y
|
|
2439
|
+
sage: f3 = -x^2 + y^2
|
|
2440
|
+
sage: F = Ideal([f1, f2, f3])
|
|
2441
|
+
sage: g = x*y - 3*x*y^2
|
|
2442
|
+
sage: g.reduce(F) # needs sage.libs.singular
|
|
2443
|
+
(-6)*y^2 + 2*y
|
|
2444
|
+
sage: g.reduce(F.gens()) # needs sage.libs.singular
|
|
2445
|
+
(-6)*y^2 + 2*y
|
|
2446
|
+
|
|
2447
|
+
::
|
|
2448
|
+
|
|
2449
|
+
sage: f = 3*x # needs sage.rings.number_field
|
|
2450
|
+
sage: f.reduce([2*x, y]) # needs sage.libs.singular sage.rings.number_field
|
|
2451
|
+
0
|
|
2452
|
+
|
|
2453
|
+
::
|
|
2454
|
+
|
|
2455
|
+
sage: # needs sage.libs.singular sage.rings.number_field
|
|
2456
|
+
sage: k.<w> = CyclotomicField(3)
|
|
2457
|
+
sage: A.<y9,y12,y13,y15> = PolynomialRing(k)
|
|
2458
|
+
sage: J = [y9 + y12]
|
|
2459
|
+
sage: f = y9 - y12; f.reduce(J)
|
|
2460
|
+
-2*y12
|
|
2461
|
+
sage: f = y13*y15; f.reduce(J)
|
|
2462
|
+
y13*y15
|
|
2463
|
+
sage: f = y13*y15 + y9 - y12; f.reduce(J)
|
|
2464
|
+
y13*y15 - 2*y12
|
|
2465
|
+
|
|
2466
|
+
Make sure the remainder returns the correct type, fixing :issue:`13903`::
|
|
2467
|
+
|
|
2468
|
+
sage: R.<y1,y2> = PolynomialRing(Qp(5), 2, order='lex') # needs sage.rings.padics
|
|
2469
|
+
sage: G = [y1^2 + y2^2, y1*y2 + y2^2, y2^3] # needs sage.rings.padics
|
|
2470
|
+
sage: type((y2^3).reduce(G)) # needs sage.libs.singular sage.rings.padics
|
|
2471
|
+
<class 'sage.rings.polynomial.multi_polynomial_element.MPolynomial_polydict'>
|
|
2472
|
+
|
|
2473
|
+
TESTS:
|
|
2474
|
+
|
|
2475
|
+
Verify that :issue:`34105` is fixed::
|
|
2476
|
+
|
|
2477
|
+
sage: R.<x,y> = AA[] # needs sage.rings.number_field
|
|
2478
|
+
sage: x.reduce(R.zero_ideal()) # needs sage.libs.singular sage.rings.number_field
|
|
2479
|
+
x
|
|
2480
|
+
"""
|
|
2481
|
+
from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal
|
|
2482
|
+
|
|
2483
|
+
k = self.base_ring()
|
|
2484
|
+
P = self.parent()
|
|
2485
|
+
|
|
2486
|
+
if isinstance(I, MPolynomialIdeal):
|
|
2487
|
+
I = I.gens()
|
|
2488
|
+
|
|
2489
|
+
if not k.is_field():
|
|
2490
|
+
raise TypeError("Can only reduce polynomials over fields.")
|
|
2491
|
+
|
|
2492
|
+
try:
|
|
2493
|
+
fs = self._singular_()
|
|
2494
|
+
Is = fs.parent().ideal(I)
|
|
2495
|
+
return P(fs.reduce(Is))
|
|
2496
|
+
except (NotImplementedError, TypeError):
|
|
2497
|
+
pass
|
|
2498
|
+
|
|
2499
|
+
I = [g for g in I if g]
|
|
2500
|
+
lI = len(I)
|
|
2501
|
+
r = P.zero()
|
|
2502
|
+
p = self
|
|
2503
|
+
|
|
2504
|
+
while p != 0:
|
|
2505
|
+
for i in range(lI):
|
|
2506
|
+
gi = I[i]
|
|
2507
|
+
plm = p.lm()
|
|
2508
|
+
gilm = gi.lm()
|
|
2509
|
+
if P.monomial_divides(gilm, plm):
|
|
2510
|
+
quot = p.lc()/gi.lc() * P.monomial_quotient(plm, gilm)
|
|
2511
|
+
p -= quot * gi
|
|
2512
|
+
break
|
|
2513
|
+
else:
|
|
2514
|
+
plt = p.lt()
|
|
2515
|
+
r += plt
|
|
2516
|
+
p -= plt
|
|
2517
|
+
return r
|
|
2518
|
+
|
|
2519
|
+
|
|
2520
|
+
###############################################################
|
|
2521
|
+
# Useful for some geometry code.
|
|
2522
|
+
###############################################################
|
|
2523
|
+
|
|
2524
|
+
def degree_lowest_rational_function(r, x):
|
|
2525
|
+
r"""
|
|
2526
|
+
Return the difference of valuations of ``r`` with respect to variable ``x``.
|
|
2527
|
+
|
|
2528
|
+
INPUT:
|
|
2529
|
+
|
|
2530
|
+
- ``r`` -- a multivariate rational function
|
|
2531
|
+
|
|
2532
|
+
- ``x`` -- a multivariate polynomial ring generator
|
|
2533
|
+
|
|
2534
|
+
OUTPUT: integer; the difference `val_x(p) - val_x(q)` where `r = p/q`
|
|
2535
|
+
|
|
2536
|
+
.. NOTE::
|
|
2537
|
+
|
|
2538
|
+
This function should be made a method of the
|
|
2539
|
+
:class:`FractionFieldElement` class.
|
|
2540
|
+
|
|
2541
|
+
EXAMPLES::
|
|
2542
|
+
|
|
2543
|
+
sage: R1 = PolynomialRing(FiniteField(5), 3, names=["a", "b", "c"])
|
|
2544
|
+
sage: F = FractionField(R1)
|
|
2545
|
+
sage: a,b,c = R1.gens()
|
|
2546
|
+
sage: f = 3*a*b^2*c^3 + 4*a*b*c
|
|
2547
|
+
sage: g = a^2*b*c^2 + 2*a^2*b^4*c^7
|
|
2548
|
+
|
|
2549
|
+
Consider the quotient
|
|
2550
|
+
`f/g = \frac{4 + 3 bc^{2}}{ac + 2 ab^{3}c^{6}}` (note the
|
|
2551
|
+
cancellation).
|
|
2552
|
+
|
|
2553
|
+
::
|
|
2554
|
+
|
|
2555
|
+
sage: # needs sage.rings.finite_rings
|
|
2556
|
+
sage: r = f/g; r
|
|
2557
|
+
(-2*b*c^2 - 1)/(2*a*b^3*c^6 + a*c)
|
|
2558
|
+
sage: degree_lowest_rational_function(r, a)
|
|
2559
|
+
-1
|
|
2560
|
+
sage: degree_lowest_rational_function(r, b)
|
|
2561
|
+
0
|
|
2562
|
+
sage: degree_lowest_rational_function(r, c)
|
|
2563
|
+
-1
|
|
2564
|
+
"""
|
|
2565
|
+
from sage.rings.fraction_field import FractionField
|
|
2566
|
+
F = FractionField(r.parent())
|
|
2567
|
+
r = F(r)
|
|
2568
|
+
f = r.numerator().polynomial(x)
|
|
2569
|
+
g = r.denominator().polynomial(x)
|
|
2570
|
+
return f.valuation() - g.valuation()
|