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,4356 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Lazy Series Rings
|
|
4
|
+
|
|
5
|
+
We provide lazy implementations for various `\NN`-graded rings.
|
|
6
|
+
|
|
7
|
+
.. csv-table::
|
|
8
|
+
:class: contentstable
|
|
9
|
+
:widths: 30, 70
|
|
10
|
+
:delim: |
|
|
11
|
+
|
|
12
|
+
:class:`LazyLaurentSeriesRing` | The ring of lazy Laurent series.
|
|
13
|
+
:class:`LazyPowerSeriesRing` | The ring of (possibly multivariate) lazy Taylor series.
|
|
14
|
+
:class:`LazyCompletionGradedAlgebra` | The completion of a graded algebra consisting of formal series.
|
|
15
|
+
:class:`LazySymmetricFunctions` | The ring of (possibly multivariate) lazy symmetric functions.
|
|
16
|
+
:class:`LazyDirichletSeriesRing` | The ring of lazy Dirichlet series.
|
|
17
|
+
|
|
18
|
+
.. SEEALSO::
|
|
19
|
+
|
|
20
|
+
:class:`sage.rings.padics.generic_nodes.pAdicRelaxedGeneric`,
|
|
21
|
+
:func:`sage.rings.padics.factory.ZpER`
|
|
22
|
+
|
|
23
|
+
.. WARNING::
|
|
24
|
+
|
|
25
|
+
When the halting precision is infinite, the default for ``bool(f)``
|
|
26
|
+
is ``True`` for any lazy series ``f`` that is not known to be zero.
|
|
27
|
+
This could end up resulting in infinite loops::
|
|
28
|
+
|
|
29
|
+
sage: L.<x> = LazyPowerSeriesRing(ZZ)
|
|
30
|
+
sage: f = L(lambda n: 0, valuation=0)
|
|
31
|
+
sage: 1 / f # not tested - infinite loop
|
|
32
|
+
|
|
33
|
+
.. SEEALSO::
|
|
34
|
+
|
|
35
|
+
The examples of :class:`LazyLaurentSeriesRing` contain a discussion
|
|
36
|
+
about the different methods of comparisons the lazy series can use.
|
|
37
|
+
|
|
38
|
+
AUTHORS:
|
|
39
|
+
|
|
40
|
+
- Kwankyu Lee (2019-02-24): initial version
|
|
41
|
+
- Tejasvi Chebrolu, Martin Rubey, Travis Scrimshaw (2021-08):
|
|
42
|
+
refactored and expanded functionality
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
# ****************************************************************************
|
|
46
|
+
# Copyright (C) 2019 Kwankyu Lee <ekwankyu@gmail.com>
|
|
47
|
+
# 2022 Martin Rubey <martin.rubey at tuwien.ac.at>
|
|
48
|
+
# 2022 Travis Scrimshaw <tcscrims at gmail.com>
|
|
49
|
+
#
|
|
50
|
+
# This program is free software: you can redistribute it and/or modify
|
|
51
|
+
# it under the terms of the GNU General Public License as published by
|
|
52
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
53
|
+
# (at your option) any later version.
|
|
54
|
+
# https://www.gnu.org/licenses/
|
|
55
|
+
# ****************************************************************************
|
|
56
|
+
|
|
57
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
58
|
+
from sage.structure.parent import Parent
|
|
59
|
+
from sage.structure.element import parent
|
|
60
|
+
|
|
61
|
+
from sage.categories.algebras import Algebras
|
|
62
|
+
from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis
|
|
63
|
+
from sage.categories.rings import Rings
|
|
64
|
+
from sage.categories.unique_factorization_domains import UniqueFactorizationDomains
|
|
65
|
+
from sage.categories.integral_domains import IntegralDomains
|
|
66
|
+
from sage.categories.fields import Fields
|
|
67
|
+
from sage.categories.complete_discrete_valuation import (CompleteDiscreteValuationFields,
|
|
68
|
+
CompleteDiscreteValuationRings)
|
|
69
|
+
|
|
70
|
+
from sage.misc.cachefunc import cached_method
|
|
71
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
72
|
+
|
|
73
|
+
from sage.rings.integer_ring import ZZ
|
|
74
|
+
from sage.rings.infinity import infinity
|
|
75
|
+
from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
|
|
76
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
77
|
+
from sage.rings.lazy_series import (LazyModuleElement,
|
|
78
|
+
LazyLaurentSeries,
|
|
79
|
+
LazyPowerSeries,
|
|
80
|
+
LazyPowerSeries_gcd_mixin,
|
|
81
|
+
LazyCompletionGradedAlgebraElement,
|
|
82
|
+
LazySymmetricFunction,
|
|
83
|
+
LazyDirichletSeries)
|
|
84
|
+
from sage.structure.global_options import GlobalOptions
|
|
85
|
+
|
|
86
|
+
from sage.data_structures.stream import (
|
|
87
|
+
Stream_zero,
|
|
88
|
+
Stream_function,
|
|
89
|
+
Stream_iterator,
|
|
90
|
+
Stream_exact,
|
|
91
|
+
Stream_uninitialized,
|
|
92
|
+
Stream_taylor
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
from types import GeneratorType
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class LazySeriesRing(UniqueRepresentation, Parent):
|
|
99
|
+
"""
|
|
100
|
+
Abstract base class for lazy series.
|
|
101
|
+
"""
|
|
102
|
+
# This will never be called directly (as it is an ABC), but we copy it
|
|
103
|
+
# for use in other subclasses.
|
|
104
|
+
@staticmethod
|
|
105
|
+
def __classcall_private__(cls, base_ring, names, sparse=True, *args, **kwds):
|
|
106
|
+
"""
|
|
107
|
+
Normalize input to ensure a unique representation.
|
|
108
|
+
|
|
109
|
+
EXAMPLES::
|
|
110
|
+
|
|
111
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
112
|
+
sage: Lp = LazyLaurentSeriesRing(QQ, 'z')
|
|
113
|
+
sage: L is Lp
|
|
114
|
+
True
|
|
115
|
+
"""
|
|
116
|
+
from sage.structure.category_object import normalize_names
|
|
117
|
+
names = normalize_names(-1, names)
|
|
118
|
+
return super().__classcall__(cls, base_ring, names, sparse, *args, **kwds)
|
|
119
|
+
|
|
120
|
+
def _element_constructor_(self, x=None, valuation=None, degree=None, constant=None, coefficients=None):
|
|
121
|
+
r"""
|
|
122
|
+
Construct a lazy series from ``x``.
|
|
123
|
+
|
|
124
|
+
INPUT:
|
|
125
|
+
|
|
126
|
+
- ``x`` -- data used to the define a series
|
|
127
|
+
- ``valuation`` -- integer (optional); a lower bound for the valuation
|
|
128
|
+
of the series
|
|
129
|
+
- ``degree`` -- (optional) the degree when the series is ``constant``
|
|
130
|
+
- ``constant`` -- (optional) the eventual constant of the series
|
|
131
|
+
- ``coefficients`` -- (optional) a callable that defines the
|
|
132
|
+
coefficients of the series; must be ``None`` if ``x`` is provided;
|
|
133
|
+
see note below
|
|
134
|
+
|
|
135
|
+
If ``valuation`` is specified and ``x`` is convertible into
|
|
136
|
+
an element of the underlying ring corresponding to series
|
|
137
|
+
with finite support or ``x`` is a lazy series of the same
|
|
138
|
+
parent, then the data is shifted so that the result has the
|
|
139
|
+
specified valuation.
|
|
140
|
+
|
|
141
|
+
.. WARNING::
|
|
142
|
+
|
|
143
|
+
If ``valuation`` is specified and ``x`` is a lazy series, then
|
|
144
|
+
the valuation will be computed. If the series ``x`` is not
|
|
145
|
+
known to be zero, then this will run forever.
|
|
146
|
+
|
|
147
|
+
.. NOTE::
|
|
148
|
+
|
|
149
|
+
When working over a base ring that takes callables as valid
|
|
150
|
+
input, then passing a function as ``x`` might be converted to
|
|
151
|
+
the base ring. If instead the input is to be treated as the
|
|
152
|
+
function giving the coefficients of the lazy series being
|
|
153
|
+
constructed, then use the ``coefficients`` argument in this
|
|
154
|
+
case and do not provide ``x``.
|
|
155
|
+
|
|
156
|
+
.. WARNING::
|
|
157
|
+
|
|
158
|
+
Polynomials, but also :class:`LazyLaurentSeries` and
|
|
159
|
+
:class:`LazyDirichletSeries` are callable. Therefore, an
|
|
160
|
+
argument ``x`` which is not convertible into an element
|
|
161
|
+
of the underlying ring corresponding to series with
|
|
162
|
+
finite support is interpreted as a function providing the
|
|
163
|
+
coefficients when evaluated at integers. Examples are
|
|
164
|
+
provided below.
|
|
165
|
+
|
|
166
|
+
.. WARNING::
|
|
167
|
+
|
|
168
|
+
If ``x`` is provided as a list, any trailing zeros are
|
|
169
|
+
ignored, because ``x`` is immediately converted into a
|
|
170
|
+
polynomial.
|
|
171
|
+
|
|
172
|
+
EXAMPLES:
|
|
173
|
+
|
|
174
|
+
If ``x`` can be converted into an element of the underlying
|
|
175
|
+
Laurent polynomial ring, we do this::
|
|
176
|
+
|
|
177
|
+
sage: L = LazyLaurentSeriesRing(GF(2), 'z')
|
|
178
|
+
sage: L(2)
|
|
179
|
+
0
|
|
180
|
+
sage: L(3)
|
|
181
|
+
1
|
|
182
|
+
|
|
183
|
+
In particular, ``x`` can be a Laurent polynomial::
|
|
184
|
+
|
|
185
|
+
sage: P.<x> = LaurentPolynomialRing(QQ)
|
|
186
|
+
sage: p = x^-2 + 3*x^3
|
|
187
|
+
sage: L.<x> = LazyLaurentSeriesRing(ZZ)
|
|
188
|
+
sage: L(p)
|
|
189
|
+
x^-2 + 3*x^3
|
|
190
|
+
|
|
191
|
+
sage: L(p, valuation=0)
|
|
192
|
+
1 + 3*x^5
|
|
193
|
+
|
|
194
|
+
sage: L(p, valuation=1)
|
|
195
|
+
x + 3*x^6
|
|
196
|
+
|
|
197
|
+
If ``x`` is callable, its evaluation at the integers,
|
|
198
|
+
beginning at ``valuation``, defines the coefficients of the series::
|
|
199
|
+
|
|
200
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
201
|
+
sage: L(lambda i: i, valuation=5, constant=1, degree=10)
|
|
202
|
+
5*z^5 + 6*z^6 + 7*z^7 + 8*z^8 + 9*z^9 + z^10 + z^11 + z^12 + O(z^13)
|
|
203
|
+
sage: L(lambda i: i, valuation=5, constant=(1, 10))
|
|
204
|
+
5*z^5 + 6*z^6 + 7*z^7 + 8*z^8 + 9*z^9 + z^10 + z^11 + z^12 + O(z^13)
|
|
205
|
+
|
|
206
|
+
sage: def g(i):
|
|
207
|
+
....: if i < 0:
|
|
208
|
+
....: return 1
|
|
209
|
+
....: return 1 + sum(range(i + 1))
|
|
210
|
+
sage: e = L(g, valuation=-5); e
|
|
211
|
+
z^-5 + z^-4 + z^-3 + z^-2 + z^-1 + 1 + 2*z + O(z^2)
|
|
212
|
+
sage: f = e^-1; f
|
|
213
|
+
z^5 - z^6 - z^11 + O(z^12)
|
|
214
|
+
sage: f.coefficient(10)
|
|
215
|
+
0
|
|
216
|
+
sage: f[20]
|
|
217
|
+
9
|
|
218
|
+
sage: f[30]
|
|
219
|
+
-219
|
|
220
|
+
|
|
221
|
+
We can omit ``x``, when defining a series with constant coefficients::
|
|
222
|
+
|
|
223
|
+
sage: X = L(constant=5, degree=2); X
|
|
224
|
+
5*z^2 + 5*z^3 + 5*z^4 + O(z^5)
|
|
225
|
+
sage: X.valuation()
|
|
226
|
+
2
|
|
227
|
+
|
|
228
|
+
sage: L(valuation=2, constant=1)
|
|
229
|
+
z^2 + z^3 + z^4 + O(z^5)
|
|
230
|
+
sage: L(constant=1)
|
|
231
|
+
Traceback (most recent call last):
|
|
232
|
+
...
|
|
233
|
+
ValueError: you must specify the degree for the polynomial 0
|
|
234
|
+
|
|
235
|
+
Alternatively, ``x`` can be a list of elements of the base ring.
|
|
236
|
+
Then these elements are read as coefficients of the terms of
|
|
237
|
+
degrees starting from the ``valuation``. In this case, ``constant``
|
|
238
|
+
may be just an element of the base ring instead of a tuple or can be
|
|
239
|
+
simply omitted if it is zero::
|
|
240
|
+
|
|
241
|
+
sage: f = L([1,2,3,4], valuation=-5)
|
|
242
|
+
sage: f
|
|
243
|
+
z^-5 + 2*z^-4 + 3*z^-3 + 4*z^-2
|
|
244
|
+
sage: g = L([1,3,5,7,9], valuation=5, constant=-1)
|
|
245
|
+
sage: g
|
|
246
|
+
z^5 + 3*z^6 + 5*z^7 + 7*z^8 + 9*z^9 - z^10 - z^11 - z^12 + O(z^13)
|
|
247
|
+
|
|
248
|
+
If ``x`` is explicitly passed as ``None``, the resulting
|
|
249
|
+
series is undefined. This can be used to define it
|
|
250
|
+
implicitly, see
|
|
251
|
+
:meth:`sage.rings.lazy_series.LazyModuleElement.define`::
|
|
252
|
+
|
|
253
|
+
sage: f = L(None, valuation=-1)
|
|
254
|
+
sage: f.define(z^-1 + z^2*f^2)
|
|
255
|
+
sage: f
|
|
256
|
+
z^-1 + 1 + 2*z + 5*z^2 + 14*z^3 + 42*z^4 + 132*z^5 + O(z^6)
|
|
257
|
+
|
|
258
|
+
We construct a lazy Laurent series over another lazy Laurent series::
|
|
259
|
+
|
|
260
|
+
sage: R.<s> = LazyLaurentSeriesRing(QQ)
|
|
261
|
+
sage: L.<z> = LazyLaurentSeriesRing(R)
|
|
262
|
+
sage: e = L(lambda n: 1/factorial(n), 0); e
|
|
263
|
+
1 + z + 1/2*z^2 + 1/6*z^3 + 1/24*z^4 + 1/120*z^5 + 1/720*z^6 + O(z^7)
|
|
264
|
+
sage: L(lambda n: 1/(1 + s^n), 0)
|
|
265
|
+
1/2 + (1 - s + s^2 - s^3 + s^4 - s^5 + s^6 + O(s^7))*z
|
|
266
|
+
+ (1 - s^2 + s^4 - s^6 + O(s^7))*z^2
|
|
267
|
+
+ (1 - s^3 + s^6 + O(s^7))*z^3 + (1 - s^4 + O(s^7))*z^4
|
|
268
|
+
+ (1 - s^5 + O(s^7))*z^5 + (1 - s^6 + O(s^7))*z^6 + O(z^7)
|
|
269
|
+
|
|
270
|
+
We note that ``e`` builds correctly because ``R`` additionally
|
|
271
|
+
requires the valuation to be specified.
|
|
272
|
+
|
|
273
|
+
In the next example the argument is interpreted as a constant
|
|
274
|
+
polynomial, which happens to be a Dirichlet series::
|
|
275
|
+
|
|
276
|
+
sage: D = LazyDirichletSeriesRing(QQ, "s")
|
|
277
|
+
sage: L.<z> = LazyLaurentSeriesRing(D)
|
|
278
|
+
sage: L(lambda n: 1/factorial(n), valuation=0) # needs sage.symbolic
|
|
279
|
+
(1 + 1/2/2^s + 1/6/3^s + 1/24/4^s + 1/120/5^s + 1/720/6^s + 1/5040/7^s + O(1/(8^s)))
|
|
280
|
+
|
|
281
|
+
We can also specify that the given function should be
|
|
282
|
+
interpreted as the coefficients of the Laurent series::
|
|
283
|
+
|
|
284
|
+
sage: L(coefficients=lambda n: 1/factorial(n), valuation=0) # needs sage.symbolic
|
|
285
|
+
1 + z + 1/2*z^2 + 1/6*z^3 + 1/24*z^4 + 1/120*z^5 + 1/720*z^6 + O(z^7)
|
|
286
|
+
|
|
287
|
+
When the argument ``x`` is callable and not convertible into
|
|
288
|
+
an element of the underlying ring of series of finite
|
|
289
|
+
support, it is evaluated at integers to compute the
|
|
290
|
+
coefficients::
|
|
291
|
+
|
|
292
|
+
sage: R.<q> = QQ[]
|
|
293
|
+
sage: D = LazyDirichletSeriesRing(ZZ, 't')
|
|
294
|
+
sage: D(1+2*q) # needs sage.symbolic
|
|
295
|
+
3 + 5/2^t + 7/3^t + 9/4^t + 11/5^t + 13/6^t + 15/7^t + O(1/(8^t))
|
|
296
|
+
|
|
297
|
+
In this example, the Dirichlet series ``m`` is considered as an
|
|
298
|
+
element in the base ring::
|
|
299
|
+
|
|
300
|
+
sage: m = D(moebius)
|
|
301
|
+
sage: s = L(m, valuation=0) # needs sage.symbolic
|
|
302
|
+
sage: s[0] # needs sage.symbolic
|
|
303
|
+
1 - 1/(2^s) - 1/(3^s) - 1/(5^s) + 1/(6^s) - 1/(7^s) + O(1/(8^s))
|
|
304
|
+
sage: s[1] # needs sage.symbolic
|
|
305
|
+
0
|
|
306
|
+
|
|
307
|
+
Converting various series from a univariate power series::
|
|
308
|
+
|
|
309
|
+
sage: # needs sage.rings.finite_rings
|
|
310
|
+
sage: L = LazyLaurentSeriesRing(GF(2), 'z')
|
|
311
|
+
sage: R = LazyPowerSeriesRing(ZZ, 'z')
|
|
312
|
+
sage: L.has_coerce_map_from(R)
|
|
313
|
+
True
|
|
314
|
+
sage: L(R(lambda n: n))
|
|
315
|
+
z + z^3 + z^5 + z^7 + O(z^8)
|
|
316
|
+
sage: L(R([2,4,6])) == L.zero()
|
|
317
|
+
True
|
|
318
|
+
sage: L(R([2,4,6], valuation=2, constant=4)) == L.zero()
|
|
319
|
+
True
|
|
320
|
+
sage: L(R([2,4,6], valuation=2, constant=5))
|
|
321
|
+
z^5 + z^6 + z^7 + O(z^8)
|
|
322
|
+
sage: L(R([2,3,4], valuation=2, constant=4))
|
|
323
|
+
z^3
|
|
324
|
+
sage: L(R([2,3,4], valuation=2, constant=5))
|
|
325
|
+
z^3 + z^5 + z^6 + z^7 + O(z^8)
|
|
326
|
+
|
|
327
|
+
Can only convert from known to be constant multivariate power series::
|
|
328
|
+
|
|
329
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
330
|
+
sage: R.<x,y> = LazyPowerSeriesRing(QQ)
|
|
331
|
+
sage: L(R(2))
|
|
332
|
+
2
|
|
333
|
+
sage: L(R.zero())
|
|
334
|
+
0
|
|
335
|
+
sage: L(x)
|
|
336
|
+
Traceback (most recent call last):
|
|
337
|
+
...
|
|
338
|
+
ValueError: unable to convert ...
|
|
339
|
+
sage: L(1 / (1 - x - y))
|
|
340
|
+
Traceback (most recent call last):
|
|
341
|
+
...
|
|
342
|
+
ValueError: unable to convert ...
|
|
343
|
+
sage: P.<x,y> = QQ[]
|
|
344
|
+
sage: f = R(lambda n: (x+y)^n if n == 0 else P.zero()); f
|
|
345
|
+
1 + O(x,y)^7
|
|
346
|
+
sage: L(f)
|
|
347
|
+
Traceback (most recent call last):
|
|
348
|
+
...
|
|
349
|
+
ValueError: unable to convert ...
|
|
350
|
+
|
|
351
|
+
Converting from the corresponding rational functions::
|
|
352
|
+
|
|
353
|
+
sage: L = LazyLaurentSeriesRing(QQ, 't')
|
|
354
|
+
sage: tt = L.gen()
|
|
355
|
+
sage: R.<t> = LaurentPolynomialRing(QQ)
|
|
356
|
+
sage: f = (1 + t) / (1 + t + t^2); f
|
|
357
|
+
(t + 1)/(t^2 + t + 1)
|
|
358
|
+
sage: f.parent()
|
|
359
|
+
Fraction Field of Univariate Polynomial Ring in t over Rational Field
|
|
360
|
+
sage: L(f)
|
|
361
|
+
1 - t^2 + t^3 - t^5 + t^6 + O(t^7)
|
|
362
|
+
sage: L(f) == (1 + tt) / (1 + tt + tt^2)
|
|
363
|
+
True
|
|
364
|
+
sage: f = (3 + t) / (t^3 - t^5); f
|
|
365
|
+
(-t - 3)/(t^5 - t^3)
|
|
366
|
+
sage: f.parent()
|
|
367
|
+
Fraction Field of Univariate Polynomial Ring in t over Rational Field
|
|
368
|
+
sage: L(f)
|
|
369
|
+
3*t^-3 + t^-2 + 3*t^-1 + 1 + 3*t + t^2 + 3*t^3 + O(t^4)
|
|
370
|
+
sage: L(f) - (3 + tt) / (tt^3 - tt^5)
|
|
371
|
+
O(t^4)
|
|
372
|
+
|
|
373
|
+
TESTS:
|
|
374
|
+
|
|
375
|
+
Checking the valuation is consistent::
|
|
376
|
+
|
|
377
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
378
|
+
sage: L([0,0,2,3], valuation=-4)
|
|
379
|
+
2*z^-4 + 3*z^-3
|
|
380
|
+
sage: L(range(5), valuation=-4)
|
|
381
|
+
z^-4 + 2*z^-3 + 3*z^-2 + 4*z^-1
|
|
382
|
+
sage: P.<x> = ZZ[]
|
|
383
|
+
sage: L(x^2 + x^5, valuation=-4)
|
|
384
|
+
z^-4 + z^-1
|
|
385
|
+
sage: L(1, valuation=-4)
|
|
386
|
+
z^-4
|
|
387
|
+
sage: L(L(1), valuation=-4)
|
|
388
|
+
z^-4
|
|
389
|
+
sage: L(1/(1-z), valuation=-4)
|
|
390
|
+
z^-4 + z^-3 + z^-2 + O(z^-1)
|
|
391
|
+
sage: L(z^-3/(1-z), valuation=-4)
|
|
392
|
+
z^-4 + z^-3 + z^-2 + O(z^-1)
|
|
393
|
+
sage: L(z^3/(1-z), valuation=-4)
|
|
394
|
+
z^-4 + z^-3 + z^-2 + O(z^-1)
|
|
395
|
+
|
|
396
|
+
sage: L(z^3/(1-z), valuation=0)
|
|
397
|
+
1 + z + z^2 + O(z^3)
|
|
398
|
+
|
|
399
|
+
sage: L(lambda n: 1/(n+1), degree=3)
|
|
400
|
+
Traceback (most recent call last):
|
|
401
|
+
...
|
|
402
|
+
ValueError: the valuation must be specified
|
|
403
|
+
|
|
404
|
+
sage: L(5, valuation=3.1)
|
|
405
|
+
Traceback (most recent call last):
|
|
406
|
+
...
|
|
407
|
+
ValueError: the valuation must be an integer
|
|
408
|
+
|
|
409
|
+
sage: L(5, valuation=6/2)
|
|
410
|
+
5*z^3
|
|
411
|
+
|
|
412
|
+
Checking that series are not interpreted as coefficients when
|
|
413
|
+
they can be interpreted as series::
|
|
414
|
+
|
|
415
|
+
sage: P.<s> = ZZ[]
|
|
416
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
417
|
+
sage: M.<w> = LazyLaurentSeriesRing(QQ)
|
|
418
|
+
sage: L(M(s^2 + s^5), valuation=-4)
|
|
419
|
+
z^-4 + z^-1
|
|
420
|
+
|
|
421
|
+
sage: D = LazyDirichletSeriesRing(ZZ, "s")
|
|
422
|
+
sage: E = LazyDirichletSeriesRing(QQ, "t")
|
|
423
|
+
sage: D(E([1,2,3])) # needs sage.symbolic
|
|
424
|
+
1 + 2/2^s + 3/3^s
|
|
425
|
+
|
|
426
|
+
This gives zero::
|
|
427
|
+
|
|
428
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
429
|
+
sage: L(lambda n: 0, degree=3, valuation=0)
|
|
430
|
+
0
|
|
431
|
+
sage: L(L.zero(), degree=3)
|
|
432
|
+
0
|
|
433
|
+
sage: L(L.zero(), degree=3, valuation=2)
|
|
434
|
+
0
|
|
435
|
+
sage: L(L.zero(), degree=3, constant=0)
|
|
436
|
+
0
|
|
437
|
+
sage: L(L.zero(), degree=3, valuation=2, constant=0)
|
|
438
|
+
0
|
|
439
|
+
|
|
440
|
+
This does not::
|
|
441
|
+
|
|
442
|
+
sage: L(lambda n: 0, degree=3, constant=1, valuation=0)
|
|
443
|
+
z^3 + z^4 + z^5 + O(z^6)
|
|
444
|
+
sage: L(L.zero(), degree=-3, constant=1)
|
|
445
|
+
z^-3 + z^-2 + z^-1 + O(1)
|
|
446
|
+
sage: L(L.zero(), valuation=2, constant=1)
|
|
447
|
+
z^2 + z^3 + z^4 + O(z^5)
|
|
448
|
+
|
|
449
|
+
This raises an error::
|
|
450
|
+
|
|
451
|
+
sage: L(lambda n: 0, valuation=3, constant=1)
|
|
452
|
+
Traceback (most recent call last):
|
|
453
|
+
...
|
|
454
|
+
ValueError: constant may only be specified if the degree is specified
|
|
455
|
+
|
|
456
|
+
We support the old input format for ``constant``::
|
|
457
|
+
|
|
458
|
+
sage: f = L(lambda i: i, valuation=-3, constant=-1, degree=3)
|
|
459
|
+
sage: g = L(lambda i: i, valuation=-3, constant=(-1,3))
|
|
460
|
+
sage: f == g
|
|
461
|
+
True
|
|
462
|
+
sage: g = L(lambda i: i, -3, (-1,3))
|
|
463
|
+
sage: f == g
|
|
464
|
+
True
|
|
465
|
+
|
|
466
|
+
We support passing a generator::
|
|
467
|
+
|
|
468
|
+
sage: L(filter(is_odd, NN), -3)
|
|
469
|
+
z^-3 + 3*z^-2 + 5*z^-1 + 7 + 9*z + 11*z^2 + 13*z^3 + O(z^4)
|
|
470
|
+
"""
|
|
471
|
+
if valuation is not None and valuation not in ZZ:
|
|
472
|
+
raise ValueError("the valuation must be an integer")
|
|
473
|
+
|
|
474
|
+
if x is None and coefficients is None:
|
|
475
|
+
if valuation is None:
|
|
476
|
+
raise ValueError("the valuation must be specified")
|
|
477
|
+
return self.element_class(self, Stream_uninitialized(valuation))
|
|
478
|
+
|
|
479
|
+
# WARNING: if x is not explicitly specified as None, it is
|
|
480
|
+
# set to 0 by Parent.__call__
|
|
481
|
+
if coefficients is not None and (x is not None and (not isinstance(x, int) or x)):
|
|
482
|
+
raise ValueError("coefficients must be None if x is provided")
|
|
483
|
+
|
|
484
|
+
BR = self._internal_poly_ring.base_ring() # this is the ring containing the elements of the stream
|
|
485
|
+
if isinstance(constant, (tuple, list)):
|
|
486
|
+
constant, degree = constant
|
|
487
|
+
if isinstance(degree, (tuple, list)):
|
|
488
|
+
constant, degree = degree
|
|
489
|
+
if constant is not None:
|
|
490
|
+
constant = BR(constant)
|
|
491
|
+
|
|
492
|
+
if coefficients is None:
|
|
493
|
+
# Try to build stuff using the internal polynomial ring constructor
|
|
494
|
+
R = self._internal_poly_ring
|
|
495
|
+
|
|
496
|
+
try:
|
|
497
|
+
x = R(x)
|
|
498
|
+
except (TypeError, ValueError):
|
|
499
|
+
pass
|
|
500
|
+
|
|
501
|
+
# If x has been converted to the internal polynomial ring
|
|
502
|
+
if parent(x) is R:
|
|
503
|
+
if not x and not constant:
|
|
504
|
+
return self.zero()
|
|
505
|
+
if x and valuation is not None:
|
|
506
|
+
x = x.shift(valuation - x.valuation())
|
|
507
|
+
if degree is None and not x:
|
|
508
|
+
if valuation is None:
|
|
509
|
+
raise ValueError("you must specify the degree for the polynomial 0")
|
|
510
|
+
degree = valuation
|
|
511
|
+
if not x:
|
|
512
|
+
coeff_stream = Stream_exact([], order=degree, constant=constant)
|
|
513
|
+
return self.element_class(self, coeff_stream)
|
|
514
|
+
initial_coefficients = [x[i] for i in range(x.valuation(), x.degree() + 1)]
|
|
515
|
+
coeff_stream = Stream_exact(initial_coefficients,
|
|
516
|
+
order=x.valuation(), degree=degree, constant=constant)
|
|
517
|
+
return self.element_class(self, coeff_stream)
|
|
518
|
+
|
|
519
|
+
# Handle when it is a lazy series
|
|
520
|
+
if isinstance(x, self.Element):
|
|
521
|
+
# If x is known to be 0
|
|
522
|
+
if isinstance(x._coeff_stream, Stream_zero):
|
|
523
|
+
if not constant:
|
|
524
|
+
if self is parent(x):
|
|
525
|
+
return x
|
|
526
|
+
return self.element_class(self, x._coeff_stream)
|
|
527
|
+
if degree is None:
|
|
528
|
+
if valuation is None:
|
|
529
|
+
raise ValueError("you must specify the degree for the polynomial 0")
|
|
530
|
+
degree = valuation
|
|
531
|
+
coeff_stream = Stream_exact([], order=degree, constant=constant)
|
|
532
|
+
return self.element_class(self, coeff_stream)
|
|
533
|
+
|
|
534
|
+
# Make the result exact
|
|
535
|
+
if degree is not None:
|
|
536
|
+
# truncate the series and then possibly make constant
|
|
537
|
+
x_val = x._coeff_stream.order()
|
|
538
|
+
if not valuation:
|
|
539
|
+
valuation = x_val
|
|
540
|
+
initial_coefficients = [x[x_val+i] for i in range(degree-valuation)]
|
|
541
|
+
if not any(initial_coefficients):
|
|
542
|
+
if not constant:
|
|
543
|
+
return self.zero()
|
|
544
|
+
# We learned some stuff about x; pass it along
|
|
545
|
+
x._coeff_stream._approximate_order += len(initial_coefficients)
|
|
546
|
+
initial_coefficients = []
|
|
547
|
+
coeff_stream = Stream_exact(initial_coefficients,
|
|
548
|
+
order=valuation, degree=degree, constant=constant)
|
|
549
|
+
return self.element_class(self, coeff_stream)
|
|
550
|
+
|
|
551
|
+
# We are just possibly shifting the result
|
|
552
|
+
ret = self.element_class(self, x._coeff_stream)
|
|
553
|
+
if valuation is None:
|
|
554
|
+
return ret
|
|
555
|
+
return ret.shift(valuation - x._coeff_stream.order())
|
|
556
|
+
|
|
557
|
+
# Handle when it is a power series
|
|
558
|
+
if isinstance(x, LazyPowerSeries):
|
|
559
|
+
stream = x._coeff_stream
|
|
560
|
+
if isinstance(stream, Stream_zero):
|
|
561
|
+
return self.zero()
|
|
562
|
+
elif isinstance(stream, Stream_exact):
|
|
563
|
+
if x.parent()._arity != 1:
|
|
564
|
+
# Special case for constant series
|
|
565
|
+
if stream._degree == 1:
|
|
566
|
+
return self(BR(stream[0]))
|
|
567
|
+
else:
|
|
568
|
+
coeffs = [BR(val) for val in stream._initial_coefficients]
|
|
569
|
+
valuation = stream._approximate_order
|
|
570
|
+
for i, c in enumerate(coeffs):
|
|
571
|
+
if c:
|
|
572
|
+
valuation += i
|
|
573
|
+
coeffs = coeffs[i:]
|
|
574
|
+
break
|
|
575
|
+
else:
|
|
576
|
+
valuation += len(coeffs)
|
|
577
|
+
coeffs = []
|
|
578
|
+
return self(coeffs,
|
|
579
|
+
degree=stream._degree,
|
|
580
|
+
constant=BR(stream._constant),
|
|
581
|
+
valuation=valuation)
|
|
582
|
+
elif x.parent()._arity == 1:
|
|
583
|
+
return self.element_class(self, stream)
|
|
584
|
+
raise ValueError(f"unable to convert {x} into {self}")
|
|
585
|
+
|
|
586
|
+
# Check if we can realize the input as a rational function
|
|
587
|
+
try:
|
|
588
|
+
FF = self._laurent_poly_ring.fraction_field()
|
|
589
|
+
x = FF(x)
|
|
590
|
+
except (TypeError, ValueError, AttributeError):
|
|
591
|
+
pass
|
|
592
|
+
else:
|
|
593
|
+
return self(x.numerator()) / self(x.denominator())
|
|
594
|
+
|
|
595
|
+
else:
|
|
596
|
+
x = coefficients
|
|
597
|
+
|
|
598
|
+
if callable(x) or isinstance(x, (GeneratorType, map, filter)):
|
|
599
|
+
if valuation is None:
|
|
600
|
+
raise ValueError("the valuation must be specified")
|
|
601
|
+
if degree is None:
|
|
602
|
+
if constant is not None:
|
|
603
|
+
raise ValueError("constant may only be specified if the degree is specified")
|
|
604
|
+
if callable(x):
|
|
605
|
+
coeff_stream = Stream_function(lambda i: BR(x(i)), self._sparse, valuation)
|
|
606
|
+
else:
|
|
607
|
+
coeff_stream = Stream_iterator(map(BR, _skip_leading_zeros(x)), valuation)
|
|
608
|
+
return self.element_class(self, coeff_stream)
|
|
609
|
+
|
|
610
|
+
# degree is not None
|
|
611
|
+
if constant is None:
|
|
612
|
+
constant = BR.zero()
|
|
613
|
+
if callable(x):
|
|
614
|
+
p = [BR(x(i)) for i in range(valuation, degree)]
|
|
615
|
+
else:
|
|
616
|
+
p = [BR(c) for c, _ in zip(_skip_leading_zeros(x), range(valuation, degree))]
|
|
617
|
+
if not any(p) and not constant:
|
|
618
|
+
return self.zero()
|
|
619
|
+
coeff_stream = Stream_exact(p, order=valuation, constant=constant, degree=degree)
|
|
620
|
+
return self.element_class(self, coeff_stream)
|
|
621
|
+
|
|
622
|
+
raise ValueError(f"unable to convert {x} into {self}")
|
|
623
|
+
|
|
624
|
+
def undefined(self, valuation=None, name=None):
|
|
625
|
+
r"""
|
|
626
|
+
Return an uninitialized series.
|
|
627
|
+
|
|
628
|
+
INPUT:
|
|
629
|
+
|
|
630
|
+
- ``valuation`` -- integer; a lower bound for the valuation
|
|
631
|
+
of the series
|
|
632
|
+
- ``name`` -- string; a name that refers to the undefined
|
|
633
|
+
stream in error messages
|
|
634
|
+
|
|
635
|
+
Power series can be defined recursively (see
|
|
636
|
+
:meth:`sage.rings.lazy_series.LazyModuleElement.define` for
|
|
637
|
+
more examples).
|
|
638
|
+
|
|
639
|
+
.. SEEALSO::
|
|
640
|
+
|
|
641
|
+
:meth:`sage.rings.padics.generic_nodes.pAdicRelaxedGeneric.unknown`
|
|
642
|
+
|
|
643
|
+
EXAMPLES::
|
|
644
|
+
|
|
645
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
646
|
+
sage: s = L.undefined(1)
|
|
647
|
+
sage: s.define(z + (s^2+s(z^2))/2)
|
|
648
|
+
sage: s
|
|
649
|
+
z + z^2 + z^3 + 2*z^4 + 3*z^5 + 6*z^6 + 11*z^7 + O(z^8)
|
|
650
|
+
|
|
651
|
+
Alternatively::
|
|
652
|
+
|
|
653
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
654
|
+
sage: f = L(None, valuation=-1)
|
|
655
|
+
sage: f.define(z^-1 + z^2*f^2)
|
|
656
|
+
sage: f
|
|
657
|
+
z^-1 + 1 + 2*z + 5*z^2 + 14*z^3 + 42*z^4 + 132*z^5 + O(z^6)
|
|
658
|
+
"""
|
|
659
|
+
if valuation is None:
|
|
660
|
+
valuation = self._minimal_valuation
|
|
661
|
+
coeff_stream = Stream_uninitialized(valuation, name=name)
|
|
662
|
+
return self.element_class(self, coeff_stream)
|
|
663
|
+
|
|
664
|
+
unknown = undefined
|
|
665
|
+
|
|
666
|
+
def _terms_of_degree(self, n, R):
|
|
667
|
+
r"""
|
|
668
|
+
Return the list of terms occurring in a coefficient of degree
|
|
669
|
+
``n`` such that coefficients are in the ring ``R``.
|
|
670
|
+
|
|
671
|
+
For example, if ``self`` is a univariate Laurent, power, or
|
|
672
|
+
Dirichlet series, this is the list containing the one of the
|
|
673
|
+
base ring. If ``self`` is a multivariate power series, this
|
|
674
|
+
is the list of monomials of total degree ``n``. If ``self``
|
|
675
|
+
is a lazy symmetric function, this is the list of basis
|
|
676
|
+
elements of total degree ``n``.
|
|
677
|
+
|
|
678
|
+
EXAMPLES::
|
|
679
|
+
|
|
680
|
+
sage: # needs sage.combinat sage.modules
|
|
681
|
+
sage: s = SymmetricFunctions(ZZ).s()
|
|
682
|
+
sage: L = LazySymmetricFunctions(s)
|
|
683
|
+
sage: m = L._terms_of_degree(3, ZZ); m
|
|
684
|
+
[s[3], s[2, 1], s[1, 1, 1]]
|
|
685
|
+
"""
|
|
686
|
+
raise NotImplementedError
|
|
687
|
+
|
|
688
|
+
def define_implicitly(self, series, equations, max_lookahead=1):
|
|
689
|
+
r"""
|
|
690
|
+
Define series by solving functional equations.
|
|
691
|
+
|
|
692
|
+
INPUT:
|
|
693
|
+
|
|
694
|
+
- ``series`` -- list of undefined series or pairs each
|
|
695
|
+
consisting of a series and its initial values
|
|
696
|
+
- ``equations`` -- list of equations defining the series
|
|
697
|
+
- ``max_lookahead``-- (default: ``1``); a positive integer
|
|
698
|
+
specifying how many elements beyond the currently known
|
|
699
|
+
(i.e., approximate) order of each equation to extract
|
|
700
|
+
linear equations from
|
|
701
|
+
|
|
702
|
+
EXAMPLES::
|
|
703
|
+
|
|
704
|
+
sage: # needs sage.modules
|
|
705
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
706
|
+
sage: f = L.undefined(0)
|
|
707
|
+
sage: F = diff(f, 2)
|
|
708
|
+
sage: L.define_implicitly([(f, [1, 0])], [F + f])
|
|
709
|
+
sage: f
|
|
710
|
+
1 - 1/2*z^2 + 1/24*z^4 - 1/720*z^6 + O(z^7)
|
|
711
|
+
sage: cos(z)
|
|
712
|
+
1 - 1/2*z^2 + 1/24*z^4 - 1/720*z^6 + O(z^7)
|
|
713
|
+
sage: F
|
|
714
|
+
-1 + 1/2*z^2 - 1/24*z^4 + 1/720*z^6 + O(z^7)
|
|
715
|
+
|
|
716
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
717
|
+
sage: f = L.undefined(0)
|
|
718
|
+
sage: L.define_implicitly([f], [2*z*f(z^3) + z*f^3 - 3*f + 3])
|
|
719
|
+
sage: f
|
|
720
|
+
1 + z + z^2 + 2*z^3 + 5*z^4 + 11*z^5 + 28*z^6 + O(z^7)
|
|
721
|
+
|
|
722
|
+
From Exercise 6.63b in [EnumComb2]_::
|
|
723
|
+
|
|
724
|
+
sage: # needs sage.modules
|
|
725
|
+
sage: g = L.undefined()
|
|
726
|
+
sage: z1 = z*diff(g, z)
|
|
727
|
+
sage: z2 = z1 + z^2 * diff(g, z, 2)
|
|
728
|
+
sage: z3 = z1 + 3 * z^2 * diff(g, z, 2) + z^3 * diff(g, z, 3)
|
|
729
|
+
sage: e1 = g^2 * z3 - 15*g*z1*z2 + 30*z1^3
|
|
730
|
+
sage: e2 = g * z2 - 3 * z1^2
|
|
731
|
+
sage: e3 = g * z2 - 3 * z1^2
|
|
732
|
+
sage: e = e1^2 + 32 * e2^3 - g^10 * e3^2
|
|
733
|
+
sage: L.define_implicitly([(g, [1, 2])], [e])
|
|
734
|
+
sage: sol = L(lambda n: 1 if not n else (2 if is_square(n) else 0)); sol
|
|
735
|
+
1 + 2*z + 2*z^4 + O(z^7)
|
|
736
|
+
sage: all(g[i] == sol[i] for i in range(50))
|
|
737
|
+
True
|
|
738
|
+
|
|
739
|
+
Some more examples over different rings::
|
|
740
|
+
|
|
741
|
+
sage: # needs sage.symbolic
|
|
742
|
+
sage: L.<z> = LazyPowerSeriesRing(SR)
|
|
743
|
+
sage: G = L.undefined(0)
|
|
744
|
+
sage: L.define_implicitly([(G, [ln(2)])], [diff(G) - exp(-G(-z))])
|
|
745
|
+
sage: G
|
|
746
|
+
log(2) + z + 1/2*z^2 + (-1/12*z^4) + 1/45*z^6 + O(z^7)
|
|
747
|
+
sage: L.<z> = LazyPowerSeriesRing(RR)
|
|
748
|
+
sage: G = L.undefined(0)
|
|
749
|
+
sage: L.define_implicitly([(G, [log(2)])], [diff(G) - exp(-G(-z))])
|
|
750
|
+
sage: G
|
|
751
|
+
0.693147180559945 + 1.00000000000000*z + 0.500000000000000*z^2
|
|
752
|
+
- 0.0833333333333333*z^4 + 0.0222222222222222*z^6 + O(1.00000000000000*z^7)
|
|
753
|
+
|
|
754
|
+
We solve the recurrence relation in (3.12) of Prellberg and Brak
|
|
755
|
+
:doi:`10.1007/BF02183685`::
|
|
756
|
+
|
|
757
|
+
sage: # needs sage.modules
|
|
758
|
+
sage: q, y = QQ['q,y'].fraction_field().gens()
|
|
759
|
+
sage: L.<x> = LazyPowerSeriesRing(q.parent())
|
|
760
|
+
sage: R = L.undefined()
|
|
761
|
+
sage: L.define_implicitly([(R, [0])], [(1-q*x)*R - (y*q*x+y)*R(q*x) - q*x*R*R(q*x) - x*y*q])
|
|
762
|
+
sage: R[0]
|
|
763
|
+
0
|
|
764
|
+
sage: R[1]
|
|
765
|
+
(-q*y)/(q*y - 1)
|
|
766
|
+
sage: R[2]
|
|
767
|
+
(q^3*y^2 + q^2*y)/(q^3*y^2 - q^2*y - q*y + 1)
|
|
768
|
+
sage: R[3].factor()
|
|
769
|
+
(-1) * y * q^3 * (q*y - 1)^-2 * (q^2*y - 1)^-1 * (q^3*y - 1)^-1
|
|
770
|
+
* (q^4*y^3 + q^3*y^2 + q^2*y^2 - q^2*y - q*y - 1)
|
|
771
|
+
sage: Rp = L.undefined(1)
|
|
772
|
+
sage: L.define_implicitly([Rp], [(y*q*x+y)*Rp(q*x) + q*x*Rp*Rp(q*x) + x*y*q - (1-q*x)*Rp])
|
|
773
|
+
sage: all(R[n] == Rp[n] for n in range(7))
|
|
774
|
+
True
|
|
775
|
+
|
|
776
|
+
Another example::
|
|
777
|
+
|
|
778
|
+
sage: # needs sage.modules
|
|
779
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ["x,y,f1,f2"].fraction_field())
|
|
780
|
+
sage: L.base_ring().inject_variables()
|
|
781
|
+
Defining x, y, f1, f2
|
|
782
|
+
sage: F = L.undefined()
|
|
783
|
+
sage: L.define_implicitly([(F, [0, f1, f2])], [F(2*z) - (1+exp(x*z)+exp(y*z))*F - exp((x+y)*z)*F(-z)])
|
|
784
|
+
sage: F
|
|
785
|
+
f1*z + f2*z^2 + ((-1/6*x*y*f1+1/3*x*f2+1/3*y*f2)*z^3)
|
|
786
|
+
+ ((-1/24*x^2*y*f1-1/24*x*y^2*f1+1/12*x^2*f2+1/12*x*y*f2+1/12*y^2*f2)*z^4)
|
|
787
|
+
+ ... + O(z^8)
|
|
788
|
+
sage: sol = 1/(x-y)*((2*f2-y*f1)*(exp(x*z)-1)/x - (2*f2-x*f1)*(exp(y*z)-1)/y)
|
|
789
|
+
sage: F - sol
|
|
790
|
+
O(z^7)
|
|
791
|
+
|
|
792
|
+
We need to specify the initial values for the degree 1 and 2
|
|
793
|
+
components to get a unique solution in the previous example::
|
|
794
|
+
|
|
795
|
+
sage: # needs sage.modules
|
|
796
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ['x','y','f1'].fraction_field())
|
|
797
|
+
sage: L.base_ring().inject_variables()
|
|
798
|
+
Defining x, y, f1
|
|
799
|
+
sage: F = L.undefined()
|
|
800
|
+
sage: L.define_implicitly([F], [F(2*z) - (1+exp(x*z)+exp(y*z))*F - exp((x+y)*z)*F(-z)])
|
|
801
|
+
sage: F
|
|
802
|
+
<repr(...) failed: ValueError: could not determine any coefficients:
|
|
803
|
+
coefficient [3]: 6*series[3] + (-2*x - 2*y)*series[2] + (x*y)*series[1] == 0>
|
|
804
|
+
|
|
805
|
+
Let us now try to only specify the degree 0 and degree 1
|
|
806
|
+
components. We will see that this is still not enough to
|
|
807
|
+
remove the ambiguity, so an error is raised. However, we
|
|
808
|
+
will see that the dependence on ``series[1]`` disappears.
|
|
809
|
+
The equation which has no unique solution is now
|
|
810
|
+
``6*series[3] + (-2*x - 2*y)*series[2] + (x*y*f1) == 0``.::
|
|
811
|
+
|
|
812
|
+
sage: # needs sage.modules
|
|
813
|
+
sage: F = L.undefined()
|
|
814
|
+
sage: L.define_implicitly([(F, [0, f1])], [F(2*z) - (1+exp(x*z)+exp(y*z))*F - exp((x+y)*z)*F(-z)])
|
|
815
|
+
sage: F
|
|
816
|
+
<repr(...) failed: ValueError: could not determine any coefficients:
|
|
817
|
+
coefficient [3]: ... == 0>
|
|
818
|
+
|
|
819
|
+
(Note that the order of summands of the equation in the error
|
|
820
|
+
message is not deterministic.)
|
|
821
|
+
|
|
822
|
+
Laurent series examples::
|
|
823
|
+
|
|
824
|
+
sage: # needs sage.modules
|
|
825
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
826
|
+
sage: f = L.undefined(-1)
|
|
827
|
+
sage: L.define_implicitly([(f, [5])], [2+z*f(z^2) - f])
|
|
828
|
+
sage: f
|
|
829
|
+
5*z^-1 + 2 + 2*z + 2*z^3 + O(z^6)
|
|
830
|
+
sage: 2 + z*f(z^2) - f
|
|
831
|
+
O(z^6)
|
|
832
|
+
|
|
833
|
+
sage: g = L.undefined(-2)
|
|
834
|
+
sage: L.define_implicitly([(g, [5])], [2+z*g(z^2) - g])
|
|
835
|
+
sage: g
|
|
836
|
+
<repr(...) failed: ValueError: no solution as the coefficient in degree -3 of the equation is 5 != 0>
|
|
837
|
+
|
|
838
|
+
A bivariate example::
|
|
839
|
+
|
|
840
|
+
sage: # needs sage.combinat sage.modules
|
|
841
|
+
sage: L.<x, y> = LazyPowerSeriesRing(QQ)
|
|
842
|
+
sage: B = L.undefined()
|
|
843
|
+
sage: eq = y*B^2 + 1 - B(x, x-y)
|
|
844
|
+
sage: L.define_implicitly([B], [eq])
|
|
845
|
+
sage: B
|
|
846
|
+
1 + (x-y) + (2*x*y-2*y^2) + (4*x^2*y-7*x*y^2+3*y^3)
|
|
847
|
+
+ (2*x^3*y+6*x^2*y^2-18*x*y^3+10*y^4)
|
|
848
|
+
+ (30*x^3*y^2-78*x^2*y^3+66*x*y^4-18*y^5)
|
|
849
|
+
+ (28*x^4*y^2-12*x^3*y^3-128*x^2*y^4+180*x*y^5-68*y^6) + O(x,y)^7
|
|
850
|
+
|
|
851
|
+
Knödel walks::
|
|
852
|
+
|
|
853
|
+
sage: # needs sage.combinat sage.modules
|
|
854
|
+
sage: L.<z, x> = LazyPowerSeriesRing(QQ)
|
|
855
|
+
sage: F = L.undefined()
|
|
856
|
+
sage: eq = F(z, x)*(x^2*z-x+z) - (z - x*z^2 - x^2*z^2)*F(z, 0) + x
|
|
857
|
+
sage: L.define_implicitly([F], [eq])
|
|
858
|
+
sage: F
|
|
859
|
+
1 + (2*z^2+z*x) + (z^3+z^2*x) + (5*z^4+3*z^3*x+z^2*x^2)
|
|
860
|
+
+ (5*z^5+4*z^4*x+z^3*x^2) + (15*z^6+10*z^5*x+4*z^4*x^2+z^3*x^3)
|
|
861
|
+
+ O(z,x)^7
|
|
862
|
+
|
|
863
|
+
Bicolored rooted trees with black and white roots::
|
|
864
|
+
|
|
865
|
+
sage: # needs sage.combinat sage.modules
|
|
866
|
+
sage: L.<x, y> = LazyPowerSeriesRing(QQ)
|
|
867
|
+
sage: A = L.undefined()
|
|
868
|
+
sage: B = L.undefined()
|
|
869
|
+
sage: L.define_implicitly([A, B], [A - x*exp(B), B - y*exp(A)])
|
|
870
|
+
sage: A
|
|
871
|
+
x + x*y + (x^2*y+1/2*x*y^2) + (1/2*x^3*y+2*x^2*y^2+1/6*x*y^3)
|
|
872
|
+
+ (1/6*x^4*y+3*x^3*y^2+2*x^2*y^3+1/24*x*y^4)
|
|
873
|
+
+ (1/24*x^5*y+8/3*x^4*y^2+27/4*x^3*y^3+4/3*x^2*y^4+1/120*x*y^5)
|
|
874
|
+
+ O(x,y)^7
|
|
875
|
+
|
|
876
|
+
sage: # needs sage.combinat sage.modules
|
|
877
|
+
sage: h = SymmetricFunctions(QQ).h()
|
|
878
|
+
sage: S = LazySymmetricFunctions(h)
|
|
879
|
+
sage: E = S(lambda n: h[n])
|
|
880
|
+
sage: T = LazySymmetricFunctions(tensor([h, h]))
|
|
881
|
+
sage: X = tensor([h[1],h[[]]])
|
|
882
|
+
sage: Y = tensor([h[[]],h[1]])
|
|
883
|
+
sage: A = T.undefined()
|
|
884
|
+
sage: B = T.undefined()
|
|
885
|
+
sage: T.define_implicitly([A, B], [A - X*E(B), B - Y*E(A)])
|
|
886
|
+
sage: A[:3]
|
|
887
|
+
[h[1] # h[], h[1] # h[1]]
|
|
888
|
+
|
|
889
|
+
Permutations with two kinds of labels such that each cycle
|
|
890
|
+
contains at least one element of each kind (defined
|
|
891
|
+
implicitly to have a test)::
|
|
892
|
+
|
|
893
|
+
sage: # needs sage.combinat sage.modules
|
|
894
|
+
sage: p = SymmetricFunctions(QQ).p()
|
|
895
|
+
sage: S = LazySymmetricFunctions(p)
|
|
896
|
+
sage: P = S(lambda n: sum(p[la] for la in Partitions(n)))
|
|
897
|
+
sage: T = LazySymmetricFunctions(tensor([p, p]))
|
|
898
|
+
sage: X = tensor([p[1],p[[]]])
|
|
899
|
+
sage: Y = tensor([p[[]],p[1]])
|
|
900
|
+
sage: A = T.undefined()
|
|
901
|
+
sage: T.define_implicitly([A], [P(X)*P(Y)*A - P(X+Y)])
|
|
902
|
+
sage: A[:4]
|
|
903
|
+
[p[] # p[], 0, p[1] # p[1], p[1] # p[1, 1] + p[1, 1] # p[1]]
|
|
904
|
+
|
|
905
|
+
The Frobenius character of labelled Dyck words::
|
|
906
|
+
|
|
907
|
+
sage: # needs sage.combinat sage.modules
|
|
908
|
+
sage: h = SymmetricFunctions(QQ).h()
|
|
909
|
+
sage: L.<t, u> = LazyPowerSeriesRing(h.fraction_field())
|
|
910
|
+
sage: D = L.undefined()
|
|
911
|
+
sage: s1 = L.sum(lambda n: h[n]*t^(n+1)*u^(n-1), 1)
|
|
912
|
+
sage: L.define_implicitly([D], [u*D - u - u*s1*D - t*(D - D(t, 0))])
|
|
913
|
+
sage: D
|
|
914
|
+
h[] + h[1]*t^2 + ((h[1,1]+h[2])*t^4+h[2]*t^3*u)
|
|
915
|
+
+ ((h[1,1,1]+3*h[2,1]+h[3])*t^6+(2*h[2,1]+h[3])*t^5*u+h[3]*t^4*u^2)
|
|
916
|
+
+ O(t,u)^7
|
|
917
|
+
|
|
918
|
+
TESTS::
|
|
919
|
+
|
|
920
|
+
sage: # needs sage.modules
|
|
921
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
922
|
+
sage: f = L.undefined(1)
|
|
923
|
+
sage: L.define_implicitly([f], [log(1+f) - ~(1 + f) + 1])
|
|
924
|
+
sage: f
|
|
925
|
+
O(z^8)
|
|
926
|
+
|
|
927
|
+
sage: # needs sage.modules
|
|
928
|
+
sage: f = L.undefined(0)
|
|
929
|
+
sage: fp = f.derivative()
|
|
930
|
+
sage: g = L(lambda n: 0 if n < 10 else 1, 0)
|
|
931
|
+
sage: L.define_implicitly([f], [f.derivative() * g + f])
|
|
932
|
+
sage: f[0]
|
|
933
|
+
0
|
|
934
|
+
sage: fp[0]
|
|
935
|
+
0
|
|
936
|
+
sage: fp[1]
|
|
937
|
+
0
|
|
938
|
+
sage: fp[2]
|
|
939
|
+
0
|
|
940
|
+
sage: f[1]
|
|
941
|
+
0
|
|
942
|
+
|
|
943
|
+
Some systems of coupled functional equations::
|
|
944
|
+
|
|
945
|
+
sage: # needs sage.modules
|
|
946
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
947
|
+
sage: A = L.undefined()
|
|
948
|
+
sage: B = L.undefined()
|
|
949
|
+
sage: L.define_implicitly([A, B], [A - B, A + B + 2])
|
|
950
|
+
sage: A
|
|
951
|
+
-1 + O(z^7)
|
|
952
|
+
sage: B
|
|
953
|
+
-1 + O(z^7)
|
|
954
|
+
|
|
955
|
+
sage: # needs sage.modules
|
|
956
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
957
|
+
sage: A = L.undefined()
|
|
958
|
+
sage: B = L.undefined()
|
|
959
|
+
sage: FA = A^2 + B - 2 - z*B
|
|
960
|
+
sage: FB = B^2 - A
|
|
961
|
+
sage: L.define_implicitly([(A, [1]), (B, [1])], [FA, FB])
|
|
962
|
+
sage: A^2 + B - 2 - z*B
|
|
963
|
+
O(z^7)
|
|
964
|
+
sage: B^2 - A
|
|
965
|
+
O(z^7)
|
|
966
|
+
|
|
967
|
+
sage: # needs sage.modules
|
|
968
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
969
|
+
sage: A = L.undefined()
|
|
970
|
+
sage: B = L.undefined()
|
|
971
|
+
sage: FA = A^2 + B^2 - 2 - z*B
|
|
972
|
+
sage: FB = B^3 + 2*A^3 - 3 - z*(A + B)
|
|
973
|
+
sage: L.define_implicitly([(A, [1]), (B, [1])], [FA, FB])
|
|
974
|
+
sage: A^2 + B^2 - 2 - z*B
|
|
975
|
+
O(z^7)
|
|
976
|
+
sage: B^3 + 2*A^3 - 3 - z*(A + B)
|
|
977
|
+
O(z^7)
|
|
978
|
+
|
|
979
|
+
sage: # needs sage.modules
|
|
980
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
981
|
+
sage: A = L.undefined(valuation=3)
|
|
982
|
+
sage: B = L.undefined(valuation=2)
|
|
983
|
+
sage: C = L.undefined(valuation=2)
|
|
984
|
+
sage: FA = (A^2 + B^2)*z^2
|
|
985
|
+
sage: FB = A*B*z
|
|
986
|
+
sage: FC = (A + B + C)*z^2
|
|
987
|
+
sage: L.define_implicitly([A, B, C], [FA, FB, FC])
|
|
988
|
+
sage: A
|
|
989
|
+
O(z^10)
|
|
990
|
+
sage: B
|
|
991
|
+
O(z^16)
|
|
992
|
+
sage: C
|
|
993
|
+
O(z^23)
|
|
994
|
+
|
|
995
|
+
sage: # needs sage.modules
|
|
996
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
997
|
+
sage: A = L.undefined()
|
|
998
|
+
sage: B = L.undefined()
|
|
999
|
+
sage: C = L.undefined()
|
|
1000
|
+
sage: L.define_implicitly([A, B, C], [B - C - 1, B*z + 2*C + 1, A + 2*C + 1])
|
|
1001
|
+
sage: A + 2*C + 1
|
|
1002
|
+
O(z^7)
|
|
1003
|
+
|
|
1004
|
+
The following system does not determine `B`, but the solver
|
|
1005
|
+
will inductively discover that each coefficient of `A` must
|
|
1006
|
+
be zero. Therefore, asking for a coefficient of `B` will
|
|
1007
|
+
loop forever::
|
|
1008
|
+
|
|
1009
|
+
sage: # needs sage.modules
|
|
1010
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
1011
|
+
sage: A = L.undefined()
|
|
1012
|
+
sage: B = L.undefined()
|
|
1013
|
+
sage: C = L.undefined()
|
|
1014
|
+
sage: D = L.undefined()
|
|
1015
|
+
sage: L.define_implicitly([(A, [0,0,0]), (B, [0,0]), (C, [0,0]), (D, [0,0])], [C^2 + D^2, A + B + C + D, A*D])
|
|
1016
|
+
sage: B[2] # not tested
|
|
1017
|
+
|
|
1018
|
+
A bivariate example involving composition of series::
|
|
1019
|
+
|
|
1020
|
+
sage: # needs sage.modules
|
|
1021
|
+
sage: R.<z,q> = LazyPowerSeriesRing(QQ)
|
|
1022
|
+
sage: g = R.undefined()
|
|
1023
|
+
sage: R.define_implicitly([g], [g - (z*q + z*g*~(1-g))])
|
|
1024
|
+
sage: g
|
|
1025
|
+
z*q + z^2*q + z^3*q + (z^4*q+z^3*q^2) + (z^5*q+3*z^4*q^2) + O(z,q)^7
|
|
1026
|
+
|
|
1027
|
+
The following does not work, because the equations
|
|
1028
|
+
determining the coefficients come in bad order::
|
|
1029
|
+
|
|
1030
|
+
sage: # needs sage.modules
|
|
1031
|
+
sage: L.<x,y,t> = LazyPowerSeriesRing(QQ)
|
|
1032
|
+
sage: A = L.undefined(name="A")
|
|
1033
|
+
sage: B = L.undefined(name="B")
|
|
1034
|
+
sage: eq0 = t*x*y*B(0, 0, t) + (t - x*y)*A(x, y, t) + x*y - t*A(0, y, t)
|
|
1035
|
+
sage: eq1 = (t*x-t)*B(0, y, t) + (t - x*y)*B(x, y, t)
|
|
1036
|
+
sage: L.define_implicitly([A, B], [eq0, eq1])
|
|
1037
|
+
sage: A[1]
|
|
1038
|
+
Traceback (most recent call last):
|
|
1039
|
+
...
|
|
1040
|
+
ValueError: could not determine any coefficients:
|
|
1041
|
+
equation 0:
|
|
1042
|
+
coefficient [x*y*t]: A[x*y] - A[t] == 0
|
|
1043
|
+
equation 1:
|
|
1044
|
+
coefficient [x*t^2]: B[x*t] + B[t] == 0
|
|
1045
|
+
coefficient [x*y*t]: B[x*y] - B[t] == 0
|
|
1046
|
+
|
|
1047
|
+
Check the error message in the case of symmetric functions::
|
|
1048
|
+
|
|
1049
|
+
sage: # needs sage.modules
|
|
1050
|
+
sage: p = SymmetricFunctions(QQ).p()
|
|
1051
|
+
sage: T = LazySymmetricFunctions(tensor([p, p]))
|
|
1052
|
+
sage: X = tensor([p[1],p[[]]])
|
|
1053
|
+
sage: Y = tensor([p[[]],p[1]])
|
|
1054
|
+
sage: A = T.undefined(name="A")
|
|
1055
|
+
sage: B = T.undefined(name="B")
|
|
1056
|
+
sage: T.define_implicitly([A, B], [X*A - Y*B])
|
|
1057
|
+
sage: A
|
|
1058
|
+
<repr(...) failed: ValueError: could not determine any coefficients:
|
|
1059
|
+
coefficient [p[1] # p[1]]: -B[p[1] # p[]] + A[p[] # p[1]] == 0>
|
|
1060
|
+
|
|
1061
|
+
An example we cannot solve because we only look at the next
|
|
1062
|
+
non-vanishing equations::
|
|
1063
|
+
|
|
1064
|
+
sage: # needs sage.modules
|
|
1065
|
+
sage: L.<x> = LazyPowerSeriesRing(QQ)
|
|
1066
|
+
sage: A = L.undefined()
|
|
1067
|
+
sage: eq1 = diff(A, x) + diff(A, x, 2)
|
|
1068
|
+
sage: eq2 = A + diff(A, x) + diff(A, x, 2)
|
|
1069
|
+
sage: L.define_implicitly([A], [eq1, eq2])
|
|
1070
|
+
sage: A[1]
|
|
1071
|
+
Traceback (most recent call last):
|
|
1072
|
+
...
|
|
1073
|
+
ValueError: could not determine any coefficients:
|
|
1074
|
+
equation 0:
|
|
1075
|
+
coefficient [0]: 2*series[2] + series[1] == 0
|
|
1076
|
+
equation 1:
|
|
1077
|
+
coefficient [0]: 2*series[2] + series[1] == 0
|
|
1078
|
+
|
|
1079
|
+
sage: # needs sage.modules
|
|
1080
|
+
sage: A = L.undefined()
|
|
1081
|
+
sage: eq1 = diff(A, x) + diff(A, x, 2)
|
|
1082
|
+
sage: eq2 = A + diff(A, x) + diff(A, x, 2)
|
|
1083
|
+
sage: L.define_implicitly([A], [eq1, eq2], max_lookahead=2)
|
|
1084
|
+
sage: A
|
|
1085
|
+
O(x^7)
|
|
1086
|
+
"""
|
|
1087
|
+
s = [a[0]._coeff_stream if isinstance(a, (tuple, list))
|
|
1088
|
+
else a._coeff_stream
|
|
1089
|
+
for a in series]
|
|
1090
|
+
ics = [a[1] if isinstance(a, (tuple, list))
|
|
1091
|
+
else []
|
|
1092
|
+
for a in series]
|
|
1093
|
+
eqs = [eq._coeff_stream for eq in equations]
|
|
1094
|
+
for f, ic in zip(s, ics):
|
|
1095
|
+
f.define_implicitly(s, ic, eqs,
|
|
1096
|
+
self.base_ring(),
|
|
1097
|
+
self._internal_poly_ring.base_ring(),
|
|
1098
|
+
self._terms_of_degree,
|
|
1099
|
+
max_lookahead=max_lookahead)
|
|
1100
|
+
|
|
1101
|
+
class options(GlobalOptions):
|
|
1102
|
+
r"""
|
|
1103
|
+
Set and display the options for lazy series.
|
|
1104
|
+
|
|
1105
|
+
If no parameters are set, then the function returns a copy of
|
|
1106
|
+
the options dictionary.
|
|
1107
|
+
|
|
1108
|
+
The ``options`` to lazy series can be accessed as using
|
|
1109
|
+
:class:`LazySeriesRing.options`.
|
|
1110
|
+
|
|
1111
|
+
@OPTIONS@
|
|
1112
|
+
|
|
1113
|
+
EXAMPLES::
|
|
1114
|
+
|
|
1115
|
+
sage: LLS.<z> = LazyLaurentSeriesRing(QQ)
|
|
1116
|
+
sage: LLS.options
|
|
1117
|
+
Current options for lazy series rings
|
|
1118
|
+
- constant_length: 3
|
|
1119
|
+
- display_length: 7
|
|
1120
|
+
- halting_precision: None
|
|
1121
|
+
- secure: False
|
|
1122
|
+
|
|
1123
|
+
sage: LLS.options.display_length
|
|
1124
|
+
7
|
|
1125
|
+
sage: f = 1 / (1 + z)
|
|
1126
|
+
sage: f
|
|
1127
|
+
1 - z + z^2 - z^3 + z^4 - z^5 + z^6 + O(z^7)
|
|
1128
|
+
sage: LLS.options.display_length = 10
|
|
1129
|
+
sage: f
|
|
1130
|
+
1 - z + z^2 - z^3 + z^4 - z^5 + z^6 - z^7 + z^8 - z^9 + O(z^10)
|
|
1131
|
+
sage: g = LLS(lambda n: n^2, valuation=-2, degree=5, constant=42)
|
|
1132
|
+
sage: g
|
|
1133
|
+
4*z^-2 + z^-1 + z + 4*z^2 + 9*z^3 + 16*z^4 + 42*z^5 + 42*z^6 + 42*z^7 + O(z^8)
|
|
1134
|
+
sage: h = 1 / (1 - z) # This is exact
|
|
1135
|
+
sage: h
|
|
1136
|
+
1 + z + z^2 + O(z^3)
|
|
1137
|
+
sage: LLS.options.constant_length = 1
|
|
1138
|
+
sage: g
|
|
1139
|
+
4*z^-2 + z^-1 + z + 4*z^2 + 9*z^3 + 16*z^4 + 42*z^5 + O(z^6)
|
|
1140
|
+
sage: h
|
|
1141
|
+
1 + O(z)
|
|
1142
|
+
sage: LazyLaurentSeriesRing.options._reset()
|
|
1143
|
+
sage: LazyLaurentSeriesRing.options.display_length
|
|
1144
|
+
7
|
|
1145
|
+
"""
|
|
1146
|
+
NAME = 'lazy series rings'
|
|
1147
|
+
module = 'sage.rings.lazy_series_ring'
|
|
1148
|
+
display_length = dict(default=7,
|
|
1149
|
+
description='the number of coefficients to display from the valuation',
|
|
1150
|
+
checker=lambda x: x in ZZ and x > 0)
|
|
1151
|
+
constant_length = dict(default=3,
|
|
1152
|
+
description='the number of coefficients to display for nonzero constant series',
|
|
1153
|
+
checker=lambda x: x in ZZ and x > 0)
|
|
1154
|
+
halting_precision = dict(default=None,
|
|
1155
|
+
description='the number of coefficients, beginning with the approximate valuation, to check in equality tests',
|
|
1156
|
+
checker=lambda x: x is None or x in ZZ and x > 0)
|
|
1157
|
+
secure = dict(default=False,
|
|
1158
|
+
description='whether to raise an error when a comparison is unknown',
|
|
1159
|
+
checker=lambda x: x is True or x is False)
|
|
1160
|
+
|
|
1161
|
+
@cached_method
|
|
1162
|
+
def one(self):
|
|
1163
|
+
r"""
|
|
1164
|
+
Return the constant series `1`.
|
|
1165
|
+
|
|
1166
|
+
EXAMPLES::
|
|
1167
|
+
|
|
1168
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
1169
|
+
sage: L.one()
|
|
1170
|
+
1
|
|
1171
|
+
|
|
1172
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'z')
|
|
1173
|
+
sage: L.one()
|
|
1174
|
+
1
|
|
1175
|
+
|
|
1176
|
+
sage: m = SymmetricFunctions(ZZ).m() # needs sage.combinat sage.modules
|
|
1177
|
+
sage: L = LazySymmetricFunctions(m) # needs sage.combinat sage.modules
|
|
1178
|
+
sage: L.one() # needs sage.combinat sage.modules
|
|
1179
|
+
m[]
|
|
1180
|
+
"""
|
|
1181
|
+
R = self.base_ring()
|
|
1182
|
+
coeff_stream = Stream_exact([R.one()], constant=R.zero(), order=0)
|
|
1183
|
+
return self.element_class(self, coeff_stream)
|
|
1184
|
+
|
|
1185
|
+
@cached_method
|
|
1186
|
+
def zero(self):
|
|
1187
|
+
r"""
|
|
1188
|
+
Return the zero series.
|
|
1189
|
+
|
|
1190
|
+
EXAMPLES::
|
|
1191
|
+
|
|
1192
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
1193
|
+
sage: L.zero()
|
|
1194
|
+
0
|
|
1195
|
+
|
|
1196
|
+
sage: s = SymmetricFunctions(ZZ).s() # needs sage.combinat sage.modules
|
|
1197
|
+
sage: L = LazySymmetricFunctions(s) # needs sage.combinat sage.modules
|
|
1198
|
+
sage: L.zero() # needs sage.combinat sage.modules
|
|
1199
|
+
0
|
|
1200
|
+
|
|
1201
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
1202
|
+
sage: L.zero()
|
|
1203
|
+
0
|
|
1204
|
+
|
|
1205
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'z')
|
|
1206
|
+
sage: L.zero()
|
|
1207
|
+
0
|
|
1208
|
+
"""
|
|
1209
|
+
return self.element_class(self, Stream_zero())
|
|
1210
|
+
|
|
1211
|
+
def characteristic(self):
|
|
1212
|
+
"""
|
|
1213
|
+
Return the characteristic of this lazy power series ring, which
|
|
1214
|
+
is the same as the characteristic of its base ring.
|
|
1215
|
+
|
|
1216
|
+
EXAMPLES::
|
|
1217
|
+
|
|
1218
|
+
sage: L.<t> = LazyLaurentSeriesRing(ZZ)
|
|
1219
|
+
sage: L.characteristic()
|
|
1220
|
+
0
|
|
1221
|
+
|
|
1222
|
+
sage: R.<w> = LazyLaurentSeriesRing(GF(11)); R
|
|
1223
|
+
Lazy Laurent Series Ring in w over Finite Field of size 11
|
|
1224
|
+
sage: R.characteristic()
|
|
1225
|
+
11
|
|
1226
|
+
|
|
1227
|
+
sage: R.<x, y> = LazyPowerSeriesRing(GF(7)); R
|
|
1228
|
+
Multivariate Lazy Taylor Series Ring in x, y over Finite Field of size 7
|
|
1229
|
+
sage: R.characteristic()
|
|
1230
|
+
7
|
|
1231
|
+
|
|
1232
|
+
sage: L = LazyDirichletSeriesRing(ZZ, "s")
|
|
1233
|
+
sage: L.characteristic()
|
|
1234
|
+
0
|
|
1235
|
+
"""
|
|
1236
|
+
return self.base_ring().characteristic()
|
|
1237
|
+
|
|
1238
|
+
def _coerce_map_from_(self, S):
|
|
1239
|
+
"""
|
|
1240
|
+
Return ``True`` if a coercion from ``S`` exists.
|
|
1241
|
+
|
|
1242
|
+
EXAMPLES::
|
|
1243
|
+
|
|
1244
|
+
sage: L = LazyLaurentSeriesRing(GF(2), 'z')
|
|
1245
|
+
sage: L.has_coerce_map_from(ZZ)
|
|
1246
|
+
True
|
|
1247
|
+
sage: L.has_coerce_map_from(GF(2))
|
|
1248
|
+
True
|
|
1249
|
+
sage: R = LazyPowerSeriesRing(ZZ, 'z')
|
|
1250
|
+
sage: L.has_coerce_map_from(R)
|
|
1251
|
+
True
|
|
1252
|
+
|
|
1253
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
1254
|
+
sage: R = LazyPowerSeriesRing(QQ, 'z')
|
|
1255
|
+
sage: L.has_coerce_map_from(R)
|
|
1256
|
+
True
|
|
1257
|
+
sage: R = LazyPowerSeriesRing(ZZ, 'z')
|
|
1258
|
+
sage: L.has_coerce_map_from(R)
|
|
1259
|
+
True
|
|
1260
|
+
sage: R = LazyPowerSeriesRing(ZZ['t'], 'z')
|
|
1261
|
+
sage: L.has_coerce_map_from(R)
|
|
1262
|
+
False
|
|
1263
|
+
|
|
1264
|
+
sage: L = LazyPowerSeriesRing(GF(2), 'z')
|
|
1265
|
+
sage: L.has_coerce_map_from(ZZ)
|
|
1266
|
+
True
|
|
1267
|
+
sage: L.has_coerce_map_from(GF(2))
|
|
1268
|
+
True
|
|
1269
|
+
|
|
1270
|
+
sage: # needs sage.combinat sage.modules
|
|
1271
|
+
sage: s = SymmetricFunctions(GF(2)).s()
|
|
1272
|
+
sage: L = LazySymmetricFunctions(s)
|
|
1273
|
+
sage: L.has_coerce_map_from(ZZ)
|
|
1274
|
+
True
|
|
1275
|
+
sage: L.has_coerce_map_from(GF(2))
|
|
1276
|
+
True
|
|
1277
|
+
"""
|
|
1278
|
+
if self.base_ring().has_coerce_map_from(S):
|
|
1279
|
+
return True
|
|
1280
|
+
|
|
1281
|
+
R = self._laurent_poly_ring
|
|
1282
|
+
if R.has_coerce_map_from(S):
|
|
1283
|
+
return True
|
|
1284
|
+
|
|
1285
|
+
if (isinstance(S, LazySeriesRing)
|
|
1286
|
+
and self._laurent_poly_ring.has_coerce_map_from(S._laurent_poly_ring)):
|
|
1287
|
+
return True
|
|
1288
|
+
|
|
1289
|
+
return None
|
|
1290
|
+
|
|
1291
|
+
def _coerce_map_from_base_ring(self):
|
|
1292
|
+
"""
|
|
1293
|
+
Return a coercion map from the base ring of ``self``.
|
|
1294
|
+
|
|
1295
|
+
EXAMPLES::
|
|
1296
|
+
|
|
1297
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
1298
|
+
sage: phi = L._coerce_map_from_base_ring()
|
|
1299
|
+
sage: phi(2)
|
|
1300
|
+
2
|
|
1301
|
+
sage: phi(2, valuation=-2)
|
|
1302
|
+
2*z^-2
|
|
1303
|
+
sage: phi(2, valuation=-2, constant=3, degree=1)
|
|
1304
|
+
2*z^-2 + 3*z + 3*z^2 + 3*z^3 + O(z^4)
|
|
1305
|
+
|
|
1306
|
+
sage: L = LazyDirichletSeriesRing(QQ, 'z')
|
|
1307
|
+
sage: phi = L._coerce_map_from_base_ring()
|
|
1308
|
+
sage: m = phi(2)
|
|
1309
|
+
sage: m # needs sage.symbolic
|
|
1310
|
+
2
|
|
1311
|
+
sage: m = phi(2, valuation=2)
|
|
1312
|
+
sage: m # needs sage.symbolic
|
|
1313
|
+
2/2^z
|
|
1314
|
+
sage: m = phi(2, valuation=2, constant=4)
|
|
1315
|
+
sage: m # needs sage.symbolic
|
|
1316
|
+
2/2^z + 4/3^z + 4/4^z + 4/5^z + O(1/(6^z))
|
|
1317
|
+
"""
|
|
1318
|
+
# Return a DefaultConvertMap_unique; this can pass additional
|
|
1319
|
+
# arguments to _element_constructor_, unlike the map returned
|
|
1320
|
+
# by UnitalAlgebras.ParentMethods._coerce_map_from_base_ring.
|
|
1321
|
+
return self._generic_coerce_map(self.base_ring())
|
|
1322
|
+
|
|
1323
|
+
def is_sparse(self):
|
|
1324
|
+
"""
|
|
1325
|
+
Return whether ``self`` is sparse or not.
|
|
1326
|
+
|
|
1327
|
+
EXAMPLES::
|
|
1328
|
+
|
|
1329
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z', sparse=False)
|
|
1330
|
+
sage: L.is_sparse()
|
|
1331
|
+
False
|
|
1332
|
+
|
|
1333
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z', sparse=True)
|
|
1334
|
+
sage: L.is_sparse()
|
|
1335
|
+
True
|
|
1336
|
+
"""
|
|
1337
|
+
return self._sparse
|
|
1338
|
+
|
|
1339
|
+
def is_exact(self):
|
|
1340
|
+
"""
|
|
1341
|
+
Return if ``self`` is exact or not.
|
|
1342
|
+
|
|
1343
|
+
EXAMPLES::
|
|
1344
|
+
|
|
1345
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
1346
|
+
sage: L.is_exact()
|
|
1347
|
+
True
|
|
1348
|
+
sage: L = LazyLaurentSeriesRing(RR, 'z')
|
|
1349
|
+
sage: L.is_exact()
|
|
1350
|
+
False
|
|
1351
|
+
"""
|
|
1352
|
+
return self.base_ring().is_exact()
|
|
1353
|
+
|
|
1354
|
+
def prod(self, f, a=None, b=infinity, add_one=False):
|
|
1355
|
+
r"""
|
|
1356
|
+
The product of elements of ``self``.
|
|
1357
|
+
|
|
1358
|
+
INPUT:
|
|
1359
|
+
|
|
1360
|
+
- ``f`` -- list (or iterable) of elements of ``self``
|
|
1361
|
+
- ``a``, ``b`` -- optional arguments
|
|
1362
|
+
- ``add_one`` -- (default: ``False``) if ``True``, then converts a
|
|
1363
|
+
lazy series `p_i` from ``args`` into `1 + p_i` for the product
|
|
1364
|
+
|
|
1365
|
+
If ``a`` and ``b`` are both integers, then this returns the product
|
|
1366
|
+
`\prod_{i=a}^b f(i)`, where `f(i) = p_i` if ``add_one=False`` or
|
|
1367
|
+
`f(i) = 1 + p_i` otherwise. If ``b`` is not specified, then we consider
|
|
1368
|
+
`b = \infty`. Note this corresponds to the Python ``range(a, b+1)``.
|
|
1369
|
+
|
|
1370
|
+
If `a` is any other iterable, then this returns the product
|
|
1371
|
+
`\prod_{i \in a} f(i)`, where `f(i) = p_i` if ``add_one=False`` or
|
|
1372
|
+
`f(i) = 1 + p_i`.
|
|
1373
|
+
|
|
1374
|
+
.. NOTE::
|
|
1375
|
+
|
|
1376
|
+
For infinite products, it is faster to use ``add_one=True`` since
|
|
1377
|
+
the implementation is based on `p_i` in `\prod_i (1 + p_i)`.
|
|
1378
|
+
|
|
1379
|
+
.. WARNING::
|
|
1380
|
+
|
|
1381
|
+
When ``f`` is an infinite generator, then the first argument
|
|
1382
|
+
``a`` must be ``True``. Otherwise this will loop forever.
|
|
1383
|
+
|
|
1384
|
+
.. WARNING::
|
|
1385
|
+
|
|
1386
|
+
For an *infinite* product of the form `\prod_i (1 + p_i)`,
|
|
1387
|
+
if `p_i = 0`, then this will loop forever.
|
|
1388
|
+
|
|
1389
|
+
EXAMPLES::
|
|
1390
|
+
|
|
1391
|
+
sage: L.<t> = LazyLaurentSeriesRing(QQ)
|
|
1392
|
+
sage: euler = L.prod(lambda n: 1 - t^n, PositiveIntegers())
|
|
1393
|
+
sage: euler
|
|
1394
|
+
1 - t - t^2 + t^5 + O(t^7)
|
|
1395
|
+
sage: 1 / euler
|
|
1396
|
+
1 + t + 2*t^2 + 3*t^3 + 5*t^4 + 7*t^5 + 11*t^6 + O(t^7)
|
|
1397
|
+
sage: euler - L.euler()
|
|
1398
|
+
O(t^7)
|
|
1399
|
+
sage: L.prod(lambda n: -t^n, 1, add_one=True)
|
|
1400
|
+
1 - t - t^2 + t^5 + O(t^7)
|
|
1401
|
+
|
|
1402
|
+
sage: L.prod((1 - t^n for n in PositiveIntegers()), True)
|
|
1403
|
+
1 - t - t^2 + t^5 + O(t^7)
|
|
1404
|
+
sage: L.prod((-t^n for n in PositiveIntegers()), True, add_one=True)
|
|
1405
|
+
1 - t - t^2 + t^5 + O(t^7)
|
|
1406
|
+
|
|
1407
|
+
sage: L.prod((1 + t^(n-3) for n in PositiveIntegers()), True)
|
|
1408
|
+
2*t^-3 + 4*t^-2 + 4*t^-1 + 4 + 6*t + 10*t^2 + 16*t^3 + O(t^4)
|
|
1409
|
+
|
|
1410
|
+
sage: L.prod(lambda n: 2 + t^n, -3, 5)
|
|
1411
|
+
96*t^-6 + 240*t^-5 + 336*t^-4 + 840*t^-3 + 984*t^-2 + 1248*t^-1
|
|
1412
|
+
+ 1980 + 1668*t + 1824*t^2 + 1872*t^3 + 1782*t^4 + 1710*t^5
|
|
1413
|
+
+ 1314*t^6 + 1122*t^7 + 858*t^8 + 711*t^9 + 438*t^10 + 282*t^11
|
|
1414
|
+
+ 210*t^12 + 84*t^13 + 60*t^14 + 24*t^15
|
|
1415
|
+
sage: L.prod(lambda n: t^n / (1 + abs(n)), -2, 2, add_one=True)
|
|
1416
|
+
1/3*t^-3 + 5/6*t^-2 + 13/9*t^-1 + 25/9 + 13/9*t + 5/6*t^2 + 1/3*t^3
|
|
1417
|
+
sage: L.prod(lambda n: t^-2 + t^n / n, -4, -2)
|
|
1418
|
+
1/24*t^-9 - 1/8*t^-8 - 1/6*t^-7 + 1/2*t^-6
|
|
1419
|
+
|
|
1420
|
+
sage: # needs sage.libs.pari sage.symbolic
|
|
1421
|
+
sage: D = LazyDirichletSeriesRing(QQ, "s")
|
|
1422
|
+
sage: D.prod(lambda p: (1+D(1, valuation=p)).inverse(), Primes())
|
|
1423
|
+
1 - 1/(2^s) - 1/(3^s) + 1/(4^s) - 1/(5^s) + 1/(6^s) - 1/(7^s) + O(1/(8^s))
|
|
1424
|
+
sage: D.prod(lambda p: D(1, valuation=p), Primes(), add_one=True)
|
|
1425
|
+
1 + 1/(2^s) + 1/(3^s) + 1/(5^s) + 1/(6^s) + 1/(7^s) + O(1/(8^s))
|
|
1426
|
+
"""
|
|
1427
|
+
if a is None:
|
|
1428
|
+
if add_one:
|
|
1429
|
+
return super().prod(self.one() + g for g in f)
|
|
1430
|
+
return super().prod(f)
|
|
1431
|
+
|
|
1432
|
+
if a is True:
|
|
1433
|
+
it = f
|
|
1434
|
+
elif a in ZZ:
|
|
1435
|
+
if b != infinity:
|
|
1436
|
+
if add_one:
|
|
1437
|
+
return super().prod(self.one() + f(i) for i in range(a, b+1))
|
|
1438
|
+
return super().prod(f(i) for i in range(a, b+1))
|
|
1439
|
+
from sage.sets.non_negative_integers import NonNegativeIntegers
|
|
1440
|
+
it = (f(i+a) for i in NonNegativeIntegers())
|
|
1441
|
+
else:
|
|
1442
|
+
it = (f(i) for i in a)
|
|
1443
|
+
|
|
1444
|
+
# NOTE: We must have a new variable name for each new iterator
|
|
1445
|
+
if not add_one:
|
|
1446
|
+
data = (g - self.one() for g in it)
|
|
1447
|
+
else:
|
|
1448
|
+
data = it
|
|
1449
|
+
|
|
1450
|
+
from sage.data_structures.stream import Stream_infinite_product
|
|
1451
|
+
coeff_stream = Stream_infinite_product(data)
|
|
1452
|
+
return self.element_class(self, coeff_stream)
|
|
1453
|
+
|
|
1454
|
+
def sum(self, f, a=None, b=infinity):
|
|
1455
|
+
r"""
|
|
1456
|
+
The sum of elements of ``self``.
|
|
1457
|
+
|
|
1458
|
+
INPUT:
|
|
1459
|
+
|
|
1460
|
+
- ``f`` -- list (or iterable or function) of elements of ``self``
|
|
1461
|
+
- ``a``, ``b`` -- optional arguments
|
|
1462
|
+
|
|
1463
|
+
If ``a`` and ``b`` are both integers, then this returns the sum
|
|
1464
|
+
`\sum_{i=a}^b f(i)`. If ``b`` is not specified, then we consider
|
|
1465
|
+
`b = \infty`. Note this corresponds to the Python ``range(a, b+1)``.
|
|
1466
|
+
|
|
1467
|
+
If `a` is any other iterable, then this returns the sum
|
|
1468
|
+
`\sum{i \in a} f(i)`.
|
|
1469
|
+
|
|
1470
|
+
.. WARNING::
|
|
1471
|
+
|
|
1472
|
+
When ``f`` is an infinite generator, then the first argument
|
|
1473
|
+
``a`` must be ``True``. Otherwise this will loop forever.
|
|
1474
|
+
|
|
1475
|
+
.. WARNING::
|
|
1476
|
+
|
|
1477
|
+
For an *infinite* sum of the form `\sum_i s_i`,
|
|
1478
|
+
if `s_i = 0`, then this will loop forever.
|
|
1479
|
+
|
|
1480
|
+
EXAMPLES::
|
|
1481
|
+
|
|
1482
|
+
sage: L.<t> = LazyLaurentSeriesRing(QQ)
|
|
1483
|
+
sage: L.sum(lambda n: t^n / (n+1), PositiveIntegers())
|
|
1484
|
+
1/2*t + 1/3*t^2 + 1/4*t^3 + 1/5*t^4 + 1/6*t^5 + 1/7*t^6 + 1/8*t^7 + O(t^8)
|
|
1485
|
+
|
|
1486
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
1487
|
+
sage: T = L.undefined(1)
|
|
1488
|
+
sage: D = L.undefined(0)
|
|
1489
|
+
sage: H = L.sum(lambda k: T(z^k)/k, 2)
|
|
1490
|
+
sage: T.define(z*exp(T)*D)
|
|
1491
|
+
sage: D.define(exp(H))
|
|
1492
|
+
sage: T
|
|
1493
|
+
z + z^2 + 2*z^3 + 4*z^4 + 9*z^5 + 20*z^6 + 48*z^7 + O(z^8)
|
|
1494
|
+
sage: D
|
|
1495
|
+
1 + 1/2*z^2 + 1/3*z^3 + 7/8*z^4 + 11/30*z^5 + 281/144*z^6 + O(z^7)
|
|
1496
|
+
|
|
1497
|
+
We verify the Rogers-Ramanujan identities up to degree 100::
|
|
1498
|
+
|
|
1499
|
+
sage: L.<q> = LazyPowerSeriesRing(QQ)
|
|
1500
|
+
sage: Gpi = L.prod(lambda k: -q^(1+5*k), 0, oo, add_one=True)
|
|
1501
|
+
sage: Gpi *= L.prod(lambda k: -q^(4+5*k), 0, oo, add_one=True)
|
|
1502
|
+
sage: Gp = 1 / Gpi
|
|
1503
|
+
sage: G = L.sum(lambda n: q^(n^2) / prod(1 - q^(k+1) for k in range(n)), 0, oo)
|
|
1504
|
+
sage: G - Gp
|
|
1505
|
+
O(q^7)
|
|
1506
|
+
sage: all(G[k] == Gp[k] for k in range(100))
|
|
1507
|
+
True
|
|
1508
|
+
|
|
1509
|
+
sage: Hpi = L.prod(lambda k: -q^(2+5*k), 0, oo, add_one=True)
|
|
1510
|
+
sage: Hpi *= L.prod(lambda k: -q^(3+5*k), 0, oo, add_one=True)
|
|
1511
|
+
sage: Hp = 1 / Hpi
|
|
1512
|
+
sage: H = L.sum(lambda n: q^(n^2+n) / prod(1 - q^(k+1) for k in range(n)), 0, oo)
|
|
1513
|
+
sage: H - Hp
|
|
1514
|
+
O(q^7)
|
|
1515
|
+
sage: all(H[k] == Hp[k] for k in range(100))
|
|
1516
|
+
True
|
|
1517
|
+
|
|
1518
|
+
::
|
|
1519
|
+
|
|
1520
|
+
sage: # needs sage.libs.pari sage.symbolic
|
|
1521
|
+
sage: D = LazyDirichletSeriesRing(QQ, "s")
|
|
1522
|
+
sage: D.sum(lambda p: D(1, valuation=p), Primes())
|
|
1523
|
+
1/(2^s) + 1/(3^s) + 1/(5^s) + 1/(7^s) + O(1/(9^s))
|
|
1524
|
+
"""
|
|
1525
|
+
if a is None:
|
|
1526
|
+
return super().sum(f)
|
|
1527
|
+
|
|
1528
|
+
if a is True:
|
|
1529
|
+
it = f
|
|
1530
|
+
elif a in ZZ:
|
|
1531
|
+
if b != infinity:
|
|
1532
|
+
return super().sum(f(i) for i in range(a, b+1))
|
|
1533
|
+
from sage.sets.non_negative_integers import NonNegativeIntegers
|
|
1534
|
+
it = (f(i+a) for i in NonNegativeIntegers())
|
|
1535
|
+
else:
|
|
1536
|
+
it = (f(i) for i in a)
|
|
1537
|
+
|
|
1538
|
+
from sage.data_structures.stream import Stream_infinite_sum
|
|
1539
|
+
coeff_stream = Stream_infinite_sum(it)
|
|
1540
|
+
return self.element_class(self, coeff_stream)
|
|
1541
|
+
|
|
1542
|
+
def _test_invert(self, **options):
|
|
1543
|
+
"""
|
|
1544
|
+
Test multiplicative inversion of elements of ``self``.
|
|
1545
|
+
|
|
1546
|
+
INPUT:
|
|
1547
|
+
|
|
1548
|
+
- ``options`` -- any keyword arguments accepted by :meth:`_tester`
|
|
1549
|
+
|
|
1550
|
+
EXAMPLES::
|
|
1551
|
+
|
|
1552
|
+
sage: LazyLaurentSeriesRing.options.halting_precision(5)
|
|
1553
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
1554
|
+
sage: L._test_invert()
|
|
1555
|
+
sage: LazyLaurentSeriesRing.options._reset() # reset the options
|
|
1556
|
+
|
|
1557
|
+
.. SEEALSO::
|
|
1558
|
+
|
|
1559
|
+
:class:`TestSuite`
|
|
1560
|
+
"""
|
|
1561
|
+
tester = self._tester(**options)
|
|
1562
|
+
|
|
1563
|
+
elements = tester.some_elements()
|
|
1564
|
+
for x in elements:
|
|
1565
|
+
# because of laziness, creating the inverse of x should
|
|
1566
|
+
# always succeed except if the series is 'exact'
|
|
1567
|
+
if not x.is_unit():
|
|
1568
|
+
continue
|
|
1569
|
+
y = ~x
|
|
1570
|
+
e = y * x
|
|
1571
|
+
tester.assertFalse(x.is_zero(), "zero should not be invertible")
|
|
1572
|
+
tester.assertTrue(e.is_one(), "an element (%s) times its inverse should be 1" % x)
|
|
1573
|
+
tester.assertEqual(y.valuation(), -x.valuation(), "the valuation of the inverse should be the negative of the valuation of the element (%s)" % x)
|
|
1574
|
+
|
|
1575
|
+
def _test_div(self, **options):
|
|
1576
|
+
r"""
|
|
1577
|
+
Test division of elements of this ring.
|
|
1578
|
+
|
|
1579
|
+
INPUT:
|
|
1580
|
+
|
|
1581
|
+
- ``options`` -- any keyword arguments accepted by :meth:`_tester`
|
|
1582
|
+
|
|
1583
|
+
EXAMPLES::
|
|
1584
|
+
|
|
1585
|
+
sage: LazyLaurentSeriesRing.options.halting_precision(5)
|
|
1586
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
1587
|
+
sage: L._test_div()
|
|
1588
|
+
sage: LazyLaurentSeriesRing.options._reset() # reset the options
|
|
1589
|
+
|
|
1590
|
+
.. SEEALSO::
|
|
1591
|
+
|
|
1592
|
+
:class:`TestSuite`
|
|
1593
|
+
"""
|
|
1594
|
+
from sage.misc.misc import some_tuples
|
|
1595
|
+
tester = self._tester(**options)
|
|
1596
|
+
|
|
1597
|
+
elements = list(tester.some_elements())
|
|
1598
|
+
for x, y in some_tuples(elements, 2, tester._max_runs):
|
|
1599
|
+
# because of laziness, creating the inverse of x should
|
|
1600
|
+
# always succeed except if the series is 'exact'
|
|
1601
|
+
if not y.is_unit():
|
|
1602
|
+
continue
|
|
1603
|
+
z = x / y
|
|
1604
|
+
xx = z * y
|
|
1605
|
+
try:
|
|
1606
|
+
v_z = z.valuation()
|
|
1607
|
+
except Exception as error:
|
|
1608
|
+
raise ValueError("could not compute the valuation of the quotient (%s)/(%s): %s" % (x, y, error))
|
|
1609
|
+
else:
|
|
1610
|
+
v_x = x.valuation()
|
|
1611
|
+
v_y = y.valuation()
|
|
1612
|
+
tester.assertEqual(v_z, v_x - v_y, "the valuation of the quotient should be the difference of the valuations of the elements (%s and %s)" % (x, y))
|
|
1613
|
+
tester.assertEqual(xx, x, "the element (%s) should be the quotient times the divisor (%s)" % (x, y))
|
|
1614
|
+
|
|
1615
|
+
def _test_revert(self, **options):
|
|
1616
|
+
"""
|
|
1617
|
+
Test compositional inverse of elements of this ring.
|
|
1618
|
+
|
|
1619
|
+
INPUT:
|
|
1620
|
+
|
|
1621
|
+
- ``options`` -- any keyword arguments accepted by :meth:`_tester`
|
|
1622
|
+
|
|
1623
|
+
EXAMPLES::
|
|
1624
|
+
|
|
1625
|
+
sage: LazyLaurentSeriesRing.options.halting_precision(5)
|
|
1626
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
1627
|
+
sage: L._test_revert()
|
|
1628
|
+
sage: LazyLaurentSeriesRing.options._reset()
|
|
1629
|
+
|
|
1630
|
+
.. SEEALSO::
|
|
1631
|
+
|
|
1632
|
+
:class:`TestSuite`
|
|
1633
|
+
"""
|
|
1634
|
+
if not hasattr(self.element_class, "revert") or self._arity != 1:
|
|
1635
|
+
return
|
|
1636
|
+
tester = self._tester(**options)
|
|
1637
|
+
|
|
1638
|
+
elements = tester.some_elements()
|
|
1639
|
+
count = 0
|
|
1640
|
+
for x in elements:
|
|
1641
|
+
# because of laziness, creating the compositional inverse
|
|
1642
|
+
# of x should always succeed, except if the series is
|
|
1643
|
+
# 'exact' or if it has negative valuation
|
|
1644
|
+
vx = x.valuation()
|
|
1645
|
+
if (vx != 1
|
|
1646
|
+
and not (isinstance(x._coeff_stream, Stream_exact)
|
|
1647
|
+
and ((vx == 0
|
|
1648
|
+
and x._coeff_stream._degree == 2
|
|
1649
|
+
and not x._coeff_stream._constant)
|
|
1650
|
+
or (vx == -1
|
|
1651
|
+
and x._coeff_stream._degree == 0
|
|
1652
|
+
and not x._coeff_stream._constant)))):
|
|
1653
|
+
continue
|
|
1654
|
+
try:
|
|
1655
|
+
y = x.revert()
|
|
1656
|
+
except Exception as error:
|
|
1657
|
+
raise AssertionError("compositional inverse of %s should exist: %s" % (x, error))
|
|
1658
|
+
try:
|
|
1659
|
+
vy = y.valuation()
|
|
1660
|
+
_ = y[vy]
|
|
1661
|
+
except NotImplementedError:
|
|
1662
|
+
pass
|
|
1663
|
+
except (ValueError, TypeError):
|
|
1664
|
+
tester.assertFalse(vx == 1 and x[vx].is_unit(),
|
|
1665
|
+
("the series %s should be reversible "
|
|
1666
|
+
"- its valuation is one and its leading coefficient is a unit") % x)
|
|
1667
|
+
else:
|
|
1668
|
+
count += 1
|
|
1669
|
+
e1 = y(x)
|
|
1670
|
+
e2 = x(y)
|
|
1671
|
+
tester.assertEqual(e1, e2, "y(x) and x(y) differ for x = %s and y = %s" % (x, y))
|
|
1672
|
+
# tester.assertEqual(e1, self.gen())
|
|
1673
|
+
# we want to test at least 2 elements
|
|
1674
|
+
tester.assertGreater(count, 1, msg="only %s elements in %s.some_elements() have a compositional inverse" % (count, self))
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
class LazyLaurentSeriesRing(LazySeriesRing):
|
|
1678
|
+
r"""
|
|
1679
|
+
The ring of lazy Laurent series.
|
|
1680
|
+
|
|
1681
|
+
The ring of Laurent series over a ring with the usual arithmetic
|
|
1682
|
+
where the coefficients are computed lazily.
|
|
1683
|
+
|
|
1684
|
+
INPUT:
|
|
1685
|
+
|
|
1686
|
+
- ``base_ring`` -- base ring
|
|
1687
|
+
- ``names`` -- name of the generator
|
|
1688
|
+
- ``sparse`` -- boolean (default: ``True``); whether the implementation of
|
|
1689
|
+
the series is sparse or not
|
|
1690
|
+
|
|
1691
|
+
EXAMPLES::
|
|
1692
|
+
|
|
1693
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
1694
|
+
sage: 1 / (1 - z)
|
|
1695
|
+
1 + z + z^2 + O(z^3)
|
|
1696
|
+
sage: 1 / (1 - z) == 1 / (1 - z)
|
|
1697
|
+
True
|
|
1698
|
+
sage: L in Fields
|
|
1699
|
+
True
|
|
1700
|
+
|
|
1701
|
+
Lazy Laurent series ring over a finite field::
|
|
1702
|
+
|
|
1703
|
+
sage: # needs sage.rings.finite_rings
|
|
1704
|
+
sage: L.<z> = LazyLaurentSeriesRing(GF(3)); L
|
|
1705
|
+
Lazy Laurent Series Ring in z over Finite Field of size 3
|
|
1706
|
+
sage: e = 1 / (1 + z)
|
|
1707
|
+
sage: e.coefficient(100)
|
|
1708
|
+
1
|
|
1709
|
+
sage: e.coefficient(100).parent()
|
|
1710
|
+
Finite Field of size 3
|
|
1711
|
+
|
|
1712
|
+
Series can be defined by specifying a coefficient function
|
|
1713
|
+
and a valuation::
|
|
1714
|
+
|
|
1715
|
+
sage: R.<x,y> = QQ[]
|
|
1716
|
+
sage: L.<z> = LazyLaurentSeriesRing(R)
|
|
1717
|
+
sage: def coeff(n):
|
|
1718
|
+
....: if n < 0:
|
|
1719
|
+
....: return -2 + n
|
|
1720
|
+
....: if n == 0:
|
|
1721
|
+
....: return 6
|
|
1722
|
+
....: return x + y^n
|
|
1723
|
+
sage: f = L(coeff, valuation=-5)
|
|
1724
|
+
sage: f
|
|
1725
|
+
-7*z^-5 - 6*z^-4 - 5*z^-3 - 4*z^-2 - 3*z^-1 + 6 + (x + y)*z + O(z^2)
|
|
1726
|
+
sage: 1 / (1 - f)
|
|
1727
|
+
1/7*z^5 - 6/49*z^6 + 1/343*z^7 + 8/2401*z^8 + 64/16807*z^9
|
|
1728
|
+
+ 17319/117649*z^10 + (1/49*x + 1/49*y - 180781/823543)*z^11 + O(z^12)
|
|
1729
|
+
sage: L(coeff, valuation=-3, degree=3, constant=x)
|
|
1730
|
+
-5*z^-3 - 4*z^-2 - 3*z^-1 + 6 + (x + y)*z + (y^2 + x)*z^2
|
|
1731
|
+
+ x*z^3 + x*z^4 + x*z^5 + O(z^6)
|
|
1732
|
+
|
|
1733
|
+
We can also specify a polynomial or the initial coefficients.
|
|
1734
|
+
Additionally, we may specify that all coefficients are equal to a
|
|
1735
|
+
given constant, beginning at a given degree::
|
|
1736
|
+
|
|
1737
|
+
sage: L([1, x, y, 0, x+y])
|
|
1738
|
+
1 + x*z + y*z^2 + (x + y)*z^4
|
|
1739
|
+
sage: L([1, x, y, 0, x+y], constant=2)
|
|
1740
|
+
1 + x*z + y*z^2 + (x + y)*z^4 + 2*z^5 + 2*z^6 + 2*z^7 + O(z^8)
|
|
1741
|
+
sage: L([1, x, y, 0, x+y], degree=7, constant=2)
|
|
1742
|
+
1 + x*z + y*z^2 + (x + y)*z^4 + 2*z^7 + 2*z^8 + 2*z^9 + O(z^10)
|
|
1743
|
+
sage: L([1, x, y, 0, x+y], valuation=-2)
|
|
1744
|
+
z^-2 + x*z^-1 + y + (x + y)*z^2
|
|
1745
|
+
sage: L([1, x, y, 0, x+y], valuation=-2, constant=3)
|
|
1746
|
+
z^-2 + x*z^-1 + y + (x + y)*z^2 + 3*z^3 + 3*z^4 + 3*z^5 + O(z^6)
|
|
1747
|
+
sage: L([1, x, y, 0, x+y], valuation=-2, degree=4, constant=3)
|
|
1748
|
+
z^-2 + x*z^-1 + y + (x + y)*z^2 + 3*z^4 + 3*z^5 + 3*z^6 + O(z^7)
|
|
1749
|
+
|
|
1750
|
+
Some additional examples over the integer ring::
|
|
1751
|
+
|
|
1752
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
1753
|
+
sage: L in Fields
|
|
1754
|
+
False
|
|
1755
|
+
sage: 1 / (1 - 2*z)^3
|
|
1756
|
+
1 + 6*z + 24*z^2 + 80*z^3 + 240*z^4 + 672*z^5 + 1792*z^6 + O(z^7)
|
|
1757
|
+
|
|
1758
|
+
sage: R.<x> = LaurentPolynomialRing(ZZ)
|
|
1759
|
+
sage: L(x^-2 + 3 + x)
|
|
1760
|
+
z^-2 + 3 + z
|
|
1761
|
+
sage: L(x^-2 + 3 + x, valuation=-5, constant=2)
|
|
1762
|
+
z^-5 + 3*z^-3 + z^-2 + 2*z^-1 + 2 + 2*z + O(z^2)
|
|
1763
|
+
sage: L(x^-2 + 3 + x, valuation=-5, degree=0, constant=2)
|
|
1764
|
+
z^-5 + 3*z^-3 + z^-2 + 2 + 2*z + 2*z^2 + O(z^3)
|
|
1765
|
+
|
|
1766
|
+
We can truncate a series, shift its coefficients, or replace all
|
|
1767
|
+
coefficients beginning with a given degree by a constant::
|
|
1768
|
+
|
|
1769
|
+
sage: f = 1 / (z + z^2)
|
|
1770
|
+
sage: f
|
|
1771
|
+
z^-1 - 1 + z - z^2 + z^3 - z^4 + z^5 + O(z^6)
|
|
1772
|
+
sage: L(f, valuation=2)
|
|
1773
|
+
z^2 - z^3 + z^4 - z^5 + z^6 - z^7 + z^8 + O(z^9)
|
|
1774
|
+
sage: L(f, degree=3)
|
|
1775
|
+
z^-1 - 1 + z - z^2
|
|
1776
|
+
sage: L(f, degree=3, constant=2)
|
|
1777
|
+
z^-1 - 1 + z - z^2 + 2*z^3 + 2*z^4 + 2*z^5 + O(z^6)
|
|
1778
|
+
sage: L(f, valuation=1, degree=4)
|
|
1779
|
+
z - z^2 + z^3
|
|
1780
|
+
sage: L(f, valuation=1, degree=4, constant=5)
|
|
1781
|
+
z - z^2 + z^3 + 5*z^4 + 5*z^5 + 5*z^6 + O(z^7)
|
|
1782
|
+
|
|
1783
|
+
Power series can be defined recursively (see
|
|
1784
|
+
:meth:`sage.rings.lazy_series.LazyModuleElement.define` for
|
|
1785
|
+
more examples)::
|
|
1786
|
+
|
|
1787
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
1788
|
+
sage: s = L.undefined(valuation=0)
|
|
1789
|
+
sage: s.define(1 + z*s^2)
|
|
1790
|
+
sage: s
|
|
1791
|
+
1 + z + 2*z^2 + 5*z^3 + 14*z^4 + 42*z^5 + 132*z^6 + O(z^7)
|
|
1792
|
+
|
|
1793
|
+
By default, any two series ``f`` and ``g`` that are not known to
|
|
1794
|
+
be equal are considered to be different::
|
|
1795
|
+
|
|
1796
|
+
sage: f = L(lambda n: 0, valuation=0)
|
|
1797
|
+
sage: f == 0
|
|
1798
|
+
False
|
|
1799
|
+
|
|
1800
|
+
sage: f = L(constant=1, valuation=0).derivative(); f
|
|
1801
|
+
1 + 2*z + 3*z^2 + 4*z^3 + 5*z^4 + 6*z^5 + 7*z^6 + O(z^7)
|
|
1802
|
+
sage: g = L(lambda n: (n+1), valuation=0); g
|
|
1803
|
+
1 + 2*z + 3*z^2 + 4*z^3 + 5*z^4 + 6*z^5 + 7*z^6 + O(z^7)
|
|
1804
|
+
sage: f == g
|
|
1805
|
+
False
|
|
1806
|
+
|
|
1807
|
+
.. WARNING::
|
|
1808
|
+
|
|
1809
|
+
We have imposed that ``(f == g) == not (f != g)``, and so
|
|
1810
|
+
``f != g`` returning ``True`` might not mean that the two
|
|
1811
|
+
series are actually different::
|
|
1812
|
+
|
|
1813
|
+
sage: f = L(lambda n: 0, valuation=0)
|
|
1814
|
+
sage: g = L.zero()
|
|
1815
|
+
sage: f != g
|
|
1816
|
+
True
|
|
1817
|
+
|
|
1818
|
+
This can be verified by :meth:`~sage.rings.lazy_series.is_nonzero()`,
|
|
1819
|
+
which only returns ``True`` if the series is known to be nonzero::
|
|
1820
|
+
|
|
1821
|
+
sage: (f - g).is_nonzero()
|
|
1822
|
+
False
|
|
1823
|
+
|
|
1824
|
+
The implementation of the ring can be either be a sparse or a dense one.
|
|
1825
|
+
The default is a sparse implementation::
|
|
1826
|
+
|
|
1827
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
1828
|
+
sage: L.is_sparse()
|
|
1829
|
+
True
|
|
1830
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ, sparse=False)
|
|
1831
|
+
sage: L.is_sparse()
|
|
1832
|
+
False
|
|
1833
|
+
|
|
1834
|
+
We additionally provide two other methods of performing comparisons.
|
|
1835
|
+
The first is raising a :exc:`ValueError` and the second uses a check
|
|
1836
|
+
up to a (user set) finite precision. These behaviors are set using the
|
|
1837
|
+
options ``secure`` and ``halting_precision``. In particular,
|
|
1838
|
+
this applies to series that are not specified by a finite number
|
|
1839
|
+
of initial coefficients and a constant for the remaining coefficients.
|
|
1840
|
+
Equality checking will depend on the coefficients which have
|
|
1841
|
+
already been computed. If this information is not enough to
|
|
1842
|
+
check that two series are different, then if ``L.options.secure``
|
|
1843
|
+
is set to ``True``, then we raise a :exc:`ValueError`::
|
|
1844
|
+
|
|
1845
|
+
sage: L.options.secure = True
|
|
1846
|
+
sage: f = 1 / (z + z^2); f
|
|
1847
|
+
z^-1 - 1 + z - z^2 + z^3 - z^4 + z^5 + O(z^6)
|
|
1848
|
+
sage: f2 = f * 2 # currently no coefficients computed
|
|
1849
|
+
sage: f3 = f * 3 # currently no coefficients computed
|
|
1850
|
+
sage: f2 == f3
|
|
1851
|
+
Traceback (most recent call last):
|
|
1852
|
+
...
|
|
1853
|
+
ValueError: undecidable
|
|
1854
|
+
sage: f2 # computes some of the coefficients of f2
|
|
1855
|
+
2*z^-1 - 2 + 2*z - 2*z^2 + 2*z^3 - 2*z^4 + 2*z^5 + O(z^6)
|
|
1856
|
+
sage: f3 # computes some of the coefficients of f3
|
|
1857
|
+
3*z^-1 - 3 + 3*z - 3*z^2 + 3*z^3 - 3*z^4 + 3*z^5 + O(z^6)
|
|
1858
|
+
sage: f2 == f3
|
|
1859
|
+
False
|
|
1860
|
+
sage: f2a = f + f
|
|
1861
|
+
sage: f2 == f2a
|
|
1862
|
+
Traceback (most recent call last):
|
|
1863
|
+
...
|
|
1864
|
+
ValueError: undecidable
|
|
1865
|
+
sage: zf = L(lambda n: 0, valuation=0)
|
|
1866
|
+
sage: zf == 0
|
|
1867
|
+
Traceback (most recent call last):
|
|
1868
|
+
...
|
|
1869
|
+
ValueError: undecidable
|
|
1870
|
+
|
|
1871
|
+
For boolean checks, an error is raised when it is not known to be nonzero::
|
|
1872
|
+
|
|
1873
|
+
sage: bool(zf)
|
|
1874
|
+
Traceback (most recent call last):
|
|
1875
|
+
...
|
|
1876
|
+
ValueError: undecidable
|
|
1877
|
+
|
|
1878
|
+
If the halting precision is set to a finite number `p` (for unlimited
|
|
1879
|
+
precision, it is set to ``None``), then it will check up to `p` values
|
|
1880
|
+
from the current position::
|
|
1881
|
+
|
|
1882
|
+
sage: L.options.halting_precision = 20
|
|
1883
|
+
sage: f2 = f * 2 # currently no coefficients computed
|
|
1884
|
+
sage: f3 = f * 3 # currently no coefficients computed
|
|
1885
|
+
sage: f2 == f3
|
|
1886
|
+
False
|
|
1887
|
+
sage: f2a = f + f
|
|
1888
|
+
sage: f2 == f2a
|
|
1889
|
+
True
|
|
1890
|
+
sage: zf = L(lambda n: 0, valuation=0)
|
|
1891
|
+
sage: zf == 0
|
|
1892
|
+
True
|
|
1893
|
+
|
|
1894
|
+
TESTS:
|
|
1895
|
+
|
|
1896
|
+
We reset the options::
|
|
1897
|
+
|
|
1898
|
+
sage: L.options._reset()
|
|
1899
|
+
"""
|
|
1900
|
+
Element = LazyLaurentSeries
|
|
1901
|
+
|
|
1902
|
+
# Follow the "generic" normalization
|
|
1903
|
+
__classcall_private__ = LazySeriesRing.__classcall_private__
|
|
1904
|
+
|
|
1905
|
+
def __init__(self, base_ring, names, sparse=True, category=None):
|
|
1906
|
+
"""
|
|
1907
|
+
Initialize ``self``.
|
|
1908
|
+
|
|
1909
|
+
TESTS::
|
|
1910
|
+
|
|
1911
|
+
sage: LazyLaurentSeriesRing.options.halting_precision(12)
|
|
1912
|
+
|
|
1913
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 't')
|
|
1914
|
+
sage: TestSuite(L).run()
|
|
1915
|
+
sage: L.category()
|
|
1916
|
+
Category of infinite commutative no zero divisors algebras over
|
|
1917
|
+
(Dedekind domains and euclidean domains
|
|
1918
|
+
and noetherian rings
|
|
1919
|
+
and infinite enumerated sets and metric spaces)
|
|
1920
|
+
|
|
1921
|
+
sage: L = LazyLaurentSeriesRing(QQ, 't')
|
|
1922
|
+
sage: TestSuite(L).run()
|
|
1923
|
+
sage: L.category()
|
|
1924
|
+
Join of Category of complete discrete valuation fields
|
|
1925
|
+
and Category of commutative algebras over (number fields and quotient fields and metric spaces)
|
|
1926
|
+
and Category of infinite sets
|
|
1927
|
+
|
|
1928
|
+
sage: L = LazyLaurentSeriesRing(ZZ['x, y'], 't')
|
|
1929
|
+
sage: TestSuite(L).run() # needs sage.libs.singular
|
|
1930
|
+
sage: L.category()
|
|
1931
|
+
Category of infinite commutative no zero divisors algebras over
|
|
1932
|
+
(unique factorization domains and algebras with basis over
|
|
1933
|
+
(Dedekind domains and euclidean domains
|
|
1934
|
+
and noetherian rings
|
|
1935
|
+
and infinite enumerated sets and metric spaces)
|
|
1936
|
+
and commutative algebras over
|
|
1937
|
+
(Dedekind domains and euclidean domains
|
|
1938
|
+
and noetherian rings
|
|
1939
|
+
and infinite enumerated sets and metric spaces)
|
|
1940
|
+
and infinite sets)
|
|
1941
|
+
|
|
1942
|
+
sage: L = LazyLaurentSeriesRing(GF(5), 't')
|
|
1943
|
+
sage: TestSuite(L).run()
|
|
1944
|
+
|
|
1945
|
+
sage: L = LazyLaurentSeriesRing(GF(5)['x'], 't')
|
|
1946
|
+
sage: TestSuite(L).run()
|
|
1947
|
+
|
|
1948
|
+
sage: L = LazyLaurentSeriesRing(GF(5)['x, y'], 't')
|
|
1949
|
+
sage: TestSuite(L).run() # needs sage.libs.singular
|
|
1950
|
+
|
|
1951
|
+
sage: L = LazyLaurentSeriesRing(Zmod(6), 't')
|
|
1952
|
+
sage: TestSuite(L).run(skip=['_test_revert'])
|
|
1953
|
+
sage: L.category()
|
|
1954
|
+
Category of infinite commutative algebras over
|
|
1955
|
+
(finite commutative rings and subquotients of monoids
|
|
1956
|
+
and quotients of semigroups and finite enumerated sets)
|
|
1957
|
+
|
|
1958
|
+
sage: E.<x,y> = ExteriorAlgebra(QQ) # needs sage.modules
|
|
1959
|
+
sage: L = LazyLaurentSeriesRing(E, 't') # not tested # needs sage.modules
|
|
1960
|
+
|
|
1961
|
+
sage: LazyLaurentSeriesRing.options._reset() # reset the options
|
|
1962
|
+
"""
|
|
1963
|
+
self._sparse = sparse
|
|
1964
|
+
if len(names) != 1:
|
|
1965
|
+
raise ValueError("only univariate lazy Laurent series are implemented")
|
|
1966
|
+
self._arity = 1
|
|
1967
|
+
self._minimal_valuation = None
|
|
1968
|
+
self._laurent_poly_ring = LaurentPolynomialRing(base_ring, names, sparse=sparse)
|
|
1969
|
+
self._internal_poly_ring = self._laurent_poly_ring
|
|
1970
|
+
|
|
1971
|
+
category = Algebras(base_ring.category())
|
|
1972
|
+
if base_ring in Fields():
|
|
1973
|
+
category &= CompleteDiscreteValuationFields()
|
|
1974
|
+
elif base_ring in IntegralDomains():
|
|
1975
|
+
category &= IntegralDomains()
|
|
1976
|
+
elif "Commutative" in base_ring.category().axioms():
|
|
1977
|
+
category = category.Commutative()
|
|
1978
|
+
|
|
1979
|
+
if base_ring.is_zero():
|
|
1980
|
+
category = category.Finite()
|
|
1981
|
+
else:
|
|
1982
|
+
category = category.Infinite()
|
|
1983
|
+
|
|
1984
|
+
Parent.__init__(self, base=base_ring, names=names, category=category)
|
|
1985
|
+
|
|
1986
|
+
def _repr_(self):
|
|
1987
|
+
"""
|
|
1988
|
+
Return a string representation of ``self``.
|
|
1989
|
+
|
|
1990
|
+
EXAMPLES::
|
|
1991
|
+
|
|
1992
|
+
sage: LazyLaurentSeriesRing(GF(2), 'z')
|
|
1993
|
+
Lazy Laurent Series Ring in z over Finite Field of size 2
|
|
1994
|
+
"""
|
|
1995
|
+
return "Lazy Laurent Series Ring in {} over {}".format(self.variable_name(), self.base_ring())
|
|
1996
|
+
|
|
1997
|
+
def _latex_(self):
|
|
1998
|
+
r"""
|
|
1999
|
+
Return a latex representation of ``self``.
|
|
2000
|
+
|
|
2001
|
+
EXAMPLES::
|
|
2002
|
+
|
|
2003
|
+
sage: L = LazyLaurentSeriesRing(GF(2), 'z')
|
|
2004
|
+
sage: latex(L)
|
|
2005
|
+
\Bold{F}_{2} (\!(z)\!)
|
|
2006
|
+
"""
|
|
2007
|
+
from sage.misc.latex import latex
|
|
2008
|
+
return latex(self.base_ring()) + r"(\!({})\!)".format(self.variable_name())
|
|
2009
|
+
|
|
2010
|
+
@cached_method
|
|
2011
|
+
def gen(self, n=0):
|
|
2012
|
+
r"""
|
|
2013
|
+
Return the ``n``-th generator of ``self``.
|
|
2014
|
+
|
|
2015
|
+
EXAMPLES::
|
|
2016
|
+
|
|
2017
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
2018
|
+
sage: L.gen()
|
|
2019
|
+
z
|
|
2020
|
+
sage: L.gen(3)
|
|
2021
|
+
Traceback (most recent call last):
|
|
2022
|
+
...
|
|
2023
|
+
IndexError: there is only one generator
|
|
2024
|
+
"""
|
|
2025
|
+
if n != 0:
|
|
2026
|
+
raise IndexError("there is only one generator")
|
|
2027
|
+
R = self.base_ring()
|
|
2028
|
+
coeff_stream = Stream_exact([R.one()], constant=R.zero(), order=1)
|
|
2029
|
+
return self.element_class(self, coeff_stream)
|
|
2030
|
+
|
|
2031
|
+
def ngens(self):
|
|
2032
|
+
r"""
|
|
2033
|
+
Return the number of generators of ``self``.
|
|
2034
|
+
|
|
2035
|
+
This is always 1.
|
|
2036
|
+
|
|
2037
|
+
EXAMPLES::
|
|
2038
|
+
|
|
2039
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
2040
|
+
sage: L.ngens()
|
|
2041
|
+
1
|
|
2042
|
+
"""
|
|
2043
|
+
return 1
|
|
2044
|
+
|
|
2045
|
+
@cached_method
|
|
2046
|
+
def gens(self) -> tuple:
|
|
2047
|
+
"""
|
|
2048
|
+
Return the generators of ``self``.
|
|
2049
|
+
|
|
2050
|
+
EXAMPLES::
|
|
2051
|
+
|
|
2052
|
+
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
|
|
2053
|
+
sage: L.gens()
|
|
2054
|
+
(z,)
|
|
2055
|
+
sage: 1/(1 - z)
|
|
2056
|
+
1 + z + z^2 + O(z^3)
|
|
2057
|
+
"""
|
|
2058
|
+
return tuple([self.gen(n) for n in range(self.ngens())])
|
|
2059
|
+
|
|
2060
|
+
def _an_element_(self):
|
|
2061
|
+
"""
|
|
2062
|
+
Return a Laurent series in ``self``.
|
|
2063
|
+
|
|
2064
|
+
EXAMPLES::
|
|
2065
|
+
|
|
2066
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
2067
|
+
sage: L.an_element()
|
|
2068
|
+
z^-2 + z^3 + z^4 + z^5 + O(z^6)
|
|
2069
|
+
"""
|
|
2070
|
+
return self(self._laurent_poly_ring.an_element(),
|
|
2071
|
+
valuation=-2,
|
|
2072
|
+
degree=3,
|
|
2073
|
+
constant=self.base_ring().an_element())
|
|
2074
|
+
|
|
2075
|
+
def some_elements(self):
|
|
2076
|
+
"""
|
|
2077
|
+
Return a list of elements of ``self``.
|
|
2078
|
+
|
|
2079
|
+
EXAMPLES::
|
|
2080
|
+
|
|
2081
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
2082
|
+
sage: L.some_elements()[:7]
|
|
2083
|
+
[0, 1, z,
|
|
2084
|
+
-3*z^-4 + z^-3 - 12*z^-2 - 2*z^-1 - 10 - 8*z + z^2 + z^3,
|
|
2085
|
+
z^-2 + z^3 + z^4 + z^5 + O(z^6),
|
|
2086
|
+
-2*z^-3 - 2*z^-2 + 4*z^-1 + 11 - z - 34*z^2 - 31*z^3 + O(z^4),
|
|
2087
|
+
4*z^-2 + z^-1 + z + 4*z^2 + 9*z^3 + 16*z^4 + O(z^5)]
|
|
2088
|
+
|
|
2089
|
+
sage: L = LazyLaurentSeriesRing(GF(2), 'z')
|
|
2090
|
+
sage: L.some_elements()[:7]
|
|
2091
|
+
[0, 1, z,
|
|
2092
|
+
z^-4 + z^-3 + z^2 + z^3,
|
|
2093
|
+
z^-2,
|
|
2094
|
+
1 + z + z^3 + z^4 + z^6 + O(z^7),
|
|
2095
|
+
z^-1 + z + z^3 + O(z^5)]
|
|
2096
|
+
|
|
2097
|
+
sage: L = LazyLaurentSeriesRing(GF(3), 'z')
|
|
2098
|
+
sage: L.some_elements()[:7]
|
|
2099
|
+
[0, 1, z,
|
|
2100
|
+
z^-3 + z^-1 + 2 + z + z^2 + z^3,
|
|
2101
|
+
z^-2,
|
|
2102
|
+
z^-3 + z^-2 + z^-1 + 2 + 2*z + 2*z^2 + O(z^3),
|
|
2103
|
+
z^-2 + z^-1 + z + z^2 + z^4 + O(z^5)]
|
|
2104
|
+
"""
|
|
2105
|
+
z = self.gen()
|
|
2106
|
+
elts = [self.zero(), self.one(), z, (z-3)*(z**-2+2+z)**2, self.an_element(),
|
|
2107
|
+
(1 - 2*z**-3)/(1 - z + 3*z**2),
|
|
2108
|
+
self(lambda n: n**2, valuation=-2),
|
|
2109
|
+
self(lambda n: n**2, valuation=1),
|
|
2110
|
+
self([3, 2, 1], valuation=1, constant=1)]
|
|
2111
|
+
return elts
|
|
2112
|
+
|
|
2113
|
+
def series(self, coefficient, valuation, degree=None, constant=None):
|
|
2114
|
+
r"""
|
|
2115
|
+
Return a lazy Laurent series.
|
|
2116
|
+
|
|
2117
|
+
INPUT:
|
|
2118
|
+
|
|
2119
|
+
- ``coefficient`` -- Python function that computes coefficients or a list
|
|
2120
|
+
- ``valuation`` -- integer; approximate valuation of the series
|
|
2121
|
+
- ``degree`` -- (optional) integer
|
|
2122
|
+
- ``constant`` -- (optional) an element of the base ring
|
|
2123
|
+
|
|
2124
|
+
Let the coefficient of index `i` mean the coefficient of the term
|
|
2125
|
+
of the series with exponent `i`.
|
|
2126
|
+
|
|
2127
|
+
Python function ``coefficient`` returns the value of the coefficient
|
|
2128
|
+
of index `i` from input `s` and `i` where `s` is the series itself.
|
|
2129
|
+
|
|
2130
|
+
Let ``valuation`` be `n`. All coefficients of index below `n` are zero.
|
|
2131
|
+
If ``constant`` is not specified, then the ``coefficient`` function is
|
|
2132
|
+
responsible to compute the values of all coefficients of index `\ge n`.
|
|
2133
|
+
If ``degree`` or ``constant`` is a pair `(c,m)`, then the ``coefficient``
|
|
2134
|
+
function is responsible to compute the values of all coefficients of
|
|
2135
|
+
index `\ge n` and `< m` and all the coefficients of index `\ge m`
|
|
2136
|
+
is the constant `c`.
|
|
2137
|
+
|
|
2138
|
+
EXAMPLES::
|
|
2139
|
+
|
|
2140
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
2141
|
+
sage: L.series(lambda s, i: i, 5, (1,10))
|
|
2142
|
+
5*z^5 + 6*z^6 + 7*z^7 + 8*z^8 + 9*z^9 + z^10 + z^11 + z^12 + O(z^13)
|
|
2143
|
+
|
|
2144
|
+
sage: def g(s, i):
|
|
2145
|
+
....: if i < 0:
|
|
2146
|
+
....: return 1
|
|
2147
|
+
....: else:
|
|
2148
|
+
....: return s.coefficient(i - 1) + i
|
|
2149
|
+
sage: e = L.series(g, -5); e
|
|
2150
|
+
z^-5 + z^-4 + z^-3 + z^-2 + z^-1 + 1 + 2*z + O(z^2)
|
|
2151
|
+
sage: f = e^-1; f
|
|
2152
|
+
z^5 - z^6 - z^11 + O(z^12)
|
|
2153
|
+
sage: f.coefficient(10)
|
|
2154
|
+
0
|
|
2155
|
+
sage: f.coefficient(20)
|
|
2156
|
+
9
|
|
2157
|
+
sage: f.coefficient(30)
|
|
2158
|
+
-219
|
|
2159
|
+
|
|
2160
|
+
Alternatively, the ``coefficient`` can be a list of elements of the
|
|
2161
|
+
base ring. Then these elements are read as coefficients of the terms of
|
|
2162
|
+
degrees starting from the ``valuation``. In this case, ``constant``
|
|
2163
|
+
may be just an element of the base ring instead of a tuple or can be
|
|
2164
|
+
simply omitted if it is zero. ::
|
|
2165
|
+
|
|
2166
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
2167
|
+
sage: f = L.series([1,2,3,4], -5); f
|
|
2168
|
+
z^-5 + 2*z^-4 + 3*z^-3 + 4*z^-2
|
|
2169
|
+
sage: g = L.series([1,3,5,7,9], 5, constant=-1); g
|
|
2170
|
+
z^5 + 3*z^6 + 5*z^7 + 7*z^8 + 9*z^9 - z^10 - z^11 - z^12 + O(z^13)
|
|
2171
|
+
"""
|
|
2172
|
+
if valuation is not None and valuation not in ZZ:
|
|
2173
|
+
raise ValueError("the valuation must be an integer")
|
|
2174
|
+
|
|
2175
|
+
if isinstance(constant, (list, tuple)):
|
|
2176
|
+
constant, degree = constant
|
|
2177
|
+
if isinstance(degree, (list, tuple)):
|
|
2178
|
+
constant, degree = degree
|
|
2179
|
+
|
|
2180
|
+
if constant is not None:
|
|
2181
|
+
constant = self.base_ring()(constant)
|
|
2182
|
+
|
|
2183
|
+
if isinstance(coefficient, (tuple, list)):
|
|
2184
|
+
if constant is None:
|
|
2185
|
+
constant = self.base_ring().zero()
|
|
2186
|
+
if degree is None:
|
|
2187
|
+
degree = valuation + len(coefficient)
|
|
2188
|
+
coeff_stream = Stream_exact(coefficient, order=valuation,
|
|
2189
|
+
constant=constant, degree=degree)
|
|
2190
|
+
return self.element_class(self, coeff_stream)
|
|
2191
|
+
|
|
2192
|
+
if degree is not None and valuation > degree and constant:
|
|
2193
|
+
raise ValueError('inappropriate valuation')
|
|
2194
|
+
|
|
2195
|
+
t = None
|
|
2196
|
+
t = self(lambda n: coefficient(t, n), valuation=valuation,
|
|
2197
|
+
constant=constant, degree=degree)
|
|
2198
|
+
return t
|
|
2199
|
+
|
|
2200
|
+
def _monomial(self, c, n):
|
|
2201
|
+
r"""
|
|
2202
|
+
Return the interpretation of the coefficient ``c`` at index ``n``.
|
|
2203
|
+
|
|
2204
|
+
EXAMPLES::
|
|
2205
|
+
|
|
2206
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
2207
|
+
sage: L._monomial(1, 3)
|
|
2208
|
+
z^3
|
|
2209
|
+
sage: L._monomial(2, -4)
|
|
2210
|
+
2*z^-4
|
|
2211
|
+
"""
|
|
2212
|
+
return self._laurent_poly_ring(c).shift(n)
|
|
2213
|
+
|
|
2214
|
+
def _terms_of_degree(self, n, R):
|
|
2215
|
+
r"""
|
|
2216
|
+
Return the list consisting of a single element ``1`` in the given
|
|
2217
|
+
ring.
|
|
2218
|
+
|
|
2219
|
+
EXAMPLES::
|
|
2220
|
+
|
|
2221
|
+
sage: L = LazyLaurentSeriesRing(ZZ, 'z')
|
|
2222
|
+
sage: t = L._terms_of_degree(3, ZZ['x']); t
|
|
2223
|
+
[1]
|
|
2224
|
+
sage: t[0].parent()
|
|
2225
|
+
Univariate Polynomial Ring in x over Integer Ring
|
|
2226
|
+
"""
|
|
2227
|
+
return [R.one()]
|
|
2228
|
+
|
|
2229
|
+
def uniformizer(self):
|
|
2230
|
+
"""
|
|
2231
|
+
Return a uniformizer of ``self``..
|
|
2232
|
+
|
|
2233
|
+
EXAMPLES::
|
|
2234
|
+
|
|
2235
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
2236
|
+
sage: L.uniformizer()
|
|
2237
|
+
z
|
|
2238
|
+
"""
|
|
2239
|
+
R = self.base_ring()
|
|
2240
|
+
if R not in Fields():
|
|
2241
|
+
raise TypeError("the base ring is not a field")
|
|
2242
|
+
return self.gen()
|
|
2243
|
+
|
|
2244
|
+
def residue_field(self):
|
|
2245
|
+
"""
|
|
2246
|
+
Return the residue field of the ring of integers of ``self``.
|
|
2247
|
+
|
|
2248
|
+
EXAMPLES::
|
|
2249
|
+
|
|
2250
|
+
sage: L = LazyLaurentSeriesRing(QQ, 'z')
|
|
2251
|
+
sage: L.residue_field()
|
|
2252
|
+
Rational Field
|
|
2253
|
+
"""
|
|
2254
|
+
R = self.base_ring()
|
|
2255
|
+
if R not in Fields():
|
|
2256
|
+
raise TypeError("the base ring is not a field")
|
|
2257
|
+
return R
|
|
2258
|
+
|
|
2259
|
+
def taylor(self, f):
|
|
2260
|
+
r"""
|
|
2261
|
+
Return the Taylor expansion around `0` of the function ``f``.
|
|
2262
|
+
|
|
2263
|
+
INPUT:
|
|
2264
|
+
|
|
2265
|
+
- ``f`` -- a function such that one of the following works:
|
|
2266
|
+
|
|
2267
|
+
* the substitution `f(z)`, where `z` is a generator of ``self``
|
|
2268
|
+
* `f` is a function of a single variable with no poles at `0`
|
|
2269
|
+
and has a ``derivative`` method
|
|
2270
|
+
|
|
2271
|
+
EXAMPLES::
|
|
2272
|
+
|
|
2273
|
+
sage: # needs sage.symbolic
|
|
2274
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
2275
|
+
sage: x = SR.var('x')
|
|
2276
|
+
sage: f(x) = (1 + x) / (1 - x^2)
|
|
2277
|
+
sage: L.taylor(f)
|
|
2278
|
+
1 + z + z^2 + z^3 + z^4 + z^5 + z^6 + O(z^7)
|
|
2279
|
+
|
|
2280
|
+
For inputs as symbolic functions/expressions, the function must
|
|
2281
|
+
not have any poles at `0`::
|
|
2282
|
+
|
|
2283
|
+
sage: # needs sage.symbolic
|
|
2284
|
+
sage: f(x) = (1 + x^2) / sin(x^2)
|
|
2285
|
+
sage: L.taylor(f)
|
|
2286
|
+
<repr(...) failed: ValueError: power::eval(): division by zero>
|
|
2287
|
+
sage: def g(a): return (1 + a^2) / sin(a^2)
|
|
2288
|
+
sage: L.taylor(g)
|
|
2289
|
+
z^-2 + 1 + 1/6*z^2 + 1/6*z^4 + O(z^5)
|
|
2290
|
+
"""
|
|
2291
|
+
try:
|
|
2292
|
+
return f(self.gen())
|
|
2293
|
+
except (ValueError, TypeError):
|
|
2294
|
+
pass
|
|
2295
|
+
stream = Stream_taylor(f, self.is_sparse())
|
|
2296
|
+
return self.element_class(self, stream)
|
|
2297
|
+
|
|
2298
|
+
# === special functions ===
|
|
2299
|
+
|
|
2300
|
+
def q_pochhammer(self, q=None):
|
|
2301
|
+
r"""
|
|
2302
|
+
Return the infinite ``q``-Pochhammer symbol `(a; q)_{\infty}`,
|
|
2303
|
+
where `a` is the variable of ``self``.
|
|
2304
|
+
|
|
2305
|
+
This is also one version of the quantum dilogarithm or
|
|
2306
|
+
the `q`-Exponential function.
|
|
2307
|
+
|
|
2308
|
+
INPUT:
|
|
2309
|
+
|
|
2310
|
+
- ``q`` -- (default: `q \in \QQ(q)`) the parameter `q`
|
|
2311
|
+
|
|
2312
|
+
EXAMPLES::
|
|
2313
|
+
|
|
2314
|
+
sage: q = ZZ['q'].fraction_field().gen()
|
|
2315
|
+
sage: L.<z> = LazyLaurentSeriesRing(q.parent())
|
|
2316
|
+
sage: qpoch = L.q_pochhammer(q)
|
|
2317
|
+
sage: qpoch
|
|
2318
|
+
1
|
|
2319
|
+
+ (-1/(-q + 1))*z
|
|
2320
|
+
+ (q/(q^3 - q^2 - q + 1))*z^2
|
|
2321
|
+
+ (-q^3/(-q^6 + q^5 + q^4 - q^2 - q + 1))*z^3
|
|
2322
|
+
+ (q^6/(q^10 - q^9 - q^8 + 2*q^5 - q^2 - q + 1))*z^4
|
|
2323
|
+
+ (-q^10/(-q^15 + q^14 + q^13 - q^10 - q^9 - q^8 + q^7 + q^6 + q^5 - q^2 - q + 1))*z^5
|
|
2324
|
+
+ (q^15/(q^21 - q^20 - q^19 + q^16 + 2*q^14 - q^12 - q^11 - q^10 - q^9 + 2*q^7 + q^5 - q^2 - q + 1))*z^6
|
|
2325
|
+
+ O(z^7)
|
|
2326
|
+
|
|
2327
|
+
We show that `(z; q)_n = \frac{(z; q)_{\infty}}{(q^n z; q)_{\infty}}`::
|
|
2328
|
+
|
|
2329
|
+
sage: qpoch / qpoch(q*z)
|
|
2330
|
+
1 - z + O(z^7)
|
|
2331
|
+
sage: qpoch / qpoch(q^2*z)
|
|
2332
|
+
1 + (-q - 1)*z + q*z^2 + O(z^7)
|
|
2333
|
+
sage: qpoch / qpoch(q^3*z)
|
|
2334
|
+
1 + (-q^2 - q - 1)*z + (q^3 + q^2 + q)*z^2 - q^3*z^3 + O(z^7)
|
|
2335
|
+
sage: qpoch / qpoch(q^4*z)
|
|
2336
|
+
1 + (-q^3 - q^2 - q - 1)*z + (q^5 + q^4 + 2*q^3 + q^2 + q)*z^2
|
|
2337
|
+
+ (-q^6 - q^5 - q^4 - q^3)*z^3 + q^6*z^4 + O(z^7)
|
|
2338
|
+
|
|
2339
|
+
We can also construct part of Euler's function::
|
|
2340
|
+
|
|
2341
|
+
sage: M.<a> = LazyLaurentSeriesRing(QQ)
|
|
2342
|
+
sage: phi = sum(qpoch[i](q=a)*a^i for i in range(10))
|
|
2343
|
+
sage: phi[:20] == M.euler()[:20]
|
|
2344
|
+
True
|
|
2345
|
+
|
|
2346
|
+
TESTS::
|
|
2347
|
+
|
|
2348
|
+
sage: R = ZZ['q'].fraction_field()
|
|
2349
|
+
sage: q = R.gen()
|
|
2350
|
+
sage: L.<z> = LazyLaurentSeriesRing(LazyDirichletSeriesRing(R, "s"))
|
|
2351
|
+
sage: z.q_pochhammer(q) # needs sage.symbolic
|
|
2352
|
+
1 + ((1/(q-1)))*z + ((q/(q^3-q^2-q+1)))*z^2 + ... + O(z^7)
|
|
2353
|
+
|
|
2354
|
+
REFERENCES:
|
|
2355
|
+
|
|
2356
|
+
- :wikipedia:`Q-Pochhammer_symbol`
|
|
2357
|
+
- :wikipedia:`Quantum_dilogarithm`
|
|
2358
|
+
- :wikipedia:`Q-exponential`
|
|
2359
|
+
"""
|
|
2360
|
+
if q is None:
|
|
2361
|
+
q = ZZ['q'].fraction_field().gen()
|
|
2362
|
+
if q not in self.base_ring():
|
|
2363
|
+
raise ValueError("q must be in the base ring")
|
|
2364
|
+
from sage.arith.misc import binomial
|
|
2365
|
+
qP = q.parent()
|
|
2366
|
+
one = qP.one()
|
|
2367
|
+
|
|
2368
|
+
def coeff(n):
|
|
2369
|
+
return (-1)**n * q**binomial(n, 2) / qP.prod(one - q**i for i in range(1, n+1))
|
|
2370
|
+
return self(coefficients=coeff, valuation=0)
|
|
2371
|
+
|
|
2372
|
+
def euler(self):
|
|
2373
|
+
r"""
|
|
2374
|
+
Return the Euler function as an element of ``self``.
|
|
2375
|
+
|
|
2376
|
+
The *Euler function* is defined as
|
|
2377
|
+
|
|
2378
|
+
.. MATH::
|
|
2379
|
+
|
|
2380
|
+
\phi(z) = (z; z)_{\infty}
|
|
2381
|
+
= \sum_{n=0}^{\infty} (-1)^n q^{(3n^2-n)/2}.
|
|
2382
|
+
|
|
2383
|
+
EXAMPLES::
|
|
2384
|
+
|
|
2385
|
+
sage: L.<q> = LazyLaurentSeriesRing(ZZ)
|
|
2386
|
+
sage: phi = q.euler()
|
|
2387
|
+
sage: phi
|
|
2388
|
+
1 - q - q^2 + q^5 + O(q^7)
|
|
2389
|
+
|
|
2390
|
+
We verify that `1 / phi` gives the generating function
|
|
2391
|
+
for all partitions::
|
|
2392
|
+
|
|
2393
|
+
sage: P = 1 / phi; P
|
|
2394
|
+
1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + O(q^7)
|
|
2395
|
+
sage: P[:20] == [Partitions(n).cardinality() for n in range(20)] # needs sage.libs.flint
|
|
2396
|
+
True
|
|
2397
|
+
|
|
2398
|
+
TESTS::
|
|
2399
|
+
|
|
2400
|
+
sage: L.<q> = LazyLaurentSeriesRing(LazyDirichletSeriesRing(QQ, "s"))
|
|
2401
|
+
sage: q.euler() # needs sage.symbolic
|
|
2402
|
+
1 - q - q^2 + q^5 + O(q^7)
|
|
2403
|
+
|
|
2404
|
+
REFERENCES:
|
|
2405
|
+
|
|
2406
|
+
- :wikipedia:`Euler_function`
|
|
2407
|
+
"""
|
|
2408
|
+
def coeff(n):
|
|
2409
|
+
k = ZZ(24 * n + 1)
|
|
2410
|
+
m, rem = k.sqrtrem()
|
|
2411
|
+
if rem:
|
|
2412
|
+
return ZZ.zero()
|
|
2413
|
+
return (-1) ** ((m + 1) // 6)
|
|
2414
|
+
return self(coefficients=coeff, valuation=0)
|
|
2415
|
+
|
|
2416
|
+
def jacobi_theta(self, w, a=0, b=0):
|
|
2417
|
+
r"""
|
|
2418
|
+
Return the Jacobi function `\vartheta_{ab}(w; q)` as an
|
|
2419
|
+
element of ``self``.
|
|
2420
|
+
|
|
2421
|
+
The *Jacobi theta functions* with nome `q = \exp(\pi i \tau)`
|
|
2422
|
+
for `z \in \CC` and `\tau \in \RR + \RR_{>0} i`, are defined as
|
|
2423
|
+
|
|
2424
|
+
.. MATH::
|
|
2425
|
+
|
|
2426
|
+
\begin{aligned}
|
|
2427
|
+
\vartheta_{00}(z; \tau) & = \sum_{n=0}^{\infty}
|
|
2428
|
+
(w^{2n} + w^{-2n}) q^{n^2},
|
|
2429
|
+
\|
|
|
2430
|
+
\vartheta_{01}(z; \tau) & = \sum_{n=0}^{\infty}
|
|
2431
|
+
(-1)^n (w^{2n} + w^{-2n}) q^{n^2},
|
|
2432
|
+
\\
|
|
2433
|
+
\vartheta_{10}(z; \tau) & = \sum_{n=0}^{\infty}
|
|
2434
|
+
(w^{2n+1} + w^{-2n+1}) q^{n^2+n},
|
|
2435
|
+
\\
|
|
2436
|
+
\vartheta_{11}(z; \tau) & = \sum_{n=0}^{\infty}
|
|
2437
|
+
(-1)^n (w^{2n+1} + w^{-2n+1}) q^{n^2+n},
|
|
2438
|
+
\end{aligned}
|
|
2439
|
+
|
|
2440
|
+
where `w = \exp(\pi i z)`. We consider them as formal power
|
|
2441
|
+
series in `q` with the coefficients in the Laurent polynomial
|
|
2442
|
+
ring `R[w, w^{-1}]` (for a commutative ring `R`). Here, we
|
|
2443
|
+
deviate from the standard definition of `\theta_{10}` and
|
|
2444
|
+
`\theta_{11}` by removing the overall factor of `q^{1/4}`
|
|
2445
|
+
and `i q^{1/4}`, respectively.
|
|
2446
|
+
|
|
2447
|
+
EXAMPLES::
|
|
2448
|
+
|
|
2449
|
+
sage: R.<w> = LaurentPolynomialRing(QQ)
|
|
2450
|
+
sage: L.<q> = LazyPowerSeriesRing(R)
|
|
2451
|
+
sage: L.options.display_length = 17 # to display more coefficients
|
|
2452
|
+
sage: theta = q.jacobi_theta(w)
|
|
2453
|
+
sage: theta
|
|
2454
|
+
1 + ((w^-2+w^2)*q) + ((w^-4+w^4)*q^4) + ((w^-6+w^6)*q^9)
|
|
2455
|
+
+ ((w^-8+w^8)*q^16) + O(q^17)
|
|
2456
|
+
|
|
2457
|
+
sage: th3 = q.jacobi_theta(1, 0, 0); th3
|
|
2458
|
+
1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + O(q^17)
|
|
2459
|
+
sage: th2 = q.jacobi_theta(1, 1, 0); th2
|
|
2460
|
+
2 + 2*q^2 + 2*q^6 + 2*q^12 + O(q^17)
|
|
2461
|
+
sage: th4 = q.jacobi_theta(1, 0, 1); th4
|
|
2462
|
+
1 + (-2*q) + 2*q^4 + (-2*q^9) + 2*q^16 + O(q^17)
|
|
2463
|
+
sage: th1 = -q.jacobi_theta(1, 1, 1); th1
|
|
2464
|
+
-2 + 2*q^2 + (-2*q^6) + 2*q^12 + O(q^17)
|
|
2465
|
+
|
|
2466
|
+
We verify the Jacobi triple product formula::
|
|
2467
|
+
|
|
2468
|
+
sage: JTP = L.prod(lambda n: ((1 - q^(2*n)) * (1 + w^2*q^(2*n-1))
|
|
2469
|
+
....: * (1 + w^-2*q^(2*n-1))), 1, oo)
|
|
2470
|
+
sage: JTP
|
|
2471
|
+
1 + ((w^-2+w^2)*q) + ((w^-4+w^4)*q^4) + ((w^-6+w^6)*q^9)
|
|
2472
|
+
+ ((w^-8+w^8)*q^16) + O(q^17)
|
|
2473
|
+
sage: JTP[:30] == theta[:30]
|
|
2474
|
+
True
|
|
2475
|
+
|
|
2476
|
+
We verify the Jacobi identity::
|
|
2477
|
+
|
|
2478
|
+
sage: LHS = q.jacobi_theta(1, 0, 1)^4 + q*q.jacobi_theta(1, 1, 0)^4
|
|
2479
|
+
sage: LHS
|
|
2480
|
+
1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7
|
|
2481
|
+
+ 24*q^8 + 104*q^9 + 144*q^10 + 96*q^11 + 96*q^12 + 112*q^13
|
|
2482
|
+
+ 192*q^14 + 192*q^15 + 24*q^16 + O(q^17)
|
|
2483
|
+
sage: RHS = q.jacobi_theta(1, 0, 0)^4
|
|
2484
|
+
sage: RHS
|
|
2485
|
+
1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7
|
|
2486
|
+
+ 24*q^8 + 104*q^9 + 144*q^10 + 96*q^11 + 96*q^12 + 112*q^13
|
|
2487
|
+
+ 192*q^14 + 192*q^15 + 24*q^16 + O(q^17)
|
|
2488
|
+
sage: LHS[:20] == RHS[:20]
|
|
2489
|
+
True
|
|
2490
|
+
|
|
2491
|
+
We verify some relationships to the (rescaled) Dedekind eta function::
|
|
2492
|
+
|
|
2493
|
+
sage: eta = q.euler()
|
|
2494
|
+
sage: RHS = 2 * eta(q^4)^2 / eta(q^2); RHS
|
|
2495
|
+
2 + 2*q^2 + 2*q^6 + 2*q^12 + O(q^17)
|
|
2496
|
+
sage: th2[:30] == RHS[:30]
|
|
2497
|
+
True
|
|
2498
|
+
|
|
2499
|
+
sage: RHS = eta(q^2)^5 / (eta^2 * eta(q^4)^2); RHS
|
|
2500
|
+
1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + O(q^17)
|
|
2501
|
+
sage: th3[:30] == RHS[:30]
|
|
2502
|
+
True
|
|
2503
|
+
|
|
2504
|
+
sage: RHS = eta^2 / eta(q^2); RHS
|
|
2505
|
+
1 + (-2*q) + 2*q^4 + (-2*q^9) + 2*q^16 + O(q^17)
|
|
2506
|
+
sage: th4[:30] == RHS[:30]
|
|
2507
|
+
True
|
|
2508
|
+
|
|
2509
|
+
sage: LHS = th2 * th3 * th4; LHS
|
|
2510
|
+
2 + (-6*q^2) + 10*q^6 + (-14*q^12) + O(q^17)
|
|
2511
|
+
sage: RHS = 2 * eta(q^2)^3; RHS
|
|
2512
|
+
2 + (-6*q^2) + 10*q^6 + (-14*q^12) + O(q^17)
|
|
2513
|
+
sage: LHS[:30] == RHS[:30]
|
|
2514
|
+
True
|
|
2515
|
+
|
|
2516
|
+
We verify some derivative formulas (recall our conventions)::
|
|
2517
|
+
|
|
2518
|
+
sage: LHS = th4 * th3.derivative() - th3 * th4.derivative(); LHS
|
|
2519
|
+
4 + (-24*q^4) + 36*q^8 + 40*q^12 + (-120*q^16) + O(q^17)
|
|
2520
|
+
sage: RHS = th3 * th4 * (th3^4 - th4^4) / (4*q); RHS
|
|
2521
|
+
4 + (-24*q^4) + 36*q^8 + 40*q^12 + O(q^16)
|
|
2522
|
+
sage: LHS[:30] == RHS[:30]
|
|
2523
|
+
True
|
|
2524
|
+
|
|
2525
|
+
sage: LHS = (th2 / th3) / (4*q) + (th2 / th3).derivative(); LHS
|
|
2526
|
+
1/2/q - 5 + 45/2*q + (-65*q^2) + 153*q^3 + (-336*q^4) + 1375/2*q^5
|
|
2527
|
+
+ (-1305*q^6) + 2376*q^7 + (-4181*q^8) + 7093*q^9 + (-11745*q^10)
|
|
2528
|
+
+ 38073/2*q^11 + (-30157*q^12) + 46968*q^13 + (-72041*q^14)
|
|
2529
|
+
+ 108810*q^15 + O(q^16)
|
|
2530
|
+
sage: RHS = th2 * th4^4 / (4 * q * th3); RHS
|
|
2531
|
+
1/2/q - 5 + 45/2*q + (-65*q^2) + 153*q^3 + (-336*q^4) + 1375/2*q^5
|
|
2532
|
+
+ (-1305*q^6) + 2376*q^7 + (-4181*q^8) + 7093*q^9 + (-11745*q^10)
|
|
2533
|
+
+ 38073/2*q^11 + (-30157*q^12) + 46968*q^13 + (-72041*q^14)
|
|
2534
|
+
+ 108810*q^15 + O(q^16)
|
|
2535
|
+
sage: LHS[:30] == RHS[:30]
|
|
2536
|
+
True
|
|
2537
|
+
|
|
2538
|
+
sage: LHS = (th2 / th4) / (4*q) + (th2 / th4).derivative(); LHS
|
|
2539
|
+
1/2/q + 5 + 45/2*q + 65*q^2 + 153*q^3 + 336*q^4 + 1375/2*q^5
|
|
2540
|
+
+ 1305*q^6 + 2376*q^7 + 4181*q^8 + 7093*q^9 + 11745*q^10
|
|
2541
|
+
+ 38073/2*q^11 + 30157*q^12 + 46968*q^13 + 72041*q^14
|
|
2542
|
+
+ 108810*q^15 + O(q^16)
|
|
2543
|
+
sage: RHS = th2 * th3^4 / (4 * q * th4); RHS
|
|
2544
|
+
1/2/q + 5 + 45/2*q + 65*q^2 + 153*q^3 + 336*q^4 + 1375/2*q^5
|
|
2545
|
+
+ 1305*q^6 + 2376*q^7 + 4181*q^8 + 7093*q^9 + 11745*q^10
|
|
2546
|
+
+ 38073/2*q^11 + 30157*q^12 + 46968*q^13 + 72041*q^14
|
|
2547
|
+
+ 108810*q^15 + O(q^16)
|
|
2548
|
+
sage: LHS[:30] == RHS[:30]
|
|
2549
|
+
True
|
|
2550
|
+
|
|
2551
|
+
sage: LHS = (th3 / th4).derivative(); LHS
|
|
2552
|
+
4 + 16*q + 48*q^2 + 128*q^3 + 280*q^4 + 576*q^5 + 1120*q^6 + 2048*q^7
|
|
2553
|
+
+ 3636*q^8 + 6240*q^9 + 10384*q^10 + 16896*q^11 + 26936*q^12
|
|
2554
|
+
+ 42112*q^13 + 64800*q^14 + 98304*q^15 + 147016*q^16 + O(q^17)
|
|
2555
|
+
sage: RHS = (th3^5 - th3 * th4^4) / (4 * q * th4); RHS
|
|
2556
|
+
4 + 16*q + 48*q^2 + 128*q^3 + 280*q^4 + 576*q^5 + 1120*q^6 + 2048*q^7
|
|
2557
|
+
+ 3636*q^8 + 6240*q^9 + 10384*q^10 + 16896*q^11 + 26936*q^12
|
|
2558
|
+
+ 42112*q^13 + 64800*q^14 + 98304*q^15 + O(q^16)
|
|
2559
|
+
sage: LHS[:30] == RHS[:30]
|
|
2560
|
+
True
|
|
2561
|
+
|
|
2562
|
+
We have the partition generating function::
|
|
2563
|
+
|
|
2564
|
+
sage: P = th3^(-1/6) * th4^(-2/3) * ((th3^4 - th4^4)/(16*q))^(-1/24); P
|
|
2565
|
+
1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + 15*q^7 + 22*q^8
|
|
2566
|
+
+ 30*q^9 + 42*q^10 + 56*q^11 + 77*q^12 + 101*q^13 + 135*q^14
|
|
2567
|
+
+ 176*q^15 + 231*q^16 + O(q^17)
|
|
2568
|
+
sage: 1 / q.euler()
|
|
2569
|
+
1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + 15*q^7 + 22*q^8
|
|
2570
|
+
+ 30*q^9 + 42*q^10 + 56*q^11 + 77*q^12 + 101*q^13 + 135*q^14
|
|
2571
|
+
+ 176*q^15 + 231*q^16 + O(q^17)
|
|
2572
|
+
sage: oeis(P[:30]) # optional - internet
|
|
2573
|
+
0: A000041: a(n) is the number of partitions of n (the partition numbers).
|
|
2574
|
+
...
|
|
2575
|
+
|
|
2576
|
+
We have the strict partition generating function::
|
|
2577
|
+
|
|
2578
|
+
sage: SP = th3^(1/6) * th4^(-1/3) * ((th3^4 - th4^4)/(16*q))^(1/24); SP
|
|
2579
|
+
1 + q + q^2 + 2*q^3 + 2*q^4 + 3*q^5 + 4*q^6 + 5*q^7 + 6*q^8 + 8*q^9
|
|
2580
|
+
+ 10*q^10 + 12*q^11 + 15*q^12 + 18*q^13 + 22*q^14 + 27*q^15
|
|
2581
|
+
+ 32*q^16 + O(q^17)
|
|
2582
|
+
sage: oeis(SP[:30]) # optional - internet
|
|
2583
|
+
0: A000009: Expansion of Product_{m >= 1} (1 + x^m);
|
|
2584
|
+
number of partitions of n into distinct parts;
|
|
2585
|
+
number of partitions of n into odd parts.
|
|
2586
|
+
1: A081360: Expansion of q^(-1/24) (m (1-m) / 16)^(1/24) in
|
|
2587
|
+
powers of q, where m = k^2 is the parameter and q is the nome
|
|
2588
|
+
for Jacobian elliptic functions.
|
|
2589
|
+
|
|
2590
|
+
We have the overpartition generating function::
|
|
2591
|
+
|
|
2592
|
+
sage: ~th4
|
|
2593
|
+
1 + 2*q + 4*q^2 + 8*q^3 + 14*q^4 + 24*q^5 + 40*q^6 + 64*q^7 + 100*q^8
|
|
2594
|
+
+ 154*q^9 + 232*q^10 + 344*q^11 + 504*q^12 + 728*q^13 + 1040*q^14
|
|
2595
|
+
+ 1472*q^15 + 2062*q^16 + O(q^17)
|
|
2596
|
+
sage: oeis((~th4)[:20]) # optional - internet
|
|
2597
|
+
0: A015128: Number of overpartitions of n: ... overlined.
|
|
2598
|
+
1: A004402: Expansion of 1 / Sum_{n=-oo..oo} x^(n^2).
|
|
2599
|
+
|
|
2600
|
+
We give an example over the :class:`SymbolicRing` with the input
|
|
2601
|
+
`w = e^{\pi i z}` and verify the periodicity::
|
|
2602
|
+
|
|
2603
|
+
sage: # needs sage.symbolic
|
|
2604
|
+
sage: L.<q> = LazyLaurentSeriesRing(SR)
|
|
2605
|
+
sage: z = SR.var('z')
|
|
2606
|
+
sage: theta = L.jacobi_theta(exp(pi*I*z))
|
|
2607
|
+
sage: theta
|
|
2608
|
+
1 + (e^(2*I*pi*z) + e^(-2*I*pi*z))*q
|
|
2609
|
+
+ (e^(4*I*pi*z) + e^(-4*I*pi*z))*q^4
|
|
2610
|
+
+ (e^(6*I*pi*z) + e^(-6*I*pi*z))*q^9
|
|
2611
|
+
+ (e^(8*I*pi*z) + e^(-8*I*pi*z))*q^16 + O(q^17)
|
|
2612
|
+
sage: theta.map_coefficients(lambda c: c(z=z+1))
|
|
2613
|
+
1 + (e^(2*I*pi*z) + e^(-2*I*pi*z))*q
|
|
2614
|
+
+ (e^(4*I*pi*z) + e^(-4*I*pi*z))*q^4
|
|
2615
|
+
+ (e^(6*I*pi*z) + e^(-6*I*pi*z))*q^9
|
|
2616
|
+
+ (e^(8*I*pi*z) + e^(-8*I*pi*z))*q^16 + O(q^17)
|
|
2617
|
+
sage: L.options._reset() # reset options
|
|
2618
|
+
|
|
2619
|
+
REFERENCES:
|
|
2620
|
+
|
|
2621
|
+
- :wikipedia:`Theta_function`
|
|
2622
|
+
"""
|
|
2623
|
+
if a == 0 and b == 0:
|
|
2624
|
+
def coeff(n):
|
|
2625
|
+
if n == 0:
|
|
2626
|
+
return ZZ.one()
|
|
2627
|
+
nrt, rem = ZZ(n).sqrtrem()
|
|
2628
|
+
return (w**(2*nrt) + w**(-2*nrt)) if not rem else ZZ.zero()
|
|
2629
|
+
|
|
2630
|
+
if a == 0 and b == 1:
|
|
2631
|
+
def coeff(n):
|
|
2632
|
+
if n == 0:
|
|
2633
|
+
return ZZ.one()
|
|
2634
|
+
nrt, rem = ZZ(n).sqrtrem()
|
|
2635
|
+
return (-1)**nrt * (w**(2*nrt) + w**(-2*nrt)) if not rem else ZZ.zero()
|
|
2636
|
+
|
|
2637
|
+
if a == 1 and b == 0:
|
|
2638
|
+
def coeff(n):
|
|
2639
|
+
if n == 0:
|
|
2640
|
+
return w + ~w
|
|
2641
|
+
nrt, rem = ZZ(n).sqrtrem()
|
|
2642
|
+
return (w**(2*nrt+1) + w**(-2*nrt-1)) if rem == nrt else ZZ.zero()
|
|
2643
|
+
|
|
2644
|
+
if a == 1 and b == 1:
|
|
2645
|
+
def coeff(n):
|
|
2646
|
+
if n == 0:
|
|
2647
|
+
return w + ~w
|
|
2648
|
+
nrt, rem = ZZ(n).sqrtrem()
|
|
2649
|
+
return (-1)**nrt * (w**(2*nrt+1) + w**(-2*nrt-1)) if rem == nrt else ZZ.zero()
|
|
2650
|
+
|
|
2651
|
+
return self(coefficients=coeff, valuation=0)
|
|
2652
|
+
|
|
2653
|
+
def polylog(self, s):
|
|
2654
|
+
r"""
|
|
2655
|
+
Return the polylogarithm at ``s`` as an element in ``self``.
|
|
2656
|
+
|
|
2657
|
+
The *polylogarithm* at `s` is the power series in `z`
|
|
2658
|
+
|
|
2659
|
+
.. MATH::
|
|
2660
|
+
|
|
2661
|
+
\mathrm{Li}_s(z) = \sum_{k=1}^{\infty} \frac{z^k}{k^s}.
|
|
2662
|
+
|
|
2663
|
+
EXAMPLES::
|
|
2664
|
+
|
|
2665
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
2666
|
+
sage: L.polylog(1)
|
|
2667
|
+
z + 1/2*z^2 + 1/3*z^3 + 1/4*z^4 + 1/5*z^5 + 1/6*z^6 + 1/7*z^7 + O(z^8)
|
|
2668
|
+
sage: -log(1 - z)
|
|
2669
|
+
z + 1/2*z^2 + 1/3*z^3 + 1/4*z^4 + 1/5*z^5 + 1/6*z^6 + 1/7*z^7 + O(z^8)
|
|
2670
|
+
sage: L.polylog(2)
|
|
2671
|
+
z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + 1/25*z^5 + 1/36*z^6 + 1/49*z^7 + O(z^8)
|
|
2672
|
+
sage: (-log(1-z) / z).integral()
|
|
2673
|
+
z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + 1/25*z^5 + 1/36*z^6 + O(z^7)
|
|
2674
|
+
sage: L.polylog(0)
|
|
2675
|
+
z + z^2 + z^3 + O(z^4)
|
|
2676
|
+
sage: L.polylog(-1)
|
|
2677
|
+
z + 2*z^2 + 3*z^3 + 4*z^4 + 5*z^5 + 6*z^6 + 7*z^7 + O(z^8)
|
|
2678
|
+
sage: z / (1-z)^2
|
|
2679
|
+
z + 2*z^2 + 3*z^3 + 4*z^4 + 5*z^5 + 6*z^6 + 7*z^7 + O(z^8)
|
|
2680
|
+
sage: L.polylog(-2)
|
|
2681
|
+
z + 4*z^2 + 9*z^3 + 16*z^4 + 25*z^5 + 36*z^6 + 49*z^7 + O(z^8)
|
|
2682
|
+
sage: z * (1 + z) / (1 - z)^3
|
|
2683
|
+
z + 4*z^2 + 9*z^3 + 16*z^4 + 25*z^5 + 36*z^6 + 49*z^7 + O(z^8)
|
|
2684
|
+
|
|
2685
|
+
We can compute the Eulerian numbers::
|
|
2686
|
+
|
|
2687
|
+
sage: [L.polylog(-n) * (1-z)^(n+1) for n in range(1, 6)]
|
|
2688
|
+
[z + O(z^8),
|
|
2689
|
+
z + z^2 + O(z^8),
|
|
2690
|
+
z + 4*z^2 + z^3 + O(z^8),
|
|
2691
|
+
z + 11*z^2 + 11*z^3 + z^4 + O(z^8),
|
|
2692
|
+
z + 26*z^2 + 66*z^3 + 26*z^4 + z^5 + O(z^8)]
|
|
2693
|
+
|
|
2694
|
+
REFERENCES:
|
|
2695
|
+
|
|
2696
|
+
- :wikipedia:`Polylogarithm`
|
|
2697
|
+
"""
|
|
2698
|
+
if not s:
|
|
2699
|
+
coeff_stream = Stream_exact([], constant=self.base_ring().one(), order=1)
|
|
2700
|
+
return self.element_class(self, coeff_stream)
|
|
2701
|
+
R = self.base_ring()
|
|
2702
|
+
return self(coefficients=lambda n: R(n) ** -s, valuation=1)
|
|
2703
|
+
|
|
2704
|
+
def dilog(self):
|
|
2705
|
+
r"""
|
|
2706
|
+
Return the dilogarithm as an element in ``self``.
|
|
2707
|
+
|
|
2708
|
+
.. SEEALSO::
|
|
2709
|
+
|
|
2710
|
+
:meth:`polylog`
|
|
2711
|
+
|
|
2712
|
+
EXAMPLES::
|
|
2713
|
+
|
|
2714
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
2715
|
+
sage: L.dilog()
|
|
2716
|
+
z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + 1/25*z^5 + 1/36*z^6 + 1/49*z^7 + O(z^8)
|
|
2717
|
+
sage: L.polylog(2)
|
|
2718
|
+
z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + 1/25*z^5 + 1/36*z^6 + 1/49*z^7 + O(z^8)
|
|
2719
|
+
|
|
2720
|
+
sage: # needs sage.symbolic
|
|
2721
|
+
sage: L.<x> = LazyLaurentSeriesRing(SR)
|
|
2722
|
+
sage: L.dilog()
|
|
2723
|
+
x + 1/4*x^2 + 1/9*x^3 + 1/16*x^4 + 1/25*x^5 + 1/36*x^6 + 1/49*x^7 + O(x^8)
|
|
2724
|
+
|
|
2725
|
+
REFERENCES:
|
|
2726
|
+
|
|
2727
|
+
- :wikipedia:`Dilogarithm`
|
|
2728
|
+
"""
|
|
2729
|
+
return self.polylog(2)
|
|
2730
|
+
|
|
2731
|
+
######################################################################
|
|
2732
|
+
|
|
2733
|
+
|
|
2734
|
+
class LazyPowerSeriesRing(LazySeriesRing):
|
|
2735
|
+
"""
|
|
2736
|
+
The ring of (possibly multivariate) lazy Taylor series.
|
|
2737
|
+
|
|
2738
|
+
INPUT:
|
|
2739
|
+
|
|
2740
|
+
- ``base_ring`` -- base ring of this Taylor series ring
|
|
2741
|
+
- ``names`` -- name(s) of the generator of this Taylor series ring
|
|
2742
|
+
- ``sparse`` -- boolean (default: ``True``); whether this series is sparse or not
|
|
2743
|
+
|
|
2744
|
+
EXAMPLES::
|
|
2745
|
+
|
|
2746
|
+
sage: LazyPowerSeriesRing(ZZ, 't')
|
|
2747
|
+
Lazy Taylor Series Ring in t over Integer Ring
|
|
2748
|
+
|
|
2749
|
+
sage: L.<x, y> = LazyPowerSeriesRing(QQ); L
|
|
2750
|
+
Multivariate Lazy Taylor Series Ring in x, y over Rational Field
|
|
2751
|
+
"""
|
|
2752
|
+
Element = LazyPowerSeries
|
|
2753
|
+
|
|
2754
|
+
# Follow the "generic" normalization
|
|
2755
|
+
__classcall_private__ = LazySeriesRing.__classcall_private__
|
|
2756
|
+
|
|
2757
|
+
def __init__(self, base_ring, names, sparse=True, category=None):
|
|
2758
|
+
"""
|
|
2759
|
+
Initialize ``self``.
|
|
2760
|
+
|
|
2761
|
+
TESTS::
|
|
2762
|
+
|
|
2763
|
+
sage: LazyPowerSeriesRing.options.halting_precision(12)
|
|
2764
|
+
|
|
2765
|
+
sage: L = LazyPowerSeriesRing(ZZ, 't')
|
|
2766
|
+
sage: TestSuite(L).run(skip='_test_fraction_field')
|
|
2767
|
+
sage: L = LazyPowerSeriesRing(ZZ, 's, t')
|
|
2768
|
+
sage: TestSuite(L).run(skip='_test_fraction_field')
|
|
2769
|
+
|
|
2770
|
+
sage: L = LazyPowerSeriesRing(QQ, 't')
|
|
2771
|
+
sage: TestSuite(L).run(skip='_test_fraction_field')
|
|
2772
|
+
sage: L = LazyPowerSeriesRing(QQ, 's, t')
|
|
2773
|
+
sage: TestSuite(L).run(skip='_test_fraction_field')
|
|
2774
|
+
|
|
2775
|
+
sage: L = LazyPowerSeriesRing(GF(5), 't')
|
|
2776
|
+
sage: TestSuite(L).run()
|
|
2777
|
+
|
|
2778
|
+
sage: L = LazyPowerSeriesRing(GF(5), 's, t')
|
|
2779
|
+
sage: TestSuite(L).run(skip=['_test_fraction_field'])
|
|
2780
|
+
|
|
2781
|
+
sage: L = LazyPowerSeriesRing(Zmod(6), 't')
|
|
2782
|
+
sage: TestSuite(L).run(skip=['_test_revert'])
|
|
2783
|
+
sage: L = LazyPowerSeriesRing(Zmod(6), 's, t')
|
|
2784
|
+
sage: TestSuite(L).run(skip=['_test_revert'])
|
|
2785
|
+
|
|
2786
|
+
sage: L = LazyPowerSeriesRing(QQ['q'], 't')
|
|
2787
|
+
sage: TestSuite(L).run(skip='_test_fraction_field')
|
|
2788
|
+
sage: L = LazyPowerSeriesRing(QQ['q'], 's, t')
|
|
2789
|
+
sage: TestSuite(L).run(skip='_test_fraction_field') # long time
|
|
2790
|
+
|
|
2791
|
+
sage: L = LazyPowerSeriesRing(ZZ['q'], 't')
|
|
2792
|
+
sage: TestSuite(L).run(skip='_test_fraction_field')
|
|
2793
|
+
sage: L = LazyPowerSeriesRing(ZZ['q'], 's, t')
|
|
2794
|
+
sage: TestSuite(L).run(skip='_test_fraction_field') # long time
|
|
2795
|
+
|
|
2796
|
+
sage: LazyPowerSeriesRing.options._reset() # reset the options
|
|
2797
|
+
|
|
2798
|
+
Check that :issue:`34470` is fixed::
|
|
2799
|
+
|
|
2800
|
+
sage: L.<t> = LazyPowerSeriesRing(QQ)
|
|
2801
|
+
sage: L in CompleteDiscreteValuationRings
|
|
2802
|
+
True
|
|
2803
|
+
sage: L.uniformizer()
|
|
2804
|
+
t
|
|
2805
|
+
sage: lcm(1/(1 - t^2) - 1, t)
|
|
2806
|
+
t^2
|
|
2807
|
+
|
|
2808
|
+
sage: L.<t> = LazyPowerSeriesRing(ZZ)
|
|
2809
|
+
sage: L in PrincipalIdealDomains
|
|
2810
|
+
False
|
|
2811
|
+
|
|
2812
|
+
The ideal generated by `s` and `t` is not principal::
|
|
2813
|
+
|
|
2814
|
+
sage: L = LazyPowerSeriesRing(QQ, 's, t')
|
|
2815
|
+
sage: L in PrincipalIdealDomains
|
|
2816
|
+
False
|
|
2817
|
+
"""
|
|
2818
|
+
self._sparse = sparse
|
|
2819
|
+
self._minimal_valuation = 0
|
|
2820
|
+
self._arity = len(names)
|
|
2821
|
+
if self._arity == 1:
|
|
2822
|
+
self._laurent_poly_ring = PolynomialRing(base_ring, names, sparse=sparse)
|
|
2823
|
+
self._internal_poly_ring = self._laurent_poly_ring
|
|
2824
|
+
else:
|
|
2825
|
+
self._laurent_poly_ring = PolynomialRing(base_ring, names)
|
|
2826
|
+
self._internal_poly_ring = PolynomialRing(self._laurent_poly_ring, "DUMMY_VARIABLE", sparse=sparse)
|
|
2827
|
+
category = Algebras(base_ring.category())
|
|
2828
|
+
mixin_gcd = False
|
|
2829
|
+
if self._arity == 1:
|
|
2830
|
+
if base_ring in Fields():
|
|
2831
|
+
category &= CompleteDiscreteValuationRings()
|
|
2832
|
+
mixin_gcd = True
|
|
2833
|
+
elif base_ring in Fields():
|
|
2834
|
+
category &= UniqueFactorizationDomains()
|
|
2835
|
+
mixin_gcd = True
|
|
2836
|
+
if base_ring in IntegralDomains():
|
|
2837
|
+
category &= IntegralDomains()
|
|
2838
|
+
elif base_ring in Rings().Commutative():
|
|
2839
|
+
category = category.Commutative()
|
|
2840
|
+
|
|
2841
|
+
if mixin_gcd:
|
|
2842
|
+
from sage.structure.dynamic_class import dynamic_class
|
|
2843
|
+
self.Element = dynamic_class(
|
|
2844
|
+
f"{self.Element.__name__}_gcd",
|
|
2845
|
+
(self.Element, LazyPowerSeries_gcd_mixin),
|
|
2846
|
+
doccls=self.Element)
|
|
2847
|
+
|
|
2848
|
+
if base_ring.is_zero():
|
|
2849
|
+
category = category.Finite()
|
|
2850
|
+
else:
|
|
2851
|
+
category = category.Infinite()
|
|
2852
|
+
Parent.__init__(self, base=base_ring, names=names,
|
|
2853
|
+
category=category)
|
|
2854
|
+
|
|
2855
|
+
def construction(self):
|
|
2856
|
+
"""
|
|
2857
|
+
Return a pair ``(F, R)``, where ``F`` is a
|
|
2858
|
+
:class:`CompletionFunctor` and `R` is a ring, such that
|
|
2859
|
+
``F(R)`` returns ``self``.
|
|
2860
|
+
|
|
2861
|
+
EXAMPLES::
|
|
2862
|
+
|
|
2863
|
+
sage: L = LazyPowerSeriesRing(ZZ, 't')
|
|
2864
|
+
sage: L.construction()
|
|
2865
|
+
(Completion[t, prec=+Infinity],
|
|
2866
|
+
Sparse Univariate Polynomial Ring in t over Integer Ring)
|
|
2867
|
+
"""
|
|
2868
|
+
from sage.categories.pushout import CompletionFunctor
|
|
2869
|
+
if self._arity == 1:
|
|
2870
|
+
return (CompletionFunctor(self._names[0], infinity),
|
|
2871
|
+
self._laurent_poly_ring)
|
|
2872
|
+
return (CompletionFunctor(self._names, infinity),
|
|
2873
|
+
self._laurent_poly_ring)
|
|
2874
|
+
|
|
2875
|
+
def _repr_(self):
|
|
2876
|
+
"""
|
|
2877
|
+
String representation of this Taylor series ring.
|
|
2878
|
+
|
|
2879
|
+
EXAMPLES::
|
|
2880
|
+
|
|
2881
|
+
sage: LazyPowerSeriesRing(GF(2), 'z')
|
|
2882
|
+
Lazy Taylor Series Ring in z over Finite Field of size 2
|
|
2883
|
+
"""
|
|
2884
|
+
BR = self.base_ring()
|
|
2885
|
+
if len(self.variable_names()) == 1:
|
|
2886
|
+
return "Lazy Taylor Series Ring in {} over {}".format(self.variable_name(), BR)
|
|
2887
|
+
generators_rep = ", ".join(self.variable_names())
|
|
2888
|
+
return "Multivariate Lazy Taylor Series Ring in {} over {}".format(generators_rep, BR)
|
|
2889
|
+
|
|
2890
|
+
def _latex_(self):
|
|
2891
|
+
r"""
|
|
2892
|
+
Return a latex representation of ``self``.
|
|
2893
|
+
|
|
2894
|
+
EXAMPLES::
|
|
2895
|
+
|
|
2896
|
+
sage: L = LazyPowerSeriesRing(GF(2), 'z')
|
|
2897
|
+
sage: latex(L)
|
|
2898
|
+
\Bold{F}_{2} [\![z]\!]
|
|
2899
|
+
"""
|
|
2900
|
+
from sage.misc.latex import latex
|
|
2901
|
+
generators_rep = ", ".join(self.variable_names())
|
|
2902
|
+
return latex(self.base_ring()) + r"[\![{}]\!]".format(generators_rep)
|
|
2903
|
+
|
|
2904
|
+
def _monomial(self, c, n):
|
|
2905
|
+
r"""
|
|
2906
|
+
Return the interpretation of the coefficient ``c`` at index ``n``.
|
|
2907
|
+
|
|
2908
|
+
EXAMPLES::
|
|
2909
|
+
|
|
2910
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'z')
|
|
2911
|
+
sage: L._monomial(2, 3)
|
|
2912
|
+
2*z^3
|
|
2913
|
+
"""
|
|
2914
|
+
m = len(self.variable_names())
|
|
2915
|
+
L = self._laurent_poly_ring
|
|
2916
|
+
if m == 1:
|
|
2917
|
+
return L(c) * L.gen() ** n
|
|
2918
|
+
return L(c)
|
|
2919
|
+
|
|
2920
|
+
@cached_method
|
|
2921
|
+
def _terms_of_degree(self, n, R):
|
|
2922
|
+
r"""
|
|
2923
|
+
Return the list of monomials of degree ``n`` in the polynomial
|
|
2924
|
+
ring with base ring ``R``.
|
|
2925
|
+
|
|
2926
|
+
EXAMPLES::
|
|
2927
|
+
|
|
2928
|
+
sage: L.<x> = LazyPowerSeriesRing(ZZ)
|
|
2929
|
+
sage: m = L._terms_of_degree(3, QQ["z"]); m
|
|
2930
|
+
[1]
|
|
2931
|
+
sage: m[0].parent()
|
|
2932
|
+
Univariate Polynomial Ring in z over Rational Field
|
|
2933
|
+
sage: L.<x, y> = LazyPowerSeriesRing(ZZ)
|
|
2934
|
+
sage: m = L._terms_of_degree(3, QQ["z"]); m # needs sage.combinat
|
|
2935
|
+
[y^3, x*y^2, x^2*y, x^3]
|
|
2936
|
+
sage: m[0].parent() # needs sage.combinat
|
|
2937
|
+
Multivariate Polynomial Ring in x, y over Univariate Polynomial Ring in z over Rational Field
|
|
2938
|
+
"""
|
|
2939
|
+
if self._arity == 1:
|
|
2940
|
+
return [R.one()]
|
|
2941
|
+
return [m.change_ring(R)
|
|
2942
|
+
for m in self._internal_poly_ring.base_ring().monomials_of_degree(n)]
|
|
2943
|
+
|
|
2944
|
+
@cached_method
|
|
2945
|
+
def gen(self, n=0):
|
|
2946
|
+
"""
|
|
2947
|
+
Return the ``n``-th generator of ``self``.
|
|
2948
|
+
|
|
2949
|
+
EXAMPLES::
|
|
2950
|
+
|
|
2951
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'z')
|
|
2952
|
+
sage: L.gen()
|
|
2953
|
+
z
|
|
2954
|
+
sage: L.gen(3)
|
|
2955
|
+
Traceback (most recent call last):
|
|
2956
|
+
...
|
|
2957
|
+
IndexError: there is only one generator
|
|
2958
|
+
"""
|
|
2959
|
+
m = len(self.variable_names())
|
|
2960
|
+
if n > m:
|
|
2961
|
+
if m == 1:
|
|
2962
|
+
raise IndexError("there is only one generator")
|
|
2963
|
+
raise IndexError("there are only %s generators" % m)
|
|
2964
|
+
|
|
2965
|
+
R = self._laurent_poly_ring
|
|
2966
|
+
BR = self.base_ring()
|
|
2967
|
+
if len(self.variable_names()) == 1:
|
|
2968
|
+
coeff_stream = Stream_exact([BR.one()], constant=BR.zero(), order=1)
|
|
2969
|
+
else:
|
|
2970
|
+
coeff_stream = Stream_exact([R.gen(n)], constant=R.zero(), order=1)
|
|
2971
|
+
return self.element_class(self, coeff_stream)
|
|
2972
|
+
|
|
2973
|
+
def ngens(self):
|
|
2974
|
+
r"""
|
|
2975
|
+
Return the number of generators of ``self``.
|
|
2976
|
+
|
|
2977
|
+
EXAMPLES::
|
|
2978
|
+
|
|
2979
|
+
sage: L.<z> = LazyPowerSeriesRing(ZZ)
|
|
2980
|
+
sage: L.ngens()
|
|
2981
|
+
1
|
|
2982
|
+
"""
|
|
2983
|
+
return len(self.variable_names())
|
|
2984
|
+
|
|
2985
|
+
@cached_method
|
|
2986
|
+
def gens(self) -> tuple:
|
|
2987
|
+
"""
|
|
2988
|
+
Return the generators of ``self``.
|
|
2989
|
+
|
|
2990
|
+
EXAMPLES::
|
|
2991
|
+
|
|
2992
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'x,y')
|
|
2993
|
+
sage: L.gens()
|
|
2994
|
+
(x, y)
|
|
2995
|
+
"""
|
|
2996
|
+
return tuple([self.gen(n) for n in range(self.ngens())])
|
|
2997
|
+
|
|
2998
|
+
def _element_constructor_(self, x=None, valuation=None, constant=None, degree=None, coefficients=None, check=True):
|
|
2999
|
+
"""
|
|
3000
|
+
Construct a Taylor series from ``x``.
|
|
3001
|
+
|
|
3002
|
+
INPUT:
|
|
3003
|
+
|
|
3004
|
+
- ``x`` -- data used to the define a Taylor series
|
|
3005
|
+
- ``valuation`` -- integer (optional); a lower bound for the valuation
|
|
3006
|
+
of the series
|
|
3007
|
+
- ``constant`` -- (optional) the eventual constant of the series
|
|
3008
|
+
- ``degree`` -- (optional) the degree when the series is ``constant``
|
|
3009
|
+
- ``check`` -- (optional) check that coefficients are homogeneous of
|
|
3010
|
+
the correct degree when they are retrieved
|
|
3011
|
+
|
|
3012
|
+
.. WARNING::
|
|
3013
|
+
|
|
3014
|
+
The behaviour of ``LazyPowerSeries(c)`` for a list ``c``
|
|
3015
|
+
with nonzero last element `e` changed with
|
|
3016
|
+
:issue:`32367`. To obtain the old behaviour, use
|
|
3017
|
+
``LazyPowerSeries(c, constant=e)``.
|
|
3018
|
+
|
|
3019
|
+
EXAMPLES::
|
|
3020
|
+
|
|
3021
|
+
sage: L = LazyPowerSeriesRing(GF(2), 'z')
|
|
3022
|
+
sage: L(2)
|
|
3023
|
+
0
|
|
3024
|
+
sage: L(3)
|
|
3025
|
+
1
|
|
3026
|
+
|
|
3027
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'z')
|
|
3028
|
+
sage: L(lambda i: i, 5, 1, 10)
|
|
3029
|
+
5*z^5 + 6*z^6 + 7*z^7 + 8*z^8 + 9*z^9 + z^10 + z^11 + z^12 + O(z^13)
|
|
3030
|
+
sage: L(lambda i: i, 5, (1, 10))
|
|
3031
|
+
5*z^5 + 6*z^6 + 7*z^7 + 8*z^8 + 9*z^9 + z^10 + z^11 + z^12 + O(z^13)
|
|
3032
|
+
|
|
3033
|
+
sage: X = L(constant=5, degree=2); X
|
|
3034
|
+
5*z^2 + 5*z^3 + 5*z^4 + O(z^5)
|
|
3035
|
+
sage: X.valuation()
|
|
3036
|
+
2
|
|
3037
|
+
|
|
3038
|
+
sage: e = L(lambda n: n + 1); e
|
|
3039
|
+
1 + 2*z + 3*z^2 + 4*z^3 + 5*z^4 + 6*z^5 + 7*z^6 + O(z^7)
|
|
3040
|
+
sage: f = e^-1; f
|
|
3041
|
+
1 - 2*z + z^2 + O(z^7)
|
|
3042
|
+
sage: f.coefficient(10)
|
|
3043
|
+
0
|
|
3044
|
+
sage: f[20]
|
|
3045
|
+
0
|
|
3046
|
+
|
|
3047
|
+
sage: L(valuation=2, constant=1)
|
|
3048
|
+
z^2 + z^3 + z^4 + O(z^5)
|
|
3049
|
+
sage: L(constant=1)
|
|
3050
|
+
1 + z + z^2 + O(z^3)
|
|
3051
|
+
|
|
3052
|
+
Alternatively, ``x`` can be a list of elements of the base ring.
|
|
3053
|
+
Then these elements are read as coefficients of the terms of
|
|
3054
|
+
degrees starting from the ``valuation``. In this case, ``constant``
|
|
3055
|
+
may be just an element of the base ring instead of a tuple or can be
|
|
3056
|
+
simply omitted if it is zero::
|
|
3057
|
+
|
|
3058
|
+
sage: f = L([1,2,3,4], 1); f
|
|
3059
|
+
z + 2*z^2 + 3*z^3 + 4*z^4
|
|
3060
|
+
|
|
3061
|
+
sage: g = L([1,3,5,7,9], 5, -1); g
|
|
3062
|
+
z^5 + 3*z^6 + 5*z^7 + 7*z^8 + 9*z^9 - z^10 - z^11 - z^12 + O(z^13)
|
|
3063
|
+
|
|
3064
|
+
Additionally, ``x`` can be a polynomial::
|
|
3065
|
+
|
|
3066
|
+
sage: P.<x> = QQ[]
|
|
3067
|
+
sage: p = x + 3*x^2 + x^5
|
|
3068
|
+
sage: L.<x> = LazyPowerSeriesRing(ZZ)
|
|
3069
|
+
sage: L(p)
|
|
3070
|
+
x + 3*x^2 + x^5
|
|
3071
|
+
|
|
3072
|
+
sage: L(p, valuation=0)
|
|
3073
|
+
1 + 3*x + x^4
|
|
3074
|
+
|
|
3075
|
+
sage: P.<x, y> = QQ[]
|
|
3076
|
+
sage: p = x + y^2 + x*y
|
|
3077
|
+
sage: L.<x,y> = LazyPowerSeriesRing(ZZ)
|
|
3078
|
+
sage: L(p)
|
|
3079
|
+
x + (x*y+y^2)
|
|
3080
|
+
|
|
3081
|
+
Finally ``x`` can be in the corresponding fraction field::
|
|
3082
|
+
|
|
3083
|
+
sage: R.<a,b,c> = PolynomialRing(ZZ)
|
|
3084
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'a,b,c')
|
|
3085
|
+
sage: aa, bb, cc = L.gens()
|
|
3086
|
+
sage: f = (1 + a + b) / (1 + a*b + c^3); f
|
|
3087
|
+
(a + b + 1)/(c^3 + a*b + 1)
|
|
3088
|
+
sage: f.parent()
|
|
3089
|
+
Fraction Field of Multivariate Polynomial Ring in a, b, c over Integer Ring
|
|
3090
|
+
sage: L(f) # needs sage.libs.singular
|
|
3091
|
+
1 + (a+b) - a*b - (a^2*b+a*b^2+c^3) + (a^2*b^2-a*c^3-b*c^3)
|
|
3092
|
+
+ (a^3*b^2+a^2*b^3+2*a*b*c^3) - (a^3*b^3-2*a^2*b*c^3-2*a*b^2*c^3-c^6)
|
|
3093
|
+
+ O(a,b,c)^7
|
|
3094
|
+
sage: L(f) == (1 + aa + bb) / (1 + aa*bb + cc^3) # needs sage.libs.singular
|
|
3095
|
+
True
|
|
3096
|
+
|
|
3097
|
+
TESTS::
|
|
3098
|
+
|
|
3099
|
+
sage: L.<x,y> = LazyPowerSeriesRing(ZZ)
|
|
3100
|
+
sage: L(constant=1)
|
|
3101
|
+
Traceback (most recent call last):
|
|
3102
|
+
...
|
|
3103
|
+
ValueError: constant must be zero for multivariate Taylor series
|
|
3104
|
+
|
|
3105
|
+
sage: L(lambda n: 0)
|
|
3106
|
+
O(x,y)^7
|
|
3107
|
+
|
|
3108
|
+
sage: L(lambda n: n)[3];
|
|
3109
|
+
Traceback (most recent call last):
|
|
3110
|
+
...
|
|
3111
|
+
ValueError: coefficient 3 at degree 3 is not a homogeneous polynomial
|
|
3112
|
+
|
|
3113
|
+
sage: L([1, 2, 3]);
|
|
3114
|
+
Traceback (most recent call last):
|
|
3115
|
+
...
|
|
3116
|
+
ValueError: unable to convert [1, 2, 3] into a lazy Taylor series
|
|
3117
|
+
|
|
3118
|
+
sage: L(lambda n: n, degree=3);
|
|
3119
|
+
Traceback (most recent call last):
|
|
3120
|
+
...
|
|
3121
|
+
ValueError: coefficients must be homogeneous polynomials of the correct degree
|
|
3122
|
+
"""
|
|
3123
|
+
if valuation is not None:
|
|
3124
|
+
if valuation < 0:
|
|
3125
|
+
raise ValueError("the valuation of a Taylor series must be nonnegative")
|
|
3126
|
+
# TODO: the following is nonsense, think of an iterator
|
|
3127
|
+
# if self._arity > 1 and valuation != 0:
|
|
3128
|
+
# raise ValueError(f"valuation must not be specified for multivariate Taylor series (for {x}), but was set to {valuation}")
|
|
3129
|
+
if self._arity > 1:
|
|
3130
|
+
valuation = 0
|
|
3131
|
+
|
|
3132
|
+
R = self._laurent_poly_ring
|
|
3133
|
+
BR = self._internal_poly_ring.base_ring() # this is the ring containing the elements of the stream
|
|
3134
|
+
if x is None:
|
|
3135
|
+
assert degree is None
|
|
3136
|
+
coeff_stream = Stream_uninitialized(valuation)
|
|
3137
|
+
return self.element_class(self, coeff_stream)
|
|
3138
|
+
|
|
3139
|
+
try:
|
|
3140
|
+
# Try to build stuff using the polynomial ring constructor
|
|
3141
|
+
x = R(x)
|
|
3142
|
+
except (TypeError, ValueError, AttributeError):
|
|
3143
|
+
pass
|
|
3144
|
+
if isinstance(constant, (tuple, list)):
|
|
3145
|
+
constant, degree = constant
|
|
3146
|
+
if constant is not None:
|
|
3147
|
+
if self._arity > 1 and constant:
|
|
3148
|
+
raise ValueError("constant must be zero for multivariate Taylor series")
|
|
3149
|
+
constant = BR(constant)
|
|
3150
|
+
|
|
3151
|
+
if parent(x) == R:
|
|
3152
|
+
if not x and not constant:
|
|
3153
|
+
coeff_stream = Stream_zero()
|
|
3154
|
+
else:
|
|
3155
|
+
if not x:
|
|
3156
|
+
coeff_stream = Stream_exact([],
|
|
3157
|
+
order=valuation,
|
|
3158
|
+
degree=degree,
|
|
3159
|
+
constant=constant)
|
|
3160
|
+
return self.element_class(self, coeff_stream)
|
|
3161
|
+
|
|
3162
|
+
if self._arity == 1:
|
|
3163
|
+
v = x.valuation()
|
|
3164
|
+
d = x.degree()
|
|
3165
|
+
p_list = [x[i] for i in range(v, d + 1)]
|
|
3166
|
+
if valuation is not None:
|
|
3167
|
+
v = valuation
|
|
3168
|
+
else:
|
|
3169
|
+
p_dict = x.homogeneous_components()
|
|
3170
|
+
v = min(p_dict.keys())
|
|
3171
|
+
d = max(p_dict.keys())
|
|
3172
|
+
p_list = [p_dict.get(i, 0) for i in range(v, d + 1)]
|
|
3173
|
+
|
|
3174
|
+
coeff_stream = Stream_exact(p_list,
|
|
3175
|
+
order=v,
|
|
3176
|
+
constant=constant,
|
|
3177
|
+
degree=degree)
|
|
3178
|
+
return self.element_class(self, coeff_stream)
|
|
3179
|
+
|
|
3180
|
+
if isinstance(x, LazyPowerSeries):
|
|
3181
|
+
stream = x._coeff_stream
|
|
3182
|
+
if isinstance(stream, Stream_exact):
|
|
3183
|
+
coeffs = [BR(val) for val in stream._initial_coefficients]
|
|
3184
|
+
constant = BR(stream._constant)
|
|
3185
|
+
valuation = stream._approximate_order
|
|
3186
|
+
for i, c in enumerate(coeffs):
|
|
3187
|
+
if c:
|
|
3188
|
+
valuation += i
|
|
3189
|
+
coeffs = coeffs[i:]
|
|
3190
|
+
break
|
|
3191
|
+
else:
|
|
3192
|
+
valuation += len(coeffs)
|
|
3193
|
+
coeffs = []
|
|
3194
|
+
return self(coeffs,
|
|
3195
|
+
degree=stream._degree,
|
|
3196
|
+
constant=constant,
|
|
3197
|
+
valuation=valuation)
|
|
3198
|
+
return self.element_class(self, stream)
|
|
3199
|
+
|
|
3200
|
+
# Check if we can realize the input as a rational function
|
|
3201
|
+
try:
|
|
3202
|
+
FF = self._laurent_poly_ring.fraction_field()
|
|
3203
|
+
x = FF(x)
|
|
3204
|
+
except (TypeError, ValueError, AttributeError):
|
|
3205
|
+
pass
|
|
3206
|
+
else:
|
|
3207
|
+
return self(x.numerator()) / self(x.denominator())
|
|
3208
|
+
|
|
3209
|
+
if callable(x) or isinstance(x, (GeneratorType, map, filter)):
|
|
3210
|
+
if valuation is None:
|
|
3211
|
+
valuation = 0
|
|
3212
|
+
if degree is not None:
|
|
3213
|
+
if constant is None:
|
|
3214
|
+
constant = ZZ.zero()
|
|
3215
|
+
if callable(x):
|
|
3216
|
+
p = [x(i) for i in range(valuation, degree)]
|
|
3217
|
+
else:
|
|
3218
|
+
p = [c for c, _ in zip(_skip_leading_zeros(x), range(valuation, degree))]
|
|
3219
|
+
if self._arity == 1:
|
|
3220
|
+
p = [BR(c) for c in p]
|
|
3221
|
+
else:
|
|
3222
|
+
p = [R(c) for c in p]
|
|
3223
|
+
if not all(e.is_homogeneous() and e.degree() == i
|
|
3224
|
+
for i, e in enumerate(p, valuation)):
|
|
3225
|
+
raise ValueError("coefficients must be homogeneous polynomials of the correct degree")
|
|
3226
|
+
coeff_stream = Stream_exact(p,
|
|
3227
|
+
order=valuation,
|
|
3228
|
+
constant=constant,
|
|
3229
|
+
degree=degree)
|
|
3230
|
+
return self.element_class(self, coeff_stream)
|
|
3231
|
+
if check and self._arity > 1:
|
|
3232
|
+
if callable(x):
|
|
3233
|
+
def y(n):
|
|
3234
|
+
e = R(x(n))
|
|
3235
|
+
if not e or e.is_homogeneous() and e.degree() == n:
|
|
3236
|
+
return e
|
|
3237
|
+
raise ValueError("coefficient %s at degree %s is not a homogeneous polynomial" % (e, n))
|
|
3238
|
+
coeff_stream = Stream_function(y, self._sparse, valuation)
|
|
3239
|
+
else:
|
|
3240
|
+
coeff_stream = Stream_iterator(map(R, _skip_leading_zeros(x)), valuation)
|
|
3241
|
+
elif callable(x):
|
|
3242
|
+
coeff_stream = Stream_function(lambda i: BR(x(i)), self._sparse, valuation)
|
|
3243
|
+
else:
|
|
3244
|
+
coeff_stream = Stream_iterator(map(BR, _skip_leading_zeros(x)), valuation)
|
|
3245
|
+
return self.element_class(self, coeff_stream)
|
|
3246
|
+
raise ValueError(f"unable to convert {x} into a lazy Taylor series")
|
|
3247
|
+
|
|
3248
|
+
def _an_element_(self):
|
|
3249
|
+
"""
|
|
3250
|
+
Return a Taylor series in ``self``.
|
|
3251
|
+
|
|
3252
|
+
EXAMPLES::
|
|
3253
|
+
|
|
3254
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'z')
|
|
3255
|
+
sage: L.an_element()
|
|
3256
|
+
z + z^2 + z^3 + O(z^4)
|
|
3257
|
+
|
|
3258
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'x, y')
|
|
3259
|
+
sage: L.an_element()
|
|
3260
|
+
x
|
|
3261
|
+
"""
|
|
3262
|
+
if self._arity == 1:
|
|
3263
|
+
return self(self._laurent_poly_ring.an_element(),
|
|
3264
|
+
constant=self.base_ring().an_element())
|
|
3265
|
+
return self(self._laurent_poly_ring.an_element())
|
|
3266
|
+
|
|
3267
|
+
def uniformizer(self):
|
|
3268
|
+
"""
|
|
3269
|
+
Return a uniformizer of ``self``.
|
|
3270
|
+
|
|
3271
|
+
EXAMPLES::
|
|
3272
|
+
|
|
3273
|
+
sage: L = LazyPowerSeriesRing(QQ, 'x')
|
|
3274
|
+
sage: L.uniformizer()
|
|
3275
|
+
x
|
|
3276
|
+
"""
|
|
3277
|
+
R = self.base_ring()
|
|
3278
|
+
if R not in Fields():
|
|
3279
|
+
raise TypeError("the base ring is not a field")
|
|
3280
|
+
if self._arity != 1:
|
|
3281
|
+
raise TypeError("the arity must be one")
|
|
3282
|
+
return self.gen()
|
|
3283
|
+
|
|
3284
|
+
def residue_field(self):
|
|
3285
|
+
"""
|
|
3286
|
+
Return the residue field of the ring of integers of ``self``.
|
|
3287
|
+
|
|
3288
|
+
EXAMPLES::
|
|
3289
|
+
|
|
3290
|
+
sage: L = LazyPowerSeriesRing(QQ, 'x')
|
|
3291
|
+
sage: L.residue_field()
|
|
3292
|
+
Rational Field
|
|
3293
|
+
"""
|
|
3294
|
+
R = self.base_ring()
|
|
3295
|
+
if R not in Fields():
|
|
3296
|
+
raise TypeError("the base ring is not a field")
|
|
3297
|
+
if self._arity != 1:
|
|
3298
|
+
raise TypeError("the arity must be one")
|
|
3299
|
+
return R
|
|
3300
|
+
|
|
3301
|
+
def fraction_field(self):
|
|
3302
|
+
"""
|
|
3303
|
+
Return the fraction field of ``self``.
|
|
3304
|
+
|
|
3305
|
+
If this is with a single variable over a field, then the fraction
|
|
3306
|
+
field is the field of (lazy) formal Laurent series.
|
|
3307
|
+
|
|
3308
|
+
.. TODO::
|
|
3309
|
+
|
|
3310
|
+
Implement other fraction fields.
|
|
3311
|
+
|
|
3312
|
+
EXAMPLES::
|
|
3313
|
+
|
|
3314
|
+
sage: L.<x> = LazyPowerSeriesRing(QQ)
|
|
3315
|
+
sage: L.fraction_field()
|
|
3316
|
+
Lazy Laurent Series Ring in x over Rational Field
|
|
3317
|
+
"""
|
|
3318
|
+
if self not in IntegralDomains():
|
|
3319
|
+
raise TypeError("must be an integral domain")
|
|
3320
|
+
R = self.base_ring()
|
|
3321
|
+
if self._arity == 1 and R in Fields():
|
|
3322
|
+
return LazyLaurentSeriesRing(R, names=self.variable_names())
|
|
3323
|
+
raise NotImplementedError("the fraction field is not yet implemented")
|
|
3324
|
+
|
|
3325
|
+
def some_elements(self):
|
|
3326
|
+
"""
|
|
3327
|
+
Return a list of elements of ``self``.
|
|
3328
|
+
|
|
3329
|
+
EXAMPLES::
|
|
3330
|
+
|
|
3331
|
+
sage: L = LazyPowerSeriesRing(ZZ, 'z')
|
|
3332
|
+
sage: L.some_elements()[:6]
|
|
3333
|
+
[0, 1, z + z^2 + z^3 + O(z^4),
|
|
3334
|
+
-12 - 8*z + z^2 + z^3,
|
|
3335
|
+
1 + z - 2*z^2 - 7*z^3 - z^4 + 20*z^5 + 23*z^6 + O(z^7),
|
|
3336
|
+
z + 4*z^2 + 9*z^3 + 16*z^4 + 25*z^5 + 36*z^6 + O(z^7)]
|
|
3337
|
+
|
|
3338
|
+
sage: L = LazyPowerSeriesRing(GF(3)["q"], 'z')
|
|
3339
|
+
sage: L.some_elements()[:6]
|
|
3340
|
+
[0, 1, z + q*z^2 + q*z^3 + q*z^4 + O(z^5),
|
|
3341
|
+
z + z^2 + z^3,
|
|
3342
|
+
1 + z + z^2 + 2*z^3 + 2*z^4 + 2*z^5 + O(z^6),
|
|
3343
|
+
z + z^2 + z^4 + z^5 + O(z^7)]
|
|
3344
|
+
|
|
3345
|
+
sage: L = LazyPowerSeriesRing(GF(3), 'q, t')
|
|
3346
|
+
sage: L.some_elements()[:6]
|
|
3347
|
+
[0, 1, q,
|
|
3348
|
+
q + q^2 + q^3,
|
|
3349
|
+
1 + q + q^2 - q^3 - q^4 - q^5 - q^6 + O(q,t)^7,
|
|
3350
|
+
1 + (q+t) + (q^2-q*t+t^2) + (q^3+t^3) + (q^4+q^3*t+q*t^3+t^4)
|
|
3351
|
+
+ (q^5-q^4*t+q^3*t^2+q^2*t^3-q*t^4+t^5) + (q^6-q^3*t^3+t^6) + O(q,t)^7]
|
|
3352
|
+
"""
|
|
3353
|
+
z = self.gen(0)
|
|
3354
|
+
elts = [self.zero(), self.one(), self.an_element()]
|
|
3355
|
+
if self._arity == 1:
|
|
3356
|
+
elts.extend([(z-3)*(2+z)**2, (1 - 2*z**3)/(1 - z + 3*z**2), self(lambda n: n**2)])
|
|
3357
|
+
else:
|
|
3358
|
+
PR = self._laurent_poly_ring
|
|
3359
|
+
sum_gens = PR.sum(PR.gens())
|
|
3360
|
+
elts.extend([(z-3)*(2+z)**2, (1 - 2*z**3)/(1 - z + 3*z**2), self(lambda n: sum_gens**n)])
|
|
3361
|
+
return elts
|
|
3362
|
+
|
|
3363
|
+
def taylor(self, f):
|
|
3364
|
+
r"""
|
|
3365
|
+
Return the Taylor expansion around `0` of the function ``f``.
|
|
3366
|
+
|
|
3367
|
+
INPUT:
|
|
3368
|
+
|
|
3369
|
+
- ``f`` -- a function such that one of the following works:
|
|
3370
|
+
|
|
3371
|
+
* the substitution `f(z_1, \ldots, z_n)`, where `(z_1, \ldots, z_n)`
|
|
3372
|
+
are the generators of ``self``
|
|
3373
|
+
* `f` is a function with no poles at `0` and has a ``derivative``
|
|
3374
|
+
method
|
|
3375
|
+
|
|
3376
|
+
.. WARNING::
|
|
3377
|
+
|
|
3378
|
+
For inputs as symbolic functions/expressions, this does not check
|
|
3379
|
+
that the function does not have poles at `0`.
|
|
3380
|
+
|
|
3381
|
+
EXAMPLES::
|
|
3382
|
+
|
|
3383
|
+
sage: # needs sage.symbolic
|
|
3384
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ)
|
|
3385
|
+
sage: x = SR.var('x')
|
|
3386
|
+
sage: f(x) = (1 + x) / (1 - x^3)
|
|
3387
|
+
sage: L.taylor(f)
|
|
3388
|
+
1 + z + z^3 + z^4 + z^6 + O(z^7)
|
|
3389
|
+
sage: (1 + z) / (1 - z^3)
|
|
3390
|
+
1 + z + z^3 + z^4 + z^6 + O(z^7)
|
|
3391
|
+
sage: f(x) = cos(x + pi/2)
|
|
3392
|
+
sage: L.taylor(f)
|
|
3393
|
+
-z + 1/6*z^3 - 1/120*z^5 + O(z^7)
|
|
3394
|
+
|
|
3395
|
+
For inputs as symbolic functions/expressions, the function must
|
|
3396
|
+
not have any poles at `0`::
|
|
3397
|
+
|
|
3398
|
+
sage: # needs sage.symbolic
|
|
3399
|
+
sage: L.<z> = LazyPowerSeriesRing(QQ, sparse=True)
|
|
3400
|
+
sage: f = 1 / sin(x)
|
|
3401
|
+
sage: L.taylor(f)
|
|
3402
|
+
<repr(...) failed: ValueError: power::eval(): division by zero>
|
|
3403
|
+
|
|
3404
|
+
Different multivariate inputs::
|
|
3405
|
+
|
|
3406
|
+
sage: # needs sage.symbolic
|
|
3407
|
+
sage: L.<a,b> = LazyPowerSeriesRing(QQ)
|
|
3408
|
+
sage: def f(x, y): return (1 + x) / (1 + y)
|
|
3409
|
+
sage: L.taylor(f)
|
|
3410
|
+
1 + (a-b) - (a*b-b^2) + (a*b^2-b^3) - (a*b^3-b^4) + (a*b^4-b^5) - (a*b^5-b^6) + O(a,b)^7
|
|
3411
|
+
sage: g(w, z) = (1 + w) / (1 + z)
|
|
3412
|
+
sage: L.taylor(g)
|
|
3413
|
+
1 + (a-b) - (a*b-b^2) + (a*b^2-b^3) - (a*b^3-b^4) + (a*b^4-b^5) - (a*b^5-b^6) + O(a,b)^7
|
|
3414
|
+
sage: y = SR.var('y')
|
|
3415
|
+
sage: h = (1 + x) / (1 + y)
|
|
3416
|
+
sage: L.taylor(h)
|
|
3417
|
+
1 + (a-b) - (a*b-b^2) + (a*b^2-b^3) - (a*b^3-b^4) + (a*b^4-b^5) - (a*b^5-b^6) + O(a,b)^7
|
|
3418
|
+
"""
|
|
3419
|
+
try:
|
|
3420
|
+
return f(*self.gens())
|
|
3421
|
+
except (ValueError, TypeError):
|
|
3422
|
+
pass
|
|
3423
|
+
|
|
3424
|
+
if self._arity != 1:
|
|
3425
|
+
R = self._laurent_poly_ring
|
|
3426
|
+
BR = R.base_ring()
|
|
3427
|
+
args = f.arguments()
|
|
3428
|
+
subs = {str(va): ZZ.zero() for va in args}
|
|
3429
|
+
ell = len(subs)
|
|
3430
|
+
from sage.combinat.integer_vector import integer_vectors_nk_fast_iter
|
|
3431
|
+
from sage.arith.misc import factorial
|
|
3432
|
+
|
|
3433
|
+
def taylor_expand(deg):
|
|
3434
|
+
if deg == 0:
|
|
3435
|
+
return BR(f(**subs))
|
|
3436
|
+
return R.sum(BR(f.diff(*sum(([g] * e for g, e in zip(args, al)), []))(**subs)
|
|
3437
|
+
/ ZZ.prod(factorial(a) for a in al))
|
|
3438
|
+
* R.monomial(*al) for al in integer_vectors_nk_fast_iter(deg, ell))
|
|
3439
|
+
|
|
3440
|
+
coeff_stream = Stream_function(taylor_expand, self._sparse, self._minimal_valuation)
|
|
3441
|
+
else:
|
|
3442
|
+
coeff_stream = Stream_taylor(f, self._sparse)
|
|
3443
|
+
return self.element_class(self, coeff_stream)
|
|
3444
|
+
|
|
3445
|
+
|
|
3446
|
+
######################################################################
|
|
3447
|
+
|
|
3448
|
+
|
|
3449
|
+
class LazyCompletionGradedAlgebra(LazySeriesRing):
|
|
3450
|
+
r"""
|
|
3451
|
+
The completion of a graded algebra consisting of formal series.
|
|
3452
|
+
|
|
3453
|
+
For a graded algebra `A`, we can form a completion of `A` consisting of
|
|
3454
|
+
all formal series of `A` such that each homogeneous component is
|
|
3455
|
+
a finite linear combination of basis elements of `A`.
|
|
3456
|
+
|
|
3457
|
+
INPUT:
|
|
3458
|
+
|
|
3459
|
+
- ``basis`` -- a graded algebra
|
|
3460
|
+
- ``names`` -- name(s) of the alphabets
|
|
3461
|
+
- ``sparse`` -- boolean (default: ``True``); whether we use a sparse or
|
|
3462
|
+
a dense representation
|
|
3463
|
+
|
|
3464
|
+
EXAMPLES::
|
|
3465
|
+
|
|
3466
|
+
sage: # needs sage.combinat sage.modules
|
|
3467
|
+
sage: NCSF = NonCommutativeSymmetricFunctions(QQ)
|
|
3468
|
+
sage: S = NCSF.Complete()
|
|
3469
|
+
sage: L = S.formal_series_ring(); L
|
|
3470
|
+
Lazy completion of Non-Commutative Symmetric Functions
|
|
3471
|
+
over the Rational Field in the Complete basis
|
|
3472
|
+
sage: f = 1 / (1 - L(S[1])); f
|
|
3473
|
+
S[] + S[1] + (S[1,1]) + (S[1,1,1]) + (S[1,1,1,1]) + (S[1,1,1,1,1])
|
|
3474
|
+
+ (S[1,1,1,1,1,1]) + O^7
|
|
3475
|
+
sage: g = 1 / (1 - L(S[2])); g
|
|
3476
|
+
S[] + S[2] + (S[2,2]) + (S[2,2,2]) + O^7
|
|
3477
|
+
sage: f * g
|
|
3478
|
+
S[] + S[1] + (S[1,1]+S[2]) + (S[1,1,1]+S[1,2])
|
|
3479
|
+
+ (S[1,1,1,1]+S[1,1,2]+S[2,2]) + (S[1,1,1,1,1]+S[1,1,1,2]+S[1,2,2])
|
|
3480
|
+
+ (S[1,1,1,1,1,1]+S[1,1,1,1,2]+S[1,1,2,2]+S[2,2,2]) + O^7
|
|
3481
|
+
sage: g * f
|
|
3482
|
+
S[] + S[1] + (S[1,1]+S[2]) + (S[1,1,1]+S[2,1])
|
|
3483
|
+
+ (S[1,1,1,1]+S[2,1,1]+S[2,2]) + (S[1,1,1,1,1]+S[2,1,1,1]+S[2,2,1])
|
|
3484
|
+
+ (S[1,1,1,1,1,1]+S[2,1,1,1,1]+S[2,2,1,1]+S[2,2,2]) + O^7
|
|
3485
|
+
sage: f * g - g * f
|
|
3486
|
+
(S[1,2]-S[2,1]) + (S[1,1,2]-S[2,1,1])
|
|
3487
|
+
+ (S[1,1,1,2]+S[1,2,2]-S[2,1,1,1]-S[2,2,1])
|
|
3488
|
+
+ (S[1,1,1,1,2]+S[1,1,2,2]-S[2,1,1,1,1]-S[2,2,1,1]) + O^7
|
|
3489
|
+
"""
|
|
3490
|
+
Element = LazyCompletionGradedAlgebraElement
|
|
3491
|
+
|
|
3492
|
+
def __init__(self, basis, sparse=True, category=None):
|
|
3493
|
+
"""
|
|
3494
|
+
Initialize ``self``.
|
|
3495
|
+
|
|
3496
|
+
TESTS::
|
|
3497
|
+
|
|
3498
|
+
sage: LazySymmetricFunctions.options.halting_precision(6) # needs sage.combinat sage.modules
|
|
3499
|
+
|
|
3500
|
+
sage: # needs sage.combinat sage.modules
|
|
3501
|
+
sage: s = SymmetricFunctions(QQ).s()
|
|
3502
|
+
sage: L = LazySymmetricFunctions(s)
|
|
3503
|
+
sage: TestSuite(L).run() # needs lrcalc_python
|
|
3504
|
+
sage: p = SymmetricFunctions(GF(5)).p()
|
|
3505
|
+
sage: L = LazySymmetricFunctions(p)
|
|
3506
|
+
sage: TestSuite(L).run()
|
|
3507
|
+
|
|
3508
|
+
Reversion will only work when the base ring is a field::
|
|
3509
|
+
|
|
3510
|
+
sage: # needs sage.combinat sage.modules
|
|
3511
|
+
sage: s = SymmetricFunctions(ZZ).s()
|
|
3512
|
+
sage: L = LazySymmetricFunctions(s)
|
|
3513
|
+
sage: TestSuite(L).run(skip=['_test_revert']) # needs lrcalc_python
|
|
3514
|
+
sage: s = SymmetricFunctions(QQ["q"]).s()
|
|
3515
|
+
sage: L = LazySymmetricFunctions(s)
|
|
3516
|
+
sage: TestSuite(L).run(skip=['_test_revert']) # needs lrcalc_python
|
|
3517
|
+
|
|
3518
|
+
Options are remembered across doctests::
|
|
3519
|
+
|
|
3520
|
+
sage: LazySymmetricFunctions.options._reset() # needs sage.combinat sage.modules
|
|
3521
|
+
|
|
3522
|
+
Check that :issue:`34470` is fixed. The ideal generated by
|
|
3523
|
+
`p[1]` and `p[2]` is not principal::
|
|
3524
|
+
|
|
3525
|
+
sage: p = SymmetricFunctions(QQ).p() # needs sage.combinat sage.modules
|
|
3526
|
+
sage: L = LazySymmetricFunctions(s) # needs sage.combinat sage.modules
|
|
3527
|
+
sage: L in PrincipalIdealDomains # needs sage.combinat sage.modules
|
|
3528
|
+
False
|
|
3529
|
+
|
|
3530
|
+
Check that a basis which is not graded is not enough::
|
|
3531
|
+
|
|
3532
|
+
sage: ht = SymmetricFunctions(ZZ).ht() # needs sage.combinat sage.modules
|
|
3533
|
+
sage: L = LazySymmetricFunctions(ht) # needs sage.combinat sage.modules
|
|
3534
|
+
Traceback (most recent call last):
|
|
3535
|
+
...
|
|
3536
|
+
ValueError: basis should be in GradedAlgebrasWithBasis
|
|
3537
|
+
|
|
3538
|
+
Check that :issue:`37625` is fixed::
|
|
3539
|
+
|
|
3540
|
+
sage: # needs sage.combinat sage.modules
|
|
3541
|
+
sage: R = algebras.Free(QQ, ('a', 'b'), degrees=(1, 2))
|
|
3542
|
+
sage: L = R.completion()
|
|
3543
|
+
sage: a, b = R.gens()
|
|
3544
|
+
sage: (L(a) + L(b))^2
|
|
3545
|
+
a^2 + (a*b+b*a) + b^2
|
|
3546
|
+
"""
|
|
3547
|
+
base_ring = basis.base_ring()
|
|
3548
|
+
self._minimal_valuation = 0
|
|
3549
|
+
if basis in Algebras.TensorProducts:
|
|
3550
|
+
self._arity = len(basis._sets)
|
|
3551
|
+
else:
|
|
3552
|
+
if basis not in GradedAlgebrasWithBasis:
|
|
3553
|
+
raise ValueError("basis should be in GradedAlgebrasWithBasis")
|
|
3554
|
+
self._arity = 1
|
|
3555
|
+
category = Algebras(basis.category())
|
|
3556
|
+
if basis in IntegralDomains():
|
|
3557
|
+
category &= IntegralDomains()
|
|
3558
|
+
elif basis in Rings().Commutative():
|
|
3559
|
+
category = category.Commutative()
|
|
3560
|
+
|
|
3561
|
+
if base_ring.is_zero():
|
|
3562
|
+
category = category.Finite()
|
|
3563
|
+
else:
|
|
3564
|
+
category = category.Infinite()
|
|
3565
|
+
Parent.__init__(self, base=base_ring, category=category)
|
|
3566
|
+
self._sparse = sparse
|
|
3567
|
+
self._laurent_poly_ring = basis
|
|
3568
|
+
self._internal_poly_ring = PolynomialRing(self._laurent_poly_ring, "DUMMY_VARIABLE", sparse=sparse)
|
|
3569
|
+
|
|
3570
|
+
def _repr_(self):
|
|
3571
|
+
"""
|
|
3572
|
+
String representation of the lazy symmetric functions ring.
|
|
3573
|
+
|
|
3574
|
+
EXAMPLES::
|
|
3575
|
+
|
|
3576
|
+
sage: s = SymmetricFunctions(GF(2)).s() # needs sage.combinat sage.modules
|
|
3577
|
+
sage: LazySymmetricFunctions(s) # needs sage.combinat sage.modules
|
|
3578
|
+
Lazy completion of Symmetric Functions over Finite Field of size 2 in the Schur basis
|
|
3579
|
+
"""
|
|
3580
|
+
return "Lazy completion of {}".format(self._laurent_poly_ring)
|
|
3581
|
+
|
|
3582
|
+
def _latex_(self):
|
|
3583
|
+
r"""
|
|
3584
|
+
Return a latex representation of ``self``.
|
|
3585
|
+
|
|
3586
|
+
EXAMPLES::
|
|
3587
|
+
|
|
3588
|
+
sage: s = SymmetricFunctions(GF(2)).s() # needs sage.combinat sage.modules
|
|
3589
|
+
sage: L = LazySymmetricFunctions(s) # needs sage.combinat sage.modules
|
|
3590
|
+
sage: latex(L) # needs sage.combinat sage.modules
|
|
3591
|
+
\text{\texttt{Symmetric{ }Functions{ }over{ }Finite{ }Field{ }of{ }size{ }2{ }in{ }the{ }Schur{ }basis}}
|
|
3592
|
+
"""
|
|
3593
|
+
from sage.misc.latex import latex
|
|
3594
|
+
return latex(self._laurent_poly_ring)
|
|
3595
|
+
|
|
3596
|
+
def _monomial(self, c, n):
|
|
3597
|
+
r"""
|
|
3598
|
+
Return the interpretation of the coefficient ``c`` at index ``n``.
|
|
3599
|
+
|
|
3600
|
+
EXAMPLES::
|
|
3601
|
+
|
|
3602
|
+
sage: # needs sage.combinat sage.modules
|
|
3603
|
+
sage: m = SymmetricFunctions(ZZ).m()
|
|
3604
|
+
sage: s = SymmetricFunctions(ZZ).s()
|
|
3605
|
+
sage: L = LazySymmetricFunctions(m)
|
|
3606
|
+
sage: L._monomial(s[2,1], 3)
|
|
3607
|
+
2*m[1, 1, 1] + m[2, 1]
|
|
3608
|
+
"""
|
|
3609
|
+
L = self._laurent_poly_ring
|
|
3610
|
+
return L(c)
|
|
3611
|
+
|
|
3612
|
+
@cached_method
|
|
3613
|
+
def _terms_of_degree(self, n, R):
|
|
3614
|
+
r"""
|
|
3615
|
+
Return the list of basis elements of degree ``n``.
|
|
3616
|
+
|
|
3617
|
+
EXAMPLES::
|
|
3618
|
+
|
|
3619
|
+
sage: # needs sage.combinat sage.modules
|
|
3620
|
+
sage: s = SymmetricFunctions(ZZ).s()
|
|
3621
|
+
sage: L = LazySymmetricFunctions(s)
|
|
3622
|
+
sage: m = L._terms_of_degree(3, QQ["x"]); m
|
|
3623
|
+
[s[3], s[2, 1], s[1, 1, 1]]
|
|
3624
|
+
sage: m[0].parent()
|
|
3625
|
+
Symmetric Functions over Univariate Polynomial Ring in x over Rational Field in the Schur basis
|
|
3626
|
+
sage: L = LazySymmetricFunctions(tensor([s, s]))
|
|
3627
|
+
sage: m = L._terms_of_degree(3, QQ["x"]); m
|
|
3628
|
+
[s[3] # s[],
|
|
3629
|
+
s[2, 1] # s[],
|
|
3630
|
+
s[1, 1, 1] # s[],
|
|
3631
|
+
s[2] # s[1],
|
|
3632
|
+
s[1, 1] # s[1],
|
|
3633
|
+
s[1] # s[2],
|
|
3634
|
+
s[1] # s[1, 1],
|
|
3635
|
+
s[] # s[3],
|
|
3636
|
+
s[] # s[2, 1],
|
|
3637
|
+
s[] # s[1, 1, 1]]
|
|
3638
|
+
sage: m[0].parent()
|
|
3639
|
+
Symmetric Functions over Univariate Polynomial Ring in x over Rational Field in the Schur basis
|
|
3640
|
+
# Symmetric Functions over Univariate Polynomial Ring in x over Rational Field in the Schur basis
|
|
3641
|
+
"""
|
|
3642
|
+
from sage.combinat.integer_vector import IntegerVectors
|
|
3643
|
+
from sage.misc.mrange import cartesian_product_iterator
|
|
3644
|
+
from sage.categories.tensor import tensor
|
|
3645
|
+
B = self._internal_poly_ring.base_ring()
|
|
3646
|
+
B = B.change_ring(R)
|
|
3647
|
+
if self._arity == 1:
|
|
3648
|
+
return list(B.homogeneous_component_basis(n))
|
|
3649
|
+
|
|
3650
|
+
return [tensor(m)
|
|
3651
|
+
for c in IntegerVectors(n, self._arity)
|
|
3652
|
+
for m in cartesian_product_iterator([F.homogeneous_component_basis(p)
|
|
3653
|
+
for F, p in zip(B.tensor_factors(), c)])]
|
|
3654
|
+
|
|
3655
|
+
def _element_constructor_(self, x=None, valuation=None, degree=None, constant=None, check=True):
|
|
3656
|
+
r"""
|
|
3657
|
+
Construct a lazy element in ``self`` from ``x``.
|
|
3658
|
+
|
|
3659
|
+
INPUT:
|
|
3660
|
+
|
|
3661
|
+
- ``x`` -- data used to the define a lazy element
|
|
3662
|
+
- ``valuation`` -- integer (optional); a lower bound for the valuation
|
|
3663
|
+
of the series
|
|
3664
|
+
- ``degree`` -- (optional) the degree when the lazy element
|
|
3665
|
+
has finite support
|
|
3666
|
+
- ``check`` -- (optional) check that coefficients are homogeneous of
|
|
3667
|
+
the correct degree when they are retrieved
|
|
3668
|
+
|
|
3669
|
+
EXAMPLES::
|
|
3670
|
+
|
|
3671
|
+
sage: # needs sage.combinat sage.modules
|
|
3672
|
+
sage: m = SymmetricFunctions(GF(2)).m()
|
|
3673
|
+
sage: L = LazySymmetricFunctions(m)
|
|
3674
|
+
sage: L(2)
|
|
3675
|
+
0
|
|
3676
|
+
sage: L(3)
|
|
3677
|
+
m[]
|
|
3678
|
+
|
|
3679
|
+
sage: # needs sage.combinat sage.modules
|
|
3680
|
+
sage: m = SymmetricFunctions(ZZ).m()
|
|
3681
|
+
sage: L = LazySymmetricFunctions(m)
|
|
3682
|
+
sage: f = L(lambda i: m([i]), valuation=5, degree=10); f
|
|
3683
|
+
m[5] + m[6] + m[7] + m[8] + m[9]
|
|
3684
|
+
sage: f.coefficient(6)
|
|
3685
|
+
m[6]
|
|
3686
|
+
sage: f[20]
|
|
3687
|
+
0
|
|
3688
|
+
|
|
3689
|
+
Alternatively, ``x`` can be a list of elements of the base ring.
|
|
3690
|
+
Then these elements are read as coefficients of the terms of
|
|
3691
|
+
degrees starting from the ``valuation``::
|
|
3692
|
+
|
|
3693
|
+
sage: f = L([m[1],m[2],m[3]], valuation=1); f # needs sage.combinat sage.modules
|
|
3694
|
+
m[1] + m[2] + m[3]
|
|
3695
|
+
|
|
3696
|
+
Finally, ``x`` can be a symmetric function::
|
|
3697
|
+
|
|
3698
|
+
sage: # needs sage.combinat sage.modules
|
|
3699
|
+
sage: m = SymmetricFunctions(ZZ).m()
|
|
3700
|
+
sage: s = SymmetricFunctions(ZZ).s()
|
|
3701
|
+
sage: L = LazySymmetricFunctions(m)
|
|
3702
|
+
sage: L(s.an_element())
|
|
3703
|
+
2*m[] + 2*m[1] + (3*m[1,1]+3*m[2])
|
|
3704
|
+
|
|
3705
|
+
TESTS::
|
|
3706
|
+
|
|
3707
|
+
sage: # needs sage.combinat sage.modules
|
|
3708
|
+
sage: e = SymmetricFunctions(ZZ).e()
|
|
3709
|
+
sage: h = SymmetricFunctions(ZZ).h()
|
|
3710
|
+
sage: L = LazySymmetricFunctions(tensor([h, e]))
|
|
3711
|
+
sage: L(lambda n: 0)
|
|
3712
|
+
O^7
|
|
3713
|
+
|
|
3714
|
+
sage: # needs sage.combinat sage.modules
|
|
3715
|
+
sage: L(lambda n: tensor([h[n], e([])]) + tensor([h([]), e[n]]), degree=3)
|
|
3716
|
+
(2*h[]#e[]) + (h[]#e[1]+h[1]#e[]) + (h[]#e[2]+h[2]#e[])
|
|
3717
|
+
sage: L(lambda n: n)[3];
|
|
3718
|
+
Traceback (most recent call last):
|
|
3719
|
+
...
|
|
3720
|
+
ValueError: coefficient 3*h[] # e[] should be an element
|
|
3721
|
+
of homogeneous degree 3 but has degree 0
|
|
3722
|
+
sage: L([1, 2, 3]);
|
|
3723
|
+
Traceback (most recent call last):
|
|
3724
|
+
...
|
|
3725
|
+
ValueError: coefficient 2*h[] # e[] should be an element
|
|
3726
|
+
of homogeneous degree 1 but has degree 0
|
|
3727
|
+
sage: L(lambda n: n, degree=3);
|
|
3728
|
+
Traceback (most recent call last):
|
|
3729
|
+
...
|
|
3730
|
+
ValueError: coefficient h[] # e[] should be an element
|
|
3731
|
+
of homogeneous degree 1 but has degree 0
|
|
3732
|
+
"""
|
|
3733
|
+
if valuation is None:
|
|
3734
|
+
valuation = 0
|
|
3735
|
+
if valuation < 0:
|
|
3736
|
+
raise ValueError("the valuation of a lazy completion element must be nonnegative")
|
|
3737
|
+
|
|
3738
|
+
R = self._laurent_poly_ring
|
|
3739
|
+
if x is None:
|
|
3740
|
+
assert degree is None
|
|
3741
|
+
coeff_stream = Stream_uninitialized(valuation)
|
|
3742
|
+
return self.element_class(self, coeff_stream)
|
|
3743
|
+
try:
|
|
3744
|
+
# Try to build stuff using the polynomial ring constructor
|
|
3745
|
+
x = R(x)
|
|
3746
|
+
except (TypeError, ValueError, NotImplementedError):
|
|
3747
|
+
pass
|
|
3748
|
+
if x in R:
|
|
3749
|
+
if not x:
|
|
3750
|
+
coeff_stream = Stream_zero()
|
|
3751
|
+
else:
|
|
3752
|
+
p_dict = {}
|
|
3753
|
+
if self._arity == 1:
|
|
3754
|
+
for f in x.terms():
|
|
3755
|
+
d = f.degree()
|
|
3756
|
+
p_dict[d] = p_dict.get(d, 0) + f
|
|
3757
|
+
else:
|
|
3758
|
+
for f in x.terms():
|
|
3759
|
+
try:
|
|
3760
|
+
d = f.degree()
|
|
3761
|
+
except (TypeError, ValueError, AttributeError):
|
|
3762
|
+
# FIXME: Fallback for symmetric functions in multiple variables
|
|
3763
|
+
d = sum(sum(mu.size() for mu in p) for p in f.support())
|
|
3764
|
+
p_dict[d] = p_dict.get(d, 0) + f
|
|
3765
|
+
v = min(p_dict)
|
|
3766
|
+
d = max(p_dict)
|
|
3767
|
+
p_list = [p_dict.get(i, 0) for i in range(v, d + 1)]
|
|
3768
|
+
|
|
3769
|
+
coeff_stream = Stream_exact(p_list,
|
|
3770
|
+
order=v,
|
|
3771
|
+
constant=self.base_ring().zero(),
|
|
3772
|
+
degree=degree)
|
|
3773
|
+
return self.element_class(self, coeff_stream)
|
|
3774
|
+
|
|
3775
|
+
if isinstance(x, self.Element):
|
|
3776
|
+
return self.element_class(self, x._coeff_stream)
|
|
3777
|
+
|
|
3778
|
+
if self._arity == 1:
|
|
3779
|
+
def check_homogeneous_of_degree(f, d):
|
|
3780
|
+
if not f:
|
|
3781
|
+
return
|
|
3782
|
+
try:
|
|
3783
|
+
d1 = f.homogeneous_degree()
|
|
3784
|
+
if d1 == d:
|
|
3785
|
+
return
|
|
3786
|
+
except ValueError:
|
|
3787
|
+
raise ValueError("coefficient %s should be an element of homogeneous degree %s" % (f, d))
|
|
3788
|
+
raise ValueError("coefficient %s should be an element of homogeneous degree %s but has degree %s" % (f, d, d1))
|
|
3789
|
+
else:
|
|
3790
|
+
def check_homogeneous_of_degree(f, d):
|
|
3791
|
+
if not f:
|
|
3792
|
+
return
|
|
3793
|
+
for m in f.monomials():
|
|
3794
|
+
try:
|
|
3795
|
+
d1 = m.degree()
|
|
3796
|
+
except AttributeError:
|
|
3797
|
+
# FIXME: Fallback for symmetric functions in multiple variables
|
|
3798
|
+
for t in m.support():
|
|
3799
|
+
d1 = sum(p.size() for p in t)
|
|
3800
|
+
if d1 != d:
|
|
3801
|
+
raise ValueError("coefficient %s should be an element of homogeneous degree %s but has degree %s" % (f, d, d1))
|
|
3802
|
+
except (TypeError, ValueError):
|
|
3803
|
+
raise ValueError("coefficient %s is not homogeneous")
|
|
3804
|
+
if d1 != d:
|
|
3805
|
+
raise ValueError("coefficient %s should be an element of homogeneous degree %s but has degree %s" % (f, d, d1))
|
|
3806
|
+
|
|
3807
|
+
if isinstance(x, (tuple, list)):
|
|
3808
|
+
if degree is None:
|
|
3809
|
+
degree = valuation + len(x)
|
|
3810
|
+
p = [R(e) for e in x]
|
|
3811
|
+
for i, e in enumerate(p, valuation):
|
|
3812
|
+
check_homogeneous_of_degree(e, i)
|
|
3813
|
+
coeff_stream = Stream_exact(p,
|
|
3814
|
+
order=valuation,
|
|
3815
|
+
constant=self._laurent_poly_ring.zero(),
|
|
3816
|
+
degree=degree)
|
|
3817
|
+
return self.element_class(self, coeff_stream)
|
|
3818
|
+
if callable(x):
|
|
3819
|
+
if degree is not None:
|
|
3820
|
+
p = [R(x(i)) for i in range(valuation, degree)]
|
|
3821
|
+
for i, e in enumerate(p, valuation):
|
|
3822
|
+
check_homogeneous_of_degree(e, i)
|
|
3823
|
+
coeff_stream = Stream_exact(p,
|
|
3824
|
+
order=valuation,
|
|
3825
|
+
constant=self._laurent_poly_ring.zero(),
|
|
3826
|
+
degree=degree)
|
|
3827
|
+
return self.element_class(self, coeff_stream)
|
|
3828
|
+
if check:
|
|
3829
|
+
def y(n):
|
|
3830
|
+
e = R(x(n))
|
|
3831
|
+
check_homogeneous_of_degree(e, n)
|
|
3832
|
+
return e
|
|
3833
|
+
|
|
3834
|
+
coeff_stream = Stream_function(y, self._sparse, valuation)
|
|
3835
|
+
else:
|
|
3836
|
+
coeff_stream = Stream_function(x, self._sparse, valuation)
|
|
3837
|
+
return self.element_class(self, coeff_stream)
|
|
3838
|
+
raise ValueError(f"unable to convert {x} into a lazy completion element")
|
|
3839
|
+
|
|
3840
|
+
def _an_element_(self):
|
|
3841
|
+
"""
|
|
3842
|
+
Return a lazy symmetric function in ``self``.
|
|
3843
|
+
|
|
3844
|
+
EXAMPLES::
|
|
3845
|
+
|
|
3846
|
+
sage: m = SymmetricFunctions(ZZ).m() # needs sage.combinat sage.modules
|
|
3847
|
+
sage: L = LazySymmetricFunctions(m) # needs sage.combinat sage.modules
|
|
3848
|
+
sage: L.an_element() # needs sage.combinat sage.modules
|
|
3849
|
+
2*m[] + 2*m[1] + 3*m[2]
|
|
3850
|
+
"""
|
|
3851
|
+
return self(self._laurent_poly_ring.an_element())
|
|
3852
|
+
|
|
3853
|
+
def some_elements(self):
|
|
3854
|
+
"""
|
|
3855
|
+
Return a list of elements of ``self``.
|
|
3856
|
+
|
|
3857
|
+
EXAMPLES::
|
|
3858
|
+
|
|
3859
|
+
sage: m = SymmetricFunctions(GF(5)).m() # needs sage.combinat sage.modules
|
|
3860
|
+
sage: L = LazySymmetricFunctions(m) # needs sage.combinat sage.modules
|
|
3861
|
+
sage: L.some_elements()[:5] # needs sage.combinat sage.modules
|
|
3862
|
+
[0, m[], 2*m[] + 2*m[1] + 3*m[2], 2*m[1] + 3*m[2],
|
|
3863
|
+
3*m[] + 2*m[1] + (m[1,1]+m[2])
|
|
3864
|
+
+ (2*m[1,1,1]+m[3])
|
|
3865
|
+
+ (2*m[1,1,1,1]+4*m[2,1,1]+2*m[2,2])
|
|
3866
|
+
+ (3*m[2,1,1,1]+3*m[3,1,1]+4*m[3,2]+m[5])
|
|
3867
|
+
+ (2*m[2,2,1,1]+m[2,2,2]+2*m[3,2,1]+2*m[3,3]+m[4,1,1]+3*m[4,2]+4*m[5,1]+4*m[6])
|
|
3868
|
+
+ O^7]
|
|
3869
|
+
|
|
3870
|
+
sage: # needs sage.combinat sage.modules
|
|
3871
|
+
sage: NCSF = NonCommutativeSymmetricFunctions(QQ)
|
|
3872
|
+
sage: S = NCSF.Complete()
|
|
3873
|
+
sage: L = S.formal_series_ring()
|
|
3874
|
+
sage: L.some_elements()[:4]
|
|
3875
|
+
[0, S[], 2*S[] + 2*S[1] + (3*S[1,1]), 2*S[1] + (3*S[1,1])]
|
|
3876
|
+
"""
|
|
3877
|
+
elt = self.an_element()
|
|
3878
|
+
elts = [self.zero(), self.one(), elt]
|
|
3879
|
+
# an element with no constant term
|
|
3880
|
+
elts.append(elt - elt[0])
|
|
3881
|
+
# the inverse of an element
|
|
3882
|
+
try:
|
|
3883
|
+
if elt.is_unit():
|
|
3884
|
+
elts.append(~elt)
|
|
3885
|
+
else:
|
|
3886
|
+
elts.append(~(1 - elt[0] + elt))
|
|
3887
|
+
except NotImplementedError:
|
|
3888
|
+
pass
|
|
3889
|
+
# an element with no constant term and an invertible
|
|
3890
|
+
# coefficient of the linear term
|
|
3891
|
+
it = iter(self._laurent_poly_ring.basis())
|
|
3892
|
+
temp = self.sum(b for _ in range(4) if (b := next(it)).degree())
|
|
3893
|
+
if temp:
|
|
3894
|
+
elts.append(temp)
|
|
3895
|
+
|
|
3896
|
+
return elts
|
|
3897
|
+
|
|
3898
|
+
######################################################################
|
|
3899
|
+
|
|
3900
|
+
|
|
3901
|
+
class LazySymmetricFunctions(LazyCompletionGradedAlgebra):
|
|
3902
|
+
"""
|
|
3903
|
+
The ring of lazy symmetric functions.
|
|
3904
|
+
|
|
3905
|
+
INPUT:
|
|
3906
|
+
|
|
3907
|
+
- ``basis`` -- the ring of symmetric functions
|
|
3908
|
+
- ``names`` -- name(s) of the alphabets
|
|
3909
|
+
- ``sparse`` -- boolean (default: ``True``); whether we use a sparse or a
|
|
3910
|
+
dense representation
|
|
3911
|
+
|
|
3912
|
+
EXAMPLES::
|
|
3913
|
+
|
|
3914
|
+
sage: s = SymmetricFunctions(ZZ).s() # needs sage.combinat sage.modules
|
|
3915
|
+
sage: LazySymmetricFunctions(s) # needs sage.combinat sage.modules
|
|
3916
|
+
Lazy completion of Symmetric Functions over Integer Ring in the Schur basis
|
|
3917
|
+
|
|
3918
|
+
sage: m = SymmetricFunctions(ZZ).m() # needs sage.combinat sage.modules
|
|
3919
|
+
sage: LazySymmetricFunctions(tensor([s, m])) # needs sage.combinat sage.modules
|
|
3920
|
+
Lazy completion of
|
|
3921
|
+
Symmetric Functions over Integer Ring in the Schur basis
|
|
3922
|
+
# Symmetric Functions over Integer Ring in the monomial basis
|
|
3923
|
+
"""
|
|
3924
|
+
Element = LazySymmetricFunction
|
|
3925
|
+
|
|
3926
|
+
|
|
3927
|
+
######################################################################
|
|
3928
|
+
|
|
3929
|
+
class LazyDirichletSeriesRing(LazySeriesRing):
|
|
3930
|
+
r"""
|
|
3931
|
+
The ring of lazy Dirichlet series.
|
|
3932
|
+
|
|
3933
|
+
INPUT:
|
|
3934
|
+
|
|
3935
|
+
- ``base_ring`` -- base ring of this Dirichlet series ring
|
|
3936
|
+
- ``names`` -- name of the generator of this Dirichlet series ring
|
|
3937
|
+
- ``sparse`` -- boolean (default: ``True``); whether this series is sparse or not
|
|
3938
|
+
|
|
3939
|
+
Unlike formal univariate Laurent/power series (over a field),
|
|
3940
|
+
the ring of formal Dirichlet series is not a
|
|
3941
|
+
:wikipedia:`discrete_valuation_ring`. On the other hand, it
|
|
3942
|
+
is a :wikipedia:`local_ring`. The unique maximal ideal
|
|
3943
|
+
consists of all non-invertible series, i.e., series with
|
|
3944
|
+
vanishing constant term.
|
|
3945
|
+
|
|
3946
|
+
.. TODO::
|
|
3947
|
+
|
|
3948
|
+
According to the answers in
|
|
3949
|
+
https://mathoverflow.net/questions/5522/dirichlet-series-with-integer-coefficients-as-a-ufd,
|
|
3950
|
+
(which, in particular, references :arxiv:`math/0105219`)
|
|
3951
|
+
the ring of formal Dirichlet series is actually a
|
|
3952
|
+
:wikipedia:`Unique_factorization_domain` over `\ZZ`.
|
|
3953
|
+
|
|
3954
|
+
.. NOTE::
|
|
3955
|
+
|
|
3956
|
+
An interesting valuation is described in Emil Daniel
|
|
3957
|
+
Schwab; Gheorghe Silberberg *A note on some discrete
|
|
3958
|
+
valuation rings of arithmetical functions*, Archivum
|
|
3959
|
+
Mathematicum, Vol. 36 (2000), No. 2, 103-109,
|
|
3960
|
+
http://dml.cz/dmlcz/107723. Let `J_k` be the ideal of
|
|
3961
|
+
Dirichlet series whose coefficient `f[n]` of `n^s`
|
|
3962
|
+
vanishes if `n` has less than `k` prime factors, counting
|
|
3963
|
+
multiplicities. For any Dirichlet series `f`, let `D(f)`
|
|
3964
|
+
be the largest integer `k` such that `f` is in `J_k`.
|
|
3965
|
+
Then `D` is surjective, `D(f g) = D(f) + D(g)` for
|
|
3966
|
+
nonzero `f` and `g`, and `D(f + g) \geq \min(D(f), D(g))`
|
|
3967
|
+
provided that `f + g` is nonzero.
|
|
3968
|
+
|
|
3969
|
+
For example, `J_1` are series with no constant term, and
|
|
3970
|
+
`J_2` are series such that `f[1]` and `f[p]` for prime
|
|
3971
|
+
`p` vanish.
|
|
3972
|
+
|
|
3973
|
+
Since this is a chain of increasing ideals, the ring of
|
|
3974
|
+
formal Dirichlet series is not a
|
|
3975
|
+
:wikipedia:`Noetherian_ring`.
|
|
3976
|
+
|
|
3977
|
+
Evidently, this valuation cannot be computed for a given
|
|
3978
|
+
series.
|
|
3979
|
+
|
|
3980
|
+
EXAMPLES::
|
|
3981
|
+
|
|
3982
|
+
sage: LazyDirichletSeriesRing(ZZ, 't')
|
|
3983
|
+
Lazy Dirichlet Series Ring in t over Integer Ring
|
|
3984
|
+
|
|
3985
|
+
The ideal generated by `2^-s` and `3^-s` is not principal::
|
|
3986
|
+
|
|
3987
|
+
sage: L = LazyDirichletSeriesRing(QQ, 's')
|
|
3988
|
+
sage: L in PrincipalIdealDomains
|
|
3989
|
+
False
|
|
3990
|
+
"""
|
|
3991
|
+
Element = LazyDirichletSeries
|
|
3992
|
+
|
|
3993
|
+
# Follow the "generic" normalization
|
|
3994
|
+
__classcall_private__ = LazySeriesRing.__classcall_private__
|
|
3995
|
+
|
|
3996
|
+
@lazy_attribute
|
|
3997
|
+
def _laurent_poly_ring(self):
|
|
3998
|
+
r"""
|
|
3999
|
+
Return the symbolic ring.
|
|
4000
|
+
|
|
4001
|
+
.. TODO::
|
|
4002
|
+
|
|
4003
|
+
It would be good to have something better than the symbolic ring.
|
|
4004
|
+
|
|
4005
|
+
TESTS::
|
|
4006
|
+
|
|
4007
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 't')
|
|
4008
|
+
sage: L._laurent_poly_ring is SR # needs sage.symbolic
|
|
4009
|
+
True
|
|
4010
|
+
"""
|
|
4011
|
+
from sage.symbolic.ring import SR
|
|
4012
|
+
return SR
|
|
4013
|
+
|
|
4014
|
+
def __init__(self, base_ring, names, sparse=True, category=None):
|
|
4015
|
+
r"""
|
|
4016
|
+
Initialize the ring.
|
|
4017
|
+
|
|
4018
|
+
TESTS::
|
|
4019
|
+
|
|
4020
|
+
sage: LazyDirichletSeriesRing.options.halting_precision(12)
|
|
4021
|
+
|
|
4022
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 't')
|
|
4023
|
+
sage: TestSuite(L).run() # needs sage.symbolic
|
|
4024
|
+
|
|
4025
|
+
sage: L = LazyDirichletSeriesRing(QQ, 't')
|
|
4026
|
+
sage: TestSuite(L).run() # needs sage.symbolic
|
|
4027
|
+
|
|
4028
|
+
sage: LazyDirichletSeriesRing.options._reset() # reset the options
|
|
4029
|
+
"""
|
|
4030
|
+
if base_ring.characteristic() > 0:
|
|
4031
|
+
raise ValueError("positive characteristic not allowed for Dirichlet series")
|
|
4032
|
+
|
|
4033
|
+
self._sparse = sparse
|
|
4034
|
+
self._minimal_valuation = 1
|
|
4035
|
+
self._arity = 1
|
|
4036
|
+
self._internal_poly_ring = PolynomialRing(base_ring, names, sparse=sparse)
|
|
4037
|
+
|
|
4038
|
+
category = Algebras(base_ring.category())
|
|
4039
|
+
if base_ring in IntegralDomains():
|
|
4040
|
+
category &= IntegralDomains()
|
|
4041
|
+
elif base_ring in Rings().Commutative():
|
|
4042
|
+
category = category.Commutative()
|
|
4043
|
+
category = category.Infinite()
|
|
4044
|
+
Parent.__init__(self, base=base_ring, names=names,
|
|
4045
|
+
category=category)
|
|
4046
|
+
|
|
4047
|
+
def _repr_(self):
|
|
4048
|
+
"""
|
|
4049
|
+
String representation of this Dirichlet series ring.
|
|
4050
|
+
|
|
4051
|
+
EXAMPLES::
|
|
4052
|
+
|
|
4053
|
+
sage: LazyDirichletSeriesRing(QQbar, 'z') # needs sage.rings.number_field
|
|
4054
|
+
Lazy Dirichlet Series Ring in z over Algebraic Field
|
|
4055
|
+
"""
|
|
4056
|
+
return "Lazy Dirichlet Series Ring in {} over {}".format(self.variable_name(), self.base_ring())
|
|
4057
|
+
|
|
4058
|
+
@cached_method
|
|
4059
|
+
def one(self):
|
|
4060
|
+
r"""
|
|
4061
|
+
Return the constant series `1`.
|
|
4062
|
+
|
|
4063
|
+
EXAMPLES::
|
|
4064
|
+
|
|
4065
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
4066
|
+
sage: L.one() # needs sage.symbolic
|
|
4067
|
+
1
|
|
4068
|
+
sage: ~L.one() # needs sage.symbolic
|
|
4069
|
+
1 + O(1/(8^z))
|
|
4070
|
+
"""
|
|
4071
|
+
R = self.base_ring()
|
|
4072
|
+
coeff_stream = Stream_exact([R.one()], constant=R.zero(), order=1)
|
|
4073
|
+
return self.element_class(self, coeff_stream)
|
|
4074
|
+
|
|
4075
|
+
def _coerce_map_from_(self, S):
|
|
4076
|
+
"""
|
|
4077
|
+
Return ``True`` if a coercion from ``S`` exists.
|
|
4078
|
+
|
|
4079
|
+
EXAMPLES::
|
|
4080
|
+
|
|
4081
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
4082
|
+
sage: L.has_coerce_map_from(ZZ)
|
|
4083
|
+
True
|
|
4084
|
+
sage: L.has_coerce_map_from(QQ)
|
|
4085
|
+
False
|
|
4086
|
+
"""
|
|
4087
|
+
if self.base_ring().has_coerce_map_from(S):
|
|
4088
|
+
return True
|
|
4089
|
+
return False
|
|
4090
|
+
|
|
4091
|
+
def _element_constructor_(self, x=None, valuation=None, degree=None, constant=None, coefficients=None):
|
|
4092
|
+
r"""
|
|
4093
|
+
Construct a Dirichlet series from ``x``.
|
|
4094
|
+
|
|
4095
|
+
INPUT:
|
|
4096
|
+
|
|
4097
|
+
- ``x`` -- data used to the define a Dirichlet series
|
|
4098
|
+
- ``valuation`` -- integer (optional); a lower bound for the exp of the
|
|
4099
|
+
valuation of the series
|
|
4100
|
+
- ``degree`` -- (optional) the degree when the series is ``constant``
|
|
4101
|
+
- ``constant`` -- (optional) the eventual constant of the series
|
|
4102
|
+
|
|
4103
|
+
EXAMPLES::
|
|
4104
|
+
|
|
4105
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
4106
|
+
sage: R = L(3)
|
|
4107
|
+
sage: R # needs sage.symbolic
|
|
4108
|
+
3
|
|
4109
|
+
sage: S = L(lambda i: i, constant=1, degree=6)
|
|
4110
|
+
sage: S # needs sage.symbolic
|
|
4111
|
+
1 + 2/2^z + 3/3^z + 4/4^z + 5/5^z + 1/(6^z) + 1/(7^z) + 1/(8^z) + O(1/(9^z))
|
|
4112
|
+
|
|
4113
|
+
sage: X = L(constant=5, degree=3)
|
|
4114
|
+
sage: X # needs sage.symbolic
|
|
4115
|
+
5/3^z + 5/4^z + 5/5^z + O(1/(6^z))
|
|
4116
|
+
sage: X.valuation() # needs sage.symbolic
|
|
4117
|
+
log(3)
|
|
4118
|
+
sage: e = L(moebius)
|
|
4119
|
+
sage: e # needs sage.symbolic
|
|
4120
|
+
1 - 1/(2^z) - 1/(3^z) - 1/(5^z) + 1/(6^z) - 1/(7^z) + O(1/(8^z))
|
|
4121
|
+
|
|
4122
|
+
sage: T = L([0], constant=1)
|
|
4123
|
+
sage: T # needs sage.symbolic
|
|
4124
|
+
1/(2^z) + 1/(3^z) + 1/(4^z) + O(1/(5^z))
|
|
4125
|
+
|
|
4126
|
+
sage: U = L(constant=1)
|
|
4127
|
+
sage: U # needs sage.symbolic
|
|
4128
|
+
1 + 1/(2^z) + 1/(3^z) + O(1/(4^z))
|
|
4129
|
+
|
|
4130
|
+
sage: V = L(lambda i: i, valuation=3)
|
|
4131
|
+
sage: V # needs sage.symbolic
|
|
4132
|
+
3/3^z + 4/4^z + 5/5^z + 6/6^z + 7/7^z + 8/8^z + 9/9^z + O(1/(10^z))
|
|
4133
|
+
|
|
4134
|
+
Alternatively, ``x`` can be a list of elements of the base ring.
|
|
4135
|
+
Then these elements are read as coefficients of the terms of
|
|
4136
|
+
degrees starting from the ``valuation``. In this case, ``constant``
|
|
4137
|
+
may be just an element of the base ring instead of a tuple or can be
|
|
4138
|
+
simply omitted if it is zero::
|
|
4139
|
+
|
|
4140
|
+
sage: f = L([1,2,3,4], 4)
|
|
4141
|
+
sage: f # needs sage.symbolic
|
|
4142
|
+
1/(4^z) + 2/5^z + 3/6^z + 4/7^z
|
|
4143
|
+
sage: g = L([1,3,5,7,9], 6, constant=-1)
|
|
4144
|
+
sage: g # needs sage.symbolic
|
|
4145
|
+
1/(6^z) + 3/7^z + 5/8^z + 7/9^z + 9/10^z - 1/(11^z) - 1/(12^z)
|
|
4146
|
+
- 1/(13^z) + O(1/(14^z))
|
|
4147
|
+
|
|
4148
|
+
TESTS::
|
|
4149
|
+
|
|
4150
|
+
sage: L = LazyDirichletSeriesRing(GF(2), 'z')
|
|
4151
|
+
Traceback (most recent call last):
|
|
4152
|
+
...
|
|
4153
|
+
ValueError: positive characteristic not allowed for Dirichlet series
|
|
4154
|
+
|
|
4155
|
+
sage: L.<z> = LazyLaurentSeriesRing(QQ)
|
|
4156
|
+
sage: D = LazyDirichletSeriesRing(QQ, 't')
|
|
4157
|
+
sage: d = D(L.one()) # needs sage.symbolic
|
|
4158
|
+
sage: d # needs sage.symbolic
|
|
4159
|
+
1 + 1/(2^t) + 1/(3^t) + 1/(4^t) + 1/(5^t) + 1/(6^t) + 1/(7^t) + O(1/(8^t))
|
|
4160
|
+
|
|
4161
|
+
sage: R.<z> = LaurentPolynomialRing(QQ)
|
|
4162
|
+
sage: D = LazyDirichletSeriesRing(QQ, 't')
|
|
4163
|
+
sage: dd = D(coefficients=z + z^2)
|
|
4164
|
+
sage: dd # needs sage.symbolic
|
|
4165
|
+
2 + 6/2^t + 12/3^t + 20/4^t + 30/5^t + 42/6^t + 56/7^t + O(1/(8^t))
|
|
4166
|
+
|
|
4167
|
+
sage: s = D(lambda n: n)
|
|
4168
|
+
sage: d2 = D(s, valuation=2) # needs sage.symbolic
|
|
4169
|
+
sage: d2 # needs sage.symbolic
|
|
4170
|
+
1/(2^t) + 2/3^t + 3/4^t + 4/5^t + 5/6^t + 6/7^t + 7/8^t + O(1/(9^t))
|
|
4171
|
+
|
|
4172
|
+
sage: Ds = LazyDirichletSeriesRing(ZZ, 's')
|
|
4173
|
+
sage: m = Ds(moebius, valuation=2)
|
|
4174
|
+
sage: m # needs sage.symbolic
|
|
4175
|
+
-1/(2^s) - 1/(3^s) - 1/(5^s) + 1/(6^s) - 1/(7^s) + O(1/(9^s))
|
|
4176
|
+
sage: D = LazyDirichletSeriesRing(QQ, 't')
|
|
4177
|
+
sage: dm = D(m) # needs sage.libs.pari sage.symbolic
|
|
4178
|
+
sage: dm # needs sage.libs.pari sage.symbolic
|
|
4179
|
+
-1/(2^t) - 1/(3^t) - 1/(5^t) + 1/(6^t) - 1/(7^t) + O(1/(9^t))
|
|
4180
|
+
"""
|
|
4181
|
+
if isinstance(x, (list, tuple)):
|
|
4182
|
+
p = self._internal_poly_ring(x)
|
|
4183
|
+
if valuation is None:
|
|
4184
|
+
if not p:
|
|
4185
|
+
valuation = 1 + len(x)
|
|
4186
|
+
x = p
|
|
4187
|
+
else:
|
|
4188
|
+
x = p.shift(1)
|
|
4189
|
+
else:
|
|
4190
|
+
if coefficients is not None:
|
|
4191
|
+
if valuation is None:
|
|
4192
|
+
valuation = 1
|
|
4193
|
+
return super()._element_constructor_(x, valuation, degree, constant, coefficients)
|
|
4194
|
+
|
|
4195
|
+
BR = self.base_ring()
|
|
4196
|
+
if x in BR:
|
|
4197
|
+
if valuation is None:
|
|
4198
|
+
valuation = 1
|
|
4199
|
+
x = BR(x)
|
|
4200
|
+
|
|
4201
|
+
elif not isinstance(x, LazyDirichletSeries):
|
|
4202
|
+
if valuation is None:
|
|
4203
|
+
valuation = 1
|
|
4204
|
+
|
|
4205
|
+
if isinstance(x, LazyModuleElement) or callable(x):
|
|
4206
|
+
if coefficients is not None:
|
|
4207
|
+
raise ValueError("coefficients must be None if x is provided")
|
|
4208
|
+
coefficients = x
|
|
4209
|
+
x = None
|
|
4210
|
+
|
|
4211
|
+
if valuation is not None and (valuation not in ZZ or valuation <= 0):
|
|
4212
|
+
raise ValueError("the valuation must be a positive integer")
|
|
4213
|
+
|
|
4214
|
+
return super()._element_constructor_(x, valuation, degree, constant, coefficients)
|
|
4215
|
+
|
|
4216
|
+
def _an_element_(self):
|
|
4217
|
+
"""
|
|
4218
|
+
Return a Dirichlet series in this ring.
|
|
4219
|
+
|
|
4220
|
+
EXAMPLES::
|
|
4221
|
+
|
|
4222
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
4223
|
+
sage: m = L.an_element()
|
|
4224
|
+
sage: m # needs sage.symbolic
|
|
4225
|
+
1/(4^z) + 1/(5^z) + 1/(6^z) + O(1/(7^z))
|
|
4226
|
+
"""
|
|
4227
|
+
c = self.base_ring().an_element()
|
|
4228
|
+
return self.element_class(self, Stream_exact([], constant=c, order=4))
|
|
4229
|
+
|
|
4230
|
+
def some_elements(self):
|
|
4231
|
+
"""
|
|
4232
|
+
Return a list of elements of ``self``.
|
|
4233
|
+
|
|
4234
|
+
EXAMPLES::
|
|
4235
|
+
|
|
4236
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
4237
|
+
sage: l = L.some_elements()
|
|
4238
|
+
sage: l # needs sage.symbolic
|
|
4239
|
+
[0, 1,
|
|
4240
|
+
1/(4^z) + 1/(5^z) + 1/(6^z) + O(1/(7^z)),
|
|
4241
|
+
1/(2^z) - 1/(3^z) + 2/4^z - 2/5^z + 3/6^z - 3/7^z + 4/8^z - 4/9^z,
|
|
4242
|
+
1/(2^z) - 1/(3^z) + 2/4^z - 2/5^z + 3/6^z - 3/7^z + 4/8^z - 4/9^z + 1/(10^z) + 1/(11^z) + 1/(12^z) + O(1/(13^z)),
|
|
4243
|
+
1 + 4/2^z + 9/3^z + 16/4^z + 25/5^z + 36/6^z + 49/7^z + O(1/(8^z))]
|
|
4244
|
+
|
|
4245
|
+
sage: L = LazyDirichletSeriesRing(QQ, 'z')
|
|
4246
|
+
sage: l = L.some_elements()
|
|
4247
|
+
sage: l # needs sage.symbolic
|
|
4248
|
+
[0, 1,
|
|
4249
|
+
1/2/4^z + 1/2/5^z + 1/2/6^z + O(1/(7^z)),
|
|
4250
|
+
1/2 - 1/2/2^z + 2/3^z - 2/4^z + 1/(6^z) - 1/(7^z) + 42/8^z + 2/3/9^z,
|
|
4251
|
+
1/2 - 1/2/2^z + 2/3^z - 2/4^z + 1/(6^z) - 1/(7^z) + 42/8^z + 2/3/9^z + 1/2/10^z + 1/2/11^z + 1/2/12^z + O(1/(13^z)),
|
|
4252
|
+
1 + 4/2^z + 9/3^z + 16/4^z + 25/5^z + 36/6^z + 49/7^z + O(1/(8^z))]
|
|
4253
|
+
"""
|
|
4254
|
+
R = self.base_ring()
|
|
4255
|
+
some_numbers = [c for c, _ in zip(R.some_elements(), range(9))]
|
|
4256
|
+
elts = [self.zero(), self.one(), self.an_element(),
|
|
4257
|
+
self(some_numbers),
|
|
4258
|
+
self(some_numbers, constant=R.an_element()),
|
|
4259
|
+
self(lambda n: n**2)]
|
|
4260
|
+
return elts
|
|
4261
|
+
|
|
4262
|
+
def _monomial(self, c, n):
|
|
4263
|
+
r"""
|
|
4264
|
+
Return the interpretation of the coefficient ``c`` at index ``n``.
|
|
4265
|
+
|
|
4266
|
+
EXAMPLES::
|
|
4267
|
+
|
|
4268
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
4269
|
+
sage: m = L._monomial(5, 3); m # needs sage.symbolic
|
|
4270
|
+
5/3^z
|
|
4271
|
+
"""
|
|
4272
|
+
try:
|
|
4273
|
+
L = self._laurent_poly_ring
|
|
4274
|
+
return L(c) * L(n) ** -L(self.variable_name())
|
|
4275
|
+
except (ValueError, TypeError):
|
|
4276
|
+
return '({})/{}^{}'.format(self.base_ring()(c), n, self.variable_name())
|
|
4277
|
+
|
|
4278
|
+
def _terms_of_degree(self, n, R):
|
|
4279
|
+
r"""
|
|
4280
|
+
Return the list consisting of a single element 1 in the base ring.
|
|
4281
|
+
|
|
4282
|
+
EXAMPLES::
|
|
4283
|
+
|
|
4284
|
+
sage: L = LazyDirichletSeriesRing(ZZ, 'z')
|
|
4285
|
+
sage: t = L._terms_of_degree(3, ZZ['x']); t
|
|
4286
|
+
[1]
|
|
4287
|
+
sage: t[0].parent()
|
|
4288
|
+
Univariate Polynomial Ring in x over Integer Ring
|
|
4289
|
+
"""
|
|
4290
|
+
return [R.one()]
|
|
4291
|
+
|
|
4292
|
+
def polylogarithm(self, z):
|
|
4293
|
+
r"""
|
|
4294
|
+
Return the polylogarithm at `z` considered as a Dirichlet series
|
|
4295
|
+
in ``self``.
|
|
4296
|
+
|
|
4297
|
+
The *polylogarithm* at `z` is the Dirichlet series
|
|
4298
|
+
|
|
4299
|
+
.. MATH::
|
|
4300
|
+
|
|
4301
|
+
\mathrm{Li}_s(z) = \sum_{k=1}^{\infty} \frac{z^k}{k^s}.
|
|
4302
|
+
|
|
4303
|
+
EXAMPLES::
|
|
4304
|
+
|
|
4305
|
+
sage: # needs sage.symbolic
|
|
4306
|
+
sage: R.<z> = ZZ[]
|
|
4307
|
+
sage: L = LazyDirichletSeriesRing(R, 's')
|
|
4308
|
+
sage: L.polylogarithm(z)
|
|
4309
|
+
z + z^2/2^s + z^3/3^s + z^4/4^s + z^5/5^s + z^6/6^s + z^7/7^s + O(1/(8^s))
|
|
4310
|
+
|
|
4311
|
+
At `z = 1`, this is the Riemann zeta function::
|
|
4312
|
+
|
|
4313
|
+
sage: L.polylogarithm(1) # needs sage.symbolic
|
|
4314
|
+
1 + 1/(2^s) + 1/(3^s) + 1/(4^s) + 1/(5^s) + 1/(6^s) + 1/(7^s) + O(1/(8^s))
|
|
4315
|
+
|
|
4316
|
+
At `z = -1`, this is the negative of the Dirichlet eta function::
|
|
4317
|
+
|
|
4318
|
+
sage: -L.polylogarithm(-1) # needs sage.symbolic
|
|
4319
|
+
1 - 1/(2^s) + 1/(3^s) - 1/(4^s) + 1/(5^s) - 1/(6^s) + 1/(7^s) + O(1/(8^s))
|
|
4320
|
+
|
|
4321
|
+
REFERENCES:
|
|
4322
|
+
|
|
4323
|
+
- :wikipedia:`Polylogarithm`
|
|
4324
|
+
"""
|
|
4325
|
+
if self._arity != 1:
|
|
4326
|
+
raise ValueError("must has arity 1")
|
|
4327
|
+
return self(coefficients=lambda n: z ** n)
|
|
4328
|
+
|
|
4329
|
+
polylog = polylogarithm
|
|
4330
|
+
|
|
4331
|
+
|
|
4332
|
+
def _skip_leading_zeros(iterator):
|
|
4333
|
+
"""
|
|
4334
|
+
Return an iterator which discards all leading zeros.
|
|
4335
|
+
|
|
4336
|
+
EXAMPLES::
|
|
4337
|
+
|
|
4338
|
+
sage: from sage.rings.lazy_series_ring import _skip_leading_zeros
|
|
4339
|
+
sage: it = map(lambda x: 0 if x < 10 else x, NN)
|
|
4340
|
+
sage: [x for x, _ in zip(_skip_leading_zeros(it), range(10))]
|
|
4341
|
+
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
|
|
4342
|
+
|
|
4343
|
+
sage: # needs sage.rings.finite_rings
|
|
4344
|
+
sage: it = map(GF(3), NN)
|
|
4345
|
+
sage: [x for x, _ in zip(it, range(10))]
|
|
4346
|
+
[0, 1, 2, 0, 1, 2, 0, 1, 2, 0]
|
|
4347
|
+
sage: it = map(GF(3), NN)
|
|
4348
|
+
sage: [x for x, _ in zip(_skip_leading_zeros(it), range(10))]
|
|
4349
|
+
[1, 2, 0, 1, 2, 0, 1, 2, 0, 1]
|
|
4350
|
+
"""
|
|
4351
|
+
while True:
|
|
4352
|
+
c = next(iterator)
|
|
4353
|
+
if c:
|
|
4354
|
+
yield c
|
|
4355
|
+
break
|
|
4356
|
+
yield from iterator
|