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,2794 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Modules With Basis
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- Nicolas M. Thiery (2008-2014): initial revision, axiomatization
|
|
8
|
+
- Jason Bandlow and Florent Hivert (2010): Triangular Morphisms
|
|
9
|
+
- Christian Stump (2010): :issue:`9648` module_morphism's to a wider class
|
|
10
|
+
of codomains
|
|
11
|
+
"""
|
|
12
|
+
#*****************************************************************************
|
|
13
|
+
# Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
|
|
14
|
+
# 2008-2014 Nicolas M. Thiery <nthiery at users.sf.net>
|
|
15
|
+
#
|
|
16
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
17
|
+
# http://www.gnu.org/licenses/
|
|
18
|
+
#******************************************************************************
|
|
19
|
+
|
|
20
|
+
from sage.misc.lazy_import import LazyImport, lazy_import
|
|
21
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
22
|
+
from sage.misc.cachefunc import cached_method
|
|
23
|
+
from sage.misc.abstract_method import abstract_method
|
|
24
|
+
from sage.categories.homsets import HomsetsCategory
|
|
25
|
+
from sage.categories.cartesian_product import CartesianProductsCategory
|
|
26
|
+
from sage.categories.tensor import tensor, TensorProductsCategory
|
|
27
|
+
from sage.categories.dual import DualObjectsCategory
|
|
28
|
+
from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring
|
|
29
|
+
from sage.categories.fields import Fields
|
|
30
|
+
from sage.categories.modules import Modules
|
|
31
|
+
from sage.categories.poor_man_map import PoorManMap
|
|
32
|
+
from sage.categories.map import Map
|
|
33
|
+
from sage.structure.element import Element, parent
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
lazy_import('sage.modules.with_basis.morphism',
|
|
37
|
+
['ModuleMorphismByLinearity',
|
|
38
|
+
'ModuleMorphismFromMatrix',
|
|
39
|
+
'ModuleMorphismFromFunction',
|
|
40
|
+
'DiagonalModuleMorphism',
|
|
41
|
+
'TriangularModuleMorphismByLinearity',
|
|
42
|
+
'TriangularModuleMorphismFromFunction'])
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ModulesWithBasis(CategoryWithAxiom_over_base_ring):
|
|
46
|
+
"""
|
|
47
|
+
The category of modules with a distinguished basis.
|
|
48
|
+
|
|
49
|
+
The elements are represented by expanding them in the distinguished basis.
|
|
50
|
+
The morphisms are not required to respect the distinguished basis.
|
|
51
|
+
|
|
52
|
+
EXAMPLES::
|
|
53
|
+
|
|
54
|
+
sage: ModulesWithBasis(ZZ)
|
|
55
|
+
Category of modules with basis over Integer Ring
|
|
56
|
+
sage: ModulesWithBasis(ZZ).super_categories()
|
|
57
|
+
[Category of modules over Integer Ring]
|
|
58
|
+
|
|
59
|
+
If the base ring is actually a field, this constructs instead the
|
|
60
|
+
category of vector spaces with basis::
|
|
61
|
+
|
|
62
|
+
sage: ModulesWithBasis(QQ)
|
|
63
|
+
Category of vector spaces with basis over Rational Field
|
|
64
|
+
|
|
65
|
+
sage: ModulesWithBasis(QQ).super_categories()
|
|
66
|
+
[Category of modules with basis over Rational Field,
|
|
67
|
+
Category of vector spaces over Rational Field]
|
|
68
|
+
|
|
69
|
+
Let `X` and `Y` be two modules with basis. We can build `Hom(X,Y)`::
|
|
70
|
+
|
|
71
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2]); X.rename('X') # needs sage.modules
|
|
72
|
+
sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.rename('Y') # needs sage.modules
|
|
73
|
+
sage: H = Hom(X, Y); H # needs sage.modules
|
|
74
|
+
Set of Morphisms from X to Y
|
|
75
|
+
in Category of finite dimensional vector spaces with basis over Rational Field
|
|
76
|
+
|
|
77
|
+
The simplest morphism is the zero map::
|
|
78
|
+
|
|
79
|
+
sage: H.zero() # todo: move this test into module once we have an example # needs sage.modules
|
|
80
|
+
Generic morphism:
|
|
81
|
+
From: X
|
|
82
|
+
To: Y
|
|
83
|
+
|
|
84
|
+
which we can apply to elements of `X`::
|
|
85
|
+
|
|
86
|
+
sage: x = X.monomial(1) + 3 * X.monomial(2) # needs sage.modules
|
|
87
|
+
sage: H.zero()(x) # needs sage.modules
|
|
88
|
+
0
|
|
89
|
+
|
|
90
|
+
EXAMPLES:
|
|
91
|
+
|
|
92
|
+
We now construct a more interesting morphism by extending a
|
|
93
|
+
function by linearity::
|
|
94
|
+
|
|
95
|
+
sage: phi = H(on_basis=lambda i: Y.monomial(i + 2)); phi # needs sage.modules
|
|
96
|
+
Generic morphism:
|
|
97
|
+
From: X
|
|
98
|
+
To: Y
|
|
99
|
+
sage: phi(x) # needs sage.modules
|
|
100
|
+
B[3] + 3*B[4]
|
|
101
|
+
|
|
102
|
+
We can retrieve the function acting on indices of the basis::
|
|
103
|
+
|
|
104
|
+
sage: f = phi.on_basis() # needs sage.modules
|
|
105
|
+
sage: f(1), f(2) # needs sage.modules
|
|
106
|
+
(B[3], B[4])
|
|
107
|
+
|
|
108
|
+
`Hom(X,Y)` has a natural module structure (except for the zero,
|
|
109
|
+
the operations are not yet implemented though). However since the
|
|
110
|
+
dimension is not necessarily finite, it is not a module with
|
|
111
|
+
basis; but see :class:`FiniteDimensionalModulesWithBasis` and
|
|
112
|
+
:class:`GradedModulesWithBasis`::
|
|
113
|
+
|
|
114
|
+
sage: H in ModulesWithBasis(QQ), H in Modules(QQ) # needs sage.modules
|
|
115
|
+
(False, True)
|
|
116
|
+
|
|
117
|
+
Some more playing around with categories and higher order homsets::
|
|
118
|
+
|
|
119
|
+
sage: H.category() # needs sage.modules
|
|
120
|
+
Category of homsets of finite dimensional modules with basis over Rational Field
|
|
121
|
+
sage: Hom(H, H).category() # needs sage.modules
|
|
122
|
+
Category of endsets of
|
|
123
|
+
homsets of finite dimensional modules with basis over Rational Field
|
|
124
|
+
|
|
125
|
+
.. TODO:: ``End(X)`` is an algebra.
|
|
126
|
+
|
|
127
|
+
.. NOTE::
|
|
128
|
+
|
|
129
|
+
This category currently requires an implementation of an
|
|
130
|
+
element method ``support``. Once :issue:`18066` is merged, an
|
|
131
|
+
implementation of an ``items`` method will be required.
|
|
132
|
+
|
|
133
|
+
TESTS::
|
|
134
|
+
|
|
135
|
+
sage: f = H.zero().on_basis() # needs sage.modules
|
|
136
|
+
sage: f(1) # needs sage.modules
|
|
137
|
+
0
|
|
138
|
+
sage: f(2) # needs sage.modules
|
|
139
|
+
0
|
|
140
|
+
|
|
141
|
+
sage: TestSuite(ModulesWithBasis(ZZ)).run()
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
def _call_(self, x):
|
|
145
|
+
"""
|
|
146
|
+
Construct a module with basis (resp. vector space) from the data in ``x``.
|
|
147
|
+
|
|
148
|
+
EXAMPLES::
|
|
149
|
+
|
|
150
|
+
sage: CZ = ModulesWithBasis(ZZ); CZ
|
|
151
|
+
Category of modules with basis over Integer Ring
|
|
152
|
+
sage: CQ = ModulesWithBasis(QQ); CQ
|
|
153
|
+
Category of vector spaces with basis over Rational Field
|
|
154
|
+
|
|
155
|
+
``x`` is returned unchanged if it is already in this category::
|
|
156
|
+
|
|
157
|
+
sage: CZ(CombinatorialFreeModule(ZZ, ('a', 'b', 'c'))) # needs sage.modules
|
|
158
|
+
Free module generated by {'a', 'b', 'c'} over Integer Ring
|
|
159
|
+
sage: CZ(ZZ^3) # needs sage.modules
|
|
160
|
+
Ambient free module of rank 3 over the principal ideal domain Integer Ring
|
|
161
|
+
|
|
162
|
+
If needed (and possible) the base ring is changed appropriately::
|
|
163
|
+
|
|
164
|
+
sage: CQ(ZZ^3) # indirect doctest # needs sage.modules
|
|
165
|
+
Vector space of dimension 3 over Rational Field
|
|
166
|
+
|
|
167
|
+
If ``x`` itself is not a module with basis, but there is a
|
|
168
|
+
canonical one associated to it, the latter is returned::
|
|
169
|
+
|
|
170
|
+
sage: CQ(AbelianVariety(Gamma0(37))) # indirect doctest # needs sage.libs.flint sage.modular sage.modules
|
|
171
|
+
Vector space of dimension 4 over Rational Field
|
|
172
|
+
"""
|
|
173
|
+
try:
|
|
174
|
+
M = x.free_module()
|
|
175
|
+
if M.base_ring() != self.base_ring():
|
|
176
|
+
M = M.change_ring(self.base_ring())
|
|
177
|
+
except (TypeError, AttributeError) as msg:
|
|
178
|
+
raise TypeError("%s\nunable to coerce x (=%s) into %s" % (msg, x, self))
|
|
179
|
+
return M
|
|
180
|
+
|
|
181
|
+
def is_abelian(self):
|
|
182
|
+
"""
|
|
183
|
+
Return whether this category is abelian.
|
|
184
|
+
|
|
185
|
+
This is the case if and only if the base ring is a field.
|
|
186
|
+
|
|
187
|
+
EXAMPLES::
|
|
188
|
+
|
|
189
|
+
sage: ModulesWithBasis(QQ).is_abelian()
|
|
190
|
+
True
|
|
191
|
+
sage: ModulesWithBasis(ZZ).is_abelian()
|
|
192
|
+
False
|
|
193
|
+
"""
|
|
194
|
+
return self.base_ring().is_field()
|
|
195
|
+
|
|
196
|
+
FiniteDimensional = LazyImport('sage.categories.finite_dimensional_modules_with_basis', 'FiniteDimensionalModulesWithBasis', at_startup=True)
|
|
197
|
+
Filtered = LazyImport('sage.categories.filtered_modules_with_basis', 'FilteredModulesWithBasis')
|
|
198
|
+
Graded = LazyImport('sage.categories.graded_modules_with_basis', 'GradedModulesWithBasis')
|
|
199
|
+
Super = LazyImport('sage.categories.super_modules_with_basis', 'SuperModulesWithBasis')
|
|
200
|
+
|
|
201
|
+
# To implement a module_with_basis you need to implement the
|
|
202
|
+
# following methods:
|
|
203
|
+
# - On the parent class, either basis() or an _indices attribute and
|
|
204
|
+
# monomial().
|
|
205
|
+
# - On the element class, monomial_coefficients().
|
|
206
|
+
|
|
207
|
+
class ParentMethods:
|
|
208
|
+
@cached_method
|
|
209
|
+
def basis(self):
|
|
210
|
+
"""
|
|
211
|
+
Return the basis of ``self``.
|
|
212
|
+
|
|
213
|
+
EXAMPLES::
|
|
214
|
+
|
|
215
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules
|
|
216
|
+
sage: F.basis() # needs sage.modules
|
|
217
|
+
Finite family {'a': B['a'], 'b': B['b'], 'c': B['c']}
|
|
218
|
+
|
|
219
|
+
::
|
|
220
|
+
|
|
221
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3) # needs sage.combinat sage.groups sage.modules
|
|
222
|
+
sage: list(QS3.basis()) # needs sage.combinat sage.groups sage.modules
|
|
223
|
+
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
|
|
224
|
+
"""
|
|
225
|
+
from sage.sets.family import Family
|
|
226
|
+
return Family(self._indices, self.monomial)
|
|
227
|
+
|
|
228
|
+
def module_morphism(self, on_basis=None, matrix=None, function=None,
|
|
229
|
+
diagonal=None, triangular=None, unitriangular=False,
|
|
230
|
+
**keywords):
|
|
231
|
+
r"""
|
|
232
|
+
Construct a module morphism from ``self`` to ``codomain``.
|
|
233
|
+
|
|
234
|
+
Let ``self`` be a module `X` with a basis indexed by `I`.
|
|
235
|
+
This constructs a morphism `f: X \to Y` by linearity from
|
|
236
|
+
a map `I \to Y` which is to be its restriction to the
|
|
237
|
+
basis `(x_i)_{i \in I}` of `X`. Some variants are possible
|
|
238
|
+
too.
|
|
239
|
+
|
|
240
|
+
INPUT:
|
|
241
|
+
|
|
242
|
+
- ``self`` -- a parent `X` in ``ModulesWithBasis(R)`` with
|
|
243
|
+
basis `x=(x_i)_{i\in I}`
|
|
244
|
+
|
|
245
|
+
Exactly one of the four following options must be
|
|
246
|
+
specified in order to define the morphism:
|
|
247
|
+
|
|
248
|
+
- ``on_basis`` -- a function `f` from `I` to `Y`
|
|
249
|
+
- ``diagonal`` -- a function `d` from `I` to `R`
|
|
250
|
+
- ``function`` -- a function `f` from `X` to `Y`
|
|
251
|
+
- ``matrix`` -- a matrix of size `\dim Y \times \dim X`
|
|
252
|
+
(if the keyword ``side`` is set to ``'left'``) or
|
|
253
|
+
`\dim Y \times \dim X` (if this keyword is ``'right'``)
|
|
254
|
+
|
|
255
|
+
Further options include:
|
|
256
|
+
|
|
257
|
+
- ``codomain`` -- the codomain `Y` of the morphism (default:
|
|
258
|
+
``f.codomain()`` if it's defined; otherwise it must be specified)
|
|
259
|
+
|
|
260
|
+
- ``category`` -- a category or ``None`` (default: ``None``)
|
|
261
|
+
|
|
262
|
+
- ``zero`` -- the zero of the codomain (default: ``codomain.zero()``);
|
|
263
|
+
can be used (with care) to define affine maps.
|
|
264
|
+
Only meaningful with ``on_basis``.
|
|
265
|
+
|
|
266
|
+
- ``position`` -- nonnegative integer specifying which
|
|
267
|
+
positional argument is used as the input of the function `f`
|
|
268
|
+
(default: 0); this is currently only used with ``on_basis``.
|
|
269
|
+
|
|
270
|
+
- ``triangular`` -- (default: ``None``) ``'upper'`` or
|
|
271
|
+
``'lower'`` or ``None``:
|
|
272
|
+
|
|
273
|
+
* ``'upper'`` -- if the
|
|
274
|
+
:meth:`~ModulesWithBasis.ElementMethods.leading_support`
|
|
275
|
+
of the image of the basis vector `x_i` is `i`, or
|
|
276
|
+
|
|
277
|
+
* ``'lower'`` -- if the
|
|
278
|
+
:meth:`~ModulesWithBasis.ElementMethods.trailing_support`
|
|
279
|
+
of the image of the basis vector `x_i` is `i`.
|
|
280
|
+
|
|
281
|
+
- ``unitriangular`` -- boolean (default: ``False``);
|
|
282
|
+
only meaningful for a triangular morphism.
|
|
283
|
+
As a shorthand, one may use ``unitriangular="lower"``
|
|
284
|
+
for ``triangular='lower', unitriangular=True``.
|
|
285
|
+
|
|
286
|
+
- ``side`` -- ``'left'`` or ``'right'`` (default: ``'left'``);
|
|
287
|
+
only meaningful for a morphism built from a matrix
|
|
288
|
+
|
|
289
|
+
EXAMPLES:
|
|
290
|
+
|
|
291
|
+
With the ``on_basis`` option, this returns a function `g`
|
|
292
|
+
obtained by extending `f` by linearity on the
|
|
293
|
+
``position``-th positional argument. For example, for
|
|
294
|
+
``position == 1`` and a ternary function `f`, one has:
|
|
295
|
+
|
|
296
|
+
.. MATH::
|
|
297
|
+
|
|
298
|
+
g\left( a,\ \sum_i \lambda_i x_i,\ c \right)
|
|
299
|
+
= \sum_i \lambda_i f(a, i, c).
|
|
300
|
+
|
|
301
|
+
::
|
|
302
|
+
|
|
303
|
+
sage: # needs sage.modules
|
|
304
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename('X')
|
|
305
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename('Y')
|
|
306
|
+
sage: def f(i):
|
|
307
|
+
....: return Y.monomial(i) + 2*Y.monomial(i+1)
|
|
308
|
+
sage: phi = X.module_morphism(f, codomain=Y)
|
|
309
|
+
sage: x = X.basis(); y = Y.basis()
|
|
310
|
+
sage: phi(x[1] + x[3])
|
|
311
|
+
B[1] + 2*B[2] + B[3] + 2*B[4]
|
|
312
|
+
sage: phi
|
|
313
|
+
Generic morphism:
|
|
314
|
+
From: X
|
|
315
|
+
To: Y
|
|
316
|
+
|
|
317
|
+
By default, the category is the first of
|
|
318
|
+
``Modules(R).WithBasis().FiniteDimensional()``,
|
|
319
|
+
``Modules(R).WithBasis()``, ``Modules(R)``, and
|
|
320
|
+
``CommutativeAdditiveMonoids()`` that contains both the
|
|
321
|
+
domain and the codomain::
|
|
322
|
+
|
|
323
|
+
sage: phi.category_for() # needs sage.modules
|
|
324
|
+
Category of finite dimensional vector spaces with basis
|
|
325
|
+
over Rational Field
|
|
326
|
+
|
|
327
|
+
With the ``zero`` argument, one can define affine morphisms::
|
|
328
|
+
|
|
329
|
+
sage: def f(i):
|
|
330
|
+
....: return Y.monomial(i) + 2*Y.monomial(i+1)
|
|
331
|
+
sage: phi = X.module_morphism(f, codomain=Y, zero=10*y[1]) # needs sage.modules
|
|
332
|
+
sage: phi(x[1] + x[3]) # needs sage.modules
|
|
333
|
+
11*B[1] + 2*B[2] + B[3] + 2*B[4]
|
|
334
|
+
|
|
335
|
+
In this special case, the default category is ``Sets()``::
|
|
336
|
+
|
|
337
|
+
sage: phi.category_for() # needs sage.modules
|
|
338
|
+
Category of sets
|
|
339
|
+
|
|
340
|
+
One can construct morphisms with the base ring as codomain::
|
|
341
|
+
|
|
342
|
+
sage: # needs sage.modules
|
|
343
|
+
sage: X = CombinatorialFreeModule(ZZ, [1, -1])
|
|
344
|
+
sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=ZZ)
|
|
345
|
+
sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1))
|
|
346
|
+
-1
|
|
347
|
+
sage: phi.category_for()
|
|
348
|
+
Category of commutative additive semigroups
|
|
349
|
+
sage: phi.category_for() # not implemented
|
|
350
|
+
Category of modules over Integer Ring
|
|
351
|
+
|
|
352
|
+
Or more generally any ring admitting a coercion map from
|
|
353
|
+
the base ring::
|
|
354
|
+
|
|
355
|
+
sage: # needs sage.modules
|
|
356
|
+
sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=RR)
|
|
357
|
+
sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1))
|
|
358
|
+
-1.00000000000000
|
|
359
|
+
sage: phi.category_for()
|
|
360
|
+
Category of commutative additive semigroups
|
|
361
|
+
sage: phi.category_for() # not implemented
|
|
362
|
+
Category of modules over Integer Ring
|
|
363
|
+
|
|
364
|
+
sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # needs sage.modules
|
|
365
|
+
sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # needs sage.modules
|
|
366
|
+
3
|
|
367
|
+
|
|
368
|
+
sage: phi = Y.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # needs sage.modules
|
|
369
|
+
Traceback (most recent call last):
|
|
370
|
+
...
|
|
371
|
+
ValueError: codomain(=Ring of integers modulo 4) should be a module
|
|
372
|
+
over the base ring of the domain(=Y)
|
|
373
|
+
|
|
374
|
+
On can also define module morphisms between free modules
|
|
375
|
+
over different base rings; here we implement the natural
|
|
376
|
+
map from `X = \RR^2` to `Y = \CC`::
|
|
377
|
+
|
|
378
|
+
sage: # needs sage.modules
|
|
379
|
+
sage: X = CombinatorialFreeModule(RR, ['x', 'y'])
|
|
380
|
+
sage: Y = CombinatorialFreeModule(CC, ['z'])
|
|
381
|
+
sage: x = X.monomial('x')
|
|
382
|
+
sage: y = X.monomial('y')
|
|
383
|
+
sage: z = Y.monomial('z')
|
|
384
|
+
sage: def on_basis(a):
|
|
385
|
+
....: if a == 'x':
|
|
386
|
+
....: return CC(1) * z
|
|
387
|
+
....: elif a == 'y':
|
|
388
|
+
....: return CC(I) * z
|
|
389
|
+
sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y)
|
|
390
|
+
sage: v = 3 * x + 2 * y; v
|
|
391
|
+
3.00000000000000*B['x'] + 2.00000000000000*B['y']
|
|
392
|
+
sage: phi(v) # needs sage.symbolic
|
|
393
|
+
(3.00000000000000+2.00000000000000*I)*B['z']
|
|
394
|
+
sage: phi.category_for()
|
|
395
|
+
Category of commutative additive semigroups
|
|
396
|
+
sage: phi.category_for() # not implemented
|
|
397
|
+
Category of vector spaces over Real Field with 53 bits of precision
|
|
398
|
+
|
|
399
|
+
sage: # needs sage.modules
|
|
400
|
+
sage: Y = CombinatorialFreeModule(CC['q'], ['z'])
|
|
401
|
+
sage: z = Y.monomial('z')
|
|
402
|
+
sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y)
|
|
403
|
+
sage: phi(v) # needs sage.symbolic
|
|
404
|
+
(3.00000000000000+2.00000000000000*I)*B['z']
|
|
405
|
+
|
|
406
|
+
Of course, there should be a coercion between the
|
|
407
|
+
respective base rings of the domain and the codomain for
|
|
408
|
+
this to be meaningful::
|
|
409
|
+
|
|
410
|
+
sage: Y = CombinatorialFreeModule(QQ, ['z']) # needs sage.modules
|
|
411
|
+
sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # needs sage.modules
|
|
412
|
+
Traceback (most recent call last):
|
|
413
|
+
...
|
|
414
|
+
ValueError: codomain(=Free module generated by {'z'} over Rational Field)
|
|
415
|
+
should be a module over the base ring of the domain(=Free module
|
|
416
|
+
generated by {'x', 'y'} over Real Field with 53 bits of precision)
|
|
417
|
+
|
|
418
|
+
sage: Y = CombinatorialFreeModule(RR['q'], ['z']) # needs sage.modules
|
|
419
|
+
sage: phi = Y.module_morphism(on_basis=on_basis, codomain=X) # needs sage.modules
|
|
420
|
+
Traceback (most recent call last):
|
|
421
|
+
...
|
|
422
|
+
ValueError: codomain(=Free module generated by {'x', 'y'}
|
|
423
|
+
over Real Field with 53 bits of precision) should be a module over
|
|
424
|
+
the base ring of the domain(=Free module generated by {'z'} over
|
|
425
|
+
Univariate Polynomial Ring in q over Real Field with 53 bits of precision)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
With the ``diagonal=d`` argument, this constructs the
|
|
429
|
+
module morphism `g` such that
|
|
430
|
+
|
|
431
|
+
.. MATH::
|
|
432
|
+
|
|
433
|
+
`g(x_i) = d(i) y_i`.
|
|
434
|
+
|
|
435
|
+
This assumes that the respective bases `x` and `y` of `X`
|
|
436
|
+
and `Y` have the same index set `I`::
|
|
437
|
+
|
|
438
|
+
sage: # needs sage.modules
|
|
439
|
+
sage: X = CombinatorialFreeModule(ZZ, [1, 2, 3]); X.rename('X')
|
|
440
|
+
sage: from sage.arith.misc import factorial
|
|
441
|
+
sage: phi = X.module_morphism(diagonal=factorial, codomain=X)
|
|
442
|
+
sage: x = X.basis()
|
|
443
|
+
sage: phi(x[1]), phi(x[2]), phi(x[3])
|
|
444
|
+
(B[1], 2*B[2], 6*B[3])
|
|
445
|
+
|
|
446
|
+
See also: :class:`sage.modules.with_basis.morphism.DiagonalModuleMorphism`.
|
|
447
|
+
|
|
448
|
+
With the ``matrix=m`` argument, this constructs the module
|
|
449
|
+
morphism whose matrix in the distinguished basis of `X`
|
|
450
|
+
and `Y` is `m`::
|
|
451
|
+
|
|
452
|
+
sage: # needs sage.modules
|
|
453
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename('X')
|
|
454
|
+
sage: x = X.basis()
|
|
455
|
+
sage: Y = CombinatorialFreeModule(ZZ, [3,4]); Y.rename('Y')
|
|
456
|
+
sage: y = Y.basis()
|
|
457
|
+
sage: m = matrix([[0,1,2], [3,5,0]])
|
|
458
|
+
sage: phi = X.module_morphism(matrix=m, codomain=Y)
|
|
459
|
+
sage: phi(x[1])
|
|
460
|
+
3*B[4]
|
|
461
|
+
sage: phi(x[2])
|
|
462
|
+
B[3] + 5*B[4]
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
See also: :class:`sage.modules.with_basis.morphism.ModuleMorphismFromMatrix`.
|
|
466
|
+
|
|
467
|
+
With ``triangular="upper"``, the constructed module morphism is
|
|
468
|
+
assumed to be upper triangular; that is its matrix in the
|
|
469
|
+
distinguished basis of `X` and `Y` would be upper triangular with
|
|
470
|
+
invertible elements on its diagonal. This is used to compute
|
|
471
|
+
preimages and to invert the morphism::
|
|
472
|
+
|
|
473
|
+
sage: # needs sage.modules
|
|
474
|
+
sage: I = list(range(1, 200))
|
|
475
|
+
sage: X = CombinatorialFreeModule(QQ, I); X.rename('X'); x = X.basis()
|
|
476
|
+
sage: Y = CombinatorialFreeModule(QQ, I); Y.rename('Y'); y = Y.basis()
|
|
477
|
+
sage: f = Y.sum_of_monomials * divisors
|
|
478
|
+
sage: phi = X.module_morphism(f, triangular='upper', codomain=Y)
|
|
479
|
+
sage: phi(x[2])
|
|
480
|
+
B[1] + B[2]
|
|
481
|
+
sage: phi(x[6])
|
|
482
|
+
B[1] + B[2] + B[3] + B[6]
|
|
483
|
+
sage: phi(x[30])
|
|
484
|
+
B[1] + B[2] + B[3] + B[5] + B[6] + B[10] + B[15] + B[30]
|
|
485
|
+
sage: phi.preimage(y[2])
|
|
486
|
+
-B[1] + B[2]
|
|
487
|
+
sage: phi.preimage(y[6])
|
|
488
|
+
B[1] - B[2] - B[3] + B[6]
|
|
489
|
+
sage: phi.preimage(y[30])
|
|
490
|
+
-B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30]
|
|
491
|
+
sage: (phi^-1)(y[30])
|
|
492
|
+
-B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30]
|
|
493
|
+
|
|
494
|
+
Since :issue:`8678`, one can also define a triangular
|
|
495
|
+
morphism from a function::
|
|
496
|
+
|
|
497
|
+
sage: # needs sage.modules
|
|
498
|
+
sage: X = CombinatorialFreeModule(QQ, [0,1,2,3,4]); x = X.basis()
|
|
499
|
+
sage: from sage.modules.with_basis.morphism import TriangularModuleMorphismFromFunction
|
|
500
|
+
sage: def f(x): return x + X.term(0, sum(x.coefficients()))
|
|
501
|
+
sage: phi = X.module_morphism(function=f, codomain=X,
|
|
502
|
+
....: triangular='upper')
|
|
503
|
+
sage: phi(x[2] + 3*x[4])
|
|
504
|
+
4*B[0] + B[2] + 3*B[4]
|
|
505
|
+
sage: phi.preimage(_)
|
|
506
|
+
B[2] + 3*B[4]
|
|
507
|
+
|
|
508
|
+
For details and further optional arguments, see
|
|
509
|
+
:class:`sage.modules.with_basis.morphism.TriangularModuleMorphism`.
|
|
510
|
+
|
|
511
|
+
.. WARNING::
|
|
512
|
+
|
|
513
|
+
As a temporary measure, until multivariate morphisms
|
|
514
|
+
are implemented, the constructed morphism is in
|
|
515
|
+
``Hom(codomain, domain, category)``. This is only
|
|
516
|
+
correct for unary functions.
|
|
517
|
+
|
|
518
|
+
.. TODO::
|
|
519
|
+
|
|
520
|
+
- Should codomain be ``self`` by default in the
|
|
521
|
+
diagonal, triangular, and matrix cases?
|
|
522
|
+
|
|
523
|
+
- Support for diagonal morphisms between modules not
|
|
524
|
+
sharing the same index set
|
|
525
|
+
|
|
526
|
+
TESTS::
|
|
527
|
+
|
|
528
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename('X') # needs sage.modules
|
|
529
|
+
sage: phi = X.module_morphism(codomain=X) # needs sage.modules
|
|
530
|
+
Traceback (most recent call last):
|
|
531
|
+
...
|
|
532
|
+
ValueError: module_morphism() takes exactly one option
|
|
533
|
+
out of `matrix`, `on_basis`, `function`, `diagonal`
|
|
534
|
+
|
|
535
|
+
::
|
|
536
|
+
|
|
537
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename('X') # needs sage.modules
|
|
538
|
+
sage: phi = X.module_morphism(diagonal=factorial, matrix=matrix(), # needs sage.modules
|
|
539
|
+
....: codomain=X)
|
|
540
|
+
Traceback (most recent call last):
|
|
541
|
+
...
|
|
542
|
+
ValueError: module_morphism() takes exactly one option
|
|
543
|
+
out of `matrix`, `on_basis`, `function`, `diagonal`
|
|
544
|
+
|
|
545
|
+
::
|
|
546
|
+
|
|
547
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename('X') # needs sage.modules
|
|
548
|
+
sage: phi = X.module_morphism(matrix=factorial, codomain=X) # needs sage.modules
|
|
549
|
+
Traceback (most recent call last):
|
|
550
|
+
...
|
|
551
|
+
ValueError: matrix (=...factorial...) should be a matrix
|
|
552
|
+
|
|
553
|
+
::
|
|
554
|
+
|
|
555
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename('X') # needs sage.modules
|
|
556
|
+
sage: phi = X.module_morphism(diagonal=3, codomain=X) # needs sage.modules
|
|
557
|
+
Traceback (most recent call last):
|
|
558
|
+
...
|
|
559
|
+
ValueError: diagonal (=3) should be a function
|
|
560
|
+
"""
|
|
561
|
+
if len([x for x in [matrix, on_basis, function, diagonal] if x is not None]) != 1:
|
|
562
|
+
raise ValueError("module_morphism() takes exactly one option out of `matrix`, `on_basis`, `function`, `diagonal`")
|
|
563
|
+
if matrix is not None:
|
|
564
|
+
return ModuleMorphismFromMatrix(domain=self, matrix=matrix, **keywords)
|
|
565
|
+
if diagonal is not None:
|
|
566
|
+
return DiagonalModuleMorphism(domain=self, diagonal=diagonal, **keywords)
|
|
567
|
+
if unitriangular in ["upper", "lower"] and triangular is None:
|
|
568
|
+
triangular = unitriangular
|
|
569
|
+
unitriangular = True
|
|
570
|
+
if triangular is not None:
|
|
571
|
+
if on_basis is not None:
|
|
572
|
+
return TriangularModuleMorphismByLinearity(
|
|
573
|
+
domain=self, on_basis=on_basis,
|
|
574
|
+
triangular=triangular, unitriangular=unitriangular,
|
|
575
|
+
**keywords)
|
|
576
|
+
else:
|
|
577
|
+
return TriangularModuleMorphismFromFunction(
|
|
578
|
+
domain=self, function=function,
|
|
579
|
+
triangular=triangular, unitriangular=unitriangular,
|
|
580
|
+
**keywords)
|
|
581
|
+
if on_basis is not None:
|
|
582
|
+
return ModuleMorphismByLinearity(
|
|
583
|
+
domain=self, on_basis=on_basis, **keywords)
|
|
584
|
+
else:
|
|
585
|
+
return ModuleMorphismFromFunction( # Or just SetMorphism?
|
|
586
|
+
domain=self, function=function, **keywords)
|
|
587
|
+
|
|
588
|
+
_module_morphism = module_morphism
|
|
589
|
+
|
|
590
|
+
def _repr_(self):
|
|
591
|
+
"""
|
|
592
|
+
EXAMPLES::
|
|
593
|
+
|
|
594
|
+
sage: # needs sage.modules
|
|
595
|
+
sage: class FooBar(CombinatorialFreeModule): pass
|
|
596
|
+
sage: C = FooBar(QQ, (1,2,3)); C # indirect doctest
|
|
597
|
+
Free module generated by {1, 2, 3} over Rational Field
|
|
598
|
+
sage: C._name = "foobar"; C
|
|
599
|
+
foobar over Rational Field
|
|
600
|
+
sage: C.rename('barfoo'); C
|
|
601
|
+
barfoo
|
|
602
|
+
|
|
603
|
+
sage: class FooBar(Parent):
|
|
604
|
+
....: def basis(self): return Family({1: "foo", 2: "bar"})
|
|
605
|
+
....: def base_ring(self): return QQ
|
|
606
|
+
sage: FooBar(category=ModulesWithBasis(QQ))
|
|
607
|
+
Free module generated by [1, 2] over Rational Field
|
|
608
|
+
"""
|
|
609
|
+
if hasattr(self, "_name"):
|
|
610
|
+
name = self._name
|
|
611
|
+
else:
|
|
612
|
+
name = "Free module generated by {}".format(self.basis().keys())
|
|
613
|
+
return name + " over {}".format(self.base_ring())
|
|
614
|
+
|
|
615
|
+
def _compute_support_order(self, elements, support_order=None):
|
|
616
|
+
"""
|
|
617
|
+
Return the support of a set of elements in ``self`` sorted
|
|
618
|
+
in some order.
|
|
619
|
+
|
|
620
|
+
INPUT:
|
|
621
|
+
|
|
622
|
+
- ``elements`` -- the list of elements
|
|
623
|
+
- ``support_order`` -- (optional) either something that can
|
|
624
|
+
be converted into a tuple or a key function
|
|
625
|
+
|
|
626
|
+
EXAMPLES:
|
|
627
|
+
|
|
628
|
+
A finite dimensional module::
|
|
629
|
+
|
|
630
|
+
sage: # needs sage.modules
|
|
631
|
+
sage: V = CombinatorialFreeModule(QQ, range(10), prefix='x')
|
|
632
|
+
sage: B = V.basis()
|
|
633
|
+
sage: elts = [B[0] - 2*B[3], B[5] + 2*B[0],
|
|
634
|
+
....: B[2], B[3], B[1] + B[2] + B[8]]
|
|
635
|
+
sage: V._compute_support_order(elts)
|
|
636
|
+
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
|
|
637
|
+
sage: V._compute_support_order(elts, [1,2,0,4,3,5,9,8,7,6])
|
|
638
|
+
(1, 2, 0, 4, 3, 5, 9, 8, 7, 6)
|
|
639
|
+
sage: V._compute_support_order(elts, lambda x: -x)
|
|
640
|
+
(8, 5, 3, 2, 1, 0)
|
|
641
|
+
|
|
642
|
+
An infinite dimensional module::
|
|
643
|
+
|
|
644
|
+
sage: # needs sage.modules
|
|
645
|
+
sage: V = CombinatorialFreeModule(QQ, ZZ, prefix='z')
|
|
646
|
+
sage: B = V.basis()
|
|
647
|
+
sage: elts = [B[0] - 2*B[3], B[5] + 2*B[0],
|
|
648
|
+
....: B[2], B[3], B[1] + B[2] + B[8]]
|
|
649
|
+
sage: V._compute_support_order(elts)
|
|
650
|
+
(0, 1, 2, 3, 5, 8)
|
|
651
|
+
sage: V._compute_support_order(elts, [1,2,0,4,3,5,9,8,7,6])
|
|
652
|
+
(1, 2, 0, 4, 3, 5, 9, 8, 7, 6)
|
|
653
|
+
sage: V._compute_support_order(elts, lambda x: -x)
|
|
654
|
+
(8, 5, 3, 2, 1, 0)
|
|
655
|
+
"""
|
|
656
|
+
if support_order is None:
|
|
657
|
+
try:
|
|
658
|
+
support_order = self.get_order()
|
|
659
|
+
except (ValueError, TypeError, NotImplementedError, AttributeError):
|
|
660
|
+
support_order = set()
|
|
661
|
+
for y in elements:
|
|
662
|
+
support_order.update(y.support())
|
|
663
|
+
try: # Try to sort to make the output more consistent
|
|
664
|
+
support_order = sorted(support_order)
|
|
665
|
+
except (ValueError, TypeError):
|
|
666
|
+
pass
|
|
667
|
+
try:
|
|
668
|
+
support_order = tuple(support_order)
|
|
669
|
+
except (ValueError, TypeError):
|
|
670
|
+
support = set()
|
|
671
|
+
for y in elements:
|
|
672
|
+
support.update(y.support())
|
|
673
|
+
support_order = sorted(support, key=support_order)
|
|
674
|
+
return tuple(support_order)
|
|
675
|
+
|
|
676
|
+
def echelon_form(self, elements, row_reduced=False, order=None):
|
|
677
|
+
r"""
|
|
678
|
+
Return a basis in echelon form of the subspace spanned by
|
|
679
|
+
a finite set of elements.
|
|
680
|
+
|
|
681
|
+
INPUT:
|
|
682
|
+
|
|
683
|
+
- ``elements`` -- list or finite iterable of elements of ``self``
|
|
684
|
+
- ``row_reduced`` -- boolean (default: ``False``); whether to
|
|
685
|
+
compute the basis for the row reduced echelon form
|
|
686
|
+
- ``order`` -- (optional) either something that can
|
|
687
|
+
be converted into a tuple or a key function
|
|
688
|
+
|
|
689
|
+
OUTPUT:
|
|
690
|
+
|
|
691
|
+
A list of elements of ``self`` whose expressions as vectors
|
|
692
|
+
form a matrix in echelon form. If ``base_ring`` is specified,
|
|
693
|
+
then the calculation is achieved in this base ring.
|
|
694
|
+
|
|
695
|
+
EXAMPLES::
|
|
696
|
+
|
|
697
|
+
sage: R.<x,y> = QQ[]
|
|
698
|
+
sage: C = CombinatorialFreeModule(R, ZZ, prefix='z') # needs sage.modules
|
|
699
|
+
sage: z = C.basis() # needs sage.modules
|
|
700
|
+
sage: C.echelon_form([z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]]) # needs sage.libs.singular sage.modules
|
|
701
|
+
[z[0] - z[2], z[1] - z[2]]
|
|
702
|
+
|
|
703
|
+
TESTS:
|
|
704
|
+
|
|
705
|
+
We convert the input elements to ``self``::
|
|
706
|
+
|
|
707
|
+
sage: s = SymmetricFunctions(QQ).s() # needs sage.combinat sage.modules
|
|
708
|
+
sage: s.echelon_form([1, s[1] + 5]) # needs sage.combinat sage.modules
|
|
709
|
+
[s[], s[1]]
|
|
710
|
+
"""
|
|
711
|
+
# Make sure elements consists of elements of ``self``
|
|
712
|
+
elements = [self(y) for y in elements]
|
|
713
|
+
order = self._compute_support_order(elements, order)
|
|
714
|
+
|
|
715
|
+
from sage.matrix.constructor import matrix
|
|
716
|
+
mat = matrix(self.base_ring(), [[g[s] for s in order] for g in elements])
|
|
717
|
+
# Echelonizing a matrix over a field returned the rref
|
|
718
|
+
if row_reduced and self.base_ring() not in Fields():
|
|
719
|
+
try:
|
|
720
|
+
mat = mat.rref().change_ring(self.base_ring())
|
|
721
|
+
except (ValueError, TypeError):
|
|
722
|
+
raise ValueError("unable to compute the row reduced echelon form")
|
|
723
|
+
else:
|
|
724
|
+
mat.echelonize()
|
|
725
|
+
return [self._from_dict({order[i]: c for i, c in enumerate(vec) if c},
|
|
726
|
+
remove_zeros=False)
|
|
727
|
+
for vec in mat if vec]
|
|
728
|
+
|
|
729
|
+
def submodule(self, gens, check=True, already_echelonized=False,
|
|
730
|
+
unitriangular=False, support_order=None, category=None,
|
|
731
|
+
submodule_class=None, *args, **opts):
|
|
732
|
+
r"""
|
|
733
|
+
The submodule spanned by a finite set of elements.
|
|
734
|
+
|
|
735
|
+
INPUT:
|
|
736
|
+
|
|
737
|
+
- ``gens`` -- list or family of elements of ``self``
|
|
738
|
+
- ``check`` -- boolean (default: ``True``); whether to verify that
|
|
739
|
+
the elements of ``gens`` are in ``self``
|
|
740
|
+
- ``already_echelonized`` -- boolean (default: ``False``); whether
|
|
741
|
+
the elements of ``gens`` are already in (not necessarily
|
|
742
|
+
reduced) echelon form
|
|
743
|
+
- ``unitriangular`` -- boolean (default: ``False``); whether
|
|
744
|
+
the lift morphism is unitriangular
|
|
745
|
+
- ``support_order`` -- (optional) either something that can
|
|
746
|
+
be converted into a tuple or a key function
|
|
747
|
+
- ``category`` -- (optional) the category of the submodule
|
|
748
|
+
- ``submodule_class`` -- (optional) the class of the submodule
|
|
749
|
+
to return
|
|
750
|
+
|
|
751
|
+
If ``already_echelonized`` is ``False``, then the
|
|
752
|
+
generators are put in reduced echelon form using
|
|
753
|
+
:meth:`echelonize`, and reindexed by `0,1,...`.
|
|
754
|
+
|
|
755
|
+
.. WARNING::
|
|
756
|
+
|
|
757
|
+
At this point, this method only works for finite
|
|
758
|
+
dimensional submodules and if matrices can be
|
|
759
|
+
echelonized over the base ring.
|
|
760
|
+
|
|
761
|
+
If in addition ``unitriangular`` is ``True``, then
|
|
762
|
+
the generators are made such that the coefficients of
|
|
763
|
+
the pivots are 1, so that lifting map is unitriangular.
|
|
764
|
+
|
|
765
|
+
The basis of the submodule uses the same index set as the
|
|
766
|
+
generators, and the lifting map sends `y_i` to `gens[i]`.
|
|
767
|
+
|
|
768
|
+
.. SEEALSO::
|
|
769
|
+
|
|
770
|
+
- :meth:`ModulesWithBasis.FiniteDimensional.ParentMethods.quotient_module`
|
|
771
|
+
- :class:`sage.modules.with_basis.subquotient.SubmoduleWithBasis`
|
|
772
|
+
|
|
773
|
+
EXAMPLES:
|
|
774
|
+
|
|
775
|
+
We construct a submodule of the free `\QQ`-module generated by
|
|
776
|
+
`x_0, x_1, x_2`. The submodule is spanned by `y_0 = x_0 - x_1` and
|
|
777
|
+
`y_1 - x_1 - x_2`, and its basis elements are indexed by `0` and `1`::
|
|
778
|
+
|
|
779
|
+
sage: # needs sage.modules
|
|
780
|
+
sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x')
|
|
781
|
+
sage: x = X.basis()
|
|
782
|
+
sage: gens = [x[0] - x[1], x[1] - x[2]]; gens
|
|
783
|
+
[x[0] - x[1], x[1] - x[2]]
|
|
784
|
+
sage: Y = X.submodule(gens, already_echelonized=True)
|
|
785
|
+
sage: Y.print_options(prefix='y'); Y
|
|
786
|
+
Free module generated by {0, 1} over Rational Field
|
|
787
|
+
sage: y = Y.basis()
|
|
788
|
+
sage: y[1]
|
|
789
|
+
y[1]
|
|
790
|
+
sage: y[1].lift()
|
|
791
|
+
x[1] - x[2]
|
|
792
|
+
sage: Y.retract(x[0] - x[2])
|
|
793
|
+
y[0] + y[1]
|
|
794
|
+
sage: Y.retract(x[0])
|
|
795
|
+
Traceback (most recent call last):
|
|
796
|
+
...
|
|
797
|
+
ValueError: x[0] is not in the image
|
|
798
|
+
|
|
799
|
+
By using a family to specify a basis of the submodule, we obtain a
|
|
800
|
+
submodule whose index set coincides with the index set of the family::
|
|
801
|
+
|
|
802
|
+
sage: # needs sage.modules
|
|
803
|
+
sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x')
|
|
804
|
+
sage: x = X.basis()
|
|
805
|
+
sage: gens = Family({1: x[0] - x[1], 3: x[1] - x[2]}); gens
|
|
806
|
+
Finite family {1: x[0] - x[1], 3: x[1] - x[2]}
|
|
807
|
+
sage: Y = X.submodule(gens, already_echelonized=True)
|
|
808
|
+
sage: Y.print_options(prefix='y'); Y
|
|
809
|
+
Free module generated by {1, 3} over Rational Field
|
|
810
|
+
sage: y = Y.basis()
|
|
811
|
+
sage: y[1]
|
|
812
|
+
y[1]
|
|
813
|
+
sage: y[1].lift()
|
|
814
|
+
x[0] - x[1]
|
|
815
|
+
sage: y[3].lift()
|
|
816
|
+
x[1] - x[2]
|
|
817
|
+
sage: Y.retract(x[0] - x[2])
|
|
818
|
+
y[1] + y[3]
|
|
819
|
+
sage: Y.retract(x[0])
|
|
820
|
+
Traceback (most recent call last):
|
|
821
|
+
...
|
|
822
|
+
ValueError: x[0] is not in the image
|
|
823
|
+
|
|
824
|
+
It is not necessary that the generators of the submodule form
|
|
825
|
+
a basis (an explicit basis will be computed)::
|
|
826
|
+
|
|
827
|
+
sage: # needs sage.modules
|
|
828
|
+
sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x')
|
|
829
|
+
sage: x = X.basis()
|
|
830
|
+
sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]; gens
|
|
831
|
+
[x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]
|
|
832
|
+
sage: Y = X.submodule(gens, already_echelonized=False)
|
|
833
|
+
sage: Y.print_options(prefix='y')
|
|
834
|
+
sage: Y
|
|
835
|
+
Free module generated by {0, 1} over Rational Field
|
|
836
|
+
sage: [b.lift() for b in Y.basis()]
|
|
837
|
+
[x[0] - x[2], x[1] - x[2]]
|
|
838
|
+
|
|
839
|
+
We now implement by hand the center of the algebra of the
|
|
840
|
+
symmetric group `S_3`::
|
|
841
|
+
|
|
842
|
+
sage: # needs sage.combinat sage.groups sage.modules
|
|
843
|
+
sage: S3 = SymmetricGroup(3)
|
|
844
|
+
sage: S3A = S3.algebra(QQ)
|
|
845
|
+
sage: basis = S3A.annihilator_basis(S3A.algebra_generators(),
|
|
846
|
+
....: S3A.bracket)
|
|
847
|
+
sage: basis
|
|
848
|
+
((), (1,2,3) + (1,3,2), (2,3) + (1,2) + (1,3))
|
|
849
|
+
sage: center = S3A.submodule(basis,
|
|
850
|
+
....: category=AlgebrasWithBasis(QQ).Subobjects(),
|
|
851
|
+
....: already_echelonized=True)
|
|
852
|
+
sage: center
|
|
853
|
+
Free module generated by {0, 1, 2} over Rational Field
|
|
854
|
+
sage: center in Algebras
|
|
855
|
+
True
|
|
856
|
+
sage: center.print_options(prefix='c')
|
|
857
|
+
sage: c = center.basis()
|
|
858
|
+
sage: c[1].lift()
|
|
859
|
+
(1,2,3) + (1,3,2)
|
|
860
|
+
sage: c[0]^2
|
|
861
|
+
c[0]
|
|
862
|
+
sage: e = 1/6 * (c[0]+c[1]+c[2])
|
|
863
|
+
sage: e.is_idempotent()
|
|
864
|
+
True
|
|
865
|
+
|
|
866
|
+
Of course, this center is best constructed using::
|
|
867
|
+
|
|
868
|
+
sage: center = S3A.center() # needs sage.combinat sage.groups sage.modules
|
|
869
|
+
|
|
870
|
+
We can also automatically construct a basis such that
|
|
871
|
+
the lift morphism is (lower) unitriangular::
|
|
872
|
+
|
|
873
|
+
sage: # needs sage.libs.singular sage.modules
|
|
874
|
+
sage: R.<a,b> = QQ[]
|
|
875
|
+
sage: C = CombinatorialFreeModule(R, range(3), prefix='x')
|
|
876
|
+
sage: x = C.basis()
|
|
877
|
+
sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]
|
|
878
|
+
sage: Y = C.submodule(gens, unitriangular=True)
|
|
879
|
+
sage: Y.lift.matrix()
|
|
880
|
+
[ 1 0]
|
|
881
|
+
[ 0 1]
|
|
882
|
+
[-1 -1]
|
|
883
|
+
|
|
884
|
+
We now construct a (finite-dimensional) submodule of an
|
|
885
|
+
infinite dimensional free module::
|
|
886
|
+
|
|
887
|
+
sage: # needs sage.modules
|
|
888
|
+
sage: C = CombinatorialFreeModule(QQ, ZZ, prefix='z')
|
|
889
|
+
sage: z = C.basis()
|
|
890
|
+
sage: gens = [z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]]
|
|
891
|
+
sage: Y = C.submodule(gens)
|
|
892
|
+
sage: [Y.lift(b) for b in Y.basis()]
|
|
893
|
+
[z[0] - z[2], z[1] - z[2]]
|
|
894
|
+
|
|
895
|
+
TESTS::
|
|
896
|
+
|
|
897
|
+
sage: TestSuite(Y).run() # needs sage.modules
|
|
898
|
+
sage: TestSuite(center).run() # needs sage.combinat sage.groups sage.modules
|
|
899
|
+
"""
|
|
900
|
+
# Make sure gens consists of elements of ``self``
|
|
901
|
+
from sage.sets.family import Family, AbstractFamily
|
|
902
|
+
if isinstance(gens, AbstractFamily):
|
|
903
|
+
gens = gens.map(self)
|
|
904
|
+
elif isinstance(gens, dict):
|
|
905
|
+
gens = Family(gens.keys(), gens.__getitem__)
|
|
906
|
+
else:
|
|
907
|
+
gens = [self(y) for y in gens]
|
|
908
|
+
support_order = self._compute_support_order(gens, support_order)
|
|
909
|
+
if not already_echelonized:
|
|
910
|
+
gens = self.echelon_form(gens, unitriangular, order=support_order)
|
|
911
|
+
|
|
912
|
+
if submodule_class is None:
|
|
913
|
+
from sage.modules.with_basis.subquotient import SubmoduleWithBasis as submodule_class
|
|
914
|
+
return submodule_class(gens, ambient=self,
|
|
915
|
+
support_order=support_order,
|
|
916
|
+
unitriangular=unitriangular,
|
|
917
|
+
category=category, *args, **opts)
|
|
918
|
+
|
|
919
|
+
def quotient_module(self, submodule, check=True, already_echelonized=False, category=None):
|
|
920
|
+
r"""
|
|
921
|
+
Construct the quotient module ``self`` / ``submodule``.
|
|
922
|
+
|
|
923
|
+
INPUT:
|
|
924
|
+
|
|
925
|
+
- ``submodule`` -- a submodule with basis of ``self``, or
|
|
926
|
+
something that can be turned into one via
|
|
927
|
+
``self.submodule(submodule)``
|
|
928
|
+
|
|
929
|
+
- ``check``, ``already_echelonized`` -- passed down to
|
|
930
|
+
:meth:`ModulesWithBasis.ParentMethods.submodule`
|
|
931
|
+
|
|
932
|
+
.. WARNING::
|
|
933
|
+
|
|
934
|
+
At this point, this only supports quotients by free
|
|
935
|
+
submodules admitting a basis in unitriangular echelon
|
|
936
|
+
form. In this case, the quotient is also a free
|
|
937
|
+
module, with a basis consisting of the retract of a
|
|
938
|
+
subset of the basis of ``self``.
|
|
939
|
+
|
|
940
|
+
EXAMPLES::
|
|
941
|
+
|
|
942
|
+
sage: # needs sage.modules
|
|
943
|
+
sage: X = CombinatorialFreeModule(QQ, range(3), prefix='x')
|
|
944
|
+
sage: x = X.basis()
|
|
945
|
+
sage: Y = X.quotient_module([x[0] - x[1], x[1] - x[2]],
|
|
946
|
+
....: already_echelonized=True)
|
|
947
|
+
sage: Y.print_options(prefix='y'); Y
|
|
948
|
+
Free module generated by {2} over Rational Field
|
|
949
|
+
sage: y = Y.basis()
|
|
950
|
+
sage: y[2]
|
|
951
|
+
y[2]
|
|
952
|
+
sage: y[2].lift()
|
|
953
|
+
x[2]
|
|
954
|
+
sage: Y.retract(x[0] + 2*x[1])
|
|
955
|
+
3*y[2]
|
|
956
|
+
|
|
957
|
+
sage: # needs sage.libs.singular sage.modules
|
|
958
|
+
sage: R.<a,b> = QQ[]
|
|
959
|
+
sage: C = CombinatorialFreeModule(R, range(3), prefix='x')
|
|
960
|
+
sage: x = C.basis()
|
|
961
|
+
sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]
|
|
962
|
+
sage: Y = C.quotient_module(gens)
|
|
963
|
+
|
|
964
|
+
.. SEEALSO::
|
|
965
|
+
|
|
966
|
+
- :meth:`Modules.WithBasis.ParentMethods.submodule`
|
|
967
|
+
- :meth:`Rings.ParentMethods.quotient`
|
|
968
|
+
- :class:`sage.modules.with_basis.subquotient.QuotientModuleWithBasis`
|
|
969
|
+
"""
|
|
970
|
+
from sage.modules.with_basis.subquotient import SubmoduleWithBasis, QuotientModuleWithBasis
|
|
971
|
+
if not isinstance(submodule, SubmoduleWithBasis):
|
|
972
|
+
submodule = self.submodule(submodule, check=check,
|
|
973
|
+
unitriangular=True,
|
|
974
|
+
already_echelonized=already_echelonized)
|
|
975
|
+
return QuotientModuleWithBasis(submodule, category=category)
|
|
976
|
+
|
|
977
|
+
def tensor(*parents, **kwargs):
|
|
978
|
+
"""
|
|
979
|
+
Return the tensor product of the parents.
|
|
980
|
+
|
|
981
|
+
EXAMPLES::
|
|
982
|
+
|
|
983
|
+
sage: C = AlgebrasWithBasis(QQ)
|
|
984
|
+
sage: A = C.example(); A.rename('A') # needs sage.combinat sage.modules
|
|
985
|
+
sage: A.tensor(A, A) # needs sage.combinat sage.modules
|
|
986
|
+
A # A # A
|
|
987
|
+
sage: A.rename(None) # needs sage.combinat sage.modules
|
|
988
|
+
"""
|
|
989
|
+
constructor = kwargs.pop('constructor', tensor)
|
|
990
|
+
cat = constructor.category_from_parents(parents)
|
|
991
|
+
return parents[0].__class__.Tensor(parents, category=cat)
|
|
992
|
+
|
|
993
|
+
def intersection(self, other):
|
|
994
|
+
r"""
|
|
995
|
+
Return the intersection of ``self`` with ``other``.
|
|
996
|
+
|
|
997
|
+
EXAMPLES::
|
|
998
|
+
|
|
999
|
+
sage: # needs sage.modules
|
|
1000
|
+
sage: X = CombinatorialFreeModule(QQ, range(4)); x = X.basis()
|
|
1001
|
+
sage: U = X.submodule([x[0]-x[1], x[1]-x[2], x[2]-x[3]])
|
|
1002
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c','d'])
|
|
1003
|
+
sage: G = F.submodule([F.basis()['a']])
|
|
1004
|
+
sage: X.intersection(X) is X
|
|
1005
|
+
True
|
|
1006
|
+
sage: X.intersection(U) is U
|
|
1007
|
+
True
|
|
1008
|
+
sage: X.intersection(F)
|
|
1009
|
+
Traceback (most recent call last):
|
|
1010
|
+
...
|
|
1011
|
+
TypeError: other must be a submodule
|
|
1012
|
+
sage: X.intersection(G)
|
|
1013
|
+
Traceback (most recent call last):
|
|
1014
|
+
...
|
|
1015
|
+
ArithmeticError: this module must be the ambient
|
|
1016
|
+
"""
|
|
1017
|
+
if other is self:
|
|
1018
|
+
return self
|
|
1019
|
+
if other not in self.category().Subobjects():
|
|
1020
|
+
raise TypeError("other must be a submodule")
|
|
1021
|
+
if other.ambient() != self:
|
|
1022
|
+
raise ArithmeticError("this module must be the ambient")
|
|
1023
|
+
return other
|
|
1024
|
+
|
|
1025
|
+
def cardinality(self):
|
|
1026
|
+
"""
|
|
1027
|
+
Return the cardinality of ``self``.
|
|
1028
|
+
|
|
1029
|
+
EXAMPLES::
|
|
1030
|
+
|
|
1031
|
+
sage: # needs sage.combinat sage.groups sage.modules
|
|
1032
|
+
sage: S = SymmetricGroupAlgebra(QQ, 4)
|
|
1033
|
+
sage: S.cardinality()
|
|
1034
|
+
+Infinity
|
|
1035
|
+
sage: S = SymmetricGroupAlgebra(GF(2), 4)
|
|
1036
|
+
sage: S.cardinality()
|
|
1037
|
+
16777216
|
|
1038
|
+
sage: S.cardinality().factor()
|
|
1039
|
+
2^24
|
|
1040
|
+
|
|
1041
|
+
sage: # needs sage.modules
|
|
1042
|
+
sage: E.<x,y> = ExteriorAlgebra(QQ)
|
|
1043
|
+
sage: E.cardinality()
|
|
1044
|
+
+Infinity
|
|
1045
|
+
sage: E.<x,y> = ExteriorAlgebra(GF(3))
|
|
1046
|
+
sage: E.cardinality()
|
|
1047
|
+
81
|
|
1048
|
+
|
|
1049
|
+
sage: s = SymmetricFunctions(GF(2)).s() # needs sage.combinat sage.modules
|
|
1050
|
+
sage: s.cardinality() # needs sage.combinat sage.modules
|
|
1051
|
+
+Infinity
|
|
1052
|
+
|
|
1053
|
+
sage: # needs sage.modules
|
|
1054
|
+
sage: M = CombinatorialFreeModule(QQ, [])
|
|
1055
|
+
sage: M.dimension()
|
|
1056
|
+
0
|
|
1057
|
+
sage: M.cardinality()
|
|
1058
|
+
1
|
|
1059
|
+
"""
|
|
1060
|
+
from sage.rings.infinity import Infinity
|
|
1061
|
+
if self.dimension() == Infinity:
|
|
1062
|
+
return Infinity
|
|
1063
|
+
if self.dimension() == 0:
|
|
1064
|
+
from sage.rings.integer_ring import ZZ
|
|
1065
|
+
return ZZ.one()
|
|
1066
|
+
return self.base_ring().cardinality() ** self.dimension()
|
|
1067
|
+
|
|
1068
|
+
def is_finite(self):
|
|
1069
|
+
r"""
|
|
1070
|
+
Return whether ``self`` is finite.
|
|
1071
|
+
|
|
1072
|
+
This is true if and only if ``self.basis().keys()`` and
|
|
1073
|
+
``self.base_ring()`` are both finite.
|
|
1074
|
+
|
|
1075
|
+
EXAMPLES::
|
|
1076
|
+
|
|
1077
|
+
sage: GroupAlgebra(SymmetricGroup(2), IntegerModRing(10)).is_finite() # needs sage.combinat sage.groups sage.modules
|
|
1078
|
+
True
|
|
1079
|
+
sage: GroupAlgebra(SymmetricGroup(2)).is_finite() # needs sage.combinat sage.groups sage.modules
|
|
1080
|
+
False
|
|
1081
|
+
sage: GroupAlgebra(AbelianGroup(1), IntegerModRing(10)).is_finite() # needs sage.groups sage.modules
|
|
1082
|
+
False
|
|
1083
|
+
"""
|
|
1084
|
+
return (self.base_ring().is_finite() and self.basis().keys().is_finite())
|
|
1085
|
+
|
|
1086
|
+
def monomial(self, i):
|
|
1087
|
+
"""
|
|
1088
|
+
Return the basis element indexed by ``i``.
|
|
1089
|
+
|
|
1090
|
+
INPUT:
|
|
1091
|
+
|
|
1092
|
+
- ``i`` -- an element of the index set
|
|
1093
|
+
|
|
1094
|
+
EXAMPLES::
|
|
1095
|
+
|
|
1096
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules
|
|
1097
|
+
sage: F.monomial('a') # needs sage.modules
|
|
1098
|
+
B['a']
|
|
1099
|
+
|
|
1100
|
+
``F.monomial`` is in fact (almost) a map::
|
|
1101
|
+
|
|
1102
|
+
sage: F.monomial # needs sage.modules
|
|
1103
|
+
Term map from {'a', 'b', 'c'}
|
|
1104
|
+
to Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
1105
|
+
"""
|
|
1106
|
+
return self.basis()[i]
|
|
1107
|
+
|
|
1108
|
+
def _sum_of_monomials(self, indices):
|
|
1109
|
+
"""
|
|
1110
|
+
TESTS::
|
|
1111
|
+
|
|
1112
|
+
sage: R.<x,y> = QQ[]
|
|
1113
|
+
sage: W = DifferentialWeylAlgebra(R) # needs sage.modules
|
|
1114
|
+
sage: W._sum_of_monomials([((1,0), (1,0)), ((0,0), (0,1))]) # needs sage.modules
|
|
1115
|
+
dy + x*dx
|
|
1116
|
+
"""
|
|
1117
|
+
# This is the generic implementation. When implementing a
|
|
1118
|
+
# concrete instance of a module with basis, you probably want
|
|
1119
|
+
# to override it with something faster.
|
|
1120
|
+
return self.sum(self.monomial(index) for index in indices)
|
|
1121
|
+
|
|
1122
|
+
@lazy_attribute
|
|
1123
|
+
def sum_of_monomials(self):
|
|
1124
|
+
"""
|
|
1125
|
+
Return the sum of the basis elements with indices in
|
|
1126
|
+
``indices``.
|
|
1127
|
+
|
|
1128
|
+
INPUT:
|
|
1129
|
+
|
|
1130
|
+
- ``indices`` -- list (or iterable) of indices of basis
|
|
1131
|
+
elements
|
|
1132
|
+
|
|
1133
|
+
EXAMPLES::
|
|
1134
|
+
|
|
1135
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules
|
|
1136
|
+
sage: F.sum_of_monomials(['a', 'b']) # needs sage.modules
|
|
1137
|
+
B['a'] + B['b']
|
|
1138
|
+
|
|
1139
|
+
sage: F.sum_of_monomials(['a', 'b', 'a']) # needs sage.modules
|
|
1140
|
+
2*B['a'] + B['b']
|
|
1141
|
+
|
|
1142
|
+
``F.sum_of_monomials`` is in fact (almost) a map::
|
|
1143
|
+
|
|
1144
|
+
sage: F.sum_of_monomials # needs sage.modules
|
|
1145
|
+
A map to Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
1146
|
+
"""
|
|
1147
|
+
# domain = iterables of basis indices of self.
|
|
1148
|
+
return PoorManMap(self._sum_of_monomials, codomain=self)
|
|
1149
|
+
|
|
1150
|
+
def monomial_or_zero_if_none(self, i):
|
|
1151
|
+
"""
|
|
1152
|
+
EXAMPLES::
|
|
1153
|
+
|
|
1154
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # needs sage.modules
|
|
1155
|
+
sage: F.monomial_or_zero_if_none('a') # needs sage.modules
|
|
1156
|
+
B['a']
|
|
1157
|
+
sage: F.monomial_or_zero_if_none(None) # needs sage.modules
|
|
1158
|
+
0
|
|
1159
|
+
"""
|
|
1160
|
+
if i is None:
|
|
1161
|
+
return self.zero()
|
|
1162
|
+
return self.monomial(i)
|
|
1163
|
+
|
|
1164
|
+
def term(self, index, coeff=None):
|
|
1165
|
+
"""
|
|
1166
|
+
Construct a term in ``self``.
|
|
1167
|
+
|
|
1168
|
+
INPUT:
|
|
1169
|
+
|
|
1170
|
+
- ``index`` -- the index of a basis element
|
|
1171
|
+
- ``coeff`` -- an element of the coefficient ring (default: one)
|
|
1172
|
+
|
|
1173
|
+
OUTPUT: ``coeff * B[index]``, where ``B`` is the basis of ``self``
|
|
1174
|
+
|
|
1175
|
+
EXAMPLES::
|
|
1176
|
+
|
|
1177
|
+
sage: m = matrix([[0,1], [1,1]]) # needs sage.modules
|
|
1178
|
+
sage: J.<a,b,c> = JordanAlgebra(m) # needs sage.combinat sage.modules
|
|
1179
|
+
sage: J.term(1, -2) # needs sage.combinat sage.modules
|
|
1180
|
+
0 + (-2, 0)
|
|
1181
|
+
|
|
1182
|
+
Design: should this do coercion on the coefficient ring?
|
|
1183
|
+
"""
|
|
1184
|
+
if coeff is None:
|
|
1185
|
+
coeff = self.base_ring().one()
|
|
1186
|
+
return coeff * self.monomial(index)
|
|
1187
|
+
|
|
1188
|
+
def sum_of_terms(self, terms):
|
|
1189
|
+
"""
|
|
1190
|
+
Construct a sum of terms of ``self``.
|
|
1191
|
+
|
|
1192
|
+
INPUT:
|
|
1193
|
+
|
|
1194
|
+
- ``terms`` -- list (or iterable) of pairs ``(index, coeff)``
|
|
1195
|
+
|
|
1196
|
+
OUTPUT:
|
|
1197
|
+
|
|
1198
|
+
Sum of ``coeff * B[index]`` over all ``(index, coeff)`` in
|
|
1199
|
+
``terms``, where ``B`` is the basis of ``self``.
|
|
1200
|
+
|
|
1201
|
+
EXAMPLES::
|
|
1202
|
+
|
|
1203
|
+
sage: m = matrix([[0,1], [1,1]]) # needs sage.modules
|
|
1204
|
+
sage: J.<a,b,c> = JordanAlgebra(m) # needs sage.combinat sage.modules
|
|
1205
|
+
sage: J.sum_of_terms([(0, 2), (2, -3)]) # needs sage.combinat sage.modules
|
|
1206
|
+
2 + (0, -3)
|
|
1207
|
+
"""
|
|
1208
|
+
return self.sum(self.term(index, coeff) for (index, coeff) in terms)
|
|
1209
|
+
|
|
1210
|
+
def _apply_module_morphism(self, x, on_basis, codomain=False):
|
|
1211
|
+
"""
|
|
1212
|
+
Return the image of ``x`` under the module morphism defined by
|
|
1213
|
+
extending :func:`on_basis` by linearity.
|
|
1214
|
+
|
|
1215
|
+
INPUT:
|
|
1216
|
+
|
|
1217
|
+
- ``x`` -- a element of ``self``
|
|
1218
|
+
|
|
1219
|
+
- ``on_basis`` -- a function that takes in an object indexing
|
|
1220
|
+
a basis element and returns an element of the codomain
|
|
1221
|
+
|
|
1222
|
+
- ``codomain`` -- (optional) the codomain of the morphism (by
|
|
1223
|
+
default, it is computed using :func:`on_basis`)
|
|
1224
|
+
|
|
1225
|
+
If ``codomain`` is not specified, then the function tries to
|
|
1226
|
+
compute the codomain of the module morphism by finding the image
|
|
1227
|
+
of one of the elements in the support; hence :func:`on_basis`
|
|
1228
|
+
should return an element whose parent is the codomain.
|
|
1229
|
+
|
|
1230
|
+
EXAMPLES::
|
|
1231
|
+
|
|
1232
|
+
sage: # needs sage.combinat sage.modules
|
|
1233
|
+
sage: s = SymmetricFunctions(QQ).schur()
|
|
1234
|
+
sage: a = s([3]) + s([2,1]) + s([1,1,1])
|
|
1235
|
+
sage: b = 2*a
|
|
1236
|
+
sage: f = lambda part: Integer(len(part))
|
|
1237
|
+
sage: s._apply_module_morphism(a, f) #1+2+3
|
|
1238
|
+
6
|
|
1239
|
+
sage: s._apply_module_morphism(b, f) #2*(1+2+3)
|
|
1240
|
+
12
|
|
1241
|
+
sage: s._apply_module_morphism(s(0), f)
|
|
1242
|
+
0
|
|
1243
|
+
sage: s._apply_module_morphism(s(1), f)
|
|
1244
|
+
0
|
|
1245
|
+
sage: s._apply_module_morphism(s(1), lambda part: len(part), ZZ)
|
|
1246
|
+
0
|
|
1247
|
+
sage: s._apply_module_morphism(s(1), lambda part: len(part))
|
|
1248
|
+
Traceback (most recent call last):
|
|
1249
|
+
...
|
|
1250
|
+
ValueError: codomain could not be determined
|
|
1251
|
+
"""
|
|
1252
|
+
if x == self.zero():
|
|
1253
|
+
if not codomain:
|
|
1254
|
+
from sage.sets.family import Family
|
|
1255
|
+
B = Family(self.basis())
|
|
1256
|
+
try:
|
|
1257
|
+
z = B.first()
|
|
1258
|
+
except StopIteration:
|
|
1259
|
+
raise ValueError('codomain could not be determined')
|
|
1260
|
+
codomain = on_basis(z).parent()
|
|
1261
|
+
return codomain.zero()
|
|
1262
|
+
|
|
1263
|
+
if not codomain:
|
|
1264
|
+
keys = x.support()
|
|
1265
|
+
key = keys[0]
|
|
1266
|
+
try:
|
|
1267
|
+
codomain = on_basis(key).parent()
|
|
1268
|
+
except Exception:
|
|
1269
|
+
raise ValueError('codomain could not be determined')
|
|
1270
|
+
|
|
1271
|
+
if hasattr(codomain, 'linear_combination'):
|
|
1272
|
+
mc = x.monomial_coefficients(copy=False)
|
|
1273
|
+
return codomain.linear_combination((on_basis(key), coeff)
|
|
1274
|
+
for key, coeff in mc.items())
|
|
1275
|
+
else:
|
|
1276
|
+
return_sum = codomain.zero()
|
|
1277
|
+
mc = x.monomial_coefficients(copy=False)
|
|
1278
|
+
for key, coeff in mc.items():
|
|
1279
|
+
return_sum += coeff * on_basis(key)
|
|
1280
|
+
return return_sum
|
|
1281
|
+
|
|
1282
|
+
def _apply_module_endomorphism(self, x, on_basis):
|
|
1283
|
+
"""
|
|
1284
|
+
This takes in a function ``on_basis`` from the basis indices
|
|
1285
|
+
to the elements of ``self``, and applies it linearly to ``x``.
|
|
1286
|
+
|
|
1287
|
+
EXAMPLES::
|
|
1288
|
+
|
|
1289
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1290
|
+
sage: f = lambda part: 2 * s(part.conjugate())
|
|
1291
|
+
sage: s._apply_module_endomorphism(s([2,1]) + s([1,1,1]), f) # needs sage.combinat sage.modules
|
|
1292
|
+
2*s[2, 1] + 2*s[3]
|
|
1293
|
+
"""
|
|
1294
|
+
mc = x.monomial_coefficients(copy=False)
|
|
1295
|
+
return self.linear_combination((on_basis(key), coeff)
|
|
1296
|
+
for key, coeff in mc.items())
|
|
1297
|
+
|
|
1298
|
+
def dimension(self):
|
|
1299
|
+
"""
|
|
1300
|
+
Return the dimension of ``self``.
|
|
1301
|
+
|
|
1302
|
+
EXAMPLES::
|
|
1303
|
+
|
|
1304
|
+
sage: A.<x,y> = algebras.DifferentialWeyl(QQ) # needs sage.modules
|
|
1305
|
+
sage: A.dimension() # needs sage.modules
|
|
1306
|
+
+Infinity
|
|
1307
|
+
"""
|
|
1308
|
+
try:
|
|
1309
|
+
return self.basis().cardinality()
|
|
1310
|
+
except (AttributeError, TypeError):
|
|
1311
|
+
from sage.rings.integer_ring import ZZ
|
|
1312
|
+
return ZZ(len(self.basis()))
|
|
1313
|
+
|
|
1314
|
+
def rank(self):
|
|
1315
|
+
"""
|
|
1316
|
+
Return the rank of ``self``.
|
|
1317
|
+
|
|
1318
|
+
Since there is a (distinguished) basis, the rank of ``self``
|
|
1319
|
+
is equal to the cardinality of the basis (which equals
|
|
1320
|
+
the :meth:`dimension` of ``self``).
|
|
1321
|
+
|
|
1322
|
+
EXAMPLES::
|
|
1323
|
+
|
|
1324
|
+
sage: A.<x,y> = algebras.DifferentialWeyl(QQ) # needs sage.modules
|
|
1325
|
+
sage: A.rank() # needs sage.modules
|
|
1326
|
+
+Infinity
|
|
1327
|
+
|
|
1328
|
+
sage: R.<x,y> = QQ[]
|
|
1329
|
+
sage: R.rank()
|
|
1330
|
+
+Infinity
|
|
1331
|
+
|
|
1332
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # needs sage.modules
|
|
1333
|
+
sage: F.rank() # needs sage.modules
|
|
1334
|
+
3
|
|
1335
|
+
"""
|
|
1336
|
+
return self.dimension()
|
|
1337
|
+
|
|
1338
|
+
def _from_dict(self, d, coerce=True, remove_zeros=True):
|
|
1339
|
+
"""
|
|
1340
|
+
Construct an element of ``self`` from the dictionary ``d``.
|
|
1341
|
+
|
|
1342
|
+
INPUT:
|
|
1343
|
+
|
|
1344
|
+
- ``coerce`` -- boolean; coerce the coefficients to the base ring
|
|
1345
|
+
- ``remove_zeroes`` -- boolean; remove zeros from the dictionary
|
|
1346
|
+
|
|
1347
|
+
EXAMPLES::
|
|
1348
|
+
|
|
1349
|
+
sage: # needs sage.modules
|
|
1350
|
+
sage: A.<x,y> = algebras.DifferentialWeyl(QQ)
|
|
1351
|
+
sage: K = A.basis().keys()
|
|
1352
|
+
sage: d = {K[0]: 3, K[12]: -4/3}
|
|
1353
|
+
sage: A._from_dict(d)
|
|
1354
|
+
-4/3*dx^2 + 3
|
|
1355
|
+
|
|
1356
|
+
sage: R.<x,y> = QQ[]
|
|
1357
|
+
sage: d = {K[0]: y, K[12]: -4/3} # needs sage.modules
|
|
1358
|
+
sage: A._from_dict(d, coerce=False) # needs sage.modules
|
|
1359
|
+
-4/3*dx^2 + y
|
|
1360
|
+
sage: A._from_dict(d, coerce=True) # needs sage.modules
|
|
1361
|
+
Traceback (most recent call last):
|
|
1362
|
+
...
|
|
1363
|
+
TypeError: y is not a constant polynomial
|
|
1364
|
+
"""
|
|
1365
|
+
R = self.base_ring()
|
|
1366
|
+
B = self.basis()
|
|
1367
|
+
if coerce:
|
|
1368
|
+
zero = R.zero()
|
|
1369
|
+
temp = {}
|
|
1370
|
+
if remove_zeros:
|
|
1371
|
+
for k in d:
|
|
1372
|
+
y = R(d[k])
|
|
1373
|
+
if y != zero:
|
|
1374
|
+
temp[k] = y
|
|
1375
|
+
else:
|
|
1376
|
+
for k in d:
|
|
1377
|
+
temp[k] = R(d[k])
|
|
1378
|
+
return self.sum(temp[i] * B[i] for i in temp)
|
|
1379
|
+
if remove_zeros:
|
|
1380
|
+
return self.sum(d[i] * B[i] for i in d if d[i] != 0)
|
|
1381
|
+
return self.sum(d[i] * B[i] for i in d)
|
|
1382
|
+
|
|
1383
|
+
def random_element(self, n=2):
|
|
1384
|
+
r"""
|
|
1385
|
+
Return a 'random' element of ``self``.
|
|
1386
|
+
|
|
1387
|
+
INPUT:
|
|
1388
|
+
|
|
1389
|
+
- ``n`` -- integer (default: 2); number of summands
|
|
1390
|
+
|
|
1391
|
+
ALGORITHM:
|
|
1392
|
+
|
|
1393
|
+
Return a sum of `n` terms, each of which is formed by
|
|
1394
|
+
multiplying a random element of the base ring by a random
|
|
1395
|
+
element of the group.
|
|
1396
|
+
|
|
1397
|
+
EXAMPLES::
|
|
1398
|
+
|
|
1399
|
+
sage: x = DihedralGroup(6).algebra(QQ).random_element() # needs sage.groups sage.modules
|
|
1400
|
+
sage: x.parent() is DihedralGroup(6).algebra(QQ) # needs sage.groups sage.modules
|
|
1401
|
+
True
|
|
1402
|
+
|
|
1403
|
+
Note, this result can depend on the PRNG state in libgap in a way
|
|
1404
|
+
that depends on which packages are loaded, so we must re-seed GAP
|
|
1405
|
+
to ensure a consistent result for this example::
|
|
1406
|
+
|
|
1407
|
+
sage: libgap.set_seed(0) # needs sage.libs.gap
|
|
1408
|
+
0
|
|
1409
|
+
sage: m = SU(2, 13).algebra(QQ).random_element(1) # needs sage.groups sage.libs.pari sage.modules
|
|
1410
|
+
sage: m.parent() is SU(2, 13).algebra(QQ) # needs sage.groups sage.libs.pari sage.modules
|
|
1411
|
+
True
|
|
1412
|
+
sage: p = CombinatorialFreeModule(ZZ, Partitions(4)).random_element() # needs sage.combinat sage.libs.flint sage.modules
|
|
1413
|
+
sage: p.parent() is CombinatorialFreeModule(ZZ, Partitions(4)) # needs sage.combinat sage.libs.flint sage.modules
|
|
1414
|
+
True
|
|
1415
|
+
|
|
1416
|
+
TESTS:
|
|
1417
|
+
|
|
1418
|
+
Ensure that the two issues reported in :issue:`28327` are
|
|
1419
|
+
fixed; that we don't rely unnecessarily on being able to
|
|
1420
|
+
coerce the base ring's zero into the algebra, and that
|
|
1421
|
+
we can find a random element in a trivial module::
|
|
1422
|
+
|
|
1423
|
+
sage: class Foo(CombinatorialFreeModule): # needs sage.modules
|
|
1424
|
+
....: def _element_constructor_(self, x):
|
|
1425
|
+
....: if x in self:
|
|
1426
|
+
....: return x
|
|
1427
|
+
....: else:
|
|
1428
|
+
....: raise ValueError
|
|
1429
|
+
sage: from sage.categories.magmatic_algebras import MagmaticAlgebras
|
|
1430
|
+
sage: C = MagmaticAlgebras(QQ).WithBasis().Unital()
|
|
1431
|
+
sage: F = Foo(QQ, tuple(), category=C) # needs sage.modules
|
|
1432
|
+
sage: F.random_element() == F.zero() # needs sage.modules
|
|
1433
|
+
True
|
|
1434
|
+
"""
|
|
1435
|
+
indices = self.basis().keys()
|
|
1436
|
+
a = self.zero()
|
|
1437
|
+
if not indices.is_empty():
|
|
1438
|
+
for i in range(n):
|
|
1439
|
+
a += self.term(indices.random_element(),
|
|
1440
|
+
self.base_ring().random_element())
|
|
1441
|
+
return a
|
|
1442
|
+
|
|
1443
|
+
class ElementMethods:
|
|
1444
|
+
# TODO: Define the appropriate element methods here (instead of in
|
|
1445
|
+
# subclasses). These methods should be consistent with those on
|
|
1446
|
+
# polynomials.
|
|
1447
|
+
|
|
1448
|
+
# def _neg_(self):
|
|
1449
|
+
# """
|
|
1450
|
+
# Default implementation of negation by trying to multiply by -1.
|
|
1451
|
+
# TODO: doctest
|
|
1452
|
+
# """
|
|
1453
|
+
# return self._lmul_(-self.parent().base_ring().one(), self)
|
|
1454
|
+
|
|
1455
|
+
@abstract_method
|
|
1456
|
+
def monomial_coefficients(self, copy=True):
|
|
1457
|
+
"""
|
|
1458
|
+
Return a dictionary whose keys are indices of basis elements
|
|
1459
|
+
in the support of ``self`` and whose values are the
|
|
1460
|
+
corresponding coefficients.
|
|
1461
|
+
|
|
1462
|
+
INPUT:
|
|
1463
|
+
|
|
1464
|
+
- ``copy`` -- boolean (default: ``True``); if ``self`` is
|
|
1465
|
+
internally represented by a dictionary ``d``, then make a copy of
|
|
1466
|
+
``d``; if ``False``, then this can cause undesired behavior by
|
|
1467
|
+
mutating ``d``
|
|
1468
|
+
|
|
1469
|
+
EXAMPLES::
|
|
1470
|
+
|
|
1471
|
+
sage: # needs sage.modules
|
|
1472
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1473
|
+
sage: B = F.basis()
|
|
1474
|
+
sage: f = B['a'] + 3*B['c']
|
|
1475
|
+
sage: d = f.monomial_coefficients()
|
|
1476
|
+
sage: d['a']
|
|
1477
|
+
1
|
|
1478
|
+
sage: d['c']
|
|
1479
|
+
3
|
|
1480
|
+
|
|
1481
|
+
TESTS:
|
|
1482
|
+
|
|
1483
|
+
We check that we make a copy of the coefficient dictionary::
|
|
1484
|
+
|
|
1485
|
+
sage: # needs sage.modules
|
|
1486
|
+
sage: F = CombinatorialFreeModule(ZZ, ['a','b','c'])
|
|
1487
|
+
sage: B = F.basis()
|
|
1488
|
+
sage: f = B['a'] + 3*B['c']
|
|
1489
|
+
sage: d = f.monomial_coefficients()
|
|
1490
|
+
sage: d['a'] = 5
|
|
1491
|
+
sage: f
|
|
1492
|
+
B['a'] + 3*B['c']
|
|
1493
|
+
"""
|
|
1494
|
+
|
|
1495
|
+
def _test_monomial_coefficients(self, **options):
|
|
1496
|
+
r"""
|
|
1497
|
+
Test that :meth:`monomial_coefficients` works correctly if it is implemented.
|
|
1498
|
+
|
|
1499
|
+
INPUT:
|
|
1500
|
+
|
|
1501
|
+
- ``options`` -- any keyword arguments accepted by :meth:`_tester`
|
|
1502
|
+
|
|
1503
|
+
EXAMPLES:
|
|
1504
|
+
|
|
1505
|
+
By default, this method tests only the elements returned by
|
|
1506
|
+
``self.some_elements()``::
|
|
1507
|
+
|
|
1508
|
+
sage: # needs sage.combinat sage.modules
|
|
1509
|
+
sage: A = AlgebrasWithBasis(QQ).example(); A
|
|
1510
|
+
An example of an algebra with basis:
|
|
1511
|
+
the free algebra on the generators ('a', 'b', 'c') over Rational Field
|
|
1512
|
+
sage: A.an_element()._test_monomial_coefficients()
|
|
1513
|
+
|
|
1514
|
+
See the documentation for :class:`TestSuite` for more information.
|
|
1515
|
+
"""
|
|
1516
|
+
tester = self._tester(**options)
|
|
1517
|
+
base_ring = self.parent().base_ring()
|
|
1518
|
+
basis = self.parent().basis()
|
|
1519
|
+
try:
|
|
1520
|
+
d = self.monomial_coefficients()
|
|
1521
|
+
except NotImplementedError:
|
|
1522
|
+
return
|
|
1523
|
+
tester.assertTrue(all(value.parent() == base_ring
|
|
1524
|
+
for value in d.values()))
|
|
1525
|
+
tester.assertEqual(self, self.parent().linear_combination(
|
|
1526
|
+
(basis[index], coefficient)
|
|
1527
|
+
for index, coefficient in d.items()))
|
|
1528
|
+
|
|
1529
|
+
def __getitem__(self, m):
|
|
1530
|
+
"""
|
|
1531
|
+
Return the coefficient of ``m`` in ``self``.
|
|
1532
|
+
|
|
1533
|
+
EXAMPLES::
|
|
1534
|
+
|
|
1535
|
+
sage: W.<x,y,z> = DifferentialWeylAlgebra(QQ) # needs sage.modules
|
|
1536
|
+
sage: x[((0,0,0), (0,0,0))] # needs sage.modules
|
|
1537
|
+
0
|
|
1538
|
+
sage: x[((1,0,0), (0,0,0))] # needs sage.modules
|
|
1539
|
+
1
|
|
1540
|
+
"""
|
|
1541
|
+
res = self.monomial_coefficients(copy=False).get(m)
|
|
1542
|
+
if res is None:
|
|
1543
|
+
return self.base_ring().zero()
|
|
1544
|
+
else:
|
|
1545
|
+
return res
|
|
1546
|
+
|
|
1547
|
+
def coefficient(self, m):
|
|
1548
|
+
"""
|
|
1549
|
+
Return the coefficient of ``m`` in ``self`` and raise an error
|
|
1550
|
+
if ``m`` is not in the basis indexing set.
|
|
1551
|
+
|
|
1552
|
+
INPUT:
|
|
1553
|
+
|
|
1554
|
+
- ``m`` -- a basis index of the parent of ``self``
|
|
1555
|
+
|
|
1556
|
+
OUTPUT:
|
|
1557
|
+
|
|
1558
|
+
The ``B[m]``-coordinate of ``self`` with respect to the basis
|
|
1559
|
+
``B``. Here, ``B`` denotes the given basis of the parent of
|
|
1560
|
+
``self``.
|
|
1561
|
+
|
|
1562
|
+
EXAMPLES::
|
|
1563
|
+
|
|
1564
|
+
sage: # needs sage.combinat sage.modules
|
|
1565
|
+
sage: s = CombinatorialFreeModule(QQ, Partitions())
|
|
1566
|
+
sage: z = s([4]) - 2*s([2,1]) + s([1,1,1]) + s([1])
|
|
1567
|
+
sage: z.coefficient([4])
|
|
1568
|
+
1
|
|
1569
|
+
sage: z.coefficient([2,1])
|
|
1570
|
+
-2
|
|
1571
|
+
sage: z.coefficient(Partition([2,1]))
|
|
1572
|
+
-2
|
|
1573
|
+
sage: z.coefficient([1,2])
|
|
1574
|
+
Traceback (most recent call last):
|
|
1575
|
+
...
|
|
1576
|
+
AssertionError: [1, 2] should be an element of Partitions
|
|
1577
|
+
sage: z.coefficient(Composition([2,1]))
|
|
1578
|
+
Traceback (most recent call last):
|
|
1579
|
+
...
|
|
1580
|
+
AssertionError: [2, 1] should be an element of Partitions
|
|
1581
|
+
|
|
1582
|
+
Test that ``coefficient`` also works for those parents that do
|
|
1583
|
+
not have an ``element_class``::
|
|
1584
|
+
|
|
1585
|
+
sage: # needs sage.modules sage.rings.padics sage.schemes
|
|
1586
|
+
sage: H = pAdicWeightSpace(3)
|
|
1587
|
+
sage: F = CombinatorialFreeModule(QQ, H)
|
|
1588
|
+
sage: hasattr(H, "element_class")
|
|
1589
|
+
False
|
|
1590
|
+
sage: h = H.an_element()
|
|
1591
|
+
sage: (2*F.monomial(h)).coefficient(h)
|
|
1592
|
+
2
|
|
1593
|
+
"""
|
|
1594
|
+
# NT: coefficient_fast should be the default, just with appropriate assertions
|
|
1595
|
+
# that can be turned on or off
|
|
1596
|
+
C = self.parent().basis().keys()
|
|
1597
|
+
# TODO: This should raise a ValueError - TS
|
|
1598
|
+
assert m in C, "%s should be an element of %s" % (m, C)
|
|
1599
|
+
if hasattr(C, "element_class") and not isinstance(m, C.element_class):
|
|
1600
|
+
m = C(m)
|
|
1601
|
+
return self[m]
|
|
1602
|
+
|
|
1603
|
+
def items(self):
|
|
1604
|
+
r"""
|
|
1605
|
+
Return a list of pairs ``(i, c)``, where ``c`` is the
|
|
1606
|
+
``i``-th coefficient of ``i`` in the standard basis.
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
EXAMPLES::
|
|
1610
|
+
|
|
1611
|
+
sage: # needs sage.algebras
|
|
1612
|
+
sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]),
|
|
1613
|
+
....: Matrix([[0,1], [-1,0]])])
|
|
1614
|
+
sage: elt = B(Matrix([[1,2], [-2,1]]))
|
|
1615
|
+
sage: elt.items()
|
|
1616
|
+
dict_items([(0, 1), (1, 2)])
|
|
1617
|
+
|
|
1618
|
+
::
|
|
1619
|
+
|
|
1620
|
+
sage: # needs sage.combinat sage.modules
|
|
1621
|
+
sage: h = SymmetricFunctions(QQ).h()
|
|
1622
|
+
sage: (h[2]+3*h[3]).items()
|
|
1623
|
+
dict_items([([2], 1), ([3], 3)])
|
|
1624
|
+
"""
|
|
1625
|
+
return self.monomial_coefficients(copy=False).items()
|
|
1626
|
+
|
|
1627
|
+
def is_zero(self):
|
|
1628
|
+
"""
|
|
1629
|
+
Return ``True`` if and only if ``self == 0``.
|
|
1630
|
+
|
|
1631
|
+
EXAMPLES::
|
|
1632
|
+
|
|
1633
|
+
sage: # needs sage.modules
|
|
1634
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1635
|
+
sage: B = F.basis()
|
|
1636
|
+
sage: f = B['a'] - 3*B['c']
|
|
1637
|
+
sage: f.is_zero()
|
|
1638
|
+
False
|
|
1639
|
+
sage: F.zero().is_zero()
|
|
1640
|
+
True
|
|
1641
|
+
|
|
1642
|
+
::
|
|
1643
|
+
|
|
1644
|
+
sage: # needs sage.combinat sage.modules
|
|
1645
|
+
sage: s = SymmetricFunctions(QQ).schur()
|
|
1646
|
+
sage: s([2,1]).is_zero()
|
|
1647
|
+
False
|
|
1648
|
+
sage: s(0).is_zero()
|
|
1649
|
+
True
|
|
1650
|
+
sage: (s([2,1]) - s([2,1])).is_zero()
|
|
1651
|
+
True
|
|
1652
|
+
"""
|
|
1653
|
+
zero = self.parent().base_ring().zero()
|
|
1654
|
+
return all(v == zero for v in self.monomial_coefficients(copy=False).values())
|
|
1655
|
+
|
|
1656
|
+
def __len__(self):
|
|
1657
|
+
"""
|
|
1658
|
+
Return the number of basis elements whose coefficients in
|
|
1659
|
+
``self`` are nonzero.
|
|
1660
|
+
|
|
1661
|
+
EXAMPLES::
|
|
1662
|
+
|
|
1663
|
+
sage: # needs sage.modules
|
|
1664
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1665
|
+
sage: B = F.basis()
|
|
1666
|
+
sage: f = B['a'] - 3*B['c']
|
|
1667
|
+
sage: len(f)
|
|
1668
|
+
2
|
|
1669
|
+
|
|
1670
|
+
::
|
|
1671
|
+
|
|
1672
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1673
|
+
sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules
|
|
1674
|
+
sage: len(z) # needs sage.combinat sage.modules
|
|
1675
|
+
4
|
|
1676
|
+
"""
|
|
1677
|
+
return len(self.support())
|
|
1678
|
+
|
|
1679
|
+
def length(self):
|
|
1680
|
+
"""
|
|
1681
|
+
Return the number of basis elements whose coefficients in
|
|
1682
|
+
``self`` are nonzero.
|
|
1683
|
+
|
|
1684
|
+
EXAMPLES::
|
|
1685
|
+
|
|
1686
|
+
sage: # needs sage.modules
|
|
1687
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1688
|
+
sage: B = F.basis()
|
|
1689
|
+
sage: f = B['a'] - 3*B['c']
|
|
1690
|
+
sage: f.length()
|
|
1691
|
+
2
|
|
1692
|
+
|
|
1693
|
+
::
|
|
1694
|
+
|
|
1695
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1696
|
+
sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules
|
|
1697
|
+
sage: z.length() # needs sage.combinat sage.modules
|
|
1698
|
+
4
|
|
1699
|
+
"""
|
|
1700
|
+
return len(self)
|
|
1701
|
+
|
|
1702
|
+
def support(self):
|
|
1703
|
+
"""
|
|
1704
|
+
Return an iterable of the objects indexing the basis of
|
|
1705
|
+
``self.parent()`` whose corresponding coefficients of
|
|
1706
|
+
``self`` are nonzero.
|
|
1707
|
+
|
|
1708
|
+
This method returns these objects in an arbitrary order.
|
|
1709
|
+
|
|
1710
|
+
EXAMPLES::
|
|
1711
|
+
|
|
1712
|
+
sage: # needs sage.modules
|
|
1713
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1714
|
+
sage: B = F.basis()
|
|
1715
|
+
sage: f = B['a'] - 3*B['c']
|
|
1716
|
+
sage: sorted(f.support())
|
|
1717
|
+
['a', 'c']
|
|
1718
|
+
|
|
1719
|
+
::
|
|
1720
|
+
|
|
1721
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1722
|
+
sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules
|
|
1723
|
+
sage: sorted(z.support()) # needs sage.combinat sage.modules
|
|
1724
|
+
[[1], [1, 1, 1], [2, 1], [4]]
|
|
1725
|
+
"""
|
|
1726
|
+
try:
|
|
1727
|
+
return self._support_view
|
|
1728
|
+
except AttributeError:
|
|
1729
|
+
from sage.structure.support_view import SupportView
|
|
1730
|
+
zero = self.parent().base_ring().zero()
|
|
1731
|
+
mc = self.monomial_coefficients(copy=False)
|
|
1732
|
+
support_view = SupportView(mc, zero=zero)
|
|
1733
|
+
try:
|
|
1734
|
+
# Try to cache it for next time, but this may fail for Cython classes
|
|
1735
|
+
self._support_view = support_view
|
|
1736
|
+
except AttributeError:
|
|
1737
|
+
pass
|
|
1738
|
+
return support_view
|
|
1739
|
+
|
|
1740
|
+
def monomials(self):
|
|
1741
|
+
"""
|
|
1742
|
+
Return a list of the monomials of ``self`` (in an arbitrary
|
|
1743
|
+
order).
|
|
1744
|
+
|
|
1745
|
+
The monomials of an element `a` are defined to be the basis
|
|
1746
|
+
elements whose corresponding coefficients of `a` are
|
|
1747
|
+
nonzero.
|
|
1748
|
+
|
|
1749
|
+
EXAMPLES::
|
|
1750
|
+
|
|
1751
|
+
sage: # needs sage.modules
|
|
1752
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1753
|
+
sage: B = F.basis()
|
|
1754
|
+
sage: f = B['a'] + 2*B['c']
|
|
1755
|
+
sage: f.monomials()
|
|
1756
|
+
[B['a'], B['c']]
|
|
1757
|
+
|
|
1758
|
+
sage: (F.zero()).monomials() # needs sage.modules
|
|
1759
|
+
[]
|
|
1760
|
+
"""
|
|
1761
|
+
P = self.parent()
|
|
1762
|
+
return [P.monomial(key) for key in self.support()]
|
|
1763
|
+
|
|
1764
|
+
def terms(self):
|
|
1765
|
+
"""
|
|
1766
|
+
Return a list of the (nonzero) terms of ``self`` (in an
|
|
1767
|
+
arbitrary order).
|
|
1768
|
+
|
|
1769
|
+
.. SEEALSO:: :meth:`monomials`
|
|
1770
|
+
|
|
1771
|
+
EXAMPLES::
|
|
1772
|
+
|
|
1773
|
+
sage: # needs sage.modules
|
|
1774
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1775
|
+
sage: B = F.basis()
|
|
1776
|
+
sage: f = B['a'] + 2*B['c']
|
|
1777
|
+
sage: f.terms()
|
|
1778
|
+
[B['a'], 2*B['c']]
|
|
1779
|
+
"""
|
|
1780
|
+
P = self.parent()
|
|
1781
|
+
zero = P.base_ring().zero()
|
|
1782
|
+
return [P.term(key, value)
|
|
1783
|
+
for key, value in self.monomial_coefficients(copy=False).items()
|
|
1784
|
+
if value != zero]
|
|
1785
|
+
|
|
1786
|
+
def coefficients(self, sort=True):
|
|
1787
|
+
"""
|
|
1788
|
+
Return a list of the (nonzero) coefficients appearing on
|
|
1789
|
+
the basis elements in ``self`` (in an arbitrary order).
|
|
1790
|
+
|
|
1791
|
+
INPUT:
|
|
1792
|
+
|
|
1793
|
+
- ``sort`` -- boolean (default: ``True``); to sort the coefficients
|
|
1794
|
+
based upon the default ordering of the indexing set
|
|
1795
|
+
|
|
1796
|
+
.. SEEALSO::
|
|
1797
|
+
|
|
1798
|
+
:meth:`~sage.categories.finite_dimensional_modules_with_basis.FiniteDimensionalModulesWithBasis.ElementMethods.dense_coefficient_list`
|
|
1799
|
+
|
|
1800
|
+
EXAMPLES::
|
|
1801
|
+
|
|
1802
|
+
sage: # needs sage.modules
|
|
1803
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
1804
|
+
sage: B = F.basis()
|
|
1805
|
+
sage: f = B['a'] - 3*B['c']
|
|
1806
|
+
sage: f.coefficients()
|
|
1807
|
+
[1, -3]
|
|
1808
|
+
sage: f = B['c'] - 3*B['a']
|
|
1809
|
+
sage: f.coefficients()
|
|
1810
|
+
[-3, 1]
|
|
1811
|
+
|
|
1812
|
+
::
|
|
1813
|
+
|
|
1814
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1815
|
+
sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # needs sage.combinat sage.modules
|
|
1816
|
+
sage: z.coefficients() # needs sage.combinat sage.modules
|
|
1817
|
+
[1, 1, 1, 1]
|
|
1818
|
+
"""
|
|
1819
|
+
zero = self.parent().base_ring().zero()
|
|
1820
|
+
mc = self.monomial_coefficients(copy=False)
|
|
1821
|
+
if not sort:
|
|
1822
|
+
return [value for key, value in mc.items() if value != zero]
|
|
1823
|
+
|
|
1824
|
+
v = sorted([(key, value) for key, value in mc.items()
|
|
1825
|
+
if value != zero])
|
|
1826
|
+
return [value for key, value in v]
|
|
1827
|
+
|
|
1828
|
+
def support_of_term(self):
|
|
1829
|
+
"""
|
|
1830
|
+
Return the support of ``self``, where ``self`` is a monomial
|
|
1831
|
+
(possibly with coefficient).
|
|
1832
|
+
|
|
1833
|
+
EXAMPLES::
|
|
1834
|
+
|
|
1835
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3,4]); X.rename('X') # needs sage.modules
|
|
1836
|
+
sage: X.monomial(2).support_of_term() # needs sage.modules
|
|
1837
|
+
2
|
|
1838
|
+
sage: X.term(3, 2).support_of_term() # needs sage.modules
|
|
1839
|
+
3
|
|
1840
|
+
|
|
1841
|
+
An exception is raised if ``self`` has more than one term::
|
|
1842
|
+
|
|
1843
|
+
sage: (X.monomial(2) + X.monomial(3)).support_of_term() # needs sage.modules
|
|
1844
|
+
Traceback (most recent call last):
|
|
1845
|
+
...
|
|
1846
|
+
ValueError: B[2] + B[3] is not a single term
|
|
1847
|
+
"""
|
|
1848
|
+
if len(self) == 1:
|
|
1849
|
+
return self.support()[0]
|
|
1850
|
+
else:
|
|
1851
|
+
raise ValueError("{} is not a single term".format(self))
|
|
1852
|
+
|
|
1853
|
+
def leading_support(self, *args, **kwds):
|
|
1854
|
+
r"""
|
|
1855
|
+
Return the maximal element of the support of ``self``.
|
|
1856
|
+
|
|
1857
|
+
Note that this may not be the term which actually appears
|
|
1858
|
+
first when ``self`` is printed.
|
|
1859
|
+
|
|
1860
|
+
If the default ordering of the basis elements is not what is
|
|
1861
|
+
desired, a comparison key, ``key(x)``, can be provided.
|
|
1862
|
+
|
|
1863
|
+
EXAMPLES::
|
|
1864
|
+
|
|
1865
|
+
sage: # needs sage.modules
|
|
1866
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3])
|
|
1867
|
+
sage: X.rename('X'); x = X.basis()
|
|
1868
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3)
|
|
1869
|
+
sage: x.leading_support()
|
|
1870
|
+
3
|
|
1871
|
+
sage: def key(x): return -x
|
|
1872
|
+
sage: x.leading_support(key=key)
|
|
1873
|
+
1
|
|
1874
|
+
|
|
1875
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1876
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
1877
|
+
sage: f.leading_support() # needs sage.combinat sage.modules
|
|
1878
|
+
[3]
|
|
1879
|
+
"""
|
|
1880
|
+
return max(self.support(), *args, **kwds)
|
|
1881
|
+
|
|
1882
|
+
def leading_item(self, *args, **kwds):
|
|
1883
|
+
r"""
|
|
1884
|
+
Return the pair ``(k, c)`` where
|
|
1885
|
+
|
|
1886
|
+
.. MATH::
|
|
1887
|
+
|
|
1888
|
+
c \cdot (\mbox{the basis element indexed by } k)
|
|
1889
|
+
|
|
1890
|
+
is the leading term of ``self``.
|
|
1891
|
+
|
|
1892
|
+
Here 'leading term' means that the corresponding basis element is
|
|
1893
|
+
maximal. Note that this may not be the term which actually appears
|
|
1894
|
+
first when ``self`` is printed.
|
|
1895
|
+
|
|
1896
|
+
If the default term ordering is not what is desired, a
|
|
1897
|
+
comparison function, ``key(x)``, can be provided.
|
|
1898
|
+
|
|
1899
|
+
EXAMPLES::
|
|
1900
|
+
|
|
1901
|
+
sage: # needs sage.modules
|
|
1902
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
1903
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3)
|
|
1904
|
+
sage: x.leading_item()
|
|
1905
|
+
(3, 4)
|
|
1906
|
+
sage: def key(x): return -x
|
|
1907
|
+
sage: x.leading_item(key=key)
|
|
1908
|
+
(1, 3)
|
|
1909
|
+
|
|
1910
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1911
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
1912
|
+
sage: f.leading_item() # needs sage.combinat sage.modules
|
|
1913
|
+
([3], -5)
|
|
1914
|
+
|
|
1915
|
+
The term ordering of polynomial rings is taken into account::
|
|
1916
|
+
|
|
1917
|
+
sage: R.<x,y,z> = QQ[]
|
|
1918
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_item()
|
|
1919
|
+
((0, 4, 0), 1)
|
|
1920
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
1921
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_item()
|
|
1922
|
+
((1, 2, 0), 3)
|
|
1923
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
1924
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_item()
|
|
1925
|
+
((0, 1, 3), 2)
|
|
1926
|
+
"""
|
|
1927
|
+
k = self.leading_support(*args, **kwds)
|
|
1928
|
+
return k, self[k]
|
|
1929
|
+
|
|
1930
|
+
def leading_monomial(self, *args, **kwds):
|
|
1931
|
+
r"""
|
|
1932
|
+
Return the leading monomial of ``self``.
|
|
1933
|
+
|
|
1934
|
+
This is the monomial whose corresponding basis element is
|
|
1935
|
+
maximal. Note that this may not be the term which actually appears
|
|
1936
|
+
first when ``self`` is printed.
|
|
1937
|
+
|
|
1938
|
+
If the default term ordering is not
|
|
1939
|
+
what is desired, a comparison key, ``key(x)``, can be provided.
|
|
1940
|
+
|
|
1941
|
+
EXAMPLES::
|
|
1942
|
+
|
|
1943
|
+
sage: # needs sage.modules
|
|
1944
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
1945
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3)
|
|
1946
|
+
sage: x.leading_monomial()
|
|
1947
|
+
B[3]
|
|
1948
|
+
sage: def key(x): return -x
|
|
1949
|
+
sage: x.leading_monomial(key=key)
|
|
1950
|
+
B[1]
|
|
1951
|
+
|
|
1952
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1953
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
1954
|
+
sage: f.leading_monomial() # needs sage.combinat sage.modules
|
|
1955
|
+
s[3]
|
|
1956
|
+
|
|
1957
|
+
The term ordering of polynomial rings is taken into account::
|
|
1958
|
+
|
|
1959
|
+
sage: R.<x,y,z> = QQ[]
|
|
1960
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_monomial()
|
|
1961
|
+
y^4
|
|
1962
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
1963
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_monomial()
|
|
1964
|
+
x*y^2
|
|
1965
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
1966
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_monomial()
|
|
1967
|
+
y*z^3
|
|
1968
|
+
"""
|
|
1969
|
+
return self.parent().monomial(self.leading_support(*args, **kwds))
|
|
1970
|
+
|
|
1971
|
+
def leading_coefficient(self, *args, **kwds):
|
|
1972
|
+
r"""
|
|
1973
|
+
Return the leading coefficient of ``self``.
|
|
1974
|
+
|
|
1975
|
+
This is the coefficient of the term whose corresponding basis element is
|
|
1976
|
+
maximal. Note that this may not be the term which actually appears
|
|
1977
|
+
first when ``self`` is printed.
|
|
1978
|
+
|
|
1979
|
+
If the default term ordering is not
|
|
1980
|
+
what is desired, a comparison key, ``key(x,y)``, can be provided.
|
|
1981
|
+
|
|
1982
|
+
EXAMPLES::
|
|
1983
|
+
|
|
1984
|
+
sage: # needs sage.modules
|
|
1985
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
1986
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3)
|
|
1987
|
+
sage: x.leading_coefficient()
|
|
1988
|
+
1
|
|
1989
|
+
sage: def key(x): return -x
|
|
1990
|
+
sage: x.leading_coefficient(key=key)
|
|
1991
|
+
3
|
|
1992
|
+
|
|
1993
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
1994
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
1995
|
+
sage: f.leading_coefficient() # needs sage.combinat sage.modules
|
|
1996
|
+
-5
|
|
1997
|
+
|
|
1998
|
+
The term ordering of polynomial rings is taken into account::
|
|
1999
|
+
|
|
2000
|
+
sage: R.<x,y,z> = QQ[]
|
|
2001
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_coefficient()
|
|
2002
|
+
1
|
|
2003
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
2004
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_coefficient()
|
|
2005
|
+
3
|
|
2006
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
2007
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_coefficient()
|
|
2008
|
+
2
|
|
2009
|
+
"""
|
|
2010
|
+
return self.leading_item(*args, **kwds)[1]
|
|
2011
|
+
|
|
2012
|
+
def leading_term(self, *args, **kwds):
|
|
2013
|
+
r"""
|
|
2014
|
+
Return the leading term of ``self``.
|
|
2015
|
+
|
|
2016
|
+
This is the term whose corresponding basis element is
|
|
2017
|
+
maximal. Note that this may not be the term which actually appears
|
|
2018
|
+
first when ``self`` is printed.
|
|
2019
|
+
|
|
2020
|
+
If the default term ordering is not
|
|
2021
|
+
what is desired, a comparison key, ``key(x)``, can be provided.
|
|
2022
|
+
|
|
2023
|
+
EXAMPLES::
|
|
2024
|
+
|
|
2025
|
+
sage: # needs sage.modules
|
|
2026
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
2027
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3)
|
|
2028
|
+
sage: x.leading_term()
|
|
2029
|
+
B[3]
|
|
2030
|
+
sage: def key(x): return -x
|
|
2031
|
+
sage: x.leading_term(key=key)
|
|
2032
|
+
3*B[1]
|
|
2033
|
+
|
|
2034
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2035
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
2036
|
+
sage: f.leading_term() # needs sage.combinat sage.modules
|
|
2037
|
+
-5*s[3]
|
|
2038
|
+
|
|
2039
|
+
The term ordering of polynomial rings is taken into account::
|
|
2040
|
+
|
|
2041
|
+
sage: R.<x,y,z> = QQ[]
|
|
2042
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_term()
|
|
2043
|
+
y^4
|
|
2044
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
2045
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_term()
|
|
2046
|
+
3*x*y^2
|
|
2047
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
2048
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).leading_term()
|
|
2049
|
+
2*y*z^3
|
|
2050
|
+
"""
|
|
2051
|
+
return self.parent().term(*self.leading_item(*args, **kwds))
|
|
2052
|
+
|
|
2053
|
+
def trailing_support(self, *args, **kwds):
|
|
2054
|
+
r"""
|
|
2055
|
+
Return the minimal element of the support of ``self``. Note
|
|
2056
|
+
that this may not be the term which actually appears last when
|
|
2057
|
+
``self`` is printed.
|
|
2058
|
+
|
|
2059
|
+
If the default ordering of the basis elements is not what is
|
|
2060
|
+
desired, a comparison key, ``key(x)``, can be provided.
|
|
2061
|
+
|
|
2062
|
+
EXAMPLES::
|
|
2063
|
+
|
|
2064
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X') # needs sage.modules
|
|
2065
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # needs sage.modules
|
|
2066
|
+
sage: x.trailing_support() # needs sage.modules
|
|
2067
|
+
1
|
|
2068
|
+
|
|
2069
|
+
sage: def key(x): return -x
|
|
2070
|
+
sage: x.trailing_support(key=key) # needs sage.modules
|
|
2071
|
+
3
|
|
2072
|
+
|
|
2073
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2074
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
2075
|
+
sage: f.trailing_support() # needs sage.combinat sage.modules
|
|
2076
|
+
[1]
|
|
2077
|
+
"""
|
|
2078
|
+
return min(self.support(), *args, **kwds)
|
|
2079
|
+
|
|
2080
|
+
def trailing_item(self, *args, **kwds):
|
|
2081
|
+
r"""
|
|
2082
|
+
Return the pair ``(c, k)`` where ``c*self.parent().monomial(k)``
|
|
2083
|
+
is the trailing term of ``self``.
|
|
2084
|
+
|
|
2085
|
+
This is the monomial whose corresponding basis element is
|
|
2086
|
+
minimal. Note that this may not be the term which actually appears
|
|
2087
|
+
last when ``self`` is printed.
|
|
2088
|
+
|
|
2089
|
+
If the default term ordering is not
|
|
2090
|
+
what is desired, a comparison key ``key(x)``, can be provided.
|
|
2091
|
+
|
|
2092
|
+
EXAMPLES::
|
|
2093
|
+
|
|
2094
|
+
sage: # needs sage.modules
|
|
2095
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
2096
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3)
|
|
2097
|
+
sage: x.trailing_item()
|
|
2098
|
+
(1, 3)
|
|
2099
|
+
sage: def key(x): return -x
|
|
2100
|
+
sage: x.trailing_item(key=key)
|
|
2101
|
+
(3, 1)
|
|
2102
|
+
|
|
2103
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2104
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
2105
|
+
sage: f.trailing_item() # needs sage.combinat sage.modules
|
|
2106
|
+
([1], 2)
|
|
2107
|
+
|
|
2108
|
+
The term ordering of polynomial rings is taken into account::
|
|
2109
|
+
|
|
2110
|
+
sage: R.<x,y,z> = QQ[]
|
|
2111
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_item()
|
|
2112
|
+
((1, 1, 1), 4)
|
|
2113
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
2114
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_item()
|
|
2115
|
+
((0, 1, 3), 2)
|
|
2116
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
2117
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_item()
|
|
2118
|
+
((1, 2, 0), 3)
|
|
2119
|
+
"""
|
|
2120
|
+
k = self.trailing_support(*args, **kwds)
|
|
2121
|
+
return k, self[k]
|
|
2122
|
+
|
|
2123
|
+
def trailing_monomial(self, *args, **kwds):
|
|
2124
|
+
r"""
|
|
2125
|
+
Return the trailing monomial of ``self``.
|
|
2126
|
+
|
|
2127
|
+
This is the monomial whose corresponding basis element is
|
|
2128
|
+
minimal. Note that this may not be the term which actually appears
|
|
2129
|
+
last when ``self`` is printed.
|
|
2130
|
+
|
|
2131
|
+
If the default term ordering is not
|
|
2132
|
+
what is desired, a comparison key ``key(x)``, can be provided.
|
|
2133
|
+
|
|
2134
|
+
EXAMPLES::
|
|
2135
|
+
|
|
2136
|
+
sage: # needs sage.modules
|
|
2137
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
2138
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3)
|
|
2139
|
+
sage: x.trailing_monomial()
|
|
2140
|
+
B[1]
|
|
2141
|
+
sage: def key(x): return -x
|
|
2142
|
+
sage: x.trailing_monomial(key=key)
|
|
2143
|
+
B[3]
|
|
2144
|
+
|
|
2145
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2146
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
2147
|
+
sage: f.trailing_monomial() # needs sage.combinat sage.modules
|
|
2148
|
+
s[1]
|
|
2149
|
+
|
|
2150
|
+
The term ordering of polynomial rings is taken into account::
|
|
2151
|
+
|
|
2152
|
+
sage: R.<x,y,z> = QQ[]
|
|
2153
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_monomial()
|
|
2154
|
+
x*y*z
|
|
2155
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
2156
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_monomial()
|
|
2157
|
+
y*z^3
|
|
2158
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
2159
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_monomial()
|
|
2160
|
+
x*y^2
|
|
2161
|
+
"""
|
|
2162
|
+
return self.parent().monomial(self.trailing_support(*args, **kwds))
|
|
2163
|
+
|
|
2164
|
+
def trailing_coefficient(self, *args, **kwds):
|
|
2165
|
+
r"""
|
|
2166
|
+
Return the trailing coefficient of ``self``.
|
|
2167
|
+
|
|
2168
|
+
This is the coefficient of the monomial whose corresponding basis element is
|
|
2169
|
+
minimal. Note that this may not be the term which actually appears
|
|
2170
|
+
last when ``self`` is printed.
|
|
2171
|
+
|
|
2172
|
+
If the default term ordering is not
|
|
2173
|
+
what is desired, a comparison key ``key(x)``, can be provided.
|
|
2174
|
+
|
|
2175
|
+
EXAMPLES::
|
|
2176
|
+
|
|
2177
|
+
sage: # needs sage.modules
|
|
2178
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
2179
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3)
|
|
2180
|
+
sage: x.trailing_coefficient()
|
|
2181
|
+
3
|
|
2182
|
+
sage: def key(x): return -x
|
|
2183
|
+
sage: x.trailing_coefficient(key=key)
|
|
2184
|
+
1
|
|
2185
|
+
|
|
2186
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2187
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
2188
|
+
sage: f.trailing_coefficient() # needs sage.combinat sage.modules
|
|
2189
|
+
2
|
|
2190
|
+
|
|
2191
|
+
The term ordering of polynomial rings is taken into account::
|
|
2192
|
+
|
|
2193
|
+
sage: R.<x,y,z> = QQ[]
|
|
2194
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_coefficient()
|
|
2195
|
+
4
|
|
2196
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
2197
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_coefficient()
|
|
2198
|
+
2
|
|
2199
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
2200
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_coefficient()
|
|
2201
|
+
3
|
|
2202
|
+
"""
|
|
2203
|
+
return self.trailing_item(*args, **kwds)[1]
|
|
2204
|
+
|
|
2205
|
+
def trailing_term(self, *args, **kwds):
|
|
2206
|
+
r"""
|
|
2207
|
+
Return the trailing term of ``self``.
|
|
2208
|
+
|
|
2209
|
+
This is the term whose corresponding basis element is
|
|
2210
|
+
minimal. Note that this may not be the term which actually appears
|
|
2211
|
+
last when ``self`` is printed.
|
|
2212
|
+
|
|
2213
|
+
If the default term ordering is not
|
|
2214
|
+
what is desired, a comparison key ``key(x)``, can be provided.
|
|
2215
|
+
|
|
2216
|
+
EXAMPLES::
|
|
2217
|
+
|
|
2218
|
+
sage: # needs sage.modules
|
|
2219
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
2220
|
+
sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3)
|
|
2221
|
+
sage: x.trailing_term()
|
|
2222
|
+
3*B[1]
|
|
2223
|
+
sage: def key(x): return -x
|
|
2224
|
+
sage: x.trailing_term(key=key)
|
|
2225
|
+
B[3]
|
|
2226
|
+
|
|
2227
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2228
|
+
sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # needs sage.combinat sage.modules
|
|
2229
|
+
sage: f.trailing_term() # needs sage.combinat sage.modules
|
|
2230
|
+
2*s[1]
|
|
2231
|
+
|
|
2232
|
+
The term ordering of polynomial rings is taken into account::
|
|
2233
|
+
|
|
2234
|
+
sage: R.<x,y,z> = QQ[]
|
|
2235
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_term()
|
|
2236
|
+
4*x*y*z
|
|
2237
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex')
|
|
2238
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_term()
|
|
2239
|
+
2*y*z^3
|
|
2240
|
+
sage: R.<x,y,z> = PolynomialRing(QQ, order='invlex')
|
|
2241
|
+
sage: (3*x*y^2 + 2*y*z^3 + y^4 + 4*x*y*z).trailing_term()
|
|
2242
|
+
3*x*y^2
|
|
2243
|
+
"""
|
|
2244
|
+
return self.parent().term(*self.trailing_item(*args, **kwds))
|
|
2245
|
+
|
|
2246
|
+
def map_coefficients(self, f, new_base_ring=None):
|
|
2247
|
+
"""
|
|
2248
|
+
Return the element obtained by applying ``f`` to the nonzero
|
|
2249
|
+
coefficients of ``self``.
|
|
2250
|
+
|
|
2251
|
+
If ``f`` is a :class:`sage.categories.map.Map`, then the resulting
|
|
2252
|
+
polynomial will be defined over the codomain of ``f``. Otherwise, the
|
|
2253
|
+
resulting polynomial will be over the same ring as ``self``. Set
|
|
2254
|
+
``new_base_ring`` to override this behaviour.
|
|
2255
|
+
|
|
2256
|
+
An error is raised if the coefficients cannot be
|
|
2257
|
+
converted to the new base ring.
|
|
2258
|
+
|
|
2259
|
+
INPUT:
|
|
2260
|
+
|
|
2261
|
+
- ``f`` -- a callable that will be applied to the
|
|
2262
|
+
coefficients of ``self``
|
|
2263
|
+
|
|
2264
|
+
- ``new_base_ring`` -- (optional) if given, the resulting element
|
|
2265
|
+
will be defined over this ring
|
|
2266
|
+
|
|
2267
|
+
EXAMPLES::
|
|
2268
|
+
|
|
2269
|
+
sage: # needs sage.modules
|
|
2270
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
2271
|
+
sage: B = F.basis()
|
|
2272
|
+
sage: f = B['a'] - 3*B['c']
|
|
2273
|
+
sage: f.map_coefficients(lambda x: x + 5)
|
|
2274
|
+
6*B['a'] + 2*B['c']
|
|
2275
|
+
|
|
2276
|
+
Killed coefficients are handled properly::
|
|
2277
|
+
|
|
2278
|
+
sage: f.map_coefficients(lambda x: 0) # needs sage.modules
|
|
2279
|
+
0
|
|
2280
|
+
sage: list(f.map_coefficients(lambda x: 0)) # needs sage.modules
|
|
2281
|
+
[]
|
|
2282
|
+
|
|
2283
|
+
::
|
|
2284
|
+
|
|
2285
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2286
|
+
sage: a = s([2,1]) + 2*s([3,2]) # needs sage.combinat sage.modules
|
|
2287
|
+
sage: a.map_coefficients(lambda x: x * 2) # needs sage.combinat sage.modules
|
|
2288
|
+
2*s[2, 1] + 4*s[3, 2]
|
|
2289
|
+
|
|
2290
|
+
We can map into a different base ring::
|
|
2291
|
+
|
|
2292
|
+
sage: # needs sage.modules
|
|
2293
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
2294
|
+
sage: B = F.basis()
|
|
2295
|
+
sage: a = 1/2*(B['a'] + 3*B['c']); a
|
|
2296
|
+
1/2*B['a'] + 3/2*B['c']
|
|
2297
|
+
sage: b = a.map_coefficients(lambda c: 2*c, ZZ); b
|
|
2298
|
+
B['a'] + 3*B['c']
|
|
2299
|
+
sage: b.parent()
|
|
2300
|
+
Free module generated by {'a', 'b', 'c'} over Integer Ring
|
|
2301
|
+
sage: b.map_coefficients(lambda c: 1/2*c, ZZ)
|
|
2302
|
+
Traceback (most recent call last):
|
|
2303
|
+
...
|
|
2304
|
+
TypeError: no conversion of this rational to integer
|
|
2305
|
+
|
|
2306
|
+
Coefficients are converted to the new base ring after
|
|
2307
|
+
applying the map::
|
|
2308
|
+
|
|
2309
|
+
sage: B['a'].map_coefficients(lambda c: 2*c, GF(2)) # needs sage.modules
|
|
2310
|
+
0
|
|
2311
|
+
sage: B['a'].map_coefficients(lambda c: GF(2)(c), QQ) # needs sage.modules
|
|
2312
|
+
B['a']
|
|
2313
|
+
"""
|
|
2314
|
+
R = self.parent()
|
|
2315
|
+
if isinstance(f, Map):
|
|
2316
|
+
B = f.codomain()
|
|
2317
|
+
else:
|
|
2318
|
+
B = self.base_ring()
|
|
2319
|
+
if new_base_ring is not None:
|
|
2320
|
+
B = new_base_ring
|
|
2321
|
+
if B is not self.base_ring():
|
|
2322
|
+
R = R.change_ring(B)
|
|
2323
|
+
mc = self.monomial_coefficients(copy=False)
|
|
2324
|
+
return R.sum_of_terms((m, B(f(c))) for m, c in mc.items())
|
|
2325
|
+
|
|
2326
|
+
def map_support(self, f):
|
|
2327
|
+
"""
|
|
2328
|
+
Mapping a function on the support.
|
|
2329
|
+
|
|
2330
|
+
INPUT:
|
|
2331
|
+
|
|
2332
|
+
- ``f`` -- an endofunction on the indices of the free module
|
|
2333
|
+
|
|
2334
|
+
Return a new element of ``self.parent()`` obtained by
|
|
2335
|
+
applying the function ``f`` to all of the objects indexing
|
|
2336
|
+
the basis elements.
|
|
2337
|
+
|
|
2338
|
+
EXAMPLES::
|
|
2339
|
+
|
|
2340
|
+
sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # needs sage.modules
|
|
2341
|
+
sage: x = B.an_element(); x # needs sage.modules
|
|
2342
|
+
2*B[-1] + 2*B[0] + 3*B[1]
|
|
2343
|
+
sage: x.map_support(lambda i: -i) # needs sage.modules
|
|
2344
|
+
3*B[-1] + 2*B[0] + 2*B[1]
|
|
2345
|
+
|
|
2346
|
+
``f`` needs not be injective::
|
|
2347
|
+
|
|
2348
|
+
sage: x.map_support(lambda i: 1) # needs sage.modules
|
|
2349
|
+
7*B[1]
|
|
2350
|
+
|
|
2351
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2352
|
+
sage: a = s([2,1]) + 2*s([3,2]) # needs sage.combinat sage.modules
|
|
2353
|
+
sage: a.map_support(lambda x: x.conjugate()) # needs sage.combinat sage.modules
|
|
2354
|
+
s[2, 1] + 2*s[2, 2, 1]
|
|
2355
|
+
|
|
2356
|
+
TESTS::
|
|
2357
|
+
|
|
2358
|
+
sage: B.zero() # This actually failed at some point!!! See #8890 # needs sage.modules
|
|
2359
|
+
0
|
|
2360
|
+
|
|
2361
|
+
sage: y = B.zero().map_support(lambda i: i/0); y # needs sage.modules
|
|
2362
|
+
0
|
|
2363
|
+
sage: y.parent() is B # needs sage.modules
|
|
2364
|
+
True
|
|
2365
|
+
"""
|
|
2366
|
+
return self.parent().sum_of_terms((f(m), c) for m, c in self.items())
|
|
2367
|
+
|
|
2368
|
+
def map_support_skip_none(self, f):
|
|
2369
|
+
"""
|
|
2370
|
+
Mapping a function on the support.
|
|
2371
|
+
|
|
2372
|
+
INPUT:
|
|
2373
|
+
|
|
2374
|
+
- ``f`` -- an endofunction on the indices of the free module
|
|
2375
|
+
|
|
2376
|
+
Returns a new element of ``self.parent()`` obtained by
|
|
2377
|
+
applying the function `f` to all of the objects indexing
|
|
2378
|
+
the basis elements.
|
|
2379
|
+
|
|
2380
|
+
EXAMPLES::
|
|
2381
|
+
|
|
2382
|
+
sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # needs sage.modules
|
|
2383
|
+
sage: x = B.an_element(); x # needs sage.modules
|
|
2384
|
+
2*B[-1] + 2*B[0] + 3*B[1]
|
|
2385
|
+
sage: x.map_support_skip_none(lambda i: -i if i else None) # needs sage.modules
|
|
2386
|
+
3*B[-1] + 2*B[1]
|
|
2387
|
+
|
|
2388
|
+
``f`` needs not be injective::
|
|
2389
|
+
|
|
2390
|
+
sage: x.map_support_skip_none(lambda i: 1 if i else None) # needs sage.modules
|
|
2391
|
+
5*B[1]
|
|
2392
|
+
|
|
2393
|
+
TESTS::
|
|
2394
|
+
|
|
2395
|
+
sage: y = x.map_support_skip_none(lambda i: None); y # needs sage.modules
|
|
2396
|
+
0
|
|
2397
|
+
sage: y.parent() is B # needs sage.modules
|
|
2398
|
+
True
|
|
2399
|
+
"""
|
|
2400
|
+
return self.parent().sum_of_terms((fm, c)
|
|
2401
|
+
for fm, c in ((f(m), c) for m, c in self.items())
|
|
2402
|
+
if fm is not None)
|
|
2403
|
+
|
|
2404
|
+
def map_item(self, f):
|
|
2405
|
+
"""
|
|
2406
|
+
Mapping a function on items.
|
|
2407
|
+
|
|
2408
|
+
INPUT:
|
|
2409
|
+
|
|
2410
|
+
- ``f`` -- a function mapping pairs ``(index, coeff)`` to
|
|
2411
|
+
other such pairs
|
|
2412
|
+
|
|
2413
|
+
Return a new element of ``self.parent()`` obtained by
|
|
2414
|
+
applying the function `f` to all items ``(index, coeff)`` of
|
|
2415
|
+
``self``.
|
|
2416
|
+
|
|
2417
|
+
EXAMPLES::
|
|
2418
|
+
|
|
2419
|
+
sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # needs sage.modules
|
|
2420
|
+
sage: x = B.an_element(); x # needs sage.modules
|
|
2421
|
+
2*B[-1] + 2*B[0] + 3*B[1]
|
|
2422
|
+
sage: x.map_item(lambda i, c: (-i, 2*c)) # needs sage.modules
|
|
2423
|
+
6*B[-1] + 4*B[0] + 4*B[1]
|
|
2424
|
+
|
|
2425
|
+
``f`` needs not be injective::
|
|
2426
|
+
|
|
2427
|
+
sage: x.map_item(lambda i, c: (1, 2*c)) # needs sage.modules
|
|
2428
|
+
14*B[1]
|
|
2429
|
+
|
|
2430
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage.modules
|
|
2431
|
+
sage: f = lambda m, c: (m.conjugate(), 2 * c)
|
|
2432
|
+
sage: a = s([2,1]) + s([1,1,1]) # needs sage.combinat sage.modules
|
|
2433
|
+
sage: a.map_item(f) # needs sage.combinat sage.modules
|
|
2434
|
+
2*s[2, 1] + 2*s[3]
|
|
2435
|
+
"""
|
|
2436
|
+
return self.parent().sum_of_terms(f(m, c) for m, c in self.items())
|
|
2437
|
+
|
|
2438
|
+
def tensor(*elements):
|
|
2439
|
+
"""
|
|
2440
|
+
Return the tensor product of its arguments, as an element of
|
|
2441
|
+
the tensor product of the parents of those elements.
|
|
2442
|
+
|
|
2443
|
+
EXAMPLES::
|
|
2444
|
+
|
|
2445
|
+
sage: C = AlgebrasWithBasis(QQ)
|
|
2446
|
+
sage: A = C.example() # needs sage.combinat sage.modules
|
|
2447
|
+
sage: a, b, c = A.algebra_generators() # needs sage.combinat sage.modules
|
|
2448
|
+
sage: a.tensor(b, c) # needs sage.combinat sage.modules
|
|
2449
|
+
B[word: a] # B[word: b] # B[word: c]
|
|
2450
|
+
|
|
2451
|
+
FIXME: is this a policy that we want to enforce on all parents?
|
|
2452
|
+
"""
|
|
2453
|
+
assert all(isinstance(element, Element) for element in elements)
|
|
2454
|
+
parents = [parent(element) for element in elements]
|
|
2455
|
+
return tensor(parents)._tensor_of_elements(elements) # good name ?
|
|
2456
|
+
|
|
2457
|
+
class Homsets(HomsetsCategory):
|
|
2458
|
+
class ParentMethods:
|
|
2459
|
+
def __call_on_basis__(self, **options):
|
|
2460
|
+
"""
|
|
2461
|
+
Construct a morphism in this homset from a function defined
|
|
2462
|
+
on the basis.
|
|
2463
|
+
|
|
2464
|
+
INPUT:
|
|
2465
|
+
|
|
2466
|
+
- ``on_basis`` -- a function from the indices of the
|
|
2467
|
+
basis of the domain of ``self`` to the codomain of
|
|
2468
|
+
``self``
|
|
2469
|
+
|
|
2470
|
+
This method simply delegates the work to
|
|
2471
|
+
:meth:`ModulesWithBasis.ParentMethods.module_morphism`. It
|
|
2472
|
+
is used by :meth:`Homset.__call__` to handle the
|
|
2473
|
+
``on_basis`` argument, and will disappear as soon as
|
|
2474
|
+
the logic will be generalized.
|
|
2475
|
+
|
|
2476
|
+
EXAMPLES::
|
|
2477
|
+
|
|
2478
|
+
sage: # needs sage.modules
|
|
2479
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename('X')
|
|
2480
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename('Y')
|
|
2481
|
+
sage: H = Hom(X, Y)
|
|
2482
|
+
sage: x = X.basis()
|
|
2483
|
+
sage: def on_basis(i):
|
|
2484
|
+
....: return Y.monomial(i) + 2*Y.monomial(i + 1)
|
|
2485
|
+
sage: phi = H(on_basis=on_basis) # indirect doctest
|
|
2486
|
+
sage: phi
|
|
2487
|
+
Generic morphism:
|
|
2488
|
+
From: X
|
|
2489
|
+
To: Y
|
|
2490
|
+
sage: phi(x[1] + x[3])
|
|
2491
|
+
B[1] + 2*B[2] + B[3] + 2*B[4]
|
|
2492
|
+
|
|
2493
|
+
Diagonal functions can be constructed using the ``diagonal`` option::
|
|
2494
|
+
|
|
2495
|
+
sage: # needs sage.modules
|
|
2496
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3,4]); X.rename('X')
|
|
2497
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4],
|
|
2498
|
+
....: key='Y'); Y.rename('Y')
|
|
2499
|
+
sage: H = Hom(X, Y)
|
|
2500
|
+
sage: x = X.basis()
|
|
2501
|
+
sage: phi = H(diagonal=lambda x: x^2)
|
|
2502
|
+
sage: phi(x[1] + x[2] + x[3])
|
|
2503
|
+
B[1] + 4*B[2] + 9*B[3]
|
|
2504
|
+
|
|
2505
|
+
TESTS:
|
|
2506
|
+
|
|
2507
|
+
As for usual homsets, the argument can be a Python function::
|
|
2508
|
+
|
|
2509
|
+
sage: phi = H(lambda x: Y.zero()); phi # needs sage.modules
|
|
2510
|
+
Generic morphism:
|
|
2511
|
+
From: X
|
|
2512
|
+
To: Y
|
|
2513
|
+
sage: phi(x[1] + x[3]) # needs sage.modules
|
|
2514
|
+
0
|
|
2515
|
+
|
|
2516
|
+
We check that the homset category is properly set up::
|
|
2517
|
+
|
|
2518
|
+
sage: # needs sage.modules
|
|
2519
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename('X')
|
|
2520
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename('Y')
|
|
2521
|
+
sage: H = Hom(X, Y)
|
|
2522
|
+
sage: H.zero().category_for()
|
|
2523
|
+
Category of finite dimensional vector spaces with basis over Rational Field
|
|
2524
|
+
"""
|
|
2525
|
+
return self.domain().module_morphism(codomain=self.codomain(),
|
|
2526
|
+
**options)
|
|
2527
|
+
|
|
2528
|
+
class MorphismMethods:
|
|
2529
|
+
@cached_method
|
|
2530
|
+
def on_basis(self):
|
|
2531
|
+
"""
|
|
2532
|
+
Return the action of this morphism on basis elements.
|
|
2533
|
+
|
|
2534
|
+
OUTPUT:
|
|
2535
|
+
|
|
2536
|
+
- a function from the indices of the basis of the domain to
|
|
2537
|
+
the codomain
|
|
2538
|
+
|
|
2539
|
+
EXAMPLES::
|
|
2540
|
+
|
|
2541
|
+
sage: # needs sage.modules
|
|
2542
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename('X')
|
|
2543
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename('Y')
|
|
2544
|
+
sage: H = Hom(X, Y)
|
|
2545
|
+
sage: x = X.basis()
|
|
2546
|
+
sage: f = H(lambda x: Y.zero()).on_basis()
|
|
2547
|
+
sage: f(2)
|
|
2548
|
+
0
|
|
2549
|
+
sage: f = lambda i: Y.monomial(i) + 2*Y.monomial(i+1)
|
|
2550
|
+
sage: g = H(on_basis=f).on_basis()
|
|
2551
|
+
sage: g(2)
|
|
2552
|
+
B[2] + 2*B[3]
|
|
2553
|
+
sage: g == f
|
|
2554
|
+
True
|
|
2555
|
+
"""
|
|
2556
|
+
return self._on_basis
|
|
2557
|
+
|
|
2558
|
+
def _on_basis(self, i):
|
|
2559
|
+
"""
|
|
2560
|
+
Return the image of ``self`` on the basis element indexed by ``i``.
|
|
2561
|
+
|
|
2562
|
+
INPUT:
|
|
2563
|
+
|
|
2564
|
+
- ``i`` -- the index of an element of the basis of the domain of ``self``
|
|
2565
|
+
|
|
2566
|
+
EXAMPLES::
|
|
2567
|
+
|
|
2568
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename('X') # needs sage.modules
|
|
2569
|
+
sage: phi = End(X)(lambda x: 2*x) # needs sage.modules
|
|
2570
|
+
sage: phi._on_basis(3) # needs sage.modules
|
|
2571
|
+
2*B[3]
|
|
2572
|
+
"""
|
|
2573
|
+
return self(self.domain().monomial(i))
|
|
2574
|
+
|
|
2575
|
+
class CartesianProducts(CartesianProductsCategory):
|
|
2576
|
+
"""
|
|
2577
|
+
The category of modules with basis constructed by Cartesian products
|
|
2578
|
+
of modules with basis.
|
|
2579
|
+
"""
|
|
2580
|
+
@cached_method
|
|
2581
|
+
def extra_super_categories(self):
|
|
2582
|
+
"""
|
|
2583
|
+
EXAMPLES::
|
|
2584
|
+
|
|
2585
|
+
sage: ModulesWithBasis(QQ).CartesianProducts().extra_super_categories()
|
|
2586
|
+
[Category of vector spaces with basis over Rational Field]
|
|
2587
|
+
sage: ModulesWithBasis(QQ).CartesianProducts().super_categories()
|
|
2588
|
+
[Category of Cartesian products of modules with basis over Rational Field,
|
|
2589
|
+
Category of vector spaces with basis over Rational Field,
|
|
2590
|
+
Category of Cartesian products of vector spaces over Rational Field]
|
|
2591
|
+
"""
|
|
2592
|
+
return [self.base_category()]
|
|
2593
|
+
|
|
2594
|
+
class ParentMethods:
|
|
2595
|
+
|
|
2596
|
+
def _an_element_(self):
|
|
2597
|
+
"""
|
|
2598
|
+
EXAMPLES::
|
|
2599
|
+
|
|
2600
|
+
sage: # needs sage.combinat sage.groups sage.modules
|
|
2601
|
+
sage: A = AlgebrasWithBasis(QQ).example(); A
|
|
2602
|
+
An example of an algebra with basis:
|
|
2603
|
+
the free algebra on the generators ('a', 'b', 'c')
|
|
2604
|
+
over Rational Field
|
|
2605
|
+
sage: B = HopfAlgebrasWithBasis(QQ).example(); B
|
|
2606
|
+
An example of Hopf algebra with basis:
|
|
2607
|
+
the group algebra of the Dihedral group of order 6
|
|
2608
|
+
as a permutation group over Rational Field
|
|
2609
|
+
sage: A.an_element()
|
|
2610
|
+
B[word: ] + 2*B[word: a] + 3*B[word: b] + B[word: bab]
|
|
2611
|
+
sage: B.an_element()
|
|
2612
|
+
B[()] + B[(1,2)] + 3*B[(1,2,3)] + 2*B[(1,3,2)]
|
|
2613
|
+
sage: ABA = cartesian_product((A, B, A))
|
|
2614
|
+
sage: ABA.an_element() # indirect doctest
|
|
2615
|
+
2*B[(0, word: )] + 2*B[(0, word: a)] + 3*B[(0, word: b)]
|
|
2616
|
+
"""
|
|
2617
|
+
from .cartesian_product import cartesian_product
|
|
2618
|
+
return cartesian_product([module.an_element() for module in self.modules])
|
|
2619
|
+
|
|
2620
|
+
class TensorProducts(TensorProductsCategory):
|
|
2621
|
+
"""
|
|
2622
|
+
The category of modules with basis constructed by tensor product of
|
|
2623
|
+
modules with basis.
|
|
2624
|
+
"""
|
|
2625
|
+
@cached_method
|
|
2626
|
+
def extra_super_categories(self):
|
|
2627
|
+
"""
|
|
2628
|
+
EXAMPLES::
|
|
2629
|
+
|
|
2630
|
+
sage: ModulesWithBasis(QQ).TensorProducts().extra_super_categories()
|
|
2631
|
+
[Category of vector spaces with basis over Rational Field]
|
|
2632
|
+
sage: ModulesWithBasis(QQ).TensorProducts().super_categories()
|
|
2633
|
+
[Category of tensor products of modules with basis over Rational Field,
|
|
2634
|
+
Category of vector spaces with basis over Rational Field,
|
|
2635
|
+
Category of tensor products of vector spaces over Rational Field]
|
|
2636
|
+
"""
|
|
2637
|
+
return [self.base_category()]
|
|
2638
|
+
|
|
2639
|
+
class ParentMethods:
|
|
2640
|
+
"""
|
|
2641
|
+
Implement operations on tensor products of modules with basis.
|
|
2642
|
+
"""
|
|
2643
|
+
pass
|
|
2644
|
+
|
|
2645
|
+
class ElementMethods:
|
|
2646
|
+
"""
|
|
2647
|
+
Implement operations on elements of tensor products of modules
|
|
2648
|
+
with basis.
|
|
2649
|
+
"""
|
|
2650
|
+
|
|
2651
|
+
def apply_multilinear_morphism(self, f, codomain=None):
|
|
2652
|
+
r"""
|
|
2653
|
+
Return the result of applying the morphism induced by ``f``
|
|
2654
|
+
to ``self``.
|
|
2655
|
+
|
|
2656
|
+
INPUT:
|
|
2657
|
+
|
|
2658
|
+
- ``f`` -- a multilinear morphism from the component
|
|
2659
|
+
modules of the parent tensor product to any module
|
|
2660
|
+
|
|
2661
|
+
- ``codomain`` -- the codomain of ``f`` (optional)
|
|
2662
|
+
|
|
2663
|
+
By the universal property of the tensor product, ``f``
|
|
2664
|
+
induces a linear morphism from `self.parent()` to the
|
|
2665
|
+
target module. Returns the result of applying that
|
|
2666
|
+
morphism to ``self``.
|
|
2667
|
+
|
|
2668
|
+
The codomain is used for optimizations purposes
|
|
2669
|
+
only. If it's not provided, it's recovered by calling
|
|
2670
|
+
``f`` on the zero input.
|
|
2671
|
+
|
|
2672
|
+
EXAMPLES:
|
|
2673
|
+
|
|
2674
|
+
We start with simple (admittedly not so interesting)
|
|
2675
|
+
examples, with two modules `A` and `B`::
|
|
2676
|
+
|
|
2677
|
+
sage: # needs sage.modules
|
|
2678
|
+
sage: A = CombinatorialFreeModule(ZZ, [1,2], prefix='A')
|
|
2679
|
+
sage: A.rename('A')
|
|
2680
|
+
sage: B = CombinatorialFreeModule(ZZ, [3,4], prefix='B')
|
|
2681
|
+
sage: B.rename('B')
|
|
2682
|
+
|
|
2683
|
+
and `f` the bilinear morphism `(a,b) \mapsto b \otimes a`
|
|
2684
|
+
from `A \times B` to `B \otimes A`::
|
|
2685
|
+
|
|
2686
|
+
sage: def f(a, b):
|
|
2687
|
+
....: return tensor([b,a])
|
|
2688
|
+
|
|
2689
|
+
Now, calling applying `f` on `a \otimes b` returns the same
|
|
2690
|
+
as `f(a,b)`::
|
|
2691
|
+
|
|
2692
|
+
sage: # needs sage.modules
|
|
2693
|
+
sage: a = A.monomial(1) + 2 * A.monomial(2); a
|
|
2694
|
+
A[1] + 2*A[2]
|
|
2695
|
+
sage: b = B.monomial(3) - 2 * B.monomial(4); b
|
|
2696
|
+
B[3] - 2*B[4]
|
|
2697
|
+
sage: f(a, b)
|
|
2698
|
+
B[3] # A[1] + 2*B[3] # A[2] - 2*B[4] # A[1] - 4*B[4] # A[2]
|
|
2699
|
+
sage: tensor([a, b]).apply_multilinear_morphism(f)
|
|
2700
|
+
B[3] # A[1] + 2*B[3] # A[2] - 2*B[4] # A[1] - 4*B[4] # A[2]
|
|
2701
|
+
|
|
2702
|
+
`f` may be a bilinear morphism to any module over the
|
|
2703
|
+
base ring of `A` and `B`. Here the codomain is `\ZZ`::
|
|
2704
|
+
|
|
2705
|
+
sage: def f(a, b):
|
|
2706
|
+
....: return sum(a.coefficients(), 0) * sum(b.coefficients(), 0)
|
|
2707
|
+
sage: f(a, b) # needs sage.modules
|
|
2708
|
+
-3
|
|
2709
|
+
sage: tensor([a, b]).apply_multilinear_morphism(f) # needs sage.modules
|
|
2710
|
+
-3
|
|
2711
|
+
|
|
2712
|
+
Mind the `0` in the sums above; otherwise `f` would
|
|
2713
|
+
not return `0` in `\ZZ`::
|
|
2714
|
+
|
|
2715
|
+
sage: def f(a, b):
|
|
2716
|
+
....: return sum(a.coefficients()) * sum(b.coefficients())
|
|
2717
|
+
sage: type(f(A.zero(), B.zero())) # needs sage.modules
|
|
2718
|
+
<... 'int'>
|
|
2719
|
+
|
|
2720
|
+
Which would be wrong and break this method::
|
|
2721
|
+
|
|
2722
|
+
sage: tensor([a, b]).apply_multilinear_morphism(f) # needs sage.modules
|
|
2723
|
+
Traceback (most recent call last):
|
|
2724
|
+
...
|
|
2725
|
+
AttributeError: 'int' object has no attribute 'parent'...
|
|
2726
|
+
|
|
2727
|
+
Here we consider an example where the codomain is a
|
|
2728
|
+
module with basis with a different base ring::
|
|
2729
|
+
|
|
2730
|
+
sage: # needs sage.modules
|
|
2731
|
+
sage: C = CombinatorialFreeModule(QQ, [(1,3),(2,4)], prefix='C')
|
|
2732
|
+
sage: C.rename('C')
|
|
2733
|
+
sage: def f(a, b):
|
|
2734
|
+
....: return C.sum_of_terms([((1,3), QQ(a[1]*b[3])),
|
|
2735
|
+
....: ((2,4), QQ(a[2]*b[4]))])
|
|
2736
|
+
sage: f(a,b)
|
|
2737
|
+
C[(1, 3)] - 4*C[(2, 4)]
|
|
2738
|
+
sage: tensor([a, b]).apply_multilinear_morphism(f)
|
|
2739
|
+
C[(1, 3)] - 4*C[(2, 4)]
|
|
2740
|
+
|
|
2741
|
+
We conclude with a real life application, where we
|
|
2742
|
+
check that the antipode of the Hopf algebra of
|
|
2743
|
+
Symmetric functions on the Schur basis satisfies its
|
|
2744
|
+
defining formula::
|
|
2745
|
+
|
|
2746
|
+
sage: # needs lrcalc_python sage.combinat sage.modules
|
|
2747
|
+
sage: Sym = SymmetricFunctions(QQ)
|
|
2748
|
+
sage: s = Sym.schur()
|
|
2749
|
+
sage: def f(a, b): return a * b.antipode()
|
|
2750
|
+
sage: x = 4 * s.an_element(); x
|
|
2751
|
+
8*s[] + 8*s[1] + 12*s[2]
|
|
2752
|
+
sage: x.coproduct().apply_multilinear_morphism(f)
|
|
2753
|
+
8*s[]
|
|
2754
|
+
sage: x.coproduct().apply_multilinear_morphism(f) == x.counit()
|
|
2755
|
+
True
|
|
2756
|
+
|
|
2757
|
+
We recover the constant term of `x`, as desired.
|
|
2758
|
+
|
|
2759
|
+
.. TODO::
|
|
2760
|
+
|
|
2761
|
+
Extract a method to linearize a multilinear
|
|
2762
|
+
morphism, and delegate the work there.
|
|
2763
|
+
"""
|
|
2764
|
+
K = self.parent().base_ring()
|
|
2765
|
+
modules = self.parent()._sets
|
|
2766
|
+
if codomain is None:
|
|
2767
|
+
try:
|
|
2768
|
+
codomain = f.codomain()
|
|
2769
|
+
except AttributeError:
|
|
2770
|
+
codomain = f(*[module.zero() for module in modules]).parent()
|
|
2771
|
+
if codomain in ModulesWithBasis(K):
|
|
2772
|
+
return codomain.linear_combination((f(*[module.monomial(t)
|
|
2773
|
+
for module, t in zip(modules, m)]), c)
|
|
2774
|
+
for m, c in self.items())
|
|
2775
|
+
else:
|
|
2776
|
+
return sum((c * f(*[module.monomial(t)
|
|
2777
|
+
for module, t in zip(modules, m)])
|
|
2778
|
+
for m, c in self.items()),
|
|
2779
|
+
codomain.zero())
|
|
2780
|
+
|
|
2781
|
+
class DualObjects(DualObjectsCategory):
|
|
2782
|
+
|
|
2783
|
+
@cached_method
|
|
2784
|
+
def extra_super_categories(self):
|
|
2785
|
+
"""
|
|
2786
|
+
EXAMPLES::
|
|
2787
|
+
|
|
2788
|
+
sage: ModulesWithBasis(ZZ).DualObjects().extra_super_categories()
|
|
2789
|
+
[Category of modules over Integer Ring]
|
|
2790
|
+
sage: ModulesWithBasis(QQ).DualObjects().super_categories()
|
|
2791
|
+
[Category of duals of vector spaces over Rational Field,
|
|
2792
|
+
Category of duals of modules with basis over Rational Field]
|
|
2793
|
+
"""
|
|
2794
|
+
return [Modules(self.base_category().base_ring())]
|