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,1653 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Infinite Polynomial Rings
|
|
4
|
+
|
|
5
|
+
By Infinite Polynomial Rings, we mean polynomial rings in a countably
|
|
6
|
+
infinite number of variables. The implementation consists of a wrapper
|
|
7
|
+
around the current *finite* polynomial rings in Sage.
|
|
8
|
+
|
|
9
|
+
AUTHORS:
|
|
10
|
+
|
|
11
|
+
- Simon King <simon.king@nuigalway.ie>
|
|
12
|
+
- Mike Hansen <mhansen@gmail.com>
|
|
13
|
+
|
|
14
|
+
An Infinite Polynomial Ring has finitely many generators `x_\ast,
|
|
15
|
+
y_\ast,...` and infinitely many variables of the form `x_0, x_1, x_2,
|
|
16
|
+
..., y_0, y_1, y_2,...,...`. We refer to the natural number `n` as
|
|
17
|
+
the *index* of the variable `x_n`.
|
|
18
|
+
|
|
19
|
+
INPUT:
|
|
20
|
+
|
|
21
|
+
- ``R`` -- the base ring; it has to be a commutative ring, and in some
|
|
22
|
+
applications it must even be a field
|
|
23
|
+
- ``names`` -- a finite list of generator names; generator names must be alpha-numeric
|
|
24
|
+
- ``order`` -- (optional) string; the default order is ``'lex'`` (lexicographic).
|
|
25
|
+
``'deglex'`` is degree lexicographic, and ``'degrevlex'`` (degree reverse
|
|
26
|
+
lexicographic) is possible but discouraged.
|
|
27
|
+
|
|
28
|
+
Each generator ``x`` produces an infinite sequence of variables
|
|
29
|
+
``x[1], x[2], ...`` which are printed on screen as ``x_1, x_2, ...``
|
|
30
|
+
and are latex typeset as `x_{1}, x_{2}`. Then, the Infinite
|
|
31
|
+
Polynomial Ring is formed by polynomials in these variables.
|
|
32
|
+
|
|
33
|
+
By default, the monomials are ordered lexicographically. Alternatively,
|
|
34
|
+
degree (reverse) lexicographic ordering is possible as well. However, we
|
|
35
|
+
do not guarantee that the computation of Groebner bases will terminate
|
|
36
|
+
in this case.
|
|
37
|
+
|
|
38
|
+
In either case, the variables of a Infinite Polynomial Ring X are ordered
|
|
39
|
+
according to the following rule:
|
|
40
|
+
|
|
41
|
+
``X.gen(i)[m] > X.gen(j)[n]`` if and only if ``i<j or (i==j and m>n)``
|
|
42
|
+
|
|
43
|
+
We provide a 'dense' and a 'sparse' implementation. In the dense
|
|
44
|
+
implementation, the Infinite Polynomial Ring carries a finite
|
|
45
|
+
polynomial ring that comprises *all* variables up to the maximal index
|
|
46
|
+
that has been used so far. This is potentially a very big ring and may
|
|
47
|
+
also comprise many variables that are not used.
|
|
48
|
+
|
|
49
|
+
In the sparse implementation, we try to keep the underlying finite
|
|
50
|
+
polynomial rings small, using only those variables that are really
|
|
51
|
+
needed. By default, we use the dense implementation, since it usually
|
|
52
|
+
is much faster.
|
|
53
|
+
|
|
54
|
+
EXAMPLES::
|
|
55
|
+
|
|
56
|
+
sage: X.<x,y> = InfinitePolynomialRing(ZZ, implementation='sparse')
|
|
57
|
+
sage: A.<alpha,beta> = InfinitePolynomialRing(QQ, order='deglex')
|
|
58
|
+
|
|
59
|
+
sage: f = x[5] + 2; f
|
|
60
|
+
x_5 + 2
|
|
61
|
+
sage: g = 3*y[1]; g
|
|
62
|
+
3*y_1
|
|
63
|
+
|
|
64
|
+
It has some advantages to have an underlying ring that is not
|
|
65
|
+
univariate. Hence, we always have at least two variables::
|
|
66
|
+
|
|
67
|
+
sage: g._p.parent()
|
|
68
|
+
Multivariate Polynomial Ring in y_1, y_0 over Integer Ring
|
|
69
|
+
|
|
70
|
+
sage: f2 = alpha[5] + 2; f2
|
|
71
|
+
alpha_5 + 2
|
|
72
|
+
sage: g2 = 3*beta[1]; g2
|
|
73
|
+
3*beta_1
|
|
74
|
+
sage: A.polynomial_ring()
|
|
75
|
+
Multivariate Polynomial Ring in alpha_5, alpha_4, alpha_3, alpha_2, alpha_1, alpha_0,
|
|
76
|
+
beta_5, beta_4, beta_3, beta_2, beta_1, beta_0 over Rational Field
|
|
77
|
+
|
|
78
|
+
Of course, we provide the usual polynomial arithmetic::
|
|
79
|
+
|
|
80
|
+
sage: f + g
|
|
81
|
+
x_5 + 3*y_1 + 2
|
|
82
|
+
sage: p = x[10]^2*(f+g); p
|
|
83
|
+
x_10^2*x_5 + 3*x_10^2*y_1 + 2*x_10^2
|
|
84
|
+
sage: p2 = alpha[10]^2*(f2+g2); p2
|
|
85
|
+
alpha_10^2*alpha_5 + 3*alpha_10^2*beta_1 + 2*alpha_10^2
|
|
86
|
+
|
|
87
|
+
There is a permutation action on the variables, by permuting positive
|
|
88
|
+
variable indices::
|
|
89
|
+
|
|
90
|
+
sage: P = Permutation(((10,1)))
|
|
91
|
+
sage: p^P
|
|
92
|
+
x_5*x_1^2 + 3*x_1^2*y_10 + 2*x_1^2
|
|
93
|
+
sage: p2^P
|
|
94
|
+
alpha_5*alpha_1^2 + 3*alpha_1^2*beta_10 + 2*alpha_1^2
|
|
95
|
+
|
|
96
|
+
Note that `x_0^P = x_0`, since the permutations only change *positive*
|
|
97
|
+
variable indices.
|
|
98
|
+
|
|
99
|
+
We also implemented ideals of Infinite Polynomial Rings. Here, it is
|
|
100
|
+
thoroughly assumed that the ideals are set-wise invariant under the
|
|
101
|
+
permutation action. We therefore refer to these ideals as *Symmetric
|
|
102
|
+
Ideals*. Symmetric Ideals are finitely generated modulo addition,
|
|
103
|
+
multiplication by ring elements and permutation of variables. If the
|
|
104
|
+
base ring is a field, one can compute Symmetric Groebner Bases::
|
|
105
|
+
|
|
106
|
+
sage: J = A * (alpha[1]*beta[2])
|
|
107
|
+
sage: J.groebner_basis() # needs sage.combinat sage.libs.singular
|
|
108
|
+
[alpha_1*beta_2, alpha_2*beta_1]
|
|
109
|
+
|
|
110
|
+
For more details, see :class:`~sage.rings.polynomial.symmetric_ideal.SymmetricIdeal`.
|
|
111
|
+
|
|
112
|
+
Infinite Polynomial Rings can have any commutative base ring. If the
|
|
113
|
+
base ring of an Infinite Polynomial Ring is a (classical or infinite)
|
|
114
|
+
Polynomial Ring, then our implementation tries to merge everything
|
|
115
|
+
into *one* ring. The basic requirement is that the monomial orders
|
|
116
|
+
match. In the case of two Infinite Polynomial Rings, the
|
|
117
|
+
implementations must match. Moreover, name conflicts should be
|
|
118
|
+
avoided. An overlap is only accepted if the order of variables can be
|
|
119
|
+
uniquely inferred, as in the following example::
|
|
120
|
+
|
|
121
|
+
sage: A.<a,b,c> = InfinitePolynomialRing(ZZ)
|
|
122
|
+
sage: B.<b,c,d> = InfinitePolynomialRing(A)
|
|
123
|
+
sage: B
|
|
124
|
+
Infinite polynomial ring in a, b, c, d over Integer Ring
|
|
125
|
+
|
|
126
|
+
This is also allowed if finite polynomial rings are involved::
|
|
127
|
+
|
|
128
|
+
sage: A.<a_3,a_1,b_1,c_2,c_0> = ZZ[]
|
|
129
|
+
sage: B.<b,c,d> = InfinitePolynomialRing(A, order='degrevlex')
|
|
130
|
+
sage: B
|
|
131
|
+
Infinite polynomial ring in b, c, d over
|
|
132
|
+
Multivariate Polynomial Ring in a_3, a_1 over Integer Ring
|
|
133
|
+
|
|
134
|
+
It is no problem if one generator of the Infinite Polynomial Ring is
|
|
135
|
+
called ``x`` and one variable of the base ring is also called
|
|
136
|
+
``x``. This is since no *variable* of the Infinite Polynomial Ring
|
|
137
|
+
will be called ``x``. However, a problem arises if the underlying
|
|
138
|
+
classical Polynomial Ring has a variable ``x_1``, since this can be
|
|
139
|
+
confused with a variable of the Infinite Polynomial Ring. In this
|
|
140
|
+
case, an error will be raised::
|
|
141
|
+
|
|
142
|
+
sage: X.<x,y_1> = ZZ[]
|
|
143
|
+
sage: Y.<x,z> = InfinitePolynomialRing(X)
|
|
144
|
+
|
|
145
|
+
Note that ``X`` is not merged into ``Y``; this is since the monomial
|
|
146
|
+
order of ``X`` is 'degrevlex', but of ``Y`` is 'lex'.
|
|
147
|
+
::
|
|
148
|
+
|
|
149
|
+
sage: Y
|
|
150
|
+
Infinite polynomial ring in x, z over
|
|
151
|
+
Multivariate Polynomial Ring in x, y_1 over Integer Ring
|
|
152
|
+
|
|
153
|
+
The variable ``x`` of ``X`` can still be interpreted in ``Y``,
|
|
154
|
+
although the first generator of ``Y`` is called ``x`` as well::
|
|
155
|
+
|
|
156
|
+
sage: x
|
|
157
|
+
x_*
|
|
158
|
+
sage: X('x')
|
|
159
|
+
x
|
|
160
|
+
sage: Y(X('x'))
|
|
161
|
+
x
|
|
162
|
+
sage: Y('x')
|
|
163
|
+
x
|
|
164
|
+
|
|
165
|
+
But there is only merging if the resulting monomial order is uniquely
|
|
166
|
+
determined. This is not the case in the following examples, and thus
|
|
167
|
+
an error is raised::
|
|
168
|
+
|
|
169
|
+
sage: X.<y_1,x> = ZZ[]
|
|
170
|
+
sage: Y.<y,z> = InfinitePolynomialRing(X)
|
|
171
|
+
Traceback (most recent call last):
|
|
172
|
+
...
|
|
173
|
+
CoercionException: Overlapping variables (('y', 'z'),['y_1']) are incompatible
|
|
174
|
+
sage: Y.<z,y> = InfinitePolynomialRing(X)
|
|
175
|
+
Traceback (most recent call last):
|
|
176
|
+
...
|
|
177
|
+
CoercionException: Overlapping variables (('z', 'y'),['y_1']) are incompatible
|
|
178
|
+
sage: X.<x_3,y_1,y_2> = PolynomialRing(ZZ, order='lex')
|
|
179
|
+
sage: # y_1 and y_2 would be in opposite order in an Infinite Polynomial Ring
|
|
180
|
+
sage: Y.<y> = InfinitePolynomialRing(X)
|
|
181
|
+
Traceback (most recent call last):
|
|
182
|
+
...
|
|
183
|
+
CoercionException: Overlapping variables (('y',),['y_1', 'y_2']) are incompatible
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
If the type of monomial orderings (e.g., 'degrevlex' versus 'lex') or
|
|
187
|
+
if the implementations do not match, there is no simplified
|
|
188
|
+
construction available::
|
|
189
|
+
|
|
190
|
+
sage: X.<x,y> = InfinitePolynomialRing(ZZ)
|
|
191
|
+
sage: Y.<z> = InfinitePolynomialRing(X, order='degrevlex')
|
|
192
|
+
sage: Y
|
|
193
|
+
Infinite polynomial ring in z over Infinite polynomial ring in x, y over Integer Ring
|
|
194
|
+
sage: Y.<z> = InfinitePolynomialRing(X, implementation='sparse')
|
|
195
|
+
sage: Y
|
|
196
|
+
Infinite polynomial ring in z over Infinite polynomial ring in x, y over Integer Ring
|
|
197
|
+
|
|
198
|
+
TESTS:
|
|
199
|
+
|
|
200
|
+
Infinite Polynomial Rings are part of Sage's coercion system. Hence,
|
|
201
|
+
we can do arithmetic, so that the result lives in a ring into which
|
|
202
|
+
all constituents coerce.
|
|
203
|
+
::
|
|
204
|
+
|
|
205
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
206
|
+
sage: X.<x> = InfinitePolynomialRing(R)
|
|
207
|
+
sage: x[2]/2+(5/3)*a[3]*x[4] + 1
|
|
208
|
+
5/3*a_3*x_4 + 1/2*x_2 + 1
|
|
209
|
+
|
|
210
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ, implementation='sparse')
|
|
211
|
+
sage: X.<x> = InfinitePolynomialRing(R)
|
|
212
|
+
sage: x[2]/2+(5/3)*a[3]*x[4] + 1
|
|
213
|
+
5/3*a_3*x_4 + 1/2*x_2 + 1
|
|
214
|
+
|
|
215
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ, implementation='sparse')
|
|
216
|
+
sage: X.<x> = InfinitePolynomialRing(R, implementation='sparse')
|
|
217
|
+
sage: x[2]/2+(5/3)*a[3]*x[4] + 1
|
|
218
|
+
5/3*a_3*x_4 + 1/2*x_2 + 1
|
|
219
|
+
|
|
220
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
221
|
+
sage: X.<x> = InfinitePolynomialRing(R, implementation='sparse')
|
|
222
|
+
sage: x[2]/2+(5/3)*a[3]*x[4] + 1
|
|
223
|
+
5/3*a_3*x_4 + 1/2*x_2 + 1
|
|
224
|
+
|
|
225
|
+
Check that :issue:`22514` is fixed::
|
|
226
|
+
|
|
227
|
+
sage: R.<x> = InfinitePolynomialRing(ZZ)
|
|
228
|
+
sage: a = R(3)
|
|
229
|
+
sage: a.is_constant()
|
|
230
|
+
True
|
|
231
|
+
sage: a.constant_coefficient()
|
|
232
|
+
3
|
|
233
|
+
sage: a.degree()
|
|
234
|
+
0
|
|
235
|
+
sage: b = R("2")
|
|
236
|
+
sage: b.parent() is R
|
|
237
|
+
True
|
|
238
|
+
sage: S.<y> = ZZ[]
|
|
239
|
+
sage: Q.<z> = InfinitePolynomialRing(S)
|
|
240
|
+
sage: a = Q(1+y)
|
|
241
|
+
sage: a.is_constant()
|
|
242
|
+
True
|
|
243
|
+
sage: a.constant_coefficient()
|
|
244
|
+
y + 1
|
|
245
|
+
"""
|
|
246
|
+
# ****************************************************************************
|
|
247
|
+
# Copyright (C) 2009 Simon King <simon.king@nuigalway.ie> and
|
|
248
|
+
# Mike Hansen <mhansen@gmail.com>,
|
|
249
|
+
#
|
|
250
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
251
|
+
#
|
|
252
|
+
# This code is distributed in the hope that it will be useful,
|
|
253
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
254
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
255
|
+
# General Public License for more details.
|
|
256
|
+
#
|
|
257
|
+
# The full text of the GPL is available at:
|
|
258
|
+
#
|
|
259
|
+
# https://www.gnu.org/licenses/
|
|
260
|
+
# ****************************************************************************
|
|
261
|
+
import operator
|
|
262
|
+
import re
|
|
263
|
+
from functools import reduce
|
|
264
|
+
|
|
265
|
+
from sage.rings.ring import CommutativeRing
|
|
266
|
+
from sage.categories.rings import Rings
|
|
267
|
+
from sage.structure.all import SageObject, parent
|
|
268
|
+
from sage.structure.factory import UniqueFactory
|
|
269
|
+
from sage.misc.cachefunc import cached_method
|
|
270
|
+
|
|
271
|
+
###################################################
|
|
272
|
+
# The Construction Functor
|
|
273
|
+
|
|
274
|
+
from sage.categories.pushout import InfinitePolynomialFunctor
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
###############################################################
|
|
278
|
+
# Ring Factory framework
|
|
279
|
+
|
|
280
|
+
class InfinitePolynomialRingFactory(UniqueFactory):
|
|
281
|
+
"""
|
|
282
|
+
A factory for creating infinite polynomial ring elements. It
|
|
283
|
+
makes sure that they are unique as well as handling pickling.
|
|
284
|
+
For more details, see
|
|
285
|
+
:class:`~sage.structure.factory.UniqueFactory` and
|
|
286
|
+
:mod:`~sage.rings.polynomial.infinite_polynomial_ring`.
|
|
287
|
+
|
|
288
|
+
EXAMPLES::
|
|
289
|
+
|
|
290
|
+
sage: A.<a> = InfinitePolynomialRing(QQ)
|
|
291
|
+
sage: B.<b> = InfinitePolynomialRing(A)
|
|
292
|
+
sage: B.construction()
|
|
293
|
+
[InfPoly{[a,b], "lex", "dense"}, Rational Field]
|
|
294
|
+
sage: R.<a,b> = InfinitePolynomialRing(QQ)
|
|
295
|
+
sage: R is B
|
|
296
|
+
True
|
|
297
|
+
sage: X.<x> = InfinitePolynomialRing(QQ)
|
|
298
|
+
sage: X2.<x> = InfinitePolynomialRing(QQ, implementation='sparse')
|
|
299
|
+
sage: X is X2
|
|
300
|
+
False
|
|
301
|
+
|
|
302
|
+
sage: X is loads(dumps(X))
|
|
303
|
+
True
|
|
304
|
+
"""
|
|
305
|
+
def create_key(self, R, names=('x',), order='lex', implementation='dense'):
|
|
306
|
+
"""
|
|
307
|
+
Create a key which uniquely defines the infinite polynomial ring.
|
|
308
|
+
|
|
309
|
+
TESTS::
|
|
310
|
+
|
|
311
|
+
sage: InfinitePolynomialRing.create_key(QQ, ('y1',))
|
|
312
|
+
(InfPoly{[y1], "lex", "dense"}(FractionField(...)), Integer Ring)
|
|
313
|
+
sage: _[0].all
|
|
314
|
+
[FractionField, InfPoly{[y1], "lex", "dense"}]
|
|
315
|
+
sage: InfinitePolynomialRing.create_key(QQ, names=['beta'], order='deglex',
|
|
316
|
+
....: implementation='sparse')
|
|
317
|
+
(InfPoly{[beta], "deglex", "sparse"}(FractionField(...)), Integer Ring)
|
|
318
|
+
sage: _[0].all
|
|
319
|
+
[FractionField, InfPoly{[beta], "deglex", "sparse"}]
|
|
320
|
+
sage: InfinitePolynomialRing.create_key(QQ, names=['x','y'],
|
|
321
|
+
....: implementation='dense')
|
|
322
|
+
(InfPoly{[x,y], "lex", "dense"}(FractionField(...)), Integer Ring)
|
|
323
|
+
sage: _[0].all
|
|
324
|
+
[FractionField, InfPoly{[x,y], "lex", "dense"}]
|
|
325
|
+
|
|
326
|
+
If no generator name is provided, a generator named 'x',
|
|
327
|
+
lexicographic order and the dense implementation are assumed::
|
|
328
|
+
|
|
329
|
+
sage: InfinitePolynomialRing.create_key(QQ)
|
|
330
|
+
(InfPoly{[x], "lex", "dense"}(FractionField(...)), Integer Ring)
|
|
331
|
+
sage: _[0].all
|
|
332
|
+
[FractionField, InfPoly{[x], "lex", "dense"}]
|
|
333
|
+
|
|
334
|
+
If it is attempted to use no generator, a :exc:`ValueError` is raised::
|
|
335
|
+
|
|
336
|
+
sage: InfinitePolynomialRing.create_key(ZZ, names=[])
|
|
337
|
+
Traceback (most recent call last):
|
|
338
|
+
...
|
|
339
|
+
ValueError: Infinite Polynomial Rings must have at least one generator
|
|
340
|
+
"""
|
|
341
|
+
if isinstance(names, list):
|
|
342
|
+
names = tuple(names)
|
|
343
|
+
if not names:
|
|
344
|
+
raise ValueError("Infinite Polynomial Rings must have at least one generator")
|
|
345
|
+
if len(names) > len(set(names)):
|
|
346
|
+
raise ValueError("the variable names must be distinct")
|
|
347
|
+
F = InfinitePolynomialFunctor(names, order, implementation)
|
|
348
|
+
while hasattr(R, 'construction'):
|
|
349
|
+
C = R.construction()
|
|
350
|
+
if C is None:
|
|
351
|
+
break
|
|
352
|
+
F = F * C[0]
|
|
353
|
+
R = C[1]
|
|
354
|
+
return (F, R)
|
|
355
|
+
|
|
356
|
+
def create_object(self, version, key):
|
|
357
|
+
"""
|
|
358
|
+
Return the infinite polynomial ring corresponding to the key ``key``.
|
|
359
|
+
|
|
360
|
+
TESTS::
|
|
361
|
+
|
|
362
|
+
sage: InfinitePolynomialRing.create_object('1.0', InfinitePolynomialRing.create_key(ZZ, ('x3',)))
|
|
363
|
+
Infinite polynomial ring in x3 over Integer Ring
|
|
364
|
+
"""
|
|
365
|
+
if len(key) > 2:
|
|
366
|
+
# We got an old pickle. By calling the ring constructor, it will automatically
|
|
367
|
+
# be transformed into the new scheme
|
|
368
|
+
return InfinitePolynomialRing(*key)
|
|
369
|
+
# By now, we have different unique keys, based on construction functors
|
|
370
|
+
C, R = key
|
|
371
|
+
from sage.categories.pushout import CompositeConstructionFunctor, InfinitePolynomialFunctor
|
|
372
|
+
if isinstance(C, CompositeConstructionFunctor):
|
|
373
|
+
F = C.all[-1]
|
|
374
|
+
if len(C.all) > 1:
|
|
375
|
+
R = CompositeConstructionFunctor(*C.all[:-1])(R)
|
|
376
|
+
else:
|
|
377
|
+
F = C
|
|
378
|
+
if not isinstance(F, InfinitePolynomialFunctor):
|
|
379
|
+
raise TypeError("we expected an InfinitePolynomialFunctor, not %s" % type(F))
|
|
380
|
+
if F._imple == 'sparse':
|
|
381
|
+
return InfinitePolynomialRing_sparse(R, F._gens, order=F._order)
|
|
382
|
+
return InfinitePolynomialRing_dense(R, F._gens, order=F._order)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
InfinitePolynomialRing = InfinitePolynomialRingFactory('InfinitePolynomialRing')
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
##############################################################
|
|
389
|
+
# An auxiliary dictionary-like class that returns variables
|
|
390
|
+
|
|
391
|
+
class InfiniteGenDict:
|
|
392
|
+
"""
|
|
393
|
+
A dictionary-like class that is suitable for usage in ``sage_eval``.
|
|
394
|
+
|
|
395
|
+
The generators of an Infinite Polynomial Ring are not
|
|
396
|
+
variables. Variables of an Infinite Polynomial Ring are returned
|
|
397
|
+
by indexing a generator. The purpose of this class is to return a
|
|
398
|
+
variable of an Infinite Polynomial Ring, given its string
|
|
399
|
+
representation.
|
|
400
|
+
|
|
401
|
+
EXAMPLES::
|
|
402
|
+
|
|
403
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
404
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
405
|
+
sage: D._D
|
|
406
|
+
[InfiniteGenDict defined by ['a', 'b'], {'1': 1}]
|
|
407
|
+
sage: D._D[0]['a_15']
|
|
408
|
+
a_15
|
|
409
|
+
sage: type(_)
|
|
410
|
+
<class 'sage.rings.polynomial.infinite_polynomial_element.InfinitePolynomial_dense'>
|
|
411
|
+
sage: sage_eval('3*a_3*b_5-1/2*a_7', D._D[0])
|
|
412
|
+
-1/2*a_7 + 3*a_3*b_5
|
|
413
|
+
"""
|
|
414
|
+
def __init__(self, Gens):
|
|
415
|
+
"""
|
|
416
|
+
INPUT:
|
|
417
|
+
|
|
418
|
+
- ``Gens`` -- list of generators of an infinite polynomial ring
|
|
419
|
+
|
|
420
|
+
EXAMPLES::
|
|
421
|
+
|
|
422
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
423
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
424
|
+
sage: D._D
|
|
425
|
+
[InfiniteGenDict defined by ['a', 'b'], {'1': 1}]
|
|
426
|
+
sage: D._D == loads(dumps(D._D)) # indirect doctest
|
|
427
|
+
True
|
|
428
|
+
"""
|
|
429
|
+
self._D = dict(zip(((hasattr(X, '_name') and X._name) or repr(X) for X in Gens), Gens))
|
|
430
|
+
|
|
431
|
+
def __eq__(self, other):
|
|
432
|
+
"""
|
|
433
|
+
Check whether ``self`` is equal to ``other``.
|
|
434
|
+
|
|
435
|
+
EXAMPLES::
|
|
436
|
+
|
|
437
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
438
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
439
|
+
sage: D._D
|
|
440
|
+
[InfiniteGenDict defined by ['a', 'b'], {'1': 1}]
|
|
441
|
+
sage: D._D == loads(dumps(D._D)) # indirect doctest
|
|
442
|
+
True
|
|
443
|
+
"""
|
|
444
|
+
if isinstance(other, InfiniteGenDict):
|
|
445
|
+
return self._D == other._D
|
|
446
|
+
return False
|
|
447
|
+
|
|
448
|
+
def __ne__(self, other):
|
|
449
|
+
"""
|
|
450
|
+
Check whether ``self`` is not equal to ``other``.
|
|
451
|
+
|
|
452
|
+
EXAMPLES::
|
|
453
|
+
|
|
454
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
455
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
456
|
+
sage: D._D
|
|
457
|
+
[InfiniteGenDict defined by ['a', 'b'], {'1': 1}]
|
|
458
|
+
sage: D._D != loads(dumps(D._D)) # indirect doctest
|
|
459
|
+
False
|
|
460
|
+
"""
|
|
461
|
+
return not (self == other)
|
|
462
|
+
|
|
463
|
+
def __repr__(self):
|
|
464
|
+
"""
|
|
465
|
+
EXAMPLES::
|
|
466
|
+
|
|
467
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
468
|
+
sage: D = R.gens_dict()
|
|
469
|
+
sage: D._D # indirect doctest
|
|
470
|
+
[InfiniteGenDict defined by ['a', 'b'], {'1': 1}]
|
|
471
|
+
"""
|
|
472
|
+
return "InfiniteGenDict defined by %s" % sorted(self._D)
|
|
473
|
+
|
|
474
|
+
def __getitem__(self, k):
|
|
475
|
+
"""
|
|
476
|
+
EXAMPLES::
|
|
477
|
+
|
|
478
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
479
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
480
|
+
sage: D._D
|
|
481
|
+
[InfiniteGenDict defined by ['a', 'b'], {'1': 1}]
|
|
482
|
+
sage: D._D[0]['a_15']
|
|
483
|
+
a_15
|
|
484
|
+
sage: type(_)
|
|
485
|
+
<class 'sage.rings.polynomial.infinite_polynomial_element.InfinitePolynomial_dense'>
|
|
486
|
+
"""
|
|
487
|
+
if not isinstance(k, str):
|
|
488
|
+
raise KeyError("string expected")
|
|
489
|
+
L = k.split('_')
|
|
490
|
+
try:
|
|
491
|
+
if len(L) == 2:
|
|
492
|
+
return self._D[L[0]][int(L[1])]
|
|
493
|
+
except (TypeError, ValueError):
|
|
494
|
+
pass
|
|
495
|
+
raise KeyError("%s is not a variable name" % k)
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
class GenDictWithBasering:
|
|
499
|
+
"""
|
|
500
|
+
A dictionary-like class that is suitable for usage in ``sage_eval``.
|
|
501
|
+
|
|
502
|
+
This pseudo-dictionary accepts strings as index, and then walks down
|
|
503
|
+
a chain of base rings of (infinite) polynomial rings until it finds
|
|
504
|
+
one ring that has the given string as variable name, which is then
|
|
505
|
+
returned.
|
|
506
|
+
|
|
507
|
+
EXAMPLES::
|
|
508
|
+
|
|
509
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
510
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
511
|
+
sage: D
|
|
512
|
+
GenDict of Infinite polynomial ring in a, b over Integer Ring
|
|
513
|
+
sage: D['a_15']
|
|
514
|
+
a_15
|
|
515
|
+
sage: type(_)
|
|
516
|
+
<class 'sage.rings.polynomial.infinite_polynomial_element.InfinitePolynomial_dense'>
|
|
517
|
+
sage: sage_eval('3*a_3*b_5-1/2*a_7', D)
|
|
518
|
+
-1/2*a_7 + 3*a_3*b_5
|
|
519
|
+
"""
|
|
520
|
+
def __init__(self, parent, start):
|
|
521
|
+
"""
|
|
522
|
+
INPUT:
|
|
523
|
+
|
|
524
|
+
- ``parent`` -- a ring
|
|
525
|
+
- ``start`` -- some dictionary, usually the dictionary of variables of ``parent``
|
|
526
|
+
|
|
527
|
+
EXAMPLES::
|
|
528
|
+
|
|
529
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
530
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
531
|
+
sage: D
|
|
532
|
+
GenDict of Infinite polynomial ring in a, b over Integer Ring
|
|
533
|
+
sage: D['a_15']
|
|
534
|
+
a_15
|
|
535
|
+
sage: type(_)
|
|
536
|
+
<class 'sage.rings.polynomial.infinite_polynomial_element.InfinitePolynomial_dense'>
|
|
537
|
+
sage: sage_eval('3*a_3*b_5-1/2*a_7', D)
|
|
538
|
+
-1/2*a_7 + 3*a_3*b_5
|
|
539
|
+
|
|
540
|
+
TESTS::
|
|
541
|
+
|
|
542
|
+
sage: from sage.rings.polynomial.infinite_polynomial_ring import GenDictWithBasering
|
|
543
|
+
sage: R = ZZ['x']['y']['a','b']['c']
|
|
544
|
+
sage: D = GenDictWithBasering(R,R.gens_dict())
|
|
545
|
+
sage: R.gens_dict()['a']
|
|
546
|
+
Traceback (most recent call last):
|
|
547
|
+
...
|
|
548
|
+
KeyError: 'a'
|
|
549
|
+
sage: D['a']
|
|
550
|
+
a
|
|
551
|
+
"""
|
|
552
|
+
P = self._P = parent
|
|
553
|
+
if isinstance(start, list):
|
|
554
|
+
self._D = start
|
|
555
|
+
return
|
|
556
|
+
self._D = [start]
|
|
557
|
+
while hasattr(P, 'base_ring') and (P.base_ring() is not P):
|
|
558
|
+
P = P.base_ring()
|
|
559
|
+
D = P.gens_dict()
|
|
560
|
+
if isinstance(D, GenDictWithBasering):
|
|
561
|
+
self._D.extend(D._D)
|
|
562
|
+
break
|
|
563
|
+
else:
|
|
564
|
+
self._D.append(D)
|
|
565
|
+
|
|
566
|
+
def __next__(self):
|
|
567
|
+
"""
|
|
568
|
+
Return a dictionary that can be used to interpret strings in the base ring of ``self``.
|
|
569
|
+
|
|
570
|
+
EXAMPLES::
|
|
571
|
+
|
|
572
|
+
sage: R.<a,b> = InfinitePolynomialRing(QQ['t'])
|
|
573
|
+
sage: D = R.gens_dict()
|
|
574
|
+
sage: D
|
|
575
|
+
GenDict of Infinite polynomial ring in a, b over Univariate Polynomial Ring in t over Rational Field
|
|
576
|
+
sage: next(D)
|
|
577
|
+
GenDict of Univariate Polynomial Ring in t over Rational Field
|
|
578
|
+
sage: sage_eval('t^2', next(D))
|
|
579
|
+
t^2
|
|
580
|
+
"""
|
|
581
|
+
if len(self._D) <= 1:
|
|
582
|
+
raise ValueError("no next term for %s available" % self)
|
|
583
|
+
return GenDictWithBasering(self._P.base_ring(), self._D[1:])
|
|
584
|
+
|
|
585
|
+
next = __next__
|
|
586
|
+
|
|
587
|
+
def __repr__(self):
|
|
588
|
+
"""
|
|
589
|
+
TESTS::
|
|
590
|
+
|
|
591
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
592
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
593
|
+
sage: D
|
|
594
|
+
GenDict of Infinite polynomial ring in a, b over Integer Ring
|
|
595
|
+
"""
|
|
596
|
+
return "GenDict of " + repr(self._P)
|
|
597
|
+
|
|
598
|
+
def __getitem__(self, k):
|
|
599
|
+
"""
|
|
600
|
+
TESTS::
|
|
601
|
+
|
|
602
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
603
|
+
sage: D = R.gens_dict() # indirect doctest
|
|
604
|
+
sage: D
|
|
605
|
+
GenDict of Infinite polynomial ring in a, b over Integer Ring
|
|
606
|
+
sage: D['a_15']
|
|
607
|
+
a_15
|
|
608
|
+
sage: type(_)
|
|
609
|
+
<class 'sage.rings.polynomial.infinite_polynomial_element.InfinitePolynomial_dense'>
|
|
610
|
+
"""
|
|
611
|
+
for D in self._D:
|
|
612
|
+
try:
|
|
613
|
+
return D[k]
|
|
614
|
+
except KeyError:
|
|
615
|
+
pass
|
|
616
|
+
raise KeyError("{} is not a variable name of {} or its iterated base rings".format(k, self._P))
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
##############################################################
|
|
620
|
+
# The sparse implementation
|
|
621
|
+
|
|
622
|
+
class InfinitePolynomialRing_sparse(CommutativeRing):
|
|
623
|
+
r"""
|
|
624
|
+
Sparse implementation of Infinite Polynomial Rings.
|
|
625
|
+
|
|
626
|
+
An Infinite Polynomial Ring with generators `x_\ast, y_\ast,
|
|
627
|
+
...` over a field `F` is a free commutative `F`-algebra generated
|
|
628
|
+
by `x_0, x_1, x_2, ..., y_0, y_1, y_2, ..., ...` and is equipped
|
|
629
|
+
with a permutation action on the generators, namely `x_n^P =
|
|
630
|
+
x_{P(n)}, y_{n}^P=y_{P(n)}, ...` for any permutation `P` (note
|
|
631
|
+
that variables of index zero are invariant under such
|
|
632
|
+
permutation).
|
|
633
|
+
|
|
634
|
+
It is known that any permutation invariant ideal in an Infinite
|
|
635
|
+
Polynomial Ring is finitely generated modulo the permutation
|
|
636
|
+
action -- see :class:`~sage.rings.polynomial.symmetric_ideal.SymmetricIdeal`
|
|
637
|
+
for more details.
|
|
638
|
+
|
|
639
|
+
Usually, an instance of this class is created using
|
|
640
|
+
``InfinitePolynomialRing`` with the optional parameter
|
|
641
|
+
``implementation='sparse'``. This takes care of uniqueness of
|
|
642
|
+
parent structures. However, a direct construction is possible, in
|
|
643
|
+
principle::
|
|
644
|
+
|
|
645
|
+
sage: X.<x,y> = InfinitePolynomialRing(QQ, implementation='sparse')
|
|
646
|
+
sage: Y.<x,y> = InfinitePolynomialRing(QQ, implementation='sparse')
|
|
647
|
+
sage: X is Y
|
|
648
|
+
True
|
|
649
|
+
sage: from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing_sparse
|
|
650
|
+
sage: Z = InfinitePolynomialRing_sparse(QQ, ['x','y'], 'lex')
|
|
651
|
+
|
|
652
|
+
Nevertheless, since infinite polynomial rings are supposed to be unique
|
|
653
|
+
parent structures, they do not evaluate equal. ::
|
|
654
|
+
|
|
655
|
+
sage: Z == X
|
|
656
|
+
False
|
|
657
|
+
|
|
658
|
+
The last parameter ('lex' in the above example) can also be
|
|
659
|
+
'deglex' or 'degrevlex'; this would result in an Infinite
|
|
660
|
+
Polynomial Ring in degree lexicographic or degree reverse
|
|
661
|
+
lexicographic order.
|
|
662
|
+
|
|
663
|
+
See :mod:`~sage.rings.polynomial.infinite_polynomial_ring` for
|
|
664
|
+
more details.
|
|
665
|
+
"""
|
|
666
|
+
def __init__(self, R, names, order):
|
|
667
|
+
"""
|
|
668
|
+
INPUT:
|
|
669
|
+
|
|
670
|
+
- ``R`` -- base ring
|
|
671
|
+
- ``names`` -- list of generator names
|
|
672
|
+
- ``order`` -- string determining the monomial order of the infinite polynomial ring
|
|
673
|
+
|
|
674
|
+
EXAMPLES::
|
|
675
|
+
|
|
676
|
+
sage: X.<alpha,beta> = InfinitePolynomialRing(ZZ, implementation='sparse')
|
|
677
|
+
|
|
678
|
+
Infinite Polynomial Rings are unique parent structures::
|
|
679
|
+
|
|
680
|
+
sage: X is loads(dumps(X))
|
|
681
|
+
True
|
|
682
|
+
sage: p=alpha[10]*beta[2]^3+2*alpha[1]*beta[3]
|
|
683
|
+
sage: p
|
|
684
|
+
alpha_10*beta_2^3 + 2*alpha_1*beta_3
|
|
685
|
+
|
|
686
|
+
We define another Infinite Polynomial Ring with same generator
|
|
687
|
+
names but a different order. These rings are different, but
|
|
688
|
+
allow for coercion::
|
|
689
|
+
|
|
690
|
+
sage: Y.<alpha,beta> = InfinitePolynomialRing(QQ, order='deglex', implementation='sparse')
|
|
691
|
+
sage: Y is X
|
|
692
|
+
False
|
|
693
|
+
sage: q=beta[2]^3*alpha[10]+beta[3]*alpha[1]*2
|
|
694
|
+
sage: q
|
|
695
|
+
alpha_10*beta_2^3 + 2*alpha_1*beta_3
|
|
696
|
+
sage: p==q
|
|
697
|
+
True
|
|
698
|
+
sage: X.gen(1)[2]*Y.gen(0)[1]
|
|
699
|
+
alpha_1*beta_2
|
|
700
|
+
"""
|
|
701
|
+
if not names:
|
|
702
|
+
names = ['x']
|
|
703
|
+
for n in names:
|
|
704
|
+
if not (isinstance(n, str) and n.isalnum() and (not n[0].isdigit())):
|
|
705
|
+
raise ValueError("generator names must be alphanumeric strings not starting with a digit, but %s is not" % n)
|
|
706
|
+
if len(names) != len(set(names)):
|
|
707
|
+
raise ValueError("generator names must be pairwise different")
|
|
708
|
+
self._names = tuple(names)
|
|
709
|
+
if not isinstance(order, str):
|
|
710
|
+
raise TypeError("the monomial order must be given as a string")
|
|
711
|
+
if R not in Rings().Commutative():
|
|
712
|
+
raise TypeError("the given 'base ring' (= %s) must be a commutative ring" % R)
|
|
713
|
+
|
|
714
|
+
# now, the input is accepted
|
|
715
|
+
if hasattr(R, '_underlying_ring'):
|
|
716
|
+
self._underlying_ring = R._underlying_ring
|
|
717
|
+
else:
|
|
718
|
+
self._underlying_ring = R.base_ring()
|
|
719
|
+
|
|
720
|
+
# some tools to analyse polynomial string representations.
|
|
721
|
+
self._identify_variable = lambda x, y: (-self._names.index(x), int(y))
|
|
722
|
+
self._find_maxshift = re.compile('_([0-9]+)') # findall yields stringrep of the shifts
|
|
723
|
+
self._find_variables = re.compile('[a-zA-Z0-9]+_[0-9]+')
|
|
724
|
+
self._find_varpowers = re.compile(r'([a-zA-Z0-9]+)_([0-9]+)\^?([0-9]*)') # findall yields triple "generator_name", "index", "exponent"
|
|
725
|
+
|
|
726
|
+
# Create some small underlying polynomial ring.
|
|
727
|
+
# It is used to ensure that the parent of the underlying
|
|
728
|
+
# polynomial of an element of self is actually a *multi*variate
|
|
729
|
+
# polynomial ring.
|
|
730
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
731
|
+
if len(names) == 1:
|
|
732
|
+
VarList = [names[0] + '_0', names[0] + '_1']
|
|
733
|
+
else:
|
|
734
|
+
VarList = [X + '_0' for X in names]
|
|
735
|
+
VarList.sort(key=self.varname_key, reverse=True)
|
|
736
|
+
self._minP = PolynomialRing(R, len(VarList), VarList)
|
|
737
|
+
|
|
738
|
+
# some basic data
|
|
739
|
+
self._order = order
|
|
740
|
+
self._name_dict = {name: i for i, name in enumerate(names)}
|
|
741
|
+
from sage.categories.commutative_algebras import CommutativeAlgebras
|
|
742
|
+
CommutativeRing.__init__(self, R, category=CommutativeAlgebras(R))
|
|
743
|
+
|
|
744
|
+
self._populate_coercion_lists_()
|
|
745
|
+
|
|
746
|
+
def __repr__(self):
|
|
747
|
+
"""
|
|
748
|
+
EXAMPLES::
|
|
749
|
+
|
|
750
|
+
sage: InfinitePolynomialRing(QQ) # indirect doctest
|
|
751
|
+
Infinite polynomial ring in x over Rational Field
|
|
752
|
+
|
|
753
|
+
sage: X.<alpha,beta> = InfinitePolynomialRing(ZZ, order='deglex'); X
|
|
754
|
+
Infinite polynomial ring in alpha, beta over Integer Ring
|
|
755
|
+
"""
|
|
756
|
+
return "Infinite polynomial ring in {} over {}".format(", ".join(self._names), self._base)
|
|
757
|
+
|
|
758
|
+
def _latex_(self):
|
|
759
|
+
r"""
|
|
760
|
+
EXAMPLES::
|
|
761
|
+
|
|
762
|
+
sage: from sage.misc.latex import latex
|
|
763
|
+
sage: X.<x,y> = InfinitePolynomialRing(QQ)
|
|
764
|
+
sage: latex(X) # indirect doctest
|
|
765
|
+
\Bold{Q}[x_{\ast}, y_{\ast}]
|
|
766
|
+
"""
|
|
767
|
+
from sage.misc.latex import latex
|
|
768
|
+
vars = ', '.join(latex(X) for X in self.gens())
|
|
769
|
+
return f"{latex(self.base_ring())}[{vars}]"
|
|
770
|
+
|
|
771
|
+
@cached_method
|
|
772
|
+
def _an_element_(self):
|
|
773
|
+
"""
|
|
774
|
+
Return an element of this ring.
|
|
775
|
+
|
|
776
|
+
EXAMPLES::
|
|
777
|
+
|
|
778
|
+
sage: R.<x> = InfinitePolynomialRing(QQ)
|
|
779
|
+
sage: R.an_element() # indirect doctest
|
|
780
|
+
x_1
|
|
781
|
+
"""
|
|
782
|
+
x = self.gen(0)
|
|
783
|
+
return x[1]
|
|
784
|
+
|
|
785
|
+
@cached_method
|
|
786
|
+
def one(self):
|
|
787
|
+
"""
|
|
788
|
+
TESTS::
|
|
789
|
+
|
|
790
|
+
sage: X.<x,y> = InfinitePolynomialRing(QQ)
|
|
791
|
+
sage: X.one()
|
|
792
|
+
1
|
|
793
|
+
"""
|
|
794
|
+
from sage.rings.polynomial.infinite_polynomial_element import InfinitePolynomial
|
|
795
|
+
return InfinitePolynomial(self, self._base(1))
|
|
796
|
+
|
|
797
|
+
#####################
|
|
798
|
+
# coercion
|
|
799
|
+
|
|
800
|
+
def construction(self):
|
|
801
|
+
"""
|
|
802
|
+
Return the construction of ``self``.
|
|
803
|
+
|
|
804
|
+
OUTPUT:
|
|
805
|
+
|
|
806
|
+
A pair ``F,R``, where ``F`` is a construction functor and ``R`` is a ring,
|
|
807
|
+
so that ``F(R) is self``.
|
|
808
|
+
|
|
809
|
+
EXAMPLES::
|
|
810
|
+
|
|
811
|
+
sage: R.<x,y> = InfinitePolynomialRing(GF(5))
|
|
812
|
+
sage: R.construction()
|
|
813
|
+
[InfPoly{[x,y], "lex", "dense"}, Finite Field of size 5]
|
|
814
|
+
"""
|
|
815
|
+
return [InfinitePolynomialFunctor(self._names, self._order, 'sparse'), self._base]
|
|
816
|
+
|
|
817
|
+
def _coerce_map_from_(self, S):
|
|
818
|
+
r"""
|
|
819
|
+
Coerce things into ``self``.
|
|
820
|
+
|
|
821
|
+
NOTE:
|
|
822
|
+
|
|
823
|
+
Any coercion will preserve variable names.
|
|
824
|
+
|
|
825
|
+
EXAMPLES:
|
|
826
|
+
|
|
827
|
+
Here, we check to see that elements of a *finitely* generated
|
|
828
|
+
polynomial ring with appropriate variable names coerce
|
|
829
|
+
correctly into the Infinite Polynomial Ring::
|
|
830
|
+
|
|
831
|
+
sage: X.<x> = InfinitePolynomialRing(QQ)
|
|
832
|
+
sage: px0 = PolynomialRing(QQ,'x_0').gen(0)
|
|
833
|
+
sage: px0 + x[0] # indirect doctest
|
|
834
|
+
2*x_0
|
|
835
|
+
sage: px0==x[0]
|
|
836
|
+
True
|
|
837
|
+
|
|
838
|
+
It is possible to construct an Infinite Polynomial Ring whose
|
|
839
|
+
base ring is another Infinite Polynomial Ring::
|
|
840
|
+
|
|
841
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
842
|
+
sage: X.<x> = InfinitePolynomialRing(R)
|
|
843
|
+
sage: a[2]*x[3]+x[1]*a[4]^2
|
|
844
|
+
a_4^2*x_1 + a_2*x_3
|
|
845
|
+
"""
|
|
846
|
+
# Use Construction Functors!
|
|
847
|
+
from sage.categories.pushout import pushout
|
|
848
|
+
try:
|
|
849
|
+
# the following line should not test "pushout is self", but
|
|
850
|
+
# only "pushout == self", since we also allow coercion from
|
|
851
|
+
# dense to sparse implementation!
|
|
852
|
+
P = pushout(self, S)
|
|
853
|
+
# We do not care about the orders. But base ring and generators
|
|
854
|
+
# of the pushout should remain the same as in self.
|
|
855
|
+
return P._names == self._names and P._base == self._base
|
|
856
|
+
except (TypeError, ValueError):
|
|
857
|
+
return False
|
|
858
|
+
|
|
859
|
+
def _element_constructor_(self, x):
|
|
860
|
+
"""
|
|
861
|
+
Return an element of ``self``.
|
|
862
|
+
|
|
863
|
+
INPUT:
|
|
864
|
+
|
|
865
|
+
- ``x`` -- any object that can be interpreted in ``self``
|
|
866
|
+
|
|
867
|
+
TESTS::
|
|
868
|
+
|
|
869
|
+
sage: X = InfinitePolynomialRing(QQ)
|
|
870
|
+
sage: a = X(2); a # indirect doctest
|
|
871
|
+
2
|
|
872
|
+
sage: a.parent()
|
|
873
|
+
Infinite polynomial ring in x over Rational Field
|
|
874
|
+
|
|
875
|
+
sage: R = PolynomialRing(ZZ, ['x_3'])
|
|
876
|
+
sage: b = X(R.gen()); b
|
|
877
|
+
x_3
|
|
878
|
+
sage: b.parent()
|
|
879
|
+
Infinite polynomial ring in x over Rational Field
|
|
880
|
+
sage: X('(x_1^2+2/3*x_4)*(x_2+x_5)')
|
|
881
|
+
2/3*x_5*x_4 + x_5*x_1^2 + 2/3*x_4*x_2 + x_2*x_1^2
|
|
882
|
+
|
|
883
|
+
sage: Y = InfinitePolynomialRing(ZZ)
|
|
884
|
+
sage: Y('1/3')
|
|
885
|
+
Traceback (most recent call last):
|
|
886
|
+
...
|
|
887
|
+
ValueError: cannot convert 1/3 into an element of Infinite polynomial ring in x over Integer Ring
|
|
888
|
+
|
|
889
|
+
.. WARNING::
|
|
890
|
+
|
|
891
|
+
The :issue:`37756` is not yet fixed::
|
|
892
|
+
|
|
893
|
+
sage: L.<x, y> = QQ[]
|
|
894
|
+
sage: R.<a> = InfinitePolynomialRing(QQ)
|
|
895
|
+
sage: M = InfinitePolynomialRing(L, names=["a"])
|
|
896
|
+
sage: c = a[0]
|
|
897
|
+
sage: M(c) # known bug
|
|
898
|
+
a_0
|
|
899
|
+
"""
|
|
900
|
+
from sage.rings.polynomial.infinite_polynomial_element import InfinitePolynomial
|
|
901
|
+
# In many cases, the easiest solution is to "simply" evaluate
|
|
902
|
+
# the string representation.
|
|
903
|
+
from sage.misc.sage_eval import sage_eval
|
|
904
|
+
if isinstance(x, str):
|
|
905
|
+
try:
|
|
906
|
+
x = sage_eval(x, self.gens_dict())
|
|
907
|
+
except (TypeError, ValueError, SyntaxError):
|
|
908
|
+
raise ValueError(f"cannot convert {x} into an element of {self}")
|
|
909
|
+
P = parent(x)
|
|
910
|
+
if P is self:
|
|
911
|
+
return x
|
|
912
|
+
elif self._base.has_coerce_map_from(P):
|
|
913
|
+
return InfinitePolynomial(self, self._base(x))
|
|
914
|
+
else:
|
|
915
|
+
raise ValueError(f"cannot convert {x} into an element of {self}")
|
|
916
|
+
|
|
917
|
+
if isinstance(parent(x), InfinitePolynomialRing_sparse):
|
|
918
|
+
# the easy case - parent == self - is already past
|
|
919
|
+
if x.parent() is self._base: # another easy case
|
|
920
|
+
return InfinitePolynomial(self, x)
|
|
921
|
+
xmaxind = x.max_index() # save for later
|
|
922
|
+
x = x._p
|
|
923
|
+
else:
|
|
924
|
+
xmaxind = -1
|
|
925
|
+
|
|
926
|
+
# Now, we focus on the underlying classical polynomial ring.
|
|
927
|
+
# First, try interpretation in the base ring.
|
|
928
|
+
try:
|
|
929
|
+
from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict
|
|
930
|
+
if isinstance(self._base, MPolynomialRing_polydict):
|
|
931
|
+
x = sage_eval(repr(), next(self.gens_dict()))
|
|
932
|
+
else:
|
|
933
|
+
x = self._base(x)
|
|
934
|
+
# remark: Conversion to self._P (if applicable)
|
|
935
|
+
# is done in InfinitePolynomial()
|
|
936
|
+
return InfinitePolynomial(self, x)
|
|
937
|
+
except (TypeError, ValueError):
|
|
938
|
+
pass
|
|
939
|
+
|
|
940
|
+
# By now, we can assume that x has a parent, because
|
|
941
|
+
# types like int have already been done in the previous step;
|
|
942
|
+
# and also it is not an InfinitePolynomial.
|
|
943
|
+
# If it is not a polynomial (duck typing: we need
|
|
944
|
+
# the variables attribute), we fall back to using strings
|
|
945
|
+
if not hasattr(x, 'variables'):
|
|
946
|
+
try:
|
|
947
|
+
return sage_eval(repr(x), self.gens_dict())
|
|
948
|
+
except (TypeError, ValueError, SyntaxError, NameError):
|
|
949
|
+
raise ValueError(f"cannot convert {x} into an element of {self}")
|
|
950
|
+
|
|
951
|
+
# direct conversion will only be used if the underlying polynomials are libsingular.
|
|
952
|
+
from sage.rings.polynomial.multi_polynomial import MPolynomial_libsingular
|
|
953
|
+
# try interpretation in self._P, if we have a dense implementation
|
|
954
|
+
if hasattr(self, '_P'):
|
|
955
|
+
if x.parent() is self._P:
|
|
956
|
+
return InfinitePolynomial(self, x)
|
|
957
|
+
# It's a shame to use sage_eval. However, it's even more of a shame
|
|
958
|
+
# that MPolynomialRing_polydict does not work in complicated settings.
|
|
959
|
+
# So, if self._P is libsingular (and this will be the case in many
|
|
960
|
+
# applications!), we do it "nicely". Otherwise, we have to use sage_eval.
|
|
961
|
+
if isinstance(x, MPolynomial_libsingular):
|
|
962
|
+
from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular
|
|
963
|
+
if isinstance(self._P, MPolynomialRing_libsingular):
|
|
964
|
+
if xmaxind == -1: # Otherwise, x has been an InfinitePolynomial
|
|
965
|
+
# We infer the correct variable shift.
|
|
966
|
+
# Note: Since we are in the "libsingular" case, there are
|
|
967
|
+
# no further "variables" hidden in the base ring of x.parent()
|
|
968
|
+
try:
|
|
969
|
+
VarList = [repr(v) for v in x.variables()]
|
|
970
|
+
# since interpretation in base ring
|
|
971
|
+
# was impossible, it *must* have
|
|
972
|
+
# variables
|
|
973
|
+
# This tests admissibility on the fly:
|
|
974
|
+
VarList.sort(key=self.varname_key, reverse=True)
|
|
975
|
+
except ValueError:
|
|
976
|
+
raise ValueError("cannot convert {} into an element of {} - variables are not admissible".format(x, self))
|
|
977
|
+
xmaxind = max([int(v.split('_')[1]) for v in VarList])
|
|
978
|
+
try:
|
|
979
|
+
# Apparently, in libsingular, the polynomial conversion is not done by
|
|
980
|
+
# name but by position, if the number of variables in the parents coincide.
|
|
981
|
+
# So, we shift self._P to achieve xmaxind, and if the number of variables is
|
|
982
|
+
# the same then we shift further. We then *must* be
|
|
983
|
+
# able to convert x into self._P, or conversion to self is
|
|
984
|
+
# impossible (and will be done in InfinitePolynomial(...)
|
|
985
|
+
if self._max < xmaxind:
|
|
986
|
+
self.gen()[xmaxind]
|
|
987
|
+
if self._P.ngens() == x.parent().ngens():
|
|
988
|
+
self.gen()[self._max + 1]
|
|
989
|
+
# conversion to self._P will be done in InfinitePolynomial.__init__
|
|
990
|
+
return InfinitePolynomial(self, x)
|
|
991
|
+
except (ValueError, TypeError, NameError):
|
|
992
|
+
raise ValueError("cannot convert {} (from {}, but variables {}) into an element of {} - no conversion into underlying polynomial ring {}".format(x, x.parent(), x.variables(), self, self._P))
|
|
993
|
+
# By now, x or self._P are not libsingular. Since MPolynomialRing_polydict
|
|
994
|
+
# is too buggy, we use string evaluation
|
|
995
|
+
try:
|
|
996
|
+
return sage_eval(repr(x), self.gens_dict())
|
|
997
|
+
except (ValueError, TypeError, NameError):
|
|
998
|
+
raise ValueError("cannot convert {} into an element of {} - no conversion into underlying polynomial ring".format(x, self))
|
|
999
|
+
|
|
1000
|
+
# By now, we are in the sparse case.
|
|
1001
|
+
try:
|
|
1002
|
+
VarList = [repr(v) for v in x.variables()]
|
|
1003
|
+
# since interpretation in base ring
|
|
1004
|
+
# was impossible, it *must* have
|
|
1005
|
+
# variables
|
|
1006
|
+
# This tests admissibility on the fly:
|
|
1007
|
+
VarList.sort(key=self.varname_key, reverse=True)
|
|
1008
|
+
except ValueError:
|
|
1009
|
+
raise ValueError("cannot convert {} into an element of {} - variables are not admissible".format(x, self))
|
|
1010
|
+
|
|
1011
|
+
if len(VarList) == 1:
|
|
1012
|
+
# univariate polynomial rings are crab. So, make up another variable.
|
|
1013
|
+
if VarList[0] == self._names[0] + '_0':
|
|
1014
|
+
VarList.append(self._names[0] + '_1')
|
|
1015
|
+
else:
|
|
1016
|
+
VarList.append(self._names[0] + '_0')
|
|
1017
|
+
# We ensure that polynomial conversion is done by names;
|
|
1018
|
+
# the problem is that it is done by names if the number of variables coincides.
|
|
1019
|
+
if len(VarList) == x.parent().ngens():
|
|
1020
|
+
BigList = x.parent().variable_names()
|
|
1021
|
+
ind = 2
|
|
1022
|
+
while self._names[0] + '_' + str(ind) in BigList:
|
|
1023
|
+
ind += 1
|
|
1024
|
+
VarList.append(self._names[0] + '_' + str(ind))
|
|
1025
|
+
try:
|
|
1026
|
+
VarList.sort(key=self.varname_key, reverse=True)
|
|
1027
|
+
except ValueError:
|
|
1028
|
+
raise ValueError("cannot convert {} into an element of {}; the variables are not admissible".format(x, self))
|
|
1029
|
+
|
|
1030
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
1031
|
+
R = PolynomialRing(self._base, VarList, order=self._order)
|
|
1032
|
+
if isinstance(x, MPolynomial_libsingular): # everything else is so buggy that it's even not worth to try.
|
|
1033
|
+
from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular
|
|
1034
|
+
if isinstance(R, MPolynomialRing_libsingular):
|
|
1035
|
+
try:
|
|
1036
|
+
# Problem: If there is only a partial overlap in the variables
|
|
1037
|
+
# of x.parent() and R, then R(x) raises an error (which, I think,
|
|
1038
|
+
# is a bug, since we talk here about conversion, not coercion).
|
|
1039
|
+
# Hence, for being on the safe side, we coerce into a pushout ring:
|
|
1040
|
+
x = R(1) * x
|
|
1041
|
+
return InfinitePolynomial(self, x)
|
|
1042
|
+
except (TypeError, ValueError):
|
|
1043
|
+
# OK, last resort, to be on the safe side
|
|
1044
|
+
try:
|
|
1045
|
+
return sage_eval(repr(x), self.gens_dict())
|
|
1046
|
+
except (ValueError, TypeError, NameError):
|
|
1047
|
+
raise ValueError("cannot convert {} into an element of {}; conversion of the underlying polynomial failed".format(x, self))
|
|
1048
|
+
try:
|
|
1049
|
+
return sage_eval(repr(x), self.gens_dict())
|
|
1050
|
+
except (ValueError, TypeError, NameError):
|
|
1051
|
+
raise ValueError(f"cannot convert {x} into an element of {self}")
|
|
1052
|
+
|
|
1053
|
+
def tensor_with_ring(self, R):
|
|
1054
|
+
"""
|
|
1055
|
+
Return the tensor product of ``self`` with another ring.
|
|
1056
|
+
|
|
1057
|
+
INPUT:
|
|
1058
|
+
|
|
1059
|
+
- ``R`` -- a ring
|
|
1060
|
+
|
|
1061
|
+
OUTPUT:
|
|
1062
|
+
|
|
1063
|
+
An infinite polynomial ring that, mathematically, can be seen as the
|
|
1064
|
+
tensor product of ``self`` with ``R``.
|
|
1065
|
+
|
|
1066
|
+
NOTE:
|
|
1067
|
+
|
|
1068
|
+
It is required that the underlying ring of ``self`` coerces into ``R``.
|
|
1069
|
+
Hence, the tensor product is in fact merely an extension of the base
|
|
1070
|
+
ring.
|
|
1071
|
+
|
|
1072
|
+
EXAMPLES::
|
|
1073
|
+
|
|
1074
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
1075
|
+
sage: R.tensor_with_ring(QQ)
|
|
1076
|
+
Infinite polynomial ring in a, b over Rational Field
|
|
1077
|
+
sage: R
|
|
1078
|
+
Infinite polynomial ring in a, b over Integer Ring
|
|
1079
|
+
|
|
1080
|
+
The following tests against a bug that was fixed at :issue:`10468`::
|
|
1081
|
+
|
|
1082
|
+
sage: R.<x,y> = InfinitePolynomialRing(QQ)
|
|
1083
|
+
sage: R.tensor_with_ring(QQ) is R
|
|
1084
|
+
True
|
|
1085
|
+
"""
|
|
1086
|
+
if not R.has_coerce_map_from(self._underlying_ring):
|
|
1087
|
+
raise TypeError("we cannot tensor with " + repr(R))
|
|
1088
|
+
B = self.base_ring()
|
|
1089
|
+
if hasattr(B, 'tensor_with_ring'):
|
|
1090
|
+
return InfinitePolynomialRing(B.tensor_with_ring(R), self._names, self._order, implementation='sparse')
|
|
1091
|
+
if hasattr(B, 'change_ring'): # e.g., polynomial rings
|
|
1092
|
+
return InfinitePolynomialRing(B.change_ring(R), self._names, self._order, implementation='sparse')
|
|
1093
|
+
# try to find the correct base ring in other ways:
|
|
1094
|
+
try:
|
|
1095
|
+
o = B.one() * R.one()
|
|
1096
|
+
except (TypeError, ValueError):
|
|
1097
|
+
raise TypeError("we cannot tensor with " + repr(R))
|
|
1098
|
+
return InfinitePolynomialRing(o.parent(), self._names, self._order, implementation='sparse')
|
|
1099
|
+
|
|
1100
|
+
# Basic Ring Properties
|
|
1101
|
+
# -- some stuff that is useful for quotient rings etc.
|
|
1102
|
+
def is_noetherian(self):
|
|
1103
|
+
"""
|
|
1104
|
+
Return ``False``, since polynomial rings in infinitely many
|
|
1105
|
+
variables are never Noetherian rings.
|
|
1106
|
+
|
|
1107
|
+
Since Infinite Polynomial Rings must have at least one
|
|
1108
|
+
generator, they have infinitely many variables and are thus
|
|
1109
|
+
not Noetherian, as a ring.
|
|
1110
|
+
|
|
1111
|
+
.. NOTE::
|
|
1112
|
+
|
|
1113
|
+
Infinite Polynomial Rings over a field `F` are Noetherian as
|
|
1114
|
+
`F(G)` modules, where `G` is the symmetric group of the
|
|
1115
|
+
natural numbers. But this is not what the method
|
|
1116
|
+
``is_noetherian()`` is answering.
|
|
1117
|
+
|
|
1118
|
+
TESTS::
|
|
1119
|
+
|
|
1120
|
+
sage: R = InfinitePolynomialRing(GF(2))
|
|
1121
|
+
sage: R
|
|
1122
|
+
Infinite polynomial ring in x over Finite Field of size 2
|
|
1123
|
+
sage: R.is_noetherian()
|
|
1124
|
+
False
|
|
1125
|
+
|
|
1126
|
+
sage: R.<x> = InfinitePolynomialRing(QQ)
|
|
1127
|
+
sage: R.is_noetherian()
|
|
1128
|
+
False
|
|
1129
|
+
"""
|
|
1130
|
+
return False
|
|
1131
|
+
|
|
1132
|
+
def is_field(self, *args, **kwds):
|
|
1133
|
+
"""
|
|
1134
|
+
Return ``False`` since Infinite Polynomial Rings are never fields.
|
|
1135
|
+
|
|
1136
|
+
Since Infinite Polynomial Rings must have at least one generator,
|
|
1137
|
+
they have infinitely many variables and thus never are fields.
|
|
1138
|
+
|
|
1139
|
+
EXAMPLES::
|
|
1140
|
+
|
|
1141
|
+
sage: R.<x, y> = InfinitePolynomialRing(QQ)
|
|
1142
|
+
sage: R.is_field()
|
|
1143
|
+
False
|
|
1144
|
+
|
|
1145
|
+
TESTS::
|
|
1146
|
+
|
|
1147
|
+
sage: R = InfinitePolynomialRing(GF(2))
|
|
1148
|
+
sage: R
|
|
1149
|
+
Infinite polynomial ring in x over Finite Field of size 2
|
|
1150
|
+
sage: R.is_field()
|
|
1151
|
+
False
|
|
1152
|
+
|
|
1153
|
+
:issue:`9443`::
|
|
1154
|
+
|
|
1155
|
+
sage: W = PowerSeriesRing(InfinitePolynomialRing(QQ,'a'),'x')
|
|
1156
|
+
sage: W.is_field()
|
|
1157
|
+
False
|
|
1158
|
+
"""
|
|
1159
|
+
return False
|
|
1160
|
+
|
|
1161
|
+
def varname_key(self, x):
|
|
1162
|
+
"""
|
|
1163
|
+
Key for comparison of variable names.
|
|
1164
|
+
|
|
1165
|
+
INPUT:
|
|
1166
|
+
|
|
1167
|
+
- ``x`` -- string of the form ``a+'_'+str(n)``, where a is the
|
|
1168
|
+
name of a generator, and n is an integer
|
|
1169
|
+
|
|
1170
|
+
OUTPUT: a key used to sort the variables
|
|
1171
|
+
|
|
1172
|
+
THEORY:
|
|
1173
|
+
|
|
1174
|
+
The order is defined as follows:
|
|
1175
|
+
|
|
1176
|
+
x<y `\\iff` the string ``x.split('_')[0]`` is later in the list of
|
|
1177
|
+
generator names of ``self`` than ``y.split('_')[0]``, or
|
|
1178
|
+
(``x.split('_')[0]==y.split('_')[0]`` and
|
|
1179
|
+
``int(x.split('_')[1])<int(y.split('_')[1])``)
|
|
1180
|
+
|
|
1181
|
+
EXAMPLES::
|
|
1182
|
+
|
|
1183
|
+
sage: X.<alpha,beta> = InfinitePolynomialRing(ZZ)
|
|
1184
|
+
sage: X.varname_key('alpha_1')
|
|
1185
|
+
(0, 1)
|
|
1186
|
+
sage: X.varname_key('beta_10')
|
|
1187
|
+
(-1, 10)
|
|
1188
|
+
sage: X.varname_key('beta_1')
|
|
1189
|
+
(-1, 1)
|
|
1190
|
+
sage: X.varname_key('alpha_10')
|
|
1191
|
+
(0, 10)
|
|
1192
|
+
sage: X.varname_key('alpha_1')
|
|
1193
|
+
(0, 1)
|
|
1194
|
+
sage: X.varname_key('alpha_10')
|
|
1195
|
+
(0, 10)
|
|
1196
|
+
"""
|
|
1197
|
+
try:
|
|
1198
|
+
return self._identify_variable(*x.split('_', 1))
|
|
1199
|
+
except (KeyError, ValueError, TypeError):
|
|
1200
|
+
raise ValueError("%s is not a valid variable name" % x)
|
|
1201
|
+
|
|
1202
|
+
def ngens(self):
|
|
1203
|
+
"""
|
|
1204
|
+
Return the number of generators for this ring.
|
|
1205
|
+
|
|
1206
|
+
Since there
|
|
1207
|
+
are countably infinitely many variables in this polynomial
|
|
1208
|
+
ring, by 'generators' we mean the number of infinite families
|
|
1209
|
+
of variables. See :mod:`~sage.rings.polynomial.infinite_polynomial_ring`
|
|
1210
|
+
for more details.
|
|
1211
|
+
|
|
1212
|
+
EXAMPLES::
|
|
1213
|
+
|
|
1214
|
+
sage: X.<x> = InfinitePolynomialRing(ZZ)
|
|
1215
|
+
sage: X.ngens()
|
|
1216
|
+
1
|
|
1217
|
+
|
|
1218
|
+
sage: X.<x1,x2> = InfinitePolynomialRing(QQ)
|
|
1219
|
+
sage: X.ngens()
|
|
1220
|
+
2
|
|
1221
|
+
"""
|
|
1222
|
+
return len(self._names)
|
|
1223
|
+
|
|
1224
|
+
@cached_method
|
|
1225
|
+
def gen(self, i=None):
|
|
1226
|
+
"""
|
|
1227
|
+
Return the `i`-th 'generator' (see the description in :meth:`.ngens`)
|
|
1228
|
+
of this infinite polynomial ring.
|
|
1229
|
+
|
|
1230
|
+
EXAMPLES::
|
|
1231
|
+
|
|
1232
|
+
sage: X = InfinitePolynomialRing(QQ)
|
|
1233
|
+
sage: x = X.gen()
|
|
1234
|
+
sage: x[1]
|
|
1235
|
+
x_1
|
|
1236
|
+
sage: X.gen() is X.gen(0)
|
|
1237
|
+
True
|
|
1238
|
+
sage: XX = InfinitePolynomialRing(GF(5))
|
|
1239
|
+
sage: XX.gen(0) is XX.gen()
|
|
1240
|
+
True
|
|
1241
|
+
"""
|
|
1242
|
+
if i is not None and i > len(self._names):
|
|
1243
|
+
raise ValueError
|
|
1244
|
+
j = i if i is not None else 0
|
|
1245
|
+
res = InfinitePolynomialGen(self, self._names[j])
|
|
1246
|
+
if i is None:
|
|
1247
|
+
key = ((0,), ())
|
|
1248
|
+
if key in self._cache__gen:
|
|
1249
|
+
return self._cache__gen[key]
|
|
1250
|
+
else:
|
|
1251
|
+
self._cache__gen[key] = res
|
|
1252
|
+
return res
|
|
1253
|
+
|
|
1254
|
+
def _first_ngens(self, n):
|
|
1255
|
+
"""
|
|
1256
|
+
Used by the preparser for R.<x> = ...
|
|
1257
|
+
|
|
1258
|
+
EXAMPLES::
|
|
1259
|
+
|
|
1260
|
+
sage: InfinitePolynomialRing(ZZ, 'a')._first_ngens(1)
|
|
1261
|
+
(a_*,)
|
|
1262
|
+
"""
|
|
1263
|
+
# It may be that we merge variables. If this is the case,
|
|
1264
|
+
# the new variables (as used by R.<x> = ...) come *last*,
|
|
1265
|
+
# but in order.
|
|
1266
|
+
return self.gens()[-n:]
|
|
1267
|
+
|
|
1268
|
+
@cached_method
|
|
1269
|
+
def gens_dict(self) -> GenDictWithBasering:
|
|
1270
|
+
"""
|
|
1271
|
+
Return a dictionary-like object containing the infinitely many
|
|
1272
|
+
``{var_name:variable}`` pairs.
|
|
1273
|
+
|
|
1274
|
+
EXAMPLES::
|
|
1275
|
+
|
|
1276
|
+
sage: R = InfinitePolynomialRing(ZZ, 'a')
|
|
1277
|
+
sage: D = R.gens_dict()
|
|
1278
|
+
sage: D
|
|
1279
|
+
GenDict of Infinite polynomial ring in a over Integer Ring
|
|
1280
|
+
sage: D['a_5']
|
|
1281
|
+
a_5
|
|
1282
|
+
"""
|
|
1283
|
+
return GenDictWithBasering(self, InfiniteGenDict(self.gens()))
|
|
1284
|
+
|
|
1285
|
+
def _ideal_class_(self, n=0):
|
|
1286
|
+
"""
|
|
1287
|
+
Return :class:`SymmetricIdeals` (see there for further details).
|
|
1288
|
+
|
|
1289
|
+
TESTS::
|
|
1290
|
+
|
|
1291
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ)
|
|
1292
|
+
sage: R._ideal_class_()
|
|
1293
|
+
<class 'sage.rings.polynomial.symmetric_ideal.SymmetricIdeal'>
|
|
1294
|
+
"""
|
|
1295
|
+
import sage.rings.polynomial.symmetric_ideal
|
|
1296
|
+
return sage.rings.polynomial.symmetric_ideal.SymmetricIdeal
|
|
1297
|
+
|
|
1298
|
+
def characteristic(self):
|
|
1299
|
+
"""
|
|
1300
|
+
Return the characteristic of the base field.
|
|
1301
|
+
|
|
1302
|
+
EXAMPLES::
|
|
1303
|
+
|
|
1304
|
+
sage: X.<x,y> = InfinitePolynomialRing(GF(25,'a')) # needs sage.rings.finite_rings
|
|
1305
|
+
sage: X # needs sage.rings.finite_rings
|
|
1306
|
+
Infinite polynomial ring in x, y over Finite Field in a of size 5^2
|
|
1307
|
+
sage: X.characteristic() # needs sage.rings.finite_rings
|
|
1308
|
+
5
|
|
1309
|
+
"""
|
|
1310
|
+
return self._base.characteristic()
|
|
1311
|
+
|
|
1312
|
+
def is_integral_domain(self, *args, **kwds):
|
|
1313
|
+
"""
|
|
1314
|
+
An infinite polynomial ring is an integral domain if and only if
|
|
1315
|
+
the base ring is. Arguments are passed to is_integral_domain
|
|
1316
|
+
method of base ring.
|
|
1317
|
+
|
|
1318
|
+
EXAMPLES::
|
|
1319
|
+
|
|
1320
|
+
sage: R.<x, y> = InfinitePolynomialRing(QQ)
|
|
1321
|
+
sage: R.is_integral_domain()
|
|
1322
|
+
True
|
|
1323
|
+
|
|
1324
|
+
TESTS:
|
|
1325
|
+
|
|
1326
|
+
:issue:`9443`::
|
|
1327
|
+
|
|
1328
|
+
sage: W = PolynomialRing(InfinitePolynomialRing(QQ,'a'),2,'x,y')
|
|
1329
|
+
sage: W.is_integral_domain()
|
|
1330
|
+
True
|
|
1331
|
+
"""
|
|
1332
|
+
return self._base.is_integral_domain(*args, **kwds)
|
|
1333
|
+
|
|
1334
|
+
def krull_dimension(self, *args, **kwds):
|
|
1335
|
+
"""
|
|
1336
|
+
Return ``Infinity``, since polynomial rings in infinitely many
|
|
1337
|
+
variables have infinite Krull dimension.
|
|
1338
|
+
|
|
1339
|
+
EXAMPLES::
|
|
1340
|
+
|
|
1341
|
+
sage: R.<x, y> = InfinitePolynomialRing(QQ)
|
|
1342
|
+
sage: R.krull_dimension()
|
|
1343
|
+
+Infinity
|
|
1344
|
+
"""
|
|
1345
|
+
from sage.rings.infinity import Infinity
|
|
1346
|
+
return Infinity
|
|
1347
|
+
|
|
1348
|
+
def order(self):
|
|
1349
|
+
"""
|
|
1350
|
+
Return ``Infinity``, since polynomial rings have infinitely
|
|
1351
|
+
many elements.
|
|
1352
|
+
|
|
1353
|
+
EXAMPLES::
|
|
1354
|
+
|
|
1355
|
+
sage: R.<x> = InfinitePolynomialRing(GF(2))
|
|
1356
|
+
sage: R.order()
|
|
1357
|
+
+Infinity
|
|
1358
|
+
"""
|
|
1359
|
+
from sage.rings.infinity import Infinity
|
|
1360
|
+
return Infinity
|
|
1361
|
+
|
|
1362
|
+
# Other bases
|
|
1363
|
+
def key_basis(self):
|
|
1364
|
+
r"""
|
|
1365
|
+
Return the basis of ``self`` given by key polynomials.
|
|
1366
|
+
|
|
1367
|
+
EXAMPLES::
|
|
1368
|
+
|
|
1369
|
+
sage: R.<x> = InfinitePolynomialRing(GF(2))
|
|
1370
|
+
sage: R.key_basis() # needs sage.combinat sage.modules
|
|
1371
|
+
Key polynomial basis over Finite Field of size 2
|
|
1372
|
+
"""
|
|
1373
|
+
from sage.combinat.key_polynomial import KeyPolynomialBasis
|
|
1374
|
+
return KeyPolynomialBasis(self)
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
class InfinitePolynomialGen(SageObject):
|
|
1378
|
+
"""
|
|
1379
|
+
This class provides the object which is responsible for returning
|
|
1380
|
+
variables in an infinite polynomial ring (implemented in
|
|
1381
|
+
:meth:`.__getitem__`).
|
|
1382
|
+
|
|
1383
|
+
EXAMPLES::
|
|
1384
|
+
|
|
1385
|
+
sage: # needs sage.rings.real_mpfr
|
|
1386
|
+
sage: X.<x1,x2> = InfinitePolynomialRing(RR)
|
|
1387
|
+
sage: x1
|
|
1388
|
+
x1_*
|
|
1389
|
+
sage: x1[5]
|
|
1390
|
+
x1_5
|
|
1391
|
+
sage: x1 == loads(dumps(x1))
|
|
1392
|
+
True
|
|
1393
|
+
"""
|
|
1394
|
+
|
|
1395
|
+
def __init__(self, parent, name):
|
|
1396
|
+
"""
|
|
1397
|
+
EXAMPLES::
|
|
1398
|
+
|
|
1399
|
+
sage: X.<x> = InfinitePolynomialRing(QQ)
|
|
1400
|
+
sage: loads(dumps(x))
|
|
1401
|
+
x_*
|
|
1402
|
+
"""
|
|
1403
|
+
self._name = name
|
|
1404
|
+
self._parent = parent
|
|
1405
|
+
self._output = {}
|
|
1406
|
+
|
|
1407
|
+
def __eq__(self, other):
|
|
1408
|
+
"""
|
|
1409
|
+
Check whether ``self`` is equal to ``other``.
|
|
1410
|
+
|
|
1411
|
+
EXAMPLES::
|
|
1412
|
+
|
|
1413
|
+
sage: X.<x,y> = InfinitePolynomialRing(QQ)
|
|
1414
|
+
sage: from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialGen
|
|
1415
|
+
sage: x2 = InfinitePolynomialGen(X, 'x')
|
|
1416
|
+
sage: x2 == x
|
|
1417
|
+
True
|
|
1418
|
+
"""
|
|
1419
|
+
if not isinstance(other, InfinitePolynomialGen):
|
|
1420
|
+
return False
|
|
1421
|
+
return (self._name, self._parent) == (other._name, other._parent)
|
|
1422
|
+
|
|
1423
|
+
def __ne__(self, other):
|
|
1424
|
+
"""
|
|
1425
|
+
Check whether ``self`` is not equal to ``other``.
|
|
1426
|
+
|
|
1427
|
+
EXAMPLES::
|
|
1428
|
+
|
|
1429
|
+
sage: X.<x,y> = InfinitePolynomialRing(QQ)
|
|
1430
|
+
sage: from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialGen
|
|
1431
|
+
sage: x2 = InfinitePolynomialGen(X, 'x')
|
|
1432
|
+
sage: x2 != x
|
|
1433
|
+
False
|
|
1434
|
+
"""
|
|
1435
|
+
return not (self == other)
|
|
1436
|
+
|
|
1437
|
+
def _latex_(self):
|
|
1438
|
+
r"""
|
|
1439
|
+
EXAMPLES::
|
|
1440
|
+
|
|
1441
|
+
sage: from sage.misc.latex import latex
|
|
1442
|
+
sage: X.<x,x1,xx> = InfinitePolynomialRing(QQ)
|
|
1443
|
+
sage: latex(x) # indirect doctest
|
|
1444
|
+
x_{\ast}
|
|
1445
|
+
sage: latex(x1) # indirect doctest
|
|
1446
|
+
\mathit{x1}_{\ast}
|
|
1447
|
+
sage: latex(xx) # indirect doctest
|
|
1448
|
+
\mathit{xx}_{\ast}
|
|
1449
|
+
sage: latex(x[2]) # indirect doctest
|
|
1450
|
+
x_{2}
|
|
1451
|
+
sage: latex(x1[3]) # indirect doctest
|
|
1452
|
+
\mathit{x1}_{3}
|
|
1453
|
+
"""
|
|
1454
|
+
from sage.misc.latex import latex_variable_name
|
|
1455
|
+
return latex_variable_name(self._name + '_ast')
|
|
1456
|
+
|
|
1457
|
+
def __getitem__(self, i):
|
|
1458
|
+
"""
|
|
1459
|
+
Return the variable ``x[i]`` where ``x`` is this
|
|
1460
|
+
:class:`sage.rings.polynomial.infinite_polynomial_ring.InfinitePolynomialGen`,
|
|
1461
|
+
and i is a nonnegative integer.
|
|
1462
|
+
|
|
1463
|
+
EXAMPLES::
|
|
1464
|
+
|
|
1465
|
+
sage: X.<alpha> = InfinitePolynomialRing(QQ)
|
|
1466
|
+
sage: alpha[1]
|
|
1467
|
+
alpha_1
|
|
1468
|
+
"""
|
|
1469
|
+
if int(i) != i:
|
|
1470
|
+
raise ValueError("the index (= %s) must be an integer" % i)
|
|
1471
|
+
i = int(i)
|
|
1472
|
+
if i < 0:
|
|
1473
|
+
raise ValueError("the index (= %s) must be nonnegative" % i)
|
|
1474
|
+
P = self._parent
|
|
1475
|
+
from sage.rings.polynomial.infinite_polynomial_element import InfinitePolynomial_dense, InfinitePolynomial_sparse
|
|
1476
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
1477
|
+
OUT = self._output.get(i)
|
|
1478
|
+
if hasattr(P, '_P'):
|
|
1479
|
+
if i <= P._max:
|
|
1480
|
+
# return InfinitePolynomial_dense(P, P._P.gen(P._P.variable_names().index(self._name+'_'+str(i))))
|
|
1481
|
+
if OUT is None:
|
|
1482
|
+
self._output[i] = InfinitePolynomial_dense(P, P._P.gen(P._P.variable_names().index(self._name + '_' + str(i))))
|
|
1483
|
+
else:
|
|
1484
|
+
if OUT._p.parent() is not P._P:
|
|
1485
|
+
OUT._p = P._P(OUT._p)
|
|
1486
|
+
return self._output[i]
|
|
1487
|
+
# Calculate all of the new names needed
|
|
1488
|
+
try:
|
|
1489
|
+
names = [[name + '_' + str(j) for name in P._names]
|
|
1490
|
+
for j in range(i + 1)]
|
|
1491
|
+
except OverflowError:
|
|
1492
|
+
raise IndexError("variable index is too big - consider using the sparse implementation")
|
|
1493
|
+
names = reduce(operator.add, names)
|
|
1494
|
+
names.sort(key=P.varname_key, reverse=True)
|
|
1495
|
+
# Create the new polynomial ring
|
|
1496
|
+
P._P = PolynomialRing(P.base_ring(), names, order=P._order)
|
|
1497
|
+
# Get the generators
|
|
1498
|
+
P._max = i
|
|
1499
|
+
# return InfinitePolynomial_dense(P, P._P.gen(P._P.variable_names().index(self._name+'_'+str(i))))
|
|
1500
|
+
self._output[i] = InfinitePolynomial_dense(P, P._P.gen(P._P.variable_names().index(self._name + '_' + str(i))))
|
|
1501
|
+
return self._output[i]
|
|
1502
|
+
# Now, we are in the sparse implementation
|
|
1503
|
+
if OUT is not None: # in the sparse implementation, this is ok
|
|
1504
|
+
return OUT
|
|
1505
|
+
if i == 0:
|
|
1506
|
+
names = [self._name + '_0', self._name + '_1']
|
|
1507
|
+
else:
|
|
1508
|
+
names = [self._name + '_0', self._name + '_' + str(i)]
|
|
1509
|
+
names.sort(key=P.varname_key, reverse=True)
|
|
1510
|
+
Pol = PolynomialRing(P.base_ring(), names, order=P._order)
|
|
1511
|
+
# return InfinitePolynomial_sparse(P, Pol.gen(names.index(self._name+'_'+str(i))))
|
|
1512
|
+
self._output[i] = InfinitePolynomial_sparse(P, Pol.gen(names.index(self._name + '_' + str(i))))
|
|
1513
|
+
return self._output[i]
|
|
1514
|
+
|
|
1515
|
+
def _repr_(self):
|
|
1516
|
+
"""
|
|
1517
|
+
EXAMPLES::
|
|
1518
|
+
|
|
1519
|
+
sage: X.<x,y> = InfinitePolynomialRing(QQ)
|
|
1520
|
+
sage: x # indirect doctest
|
|
1521
|
+
x_*
|
|
1522
|
+
"""
|
|
1523
|
+
return self._name + '_*'
|
|
1524
|
+
|
|
1525
|
+
def __str__(self):
|
|
1526
|
+
"""
|
|
1527
|
+
EXAMPLES::
|
|
1528
|
+
|
|
1529
|
+
sage: X.<x,y> = InfinitePolynomialRing(QQ)
|
|
1530
|
+
sage: print(x) # indirect doctest
|
|
1531
|
+
Generator for the x's in Infinite polynomial ring in x, y over Rational Field
|
|
1532
|
+
"""
|
|
1533
|
+
return f"Generator for the {self._name}'s in {self._parent}"
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
##############################################################
|
|
1537
|
+
# The dense implementation
|
|
1538
|
+
|
|
1539
|
+
class InfinitePolynomialRing_dense(InfinitePolynomialRing_sparse):
|
|
1540
|
+
"""
|
|
1541
|
+
Dense implementation of Infinite Polynomial Rings.
|
|
1542
|
+
|
|
1543
|
+
Compared with :class:`~sage.rings.polynomial.infinite_polynomial_ring.InfinitePolynomialRing_sparse`,
|
|
1544
|
+
from which this class inherits, it keeps a polynomial ring that comprises all elements that have
|
|
1545
|
+
been created so far.
|
|
1546
|
+
"""
|
|
1547
|
+
def __init__(self, R, names, order):
|
|
1548
|
+
"""
|
|
1549
|
+
EXAMPLES::
|
|
1550
|
+
|
|
1551
|
+
sage: X.<x2,alpha,y4> = InfinitePolynomialRing(ZZ, implementation='dense')
|
|
1552
|
+
sage: X == loads(dumps(X))
|
|
1553
|
+
True
|
|
1554
|
+
"""
|
|
1555
|
+
if not names:
|
|
1556
|
+
names = ['x']
|
|
1557
|
+
# Generate the initial polynomial ring
|
|
1558
|
+
self._max = 0
|
|
1559
|
+
InfinitePolynomialRing_sparse.__init__(self, R, names, order)
|
|
1560
|
+
self._P = self._minP
|
|
1561
|
+
# self._pgens = self._P.gens()
|
|
1562
|
+
|
|
1563
|
+
#####################
|
|
1564
|
+
# Coercion
|
|
1565
|
+
|
|
1566
|
+
def construction(self):
|
|
1567
|
+
"""
|
|
1568
|
+
Return the construction of ``self``.
|
|
1569
|
+
|
|
1570
|
+
OUTPUT:
|
|
1571
|
+
|
|
1572
|
+
A pair ``F,R``, where ``F`` is a construction functor and ``R`` is a ring,
|
|
1573
|
+
so that ``F(R) is self``.
|
|
1574
|
+
|
|
1575
|
+
EXAMPLES::
|
|
1576
|
+
|
|
1577
|
+
sage: R.<x,y> = InfinitePolynomialRing(GF(5))
|
|
1578
|
+
sage: R.construction()
|
|
1579
|
+
[InfPoly{[x,y], "lex", "dense"}, Finite Field of size 5]
|
|
1580
|
+
"""
|
|
1581
|
+
return [InfinitePolynomialFunctor(self._names, self._order, 'dense'), self._base]
|
|
1582
|
+
|
|
1583
|
+
def tensor_with_ring(self, R):
|
|
1584
|
+
"""
|
|
1585
|
+
Return the tensor product of ``self`` with another ring.
|
|
1586
|
+
|
|
1587
|
+
INPUT:
|
|
1588
|
+
|
|
1589
|
+
- ``R`` -- a ring
|
|
1590
|
+
|
|
1591
|
+
OUTPUT:
|
|
1592
|
+
|
|
1593
|
+
An infinite polynomial ring that, mathematically, can be seen as the
|
|
1594
|
+
tensor product of ``self`` with ``R``.
|
|
1595
|
+
|
|
1596
|
+
NOTE:
|
|
1597
|
+
|
|
1598
|
+
It is required that the underlying ring of ``self`` coerces into ``R``.
|
|
1599
|
+
Hence, the tensor product is in fact merely an extension of the base
|
|
1600
|
+
ring.
|
|
1601
|
+
|
|
1602
|
+
EXAMPLES::
|
|
1603
|
+
|
|
1604
|
+
sage: R.<a,b> = InfinitePolynomialRing(ZZ, implementation='sparse')
|
|
1605
|
+
sage: R.tensor_with_ring(QQ)
|
|
1606
|
+
Infinite polynomial ring in a, b over Rational Field
|
|
1607
|
+
sage: R
|
|
1608
|
+
Infinite polynomial ring in a, b over Integer Ring
|
|
1609
|
+
|
|
1610
|
+
The following tests against a bug that was fixed at :issue:`10468`::
|
|
1611
|
+
|
|
1612
|
+
sage: R.<x,y> = InfinitePolynomialRing(QQ, implementation='sparse')
|
|
1613
|
+
sage: R.tensor_with_ring(QQ) is R
|
|
1614
|
+
True
|
|
1615
|
+
"""
|
|
1616
|
+
if not R.has_coerce_map_from(self._underlying_ring):
|
|
1617
|
+
raise TypeError("we cannot tensor with " + repr(R))
|
|
1618
|
+
B = self.base_ring()
|
|
1619
|
+
if hasattr(B, 'tensor_with_ring'):
|
|
1620
|
+
return InfinitePolynomialRing(B.tensor_with_ring(R), self._names, self._order, implementation='dense')
|
|
1621
|
+
if hasattr(B, 'change_ring'): # e.g., polynomial rings
|
|
1622
|
+
return InfinitePolynomialRing(B.change_ring(R), self._names, self._order, implementation='dense')
|
|
1623
|
+
# try to find the correct base ring in other ways:
|
|
1624
|
+
try:
|
|
1625
|
+
o = B.one() * R.one()
|
|
1626
|
+
except (TypeError, ValueError):
|
|
1627
|
+
raise TypeError("we cannot tensor with " + repr(R))
|
|
1628
|
+
return InfinitePolynomialRing(o.parent(), self._names, self._order, implementation='dense')
|
|
1629
|
+
|
|
1630
|
+
def polynomial_ring(self):
|
|
1631
|
+
"""
|
|
1632
|
+
Return the underlying *finite* polynomial ring.
|
|
1633
|
+
|
|
1634
|
+
.. NOTE::
|
|
1635
|
+
|
|
1636
|
+
The ring returned can change over time as more variables
|
|
1637
|
+
are used.
|
|
1638
|
+
|
|
1639
|
+
Since the rings are cached, we create here a ring with variable
|
|
1640
|
+
names that do not occur in other doc tests, so that we avoid
|
|
1641
|
+
side effects.
|
|
1642
|
+
|
|
1643
|
+
EXAMPLES::
|
|
1644
|
+
|
|
1645
|
+
sage: X.<xx, yy> = InfinitePolynomialRing(ZZ)
|
|
1646
|
+
sage: X.polynomial_ring()
|
|
1647
|
+
Multivariate Polynomial Ring in xx_0, yy_0 over Integer Ring
|
|
1648
|
+
sage: a = yy[3]
|
|
1649
|
+
sage: X.polynomial_ring()
|
|
1650
|
+
Multivariate Polynomial Ring in xx_3, xx_2, xx_1, xx_0, yy_3, yy_2, yy_1, yy_0
|
|
1651
|
+
over Integer Ring
|
|
1652
|
+
"""
|
|
1653
|
+
return self._P
|