passagemath-modules 10.6.31rc3__cp314-cp314-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.
Potentially problematic release.
This version of passagemath-modules might be problematic. Click here for more details.
- passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
- passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-503f0c35.3.29.so +0 -0
- sage/algebras/all__sagemath_modules.py +20 -0
- sage/algebras/catalog.py +148 -0
- sage/algebras/clifford_algebra.py +3107 -0
- sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/clifford_algebra_element.pxd +16 -0
- sage/algebras/clifford_algebra_element.pyx +997 -0
- sage/algebras/commutative_dga.py +4252 -0
- sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/exterior_algebra_groebner.pxd +55 -0
- sage/algebras/exterior_algebra_groebner.pyx +727 -0
- sage/algebras/finite_dimensional_algebras/all.py +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
- sage/algebras/finite_gca.py +528 -0
- sage/algebras/group_algebra.py +232 -0
- sage/algebras/lie_algebras/abelian.py +197 -0
- sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
- sage/algebras/lie_algebras/all.py +25 -0
- sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
- sage/algebras/lie_algebras/bch.py +177 -0
- sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
- sage/algebras/lie_algebras/bgg_resolution.py +232 -0
- sage/algebras/lie_algebras/center_uea.py +767 -0
- sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
- sage/algebras/lie_algebras/examples.py +683 -0
- sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
- sage/algebras/lie_algebras/heisenberg.py +820 -0
- sage/algebras/lie_algebras/lie_algebra.py +1562 -0
- sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
- sage/algebras/lie_algebras/morphism.py +661 -0
- sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
- sage/algebras/lie_algebras/onsager.py +1324 -0
- sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
- sage/algebras/lie_algebras/quotient.py +462 -0
- sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
- sage/algebras/lie_algebras/representation.py +1040 -0
- sage/algebras/lie_algebras/structure_coefficients.py +459 -0
- sage/algebras/lie_algebras/subalgebra.py +967 -0
- sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
- sage/algebras/lie_algebras/verma_module.py +1630 -0
- sage/algebras/lie_algebras/virasoro.py +1186 -0
- sage/algebras/octonion_algebra.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/octonion_algebra.pxd +20 -0
- sage/algebras/octonion_algebra.pyx +987 -0
- sage/algebras/orlik_solomon.py +907 -0
- sage/algebras/orlik_terao.py +779 -0
- sage/algebras/steenrod/all.py +7 -0
- sage/algebras/steenrod/steenrod_algebra.py +4258 -0
- sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
- sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
- sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
- sage/algebras/weyl_algebra.py +1126 -0
- sage/all__sagemath_modules.py +62 -0
- sage/calculus/all__sagemath_modules.py +19 -0
- sage/calculus/expr.py +205 -0
- sage/calculus/integration.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/riemann.pyx +1521 -0
- sage/calculus/test_sympy.py +201 -0
- sage/calculus/transforms/all.py +7 -0
- sage/calculus/transforms/dft.py +844 -0
- sage/calculus/transforms/dwt.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/dwt.pxd +7 -0
- sage/calculus/transforms/dwt.pyx +160 -0
- sage/calculus/transforms/fft.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/fft.pxd +12 -0
- sage/calculus/transforms/fft.pyx +487 -0
- sage/calculus/wester.py +662 -0
- sage/coding/abstract_code.py +1108 -0
- sage/coding/ag_code.py +868 -0
- sage/coding/ag_code_decoders.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/ag_code_decoders.pyx +2639 -0
- sage/coding/all.py +15 -0
- sage/coding/bch_code.py +494 -0
- sage/coding/binary_code.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/binary_code.pxd +124 -0
- sage/coding/binary_code.pyx +4139 -0
- sage/coding/bounds_catalog.py +43 -0
- sage/coding/channel.py +819 -0
- sage/coding/channels_catalog.py +29 -0
- sage/coding/code_bounds.py +755 -0
- sage/coding/code_constructions.py +804 -0
- sage/coding/codes_catalog.py +111 -0
- sage/coding/cyclic_code.py +1329 -0
- sage/coding/databases.py +316 -0
- sage/coding/decoder.py +373 -0
- sage/coding/decoders_catalog.py +88 -0
- sage/coding/delsarte_bounds.py +709 -0
- sage/coding/encoder.py +390 -0
- sage/coding/encoders_catalog.py +64 -0
- sage/coding/extended_code.py +468 -0
- sage/coding/gabidulin_code.py +1058 -0
- sage/coding/golay_code.py +404 -0
- sage/coding/goppa_code.py +441 -0
- sage/coding/grs_code.py +2371 -0
- sage/coding/guava.py +107 -0
- sage/coding/guruswami_sudan/all.py +1 -0
- sage/coding/guruswami_sudan/gs_decoder.py +897 -0
- sage/coding/guruswami_sudan/interpolation.py +409 -0
- sage/coding/guruswami_sudan/utils.py +176 -0
- sage/coding/hamming_code.py +176 -0
- sage/coding/information_set_decoder.py +1032 -0
- sage/coding/kasami_codes.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/kasami_codes.pyx +351 -0
- sage/coding/linear_code.py +3067 -0
- sage/coding/linear_code_no_metric.py +1354 -0
- sage/coding/linear_rank_metric.py +961 -0
- sage/coding/parity_check_code.py +353 -0
- sage/coding/punctured_code.py +719 -0
- sage/coding/reed_muller_code.py +999 -0
- sage/coding/self_dual_codes.py +942 -0
- sage/coding/source_coding/all.py +2 -0
- sage/coding/source_coding/huffman.py +553 -0
- sage/coding/subfield_subcode.py +423 -0
- sage/coding/two_weight_db.py +399 -0
- sage/combinat/all__sagemath_modules.py +7 -0
- sage/combinat/cartesian_product.py +347 -0
- sage/combinat/family.py +11 -0
- sage/combinat/free_module.py +1977 -0
- sage/combinat/root_system/all.py +147 -0
- sage/combinat/root_system/ambient_space.py +527 -0
- sage/combinat/root_system/associahedron.py +471 -0
- sage/combinat/root_system/braid_move_calculator.py +143 -0
- sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-musl.so +0 -0
- sage/combinat/root_system/braid_orbit.pyx +144 -0
- sage/combinat/root_system/branching_rules.py +2301 -0
- sage/combinat/root_system/cartan_matrix.py +1245 -0
- sage/combinat/root_system/cartan_type.py +3069 -0
- sage/combinat/root_system/coxeter_group.py +162 -0
- sage/combinat/root_system/coxeter_matrix.py +1261 -0
- sage/combinat/root_system/coxeter_type.py +681 -0
- sage/combinat/root_system/dynkin_diagram.py +900 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
- sage/combinat/root_system/fundamental_group.py +795 -0
- sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
- sage/combinat/root_system/integrable_representations.py +1227 -0
- sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
- sage/combinat/root_system/pieri_factors.py +1147 -0
- sage/combinat/root_system/plot.py +1615 -0
- sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
- sage/combinat/root_system/root_lattice_realizations.py +4628 -0
- sage/combinat/root_system/root_space.py +487 -0
- sage/combinat/root_system/root_system.py +882 -0
- sage/combinat/root_system/type_A.py +348 -0
- sage/combinat/root_system/type_A_affine.py +227 -0
- sage/combinat/root_system/type_A_infinity.py +241 -0
- sage/combinat/root_system/type_B.py +347 -0
- sage/combinat/root_system/type_BC_affine.py +287 -0
- sage/combinat/root_system/type_B_affine.py +216 -0
- sage/combinat/root_system/type_C.py +317 -0
- sage/combinat/root_system/type_C_affine.py +188 -0
- sage/combinat/root_system/type_D.py +357 -0
- sage/combinat/root_system/type_D_affine.py +208 -0
- sage/combinat/root_system/type_E.py +641 -0
- sage/combinat/root_system/type_E_affine.py +231 -0
- sage/combinat/root_system/type_F.py +387 -0
- sage/combinat/root_system/type_F_affine.py +137 -0
- sage/combinat/root_system/type_G.py +293 -0
- sage/combinat/root_system/type_G_affine.py +132 -0
- sage/combinat/root_system/type_H.py +105 -0
- sage/combinat/root_system/type_I.py +110 -0
- sage/combinat/root_system/type_Q.py +150 -0
- sage/combinat/root_system/type_affine.py +509 -0
- sage/combinat/root_system/type_dual.py +704 -0
- sage/combinat/root_system/type_folded.py +301 -0
- sage/combinat/root_system/type_marked.py +748 -0
- sage/combinat/root_system/type_reducible.py +601 -0
- sage/combinat/root_system/type_relabel.py +730 -0
- sage/combinat/root_system/type_super_A.py +837 -0
- sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
- sage/combinat/root_system/weight_space.py +639 -0
- sage/combinat/root_system/weyl_characters.py +2238 -0
- sage/crypto/__init__.py +4 -0
- sage/crypto/all.py +28 -0
- sage/crypto/block_cipher/all.py +7 -0
- sage/crypto/block_cipher/des.py +1065 -0
- sage/crypto/block_cipher/miniaes.py +2171 -0
- sage/crypto/block_cipher/present.py +909 -0
- sage/crypto/block_cipher/sdes.py +1527 -0
- sage/crypto/boolean_function.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/boolean_function.pxd +10 -0
- sage/crypto/boolean_function.pyx +1487 -0
- sage/crypto/cipher.py +78 -0
- sage/crypto/classical.py +3668 -0
- sage/crypto/classical_cipher.py +569 -0
- sage/crypto/cryptosystem.py +387 -0
- sage/crypto/key_exchange/all.py +7 -0
- sage/crypto/key_exchange/catalog.py +24 -0
- sage/crypto/key_exchange/diffie_hellman.py +323 -0
- sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
- sage/crypto/lattice.py +312 -0
- sage/crypto/lfsr.py +295 -0
- sage/crypto/lwe.py +840 -0
- sage/crypto/mq/__init__.py +4 -0
- sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
- sage/crypto/mq/rijndael_gf.py +2345 -0
- sage/crypto/mq/sbox.py +7 -0
- sage/crypto/mq/sr.py +3344 -0
- sage/crypto/public_key/all.py +5 -0
- sage/crypto/public_key/blum_goldwasser.py +776 -0
- sage/crypto/sbox.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/sbox.pyx +2090 -0
- sage/crypto/sboxes.py +2090 -0
- sage/crypto/stream.py +390 -0
- sage/crypto/stream_cipher.py +297 -0
- sage/crypto/util.py +519 -0
- sage/ext/all__sagemath_modules.py +1 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_modules.py +2 -0
- sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +30 -0
- sage/ext/interpreters/wrapper_cc.pyx +252 -0
- sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +26 -0
- sage/ext/interpreters/wrapper_cdf.pyx +245 -0
- sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +23 -0
- sage/ext/interpreters/wrapper_rdf.pyx +221 -0
- sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +28 -0
- sage/ext/interpreters/wrapper_rr.pyx +335 -0
- sage/geometry/all__sagemath_modules.py +5 -0
- sage/geometry/toric_lattice.py +1745 -0
- sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/geometry/toric_lattice_element.pyx +432 -0
- sage/groups/abelian_gps/abelian_group.py +1925 -0
- sage/groups/abelian_gps/abelian_group_element.py +164 -0
- sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
- sage/groups/abelian_gps/dual_abelian_group.py +421 -0
- sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
- sage/groups/abelian_gps/element_base.py +341 -0
- sage/groups/abelian_gps/values.py +488 -0
- sage/groups/additive_abelian/additive_abelian_group.py +476 -0
- sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
- sage/groups/additive_abelian/all.py +4 -0
- sage/groups/additive_abelian/qmodnz.py +231 -0
- sage/groups/additive_abelian/qmodnz_element.py +349 -0
- sage/groups/affine_gps/affine_group.py +535 -0
- sage/groups/affine_gps/all.py +1 -0
- sage/groups/affine_gps/catalog.py +17 -0
- sage/groups/affine_gps/euclidean_group.py +246 -0
- sage/groups/affine_gps/group_element.py +562 -0
- sage/groups/all__sagemath_modules.py +12 -0
- sage/groups/galois_group.py +479 -0
- sage/groups/matrix_gps/all.py +4 -0
- sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
- sage/groups/matrix_gps/catalog.py +26 -0
- sage/groups/matrix_gps/coxeter_group.py +927 -0
- sage/groups/matrix_gps/finitely_generated.py +487 -0
- sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/matrix_gps/group_element.pxd +11 -0
- sage/groups/matrix_gps/group_element.pyx +431 -0
- sage/groups/matrix_gps/linear.py +440 -0
- sage/groups/matrix_gps/matrix_group.py +617 -0
- sage/groups/matrix_gps/named_group.py +296 -0
- sage/groups/matrix_gps/orthogonal.py +544 -0
- sage/groups/matrix_gps/symplectic.py +251 -0
- sage/groups/matrix_gps/unitary.py +436 -0
- sage/groups/misc_gps/all__sagemath_modules.py +1 -0
- sage/groups/misc_gps/argument_groups.py +1905 -0
- sage/groups/misc_gps/imaginary_groups.py +479 -0
- sage/groups/perm_gps/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
- sage/homology/algebraic_topological_model.py +595 -0
- sage/homology/all.py +2 -0
- sage/homology/all__sagemath_modules.py +8 -0
- sage/homology/chain_complex.py +2148 -0
- sage/homology/chain_complex_homspace.py +165 -0
- sage/homology/chain_complex_morphism.py +629 -0
- sage/homology/chain_homotopy.py +604 -0
- sage/homology/chains.py +653 -0
- sage/homology/free_resolution.py +923 -0
- sage/homology/graded_resolution.py +567 -0
- sage/homology/hochschild_complex.py +756 -0
- sage/homology/homology_group.py +188 -0
- sage/homology/homology_morphism.py +422 -0
- sage/homology/homology_vector_space_with_basis.py +1454 -0
- sage/homology/koszul_complex.py +169 -0
- sage/homology/matrix_utils.py +205 -0
- sage/libs/all__sagemath_modules.py +1 -0
- sage/libs/gsl/__init__.py +1 -0
- sage/libs/gsl/airy.pxd +56 -0
- sage/libs/gsl/all.pxd +66 -0
- sage/libs/gsl/array.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/gsl/array.pxd +5 -0
- sage/libs/gsl/array.pyx +102 -0
- sage/libs/gsl/bessel.pxd +208 -0
- sage/libs/gsl/blas.pxd +116 -0
- sage/libs/gsl/blas_types.pxd +34 -0
- sage/libs/gsl/block.pxd +52 -0
- sage/libs/gsl/chebyshev.pxd +37 -0
- sage/libs/gsl/clausen.pxd +12 -0
- sage/libs/gsl/combination.pxd +47 -0
- sage/libs/gsl/complex.pxd +151 -0
- sage/libs/gsl/coulomb.pxd +30 -0
- sage/libs/gsl/coupling.pxd +21 -0
- sage/libs/gsl/dawson.pxd +12 -0
- sage/libs/gsl/debye.pxd +24 -0
- sage/libs/gsl/dilog.pxd +14 -0
- sage/libs/gsl/eigen.pxd +46 -0
- sage/libs/gsl/elementary.pxd +12 -0
- sage/libs/gsl/ellint.pxd +48 -0
- sage/libs/gsl/elljac.pxd +8 -0
- sage/libs/gsl/erf.pxd +32 -0
- sage/libs/gsl/errno.pxd +26 -0
- sage/libs/gsl/exp.pxd +44 -0
- sage/libs/gsl/expint.pxd +44 -0
- sage/libs/gsl/fermi_dirac.pxd +44 -0
- sage/libs/gsl/fft.pxd +121 -0
- sage/libs/gsl/fit.pxd +50 -0
- sage/libs/gsl/gamma.pxd +94 -0
- sage/libs/gsl/gegenbauer.pxd +26 -0
- sage/libs/gsl/histogram.pxd +176 -0
- sage/libs/gsl/hyperg.pxd +52 -0
- sage/libs/gsl/integration.pxd +69 -0
- sage/libs/gsl/interp.pxd +109 -0
- sage/libs/gsl/laguerre.pxd +24 -0
- sage/libs/gsl/lambert.pxd +16 -0
- sage/libs/gsl/legendre.pxd +90 -0
- sage/libs/gsl/linalg.pxd +185 -0
- sage/libs/gsl/log.pxd +26 -0
- sage/libs/gsl/math.pxd +43 -0
- sage/libs/gsl/matrix.pxd +143 -0
- sage/libs/gsl/matrix_complex.pxd +130 -0
- sage/libs/gsl/min.pxd +67 -0
- sage/libs/gsl/monte.pxd +56 -0
- sage/libs/gsl/ntuple.pxd +32 -0
- sage/libs/gsl/odeiv.pxd +70 -0
- sage/libs/gsl/permutation.pxd +78 -0
- sage/libs/gsl/poly.pxd +40 -0
- sage/libs/gsl/pow_int.pxd +12 -0
- sage/libs/gsl/psi.pxd +28 -0
- sage/libs/gsl/qrng.pxd +29 -0
- sage/libs/gsl/random.pxd +257 -0
- sage/libs/gsl/rng.pxd +100 -0
- sage/libs/gsl/roots.pxd +72 -0
- sage/libs/gsl/sort.pxd +36 -0
- sage/libs/gsl/statistics.pxd +59 -0
- sage/libs/gsl/sum.pxd +55 -0
- sage/libs/gsl/synchrotron.pxd +16 -0
- sage/libs/gsl/transport.pxd +24 -0
- sage/libs/gsl/trig.pxd +58 -0
- sage/libs/gsl/types.pxd +137 -0
- sage/libs/gsl/vector.pxd +101 -0
- sage/libs/gsl/vector_complex.pxd +83 -0
- sage/libs/gsl/wavelet.pxd +49 -0
- sage/libs/gsl/zeta.pxd +28 -0
- sage/libs/mpc/__init__.pxd +114 -0
- sage/libs/mpc/types.pxd +28 -0
- sage/libs/mpfr/__init__.pxd +299 -0
- sage/libs/mpfr/types.pxd +26 -0
- sage/libs/mpmath/__init__.py +1 -0
- sage/libs/mpmath/all.py +27 -0
- sage/libs/mpmath/all__sagemath_modules.py +1 -0
- sage/libs/mpmath/utils.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/action.pxd +26 -0
- sage/matrix/action.pyx +596 -0
- sage/matrix/all.py +9 -0
- sage/matrix/args.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/args.pxd +144 -0
- sage/matrix/args.pyx +1668 -0
- sage/matrix/benchmark.py +1258 -0
- sage/matrix/berlekamp_massey.py +95 -0
- sage/matrix/compute_J_ideal.py +926 -0
- sage/matrix/constructor.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_cdv.pxd +4 -0
- sage/matrix/matrix_cdv.pyx +93 -0
- sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_complex_double_dense.pxd +5 -0
- sage/matrix/matrix_complex_double_dense.pyx +98 -0
- sage/matrix/matrix_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_dense.pxd +5 -0
- sage/matrix/matrix_dense.pyx +343 -0
- sage/matrix/matrix_domain_dense.pxd +5 -0
- sage/matrix/matrix_domain_sparse.pxd +5 -0
- sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_dense.pxd +7 -0
- sage/matrix/matrix_double_dense.pyx +3906 -0
- sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_sparse.pxd +6 -0
- sage/matrix/matrix_double_sparse.pyx +248 -0
- sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_dense.pxd +7 -0
- sage/matrix/matrix_generic_dense.pyx +354 -0
- sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_sparse.pxd +7 -0
- sage/matrix/matrix_generic_sparse.pyx +461 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
- sage/matrix/matrix_misc.py +313 -0
- sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_dense.pxd +14 -0
- sage/matrix/matrix_numpy_dense.pyx +450 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
- sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
- sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_polynomial_dense.pxd +5 -0
- sage/matrix/matrix_polynomial_dense.pyx +5341 -0
- sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_real_double_dense.pxd +7 -0
- sage/matrix/matrix_real_double_dense.pyx +122 -0
- sage/matrix/matrix_space.py +2848 -0
- sage/matrix/matrix_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_sparse.pxd +5 -0
- sage/matrix/matrix_sparse.pyx +1222 -0
- sage/matrix/matrix_window.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_window.pxd +37 -0
- sage/matrix/matrix_window.pyx +242 -0
- sage/matrix/misc_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/misc_mpfr.pyx +80 -0
- sage/matrix/operation_table.py +1182 -0
- sage/matrix/special.py +3666 -0
- sage/matrix/strassen.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/strassen.pyx +851 -0
- sage/matrix/symplectic_basis.py +541 -0
- sage/matrix/template.pxd +6 -0
- sage/matrix/tests.py +71 -0
- sage/matroids/advanced.py +77 -0
- sage/matroids/all.py +13 -0
- sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_exchange_matroid.pxd +96 -0
- sage/matroids/basis_exchange_matroid.pyx +2344 -0
- sage/matroids/basis_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_matroid.pxd +45 -0
- sage/matroids/basis_matroid.pyx +1217 -0
- sage/matroids/catalog.py +44 -0
- sage/matroids/chow_ring.py +473 -0
- sage/matroids/chow_ring_ideal.py +849 -0
- sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuit_closures_matroid.pxd +16 -0
- sage/matroids/circuit_closures_matroid.pyx +559 -0
- sage/matroids/circuits_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuits_matroid.pxd +38 -0
- sage/matroids/circuits_matroid.pyx +947 -0
- sage/matroids/constructor.py +1086 -0
- sage/matroids/database_collections.py +365 -0
- sage/matroids/database_matroids.py +5338 -0
- sage/matroids/dual_matroid.py +583 -0
- sage/matroids/extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/flats_matroid.pxd +28 -0
- sage/matroids/flats_matroid.pyx +715 -0
- sage/matroids/gammoid.py +600 -0
- sage/matroids/graphic_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/graphic_matroid.pxd +39 -0
- sage/matroids/graphic_matroid.pyx +2024 -0
- sage/matroids/lean_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/lean_matrix.pxd +126 -0
- sage/matroids/lean_matrix.pyx +3667 -0
- sage/matroids/linear_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/matroid.pxd +243 -0
- sage/matroids/matroid.pyx +8759 -0
- sage/matroids/matroids_catalog.py +190 -0
- sage/matroids/matroids_plot_helpers.py +890 -0
- sage/matroids/minor_matroid.py +480 -0
- sage/matroids/minorfix.h +9 -0
- sage/matroids/named_matroids.py +5 -0
- sage/matroids/rank_matroid.py +268 -0
- sage/matroids/set_system.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/set_system.pxd +38 -0
- sage/matroids/set_system.pyx +800 -0
- sage/matroids/transversal_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/transversal_matroid.pxd +14 -0
- sage/matroids/transversal_matroid.pyx +893 -0
- sage/matroids/union_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/unpickling.pyx +843 -0
- sage/matroids/utilities.py +809 -0
- sage/misc/all__sagemath_modules.py +20 -0
- sage/misc/c3.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/c3.pyx +238 -0
- sage/misc/compat.py +87 -0
- sage/misc/element_with_label.py +173 -0
- sage/misc/func_persist.py +79 -0
- sage/misc/pickle_old.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/pickle_old.pyx +19 -0
- sage/misc/proof.py +7 -0
- sage/misc/replace_dot_all.py +472 -0
- sage/misc/sagedoc_conf.py +168 -0
- sage/misc/sphinxify.py +167 -0
- sage/misc/test_class_pickling.py +85 -0
- sage/modules/all.py +42 -0
- sage/modules/complex_double_vector.py +25 -0
- sage/modules/diamond_cutting.py +380 -0
- sage/modules/fg_pid/all.py +1 -0
- sage/modules/fg_pid/fgp_element.py +456 -0
- sage/modules/fg_pid/fgp_module.py +2091 -0
- sage/modules/fg_pid/fgp_morphism.py +550 -0
- sage/modules/filtered_vector_space.py +1271 -0
- sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/finite_submodule_iter.pxd +27 -0
- sage/modules/finite_submodule_iter.pyx +452 -0
- sage/modules/fp_graded/all.py +1 -0
- sage/modules/fp_graded/element.py +346 -0
- sage/modules/fp_graded/free_element.py +298 -0
- sage/modules/fp_graded/free_homspace.py +53 -0
- sage/modules/fp_graded/free_module.py +1060 -0
- sage/modules/fp_graded/free_morphism.py +217 -0
- sage/modules/fp_graded/homspace.py +563 -0
- sage/modules/fp_graded/module.py +1340 -0
- sage/modules/fp_graded/morphism.py +1990 -0
- sage/modules/fp_graded/steenrod/all.py +1 -0
- sage/modules/fp_graded/steenrod/homspace.py +65 -0
- sage/modules/fp_graded/steenrod/module.py +477 -0
- sage/modules/fp_graded/steenrod/morphism.py +404 -0
- sage/modules/fp_graded/steenrod/profile.py +241 -0
- sage/modules/free_module.py +8447 -0
- sage/modules/free_module_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/free_module_element.pxd +22 -0
- sage/modules/free_module_element.pyx +5445 -0
- sage/modules/free_module_homspace.py +369 -0
- sage/modules/free_module_integer.py +896 -0
- sage/modules/free_module_morphism.py +823 -0
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module.py +1706 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
- sage/modules/matrix_morphism.py +1745 -0
- sage/modules/misc.py +103 -0
- sage/modules/module_functors.py +192 -0
- sage/modules/multi_filtered_vector_space.py +719 -0
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +699 -0
- sage/modules/real_double_vector.py +22 -0
- sage/modules/submodule.py +255 -0
- sage/modules/tensor_operations.py +567 -0
- sage/modules/torsion_quadratic_module.py +1352 -0
- sage/modules/tutorial_free_modules.py +248 -0
- sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_complex_double_dense.pxd +6 -0
- sage/modules/vector_complex_double_dense.pyx +117 -0
- sage/modules/vector_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_double_dense.pxd +6 -0
- sage/modules/vector_double_dense.pyx +604 -0
- sage/modules/vector_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_dense.pxd +15 -0
- sage/modules/vector_integer_dense.pyx +361 -0
- sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_sparse.pxd +29 -0
- sage/modules/vector_integer_sparse.pyx +406 -0
- sage/modules/vector_modn_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_dense.pxd +12 -0
- sage/modules/vector_modn_dense.pyx +394 -0
- sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_sparse.pxd +21 -0
- sage/modules/vector_modn_sparse.pyx +298 -0
- sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_dense.pxd +15 -0
- sage/modules/vector_numpy_dense.pyx +304 -0
- sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_integer_dense.pxd +7 -0
- sage/modules/vector_numpy_integer_dense.pyx +54 -0
- sage/modules/vector_rational_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_dense.pxd +15 -0
- sage/modules/vector_rational_dense.pyx +387 -0
- sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_sparse.pxd +30 -0
- sage/modules/vector_rational_sparse.pyx +413 -0
- sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_real_double_dense.pxd +6 -0
- sage/modules/vector_real_double_dense.pyx +126 -0
- sage/modules/vector_space_homspace.py +430 -0
- sage/modules/vector_space_morphism.py +989 -0
- sage/modules/with_basis/all.py +15 -0
- sage/modules/with_basis/cell_module.py +494 -0
- sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/with_basis/indexed_element.pxd +13 -0
- sage/modules/with_basis/indexed_element.pyx +1058 -0
- sage/modules/with_basis/invariant.py +1075 -0
- sage/modules/with_basis/morphism.py +1636 -0
- sage/modules/with_basis/representation.py +2939 -0
- sage/modules/with_basis/subquotient.py +685 -0
- sage/numerical/all__sagemath_modules.py +6 -0
- sage/numerical/gauss_legendre.cpython-314-aarch64-linux-musl.so +0 -0
- sage/numerical/gauss_legendre.pyx +381 -0
- sage/numerical/optimize.py +910 -0
- sage/probability/all.py +10 -0
- sage/probability/probability_distribution.cpython-314-aarch64-linux-musl.so +0 -0
- sage/probability/probability_distribution.pyx +1242 -0
- sage/probability/random_variable.py +411 -0
- sage/quadratic_forms/all.py +4 -0
- sage/quadratic_forms/all__sagemath_modules.py +15 -0
- sage/quadratic_forms/binary_qf.py +2042 -0
- sage/quadratic_forms/bqf_class_group.py +748 -0
- sage/quadratic_forms/constructions.py +93 -0
- sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/count_local_2.pyx +365 -0
- sage/quadratic_forms/extras.py +195 -0
- sage/quadratic_forms/quadratic_form.py +1753 -0
- sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
- sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
- sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
- sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
- sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
- sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
- sage/quadratic_forms/quadratic_form__theta.py +352 -0
- sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
- sage/quadratic_forms/random_quadraticform.py +209 -0
- sage/quadratic_forms/ternary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/ternary.pyx +1154 -0
- sage/quadratic_forms/ternary_qf.py +2027 -0
- sage/rings/all__sagemath_modules.py +28 -0
- sage/rings/asymptotic/all__sagemath_modules.py +1 -0
- sage/rings/asymptotic/misc.py +1252 -0
- sage/rings/cc.py +4 -0
- sage/rings/cfinite_sequence.py +1306 -0
- sage/rings/complex_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_conversion.pxd +8 -0
- sage/rings/complex_conversion.pyx +23 -0
- sage/rings/complex_double.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_double.pxd +21 -0
- sage/rings/complex_double.pyx +2654 -0
- sage/rings/complex_mpc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpc.pxd +21 -0
- sage/rings/complex_mpc.pyx +2576 -0
- sage/rings/complex_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpfr.pxd +18 -0
- sage/rings/complex_mpfr.pyx +3602 -0
- sage/rings/derivation.py +2334 -0
- sage/rings/finite_rings/all__sagemath_modules.py +1 -0
- sage/rings/finite_rings/maps_finite_field.py +191 -0
- sage/rings/function_field/all__sagemath_modules.py +8 -0
- sage/rings/function_field/derivations.py +102 -0
- sage/rings/function_field/derivations_rational.py +132 -0
- sage/rings/function_field/differential.py +853 -0
- sage/rings/function_field/divisor.py +1107 -0
- sage/rings/function_field/drinfeld_modules/action.py +199 -0
- sage/rings/function_field/drinfeld_modules/all.py +1 -0
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
- sage/rings/function_field/drinfeld_modules/homset.py +420 -0
- sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
- sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +935 -0
- sage/rings/invariants/all.py +4 -0
- sage/rings/invariants/invariant_theory.py +4597 -0
- sage/rings/invariants/reconstruction.py +395 -0
- sage/rings/polynomial/all__sagemath_modules.py +17 -0
- sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
- sage/rings/polynomial/ore_function_element.py +952 -0
- sage/rings/polynomial/ore_function_field.py +1028 -0
- sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
- sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
- sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
- sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
- sage/rings/polynomial/skew_polynomial_ring.py +908 -0
- sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_double_element_gsl.pxd +8 -0
- sage/rings/real_double_element_gsl.pyx +794 -0
- sage/rings/real_field.py +58 -0
- sage/rings/real_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_mpfr.pxd +29 -0
- sage/rings/real_mpfr.pyx +6122 -0
- sage/rings/ring_extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension.pxd +42 -0
- sage/rings/ring_extension.pyx +2779 -0
- sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_conversion.pxd +16 -0
- sage/rings/ring_extension_conversion.pyx +462 -0
- sage/rings/ring_extension_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_element.pxd +21 -0
- sage/rings/ring_extension_element.pyx +1635 -0
- sage/rings/ring_extension_homset.py +64 -0
- sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_morphism.pxd +35 -0
- sage/rings/ring_extension_morphism.pyx +920 -0
- sage/schemes/all__sagemath_modules.py +1 -0
- sage/schemes/projective/all__sagemath_modules.py +1 -0
- sage/schemes/projective/coherent_sheaf.py +300 -0
- sage/schemes/projective/cohomology.py +510 -0
- sage/stats/all.py +15 -0
- sage/stats/basic_stats.py +489 -0
- sage/stats/distributions/all.py +7 -0
- sage/stats/distributions/catalog.py +34 -0
- sage/stats/distributions/dgs.h +50 -0
- sage/stats/distributions/dgs.pxd +111 -0
- sage/stats/distributions/dgs_bern.h +400 -0
- sage/stats/distributions/dgs_gauss.h +614 -0
- sage/stats/distributions/dgs_misc.h +104 -0
- sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
- sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
- sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
- sage/stats/hmm/all.py +15 -0
- sage/stats/hmm/chmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/distributions.pxd +29 -0
- sage/stats/hmm/distributions.pyx +531 -0
- sage/stats/hmm/hmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/hmm.pxd +17 -0
- sage/stats/hmm/hmm.pyx +1388 -0
- sage/stats/hmm/util.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/intlist.pxd +14 -0
- sage/stats/intlist.pyx +588 -0
- sage/stats/r.py +49 -0
- sage/stats/time_series.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/time_series.pxd +6 -0
- sage/stats/time_series.pyx +2546 -0
- sage/tensor/all.py +2 -0
- sage/tensor/modules/all.py +8 -0
- sage/tensor/modules/alternating_contr_tensor.py +761 -0
- sage/tensor/modules/comp.py +5598 -0
- sage/tensor/modules/ext_pow_free_module.py +824 -0
- sage/tensor/modules/finite_rank_free_module.py +3589 -0
- sage/tensor/modules/format_utilities.py +333 -0
- sage/tensor/modules/free_module_alt_form.py +858 -0
- sage/tensor/modules/free_module_automorphism.py +1207 -0
- sage/tensor/modules/free_module_basis.py +1074 -0
- sage/tensor/modules/free_module_element.py +284 -0
- sage/tensor/modules/free_module_homset.py +652 -0
- sage/tensor/modules/free_module_linear_group.py +564 -0
- sage/tensor/modules/free_module_morphism.py +1581 -0
- sage/tensor/modules/free_module_tensor.py +3289 -0
- sage/tensor/modules/reflexive_module.py +386 -0
- sage/tensor/modules/tensor_free_module.py +780 -0
- sage/tensor/modules/tensor_free_submodule.py +538 -0
- sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
- sage/tensor/modules/tensor_with_indices.py +1043 -0
|
@@ -0,0 +1,1977 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
"""
|
|
3
|
+
Free modules
|
|
4
|
+
"""
|
|
5
|
+
# ****************************************************************************
|
|
6
|
+
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
|
|
7
|
+
# 2007-2009 Nicolas M. Thiery <nthiery at users.sf.net>
|
|
8
|
+
# 2010 Christian Stump <christian.stump@univie.ac.at>
|
|
9
|
+
#
|
|
10
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
11
|
+
# https://www.gnu.org/licenses/
|
|
12
|
+
# ****************************************************************************
|
|
13
|
+
|
|
14
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
15
|
+
from sage.structure.parent import Parent
|
|
16
|
+
from sage.structure.indexed_generators import IndexedGenerators, parse_indices_names
|
|
17
|
+
from sage.modules.module import Module
|
|
18
|
+
from sage.rings.integer import Integer
|
|
19
|
+
from sage.structure.element import parent
|
|
20
|
+
from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
|
|
21
|
+
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
|
|
22
|
+
from sage.combinat.cartesian_product import CartesianProduct_iters
|
|
23
|
+
from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
|
|
24
|
+
from sage.misc.cachefunc import cached_method
|
|
25
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
26
|
+
from sage.categories.morphism import SetMorphism
|
|
27
|
+
from sage.categories.category import Category
|
|
28
|
+
from sage.categories.sets_cat import Sets
|
|
29
|
+
from sage.categories.modules_with_basis import ModulesWithBasis
|
|
30
|
+
from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis
|
|
31
|
+
from sage.categories.tensor import tensor
|
|
32
|
+
import sage.data_structures.blas_dict as blas
|
|
33
|
+
from sage.typeset.ascii_art import AsciiArt, ascii_art
|
|
34
|
+
from sage.typeset.unicode_art import UnicodeArt, unicode_art
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class CombinatorialFreeModule(UniqueRepresentation, Module, IndexedGenerators):
|
|
38
|
+
r"""
|
|
39
|
+
Class for free modules with a named basis.
|
|
40
|
+
|
|
41
|
+
INPUT:
|
|
42
|
+
|
|
43
|
+
- ``R`` -- base ring
|
|
44
|
+
|
|
45
|
+
- ``basis_keys`` -- list; tuple, family, set, etc. defining the
|
|
46
|
+
indexing set for the basis of this module
|
|
47
|
+
|
|
48
|
+
- ``element_class`` -- the class of which elements of this module
|
|
49
|
+
should be instances (default: None, in which case the
|
|
50
|
+
elements are instances of
|
|
51
|
+
:class:`~sage.modules.with_basis.indexed_element.IndexedFreeModuleElement`)
|
|
52
|
+
|
|
53
|
+
- ``category`` -- the category in which this module lies (optional,
|
|
54
|
+
default None, in which case use the "category of modules with
|
|
55
|
+
basis" over the base ring ``R``); this should be a subcategory
|
|
56
|
+
of :class:`ModulesWithBasis`
|
|
57
|
+
|
|
58
|
+
For the options controlling the printing of elements, see
|
|
59
|
+
:class:`~sage.structure.indexed_generators.IndexedGenerators`.
|
|
60
|
+
|
|
61
|
+
.. NOTE::
|
|
62
|
+
|
|
63
|
+
These print options may also be accessed and modified using the
|
|
64
|
+
:meth:`print_options` method, after the module has been defined.
|
|
65
|
+
|
|
66
|
+
EXAMPLES:
|
|
67
|
+
|
|
68
|
+
We construct a free module whose basis is indexed by the letters a, b, c::
|
|
69
|
+
|
|
70
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
71
|
+
sage: F
|
|
72
|
+
Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
73
|
+
|
|
74
|
+
Its basis is a family, indexed by a, b, c::
|
|
75
|
+
|
|
76
|
+
sage: e = F.basis()
|
|
77
|
+
sage: e
|
|
78
|
+
Finite family {'a': B['a'], 'b': B['b'], 'c': B['c']}
|
|
79
|
+
|
|
80
|
+
::
|
|
81
|
+
|
|
82
|
+
sage: [x for x in e]
|
|
83
|
+
[B['a'], B['b'], B['c']]
|
|
84
|
+
sage: [k for k in e.keys()]
|
|
85
|
+
['a', 'b', 'c']
|
|
86
|
+
|
|
87
|
+
Let us construct some elements, and compute with them::
|
|
88
|
+
|
|
89
|
+
sage: e['a']
|
|
90
|
+
B['a']
|
|
91
|
+
sage: 2*e['a']
|
|
92
|
+
2*B['a']
|
|
93
|
+
sage: e['a'] + 3*e['b']
|
|
94
|
+
B['a'] + 3*B['b']
|
|
95
|
+
|
|
96
|
+
Some uses of
|
|
97
|
+
:meth:`sage.categories.commutative_additive_semigroups.CommutativeAdditiveSemigroups.ParentMethods.summation`
|
|
98
|
+
and :meth:`sum`::
|
|
99
|
+
|
|
100
|
+
sage: F = CombinatorialFreeModule(QQ, [1,2,3,4])
|
|
101
|
+
sage: F.summation(F.monomial(1), F.monomial(3))
|
|
102
|
+
B[1] + B[3]
|
|
103
|
+
|
|
104
|
+
sage: F = CombinatorialFreeModule(QQ, [1,2,3,4])
|
|
105
|
+
sage: F.sum(F.monomial(i) for i in [1,2,3])
|
|
106
|
+
B[1] + B[2] + B[3]
|
|
107
|
+
|
|
108
|
+
Note that free modules with a given basis and parameters are unique::
|
|
109
|
+
|
|
110
|
+
sage: F1 = CombinatorialFreeModule(QQ, (1,2,3,4))
|
|
111
|
+
sage: F1 is F
|
|
112
|
+
True
|
|
113
|
+
|
|
114
|
+
The identity of the constructed free module depends on the order of the
|
|
115
|
+
basis and on the other parameters, like the prefix. Note that :class:`CombinatorialFreeModule` is
|
|
116
|
+
a :class:`~sage.structure.unique_representation.UniqueRepresentation`. Hence,
|
|
117
|
+
two combinatorial free modules evaluate equal if and only if they are
|
|
118
|
+
identical::
|
|
119
|
+
|
|
120
|
+
sage: F1 = CombinatorialFreeModule(QQ, (1,2,3,4))
|
|
121
|
+
sage: F1 is F
|
|
122
|
+
True
|
|
123
|
+
sage: F1 = CombinatorialFreeModule(QQ, [4,3,2,1])
|
|
124
|
+
sage: F1 == F
|
|
125
|
+
False
|
|
126
|
+
sage: F2 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F')
|
|
127
|
+
sage: F2 == F
|
|
128
|
+
False
|
|
129
|
+
|
|
130
|
+
Because of this, if you create a free module with certain parameters and
|
|
131
|
+
then modify its prefix or other print options, this affects all modules
|
|
132
|
+
which were defined using the same parameters.
|
|
133
|
+
::
|
|
134
|
+
|
|
135
|
+
sage: F2.print_options(prefix='x')
|
|
136
|
+
sage: F2.prefix()
|
|
137
|
+
'x'
|
|
138
|
+
sage: F3 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F')
|
|
139
|
+
sage: F3 is F2 # F3 was defined just like F2
|
|
140
|
+
True
|
|
141
|
+
sage: F3.prefix()
|
|
142
|
+
'x'
|
|
143
|
+
sage: F4 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F', bracket=True)
|
|
144
|
+
sage: F4 == F2 # F4 was NOT defined just like F2
|
|
145
|
+
False
|
|
146
|
+
sage: F4.prefix()
|
|
147
|
+
'F'
|
|
148
|
+
|
|
149
|
+
sage: F2.print_options(prefix='F') #reset for following doctests
|
|
150
|
+
|
|
151
|
+
The constructed module is in the category of modules with basis
|
|
152
|
+
over the base ring::
|
|
153
|
+
|
|
154
|
+
sage: CombinatorialFreeModule(QQ, Partitions()).category() # needs sage.combinat
|
|
155
|
+
Category of vector spaces with basis over Rational Field
|
|
156
|
+
|
|
157
|
+
If furthermore the index set is finite (i.e. in the category
|
|
158
|
+
``Sets().Finite()``), then the module is declared as being finite
|
|
159
|
+
dimensional::
|
|
160
|
+
|
|
161
|
+
sage: CombinatorialFreeModule(QQ, [1,2,3,4]).category()
|
|
162
|
+
Category of finite dimensional vector spaces with basis over Rational Field
|
|
163
|
+
sage: CombinatorialFreeModule(QQ, Partitions(3), # needs sage.combinat
|
|
164
|
+
....: category=Algebras(QQ).WithBasis()).category()
|
|
165
|
+
Category of finite dimensional algebras with basis over Rational Field
|
|
166
|
+
|
|
167
|
+
See :mod:`sage.categories.examples.algebras_with_basis` and
|
|
168
|
+
:mod:`sage.categories.examples.hopf_algebras_with_basis` for
|
|
169
|
+
illustrations of the use of the ``category`` keyword, and see
|
|
170
|
+
:class:`sage.combinat.root_system.weight_space.WeightSpace` for an
|
|
171
|
+
example of the use of ``element_class``.
|
|
172
|
+
|
|
173
|
+
Customizing print and LaTeX representations of elements::
|
|
174
|
+
|
|
175
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b'], prefix='x')
|
|
176
|
+
sage: original_print_options = F.print_options()
|
|
177
|
+
sage: sorted(original_print_options.items())
|
|
178
|
+
[('bracket', None),
|
|
179
|
+
('iterate_key', False),
|
|
180
|
+
('latex_bracket', False), ('latex_names', None),
|
|
181
|
+
('latex_prefix', None), ('latex_scalar_mult', None),
|
|
182
|
+
('names', None), ('prefix', 'x'),
|
|
183
|
+
('scalar_mult', '*'),
|
|
184
|
+
('sorting_key', <function ...<lambda> at ...>),
|
|
185
|
+
('sorting_reverse', False), ('string_quotes', True),
|
|
186
|
+
('tensor_symbol', None)]
|
|
187
|
+
|
|
188
|
+
sage: e = F.basis()
|
|
189
|
+
sage: e['a'] - 3 * e['b']
|
|
190
|
+
x['a'] - 3*x['b']
|
|
191
|
+
|
|
192
|
+
sage: F.print_options(prefix='x', scalar_mult=' ', bracket='{')
|
|
193
|
+
sage: e['a'] - 3 * e['b']
|
|
194
|
+
x{'a'} - 3 x{'b'}
|
|
195
|
+
sage: latex(e['a'] - 3 * e['b'])
|
|
196
|
+
x_{a} - 3 x_{b}
|
|
197
|
+
|
|
198
|
+
sage: F.print_options(latex_prefix='y')
|
|
199
|
+
sage: latex(e['a'] - 3 * e['b'])
|
|
200
|
+
y_{a} - 3 y_{b}
|
|
201
|
+
|
|
202
|
+
sage: F.print_options(sorting_reverse=True)
|
|
203
|
+
sage: e['a'] - 3 * e['b']
|
|
204
|
+
-3 x{'b'} + x{'a'}
|
|
205
|
+
sage: F.print_options(**original_print_options) # reset print options
|
|
206
|
+
|
|
207
|
+
sage: F = CombinatorialFreeModule(QQ, [(1,2), (3,4)])
|
|
208
|
+
sage: e = F.basis()
|
|
209
|
+
sage: e[(1,2)] - 3 * e[(3,4)]
|
|
210
|
+
B[(1, 2)] - 3*B[(3, 4)]
|
|
211
|
+
|
|
212
|
+
sage: F.print_options(bracket=['_{', '}'])
|
|
213
|
+
sage: e[(1,2)] - 3 * e[(3,4)]
|
|
214
|
+
B_{(1, 2)} - 3*B_{(3, 4)}
|
|
215
|
+
|
|
216
|
+
sage: F.print_options(prefix='', bracket=False)
|
|
217
|
+
sage: e[(1,2)] - 3 * e[(3,4)]
|
|
218
|
+
(1, 2) - 3*(3, 4)
|
|
219
|
+
|
|
220
|
+
TESTS:
|
|
221
|
+
|
|
222
|
+
Before :issue:`14054`, combinatorial free modules violated the unique
|
|
223
|
+
parent condition. That caused a problem. The tensor product construction
|
|
224
|
+
involves maps, but maps check that their domain and the parent of a
|
|
225
|
+
to-be-mapped element are identical (not just equal). However, the tensor
|
|
226
|
+
product was cached by a :class:`~sage.misc.cachefunc.cached_method`, which
|
|
227
|
+
involves comparison by equality (not identity). Hence, the last line of
|
|
228
|
+
the following example used to fail with an assertion error::
|
|
229
|
+
|
|
230
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2,3], prefix='F')
|
|
231
|
+
sage: G = CombinatorialFreeModule(ZZ, [1,2,3,4], prefix='G')
|
|
232
|
+
sage: f = F.monomial(1) + 2 * F.monomial(2)
|
|
233
|
+
sage: g = 2*G.monomial(3) + G.monomial(4)
|
|
234
|
+
sage: tensor([f, g])
|
|
235
|
+
2*F[1] # G[3] + F[1] # G[4] + 4*F[2] # G[3] + 2*F[2] # G[4]
|
|
236
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2,3], prefix='x')
|
|
237
|
+
sage: G = CombinatorialFreeModule(ZZ, [1,2,3,4], prefix='y')
|
|
238
|
+
sage: f = F.monomial(1) + 2 * F.monomial(2)
|
|
239
|
+
sage: g = 2*G.monomial(3) + G.monomial(4)
|
|
240
|
+
sage: tensor([f, g])
|
|
241
|
+
2*x[1] # y[3] + x[1] # y[4] + 4*x[2] # y[3] + 2*x[2] # y[4]
|
|
242
|
+
|
|
243
|
+
We check that we can use the shorthand ``C.<a,b,...> = ...``::
|
|
244
|
+
|
|
245
|
+
sage: C.<x,y,z> = CombinatorialFreeModule(QQ)
|
|
246
|
+
sage: C
|
|
247
|
+
Free module generated by {'x', 'y', 'z'} over Rational Field
|
|
248
|
+
sage: a = x - y + 4*z; a
|
|
249
|
+
x - y + 4*z
|
|
250
|
+
sage: a.parent() is C
|
|
251
|
+
True
|
|
252
|
+
|
|
253
|
+
TESTS::
|
|
254
|
+
|
|
255
|
+
sage: # needs sage.combinat
|
|
256
|
+
sage: XQ = SchubertPolynomialRing(QQ)
|
|
257
|
+
sage: XZ = SchubertPolynomialRing(ZZ)
|
|
258
|
+
sage: XQ == XZ
|
|
259
|
+
False
|
|
260
|
+
sage: XQ == XQ
|
|
261
|
+
True
|
|
262
|
+
|
|
263
|
+
We check that issue :issue:`28681` is fixed::
|
|
264
|
+
|
|
265
|
+
sage: F = CombinatorialFreeModule(ZZ, ZZ); F.rename('F')
|
|
266
|
+
sage: FF = tensor((F,F))
|
|
267
|
+
sage: cartesian_product((FF,FF))
|
|
268
|
+
F # F (+) F # F
|
|
269
|
+
"""
|
|
270
|
+
|
|
271
|
+
@staticmethod
|
|
272
|
+
def __classcall_private__(cls, base_ring, basis_keys=None, category=None,
|
|
273
|
+
prefix=None, names=None, **keywords):
|
|
274
|
+
"""
|
|
275
|
+
TESTS::
|
|
276
|
+
|
|
277
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
278
|
+
sage: G = CombinatorialFreeModule(QQ, ('a','b','c'))
|
|
279
|
+
sage: F is G
|
|
280
|
+
True
|
|
281
|
+
|
|
282
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'], latex_bracket=['LEFT', 'RIGHT'])
|
|
283
|
+
sage: F.print_options()['latex_bracket']
|
|
284
|
+
('LEFT', 'RIGHT')
|
|
285
|
+
|
|
286
|
+
sage: F is G
|
|
287
|
+
False
|
|
288
|
+
|
|
289
|
+
We check that the category is properly straightened::
|
|
290
|
+
|
|
291
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b'])
|
|
292
|
+
sage: F1 = CombinatorialFreeModule(QQ, ['a','b'], category=ModulesWithBasis(QQ))
|
|
293
|
+
sage: F2 = CombinatorialFreeModule(QQ, ['a','b'], category=[ModulesWithBasis(QQ)])
|
|
294
|
+
sage: F3 = CombinatorialFreeModule(QQ, ['a','b'], category=(ModulesWithBasis(QQ),))
|
|
295
|
+
sage: F4 = CombinatorialFreeModule(QQ, ['a','b'], category=(ModulesWithBasis(QQ),CommutativeAdditiveSemigroups()))
|
|
296
|
+
sage: F5 = CombinatorialFreeModule(QQ, ['a','b'], category=(ModulesWithBasis(QQ),Category.join((LeftModules(QQ), RightModules(QQ)))))
|
|
297
|
+
sage: F6 = CombinatorialFreeModule(QQ, ['a','b'], category=ModulesWithBasis(QQ).FiniteDimensional())
|
|
298
|
+
sage: F1 is F, F2 is F, F3 is F, F4 is F, F5 is F, F6 is F
|
|
299
|
+
(True, True, True, True, True, True)
|
|
300
|
+
|
|
301
|
+
sage: G = CombinatorialFreeModule(QQ, ['a','b'], category=AlgebrasWithBasis(QQ))
|
|
302
|
+
sage: F is G
|
|
303
|
+
False
|
|
304
|
+
"""
|
|
305
|
+
if isinstance(basis_keys, range):
|
|
306
|
+
basis_keys = tuple(basis_keys)
|
|
307
|
+
if isinstance(basis_keys, (list, tuple)):
|
|
308
|
+
basis_keys = FiniteEnumeratedSet(basis_keys)
|
|
309
|
+
category = ModulesWithBasis(base_ring).or_subcategory(category)
|
|
310
|
+
if basis_keys in Sets().Finite():
|
|
311
|
+
category = category.FiniteDimensional()
|
|
312
|
+
# bracket or latex_bracket might be lists, so convert
|
|
313
|
+
# them to tuples so that they're hashable.
|
|
314
|
+
bracket = keywords.get('bracket', None)
|
|
315
|
+
if isinstance(bracket, list):
|
|
316
|
+
keywords['bracket'] = tuple(bracket)
|
|
317
|
+
latex_bracket = keywords.get('latex_bracket', None)
|
|
318
|
+
if isinstance(latex_bracket, list):
|
|
319
|
+
keywords['latex_bracket'] = tuple(latex_bracket)
|
|
320
|
+
|
|
321
|
+
names, basis_keys, prefix = parse_indices_names(names, basis_keys, prefix, keywords)
|
|
322
|
+
if prefix is None:
|
|
323
|
+
prefix = "B"
|
|
324
|
+
|
|
325
|
+
if keywords.get('latex_names', None) is not None:
|
|
326
|
+
latex_names = keywords['latex_names']
|
|
327
|
+
if isinstance(latex_names, str):
|
|
328
|
+
latex_names = latex_names.split(',')
|
|
329
|
+
latex_names = tuple(latex_names)
|
|
330
|
+
keywords['latex_names'] = latex_names
|
|
331
|
+
|
|
332
|
+
return super().__classcall__(cls,
|
|
333
|
+
base_ring, basis_keys, category=category, prefix=prefix, names=names,
|
|
334
|
+
**keywords)
|
|
335
|
+
|
|
336
|
+
Element = IndexedFreeModuleElement
|
|
337
|
+
|
|
338
|
+
@lazy_attribute
|
|
339
|
+
def element_class(self):
|
|
340
|
+
"""
|
|
341
|
+
The (default) class for the elements of this parent.
|
|
342
|
+
|
|
343
|
+
Overrides :meth:`Parent.element_class` to force the
|
|
344
|
+
construction of Python class. This is currently needed to
|
|
345
|
+
inherit really all the features from categories, and in
|
|
346
|
+
particular the initialization of ``_mul_`` in
|
|
347
|
+
:meth:`Magmas.ParentMethods.__init_extra__`.
|
|
348
|
+
|
|
349
|
+
EXAMPLES::
|
|
350
|
+
|
|
351
|
+
sage: # needs sage.combinat
|
|
352
|
+
sage: A = Algebras(QQ).WithBasis().example(); A
|
|
353
|
+
An example of an algebra with basis:
|
|
354
|
+
the free algebra on the generators ('a', 'b', 'c') over Rational Field
|
|
355
|
+
sage: A.element_class.mro()
|
|
356
|
+
[<class 'sage.categories.examples.algebras_with_basis.FreeAlgebra_with_category.element_class'>,
|
|
357
|
+
<class 'sage.modules.with_basis.indexed_element.IndexedFreeModuleElement'>,
|
|
358
|
+
...]
|
|
359
|
+
sage: a,b,c = A.algebra_generators()
|
|
360
|
+
sage: a * b
|
|
361
|
+
B[word: ab]
|
|
362
|
+
|
|
363
|
+
TESTS::
|
|
364
|
+
|
|
365
|
+
sage: A.__class__.element_class.__module__ # needs sage.combinat
|
|
366
|
+
'sage.combinat.free_module'
|
|
367
|
+
"""
|
|
368
|
+
return self.__make_element_class__(self.Element,
|
|
369
|
+
name="%s.element_class" % self.__class__.__name__,
|
|
370
|
+
module=self.__class__.__module__,
|
|
371
|
+
inherit=True)
|
|
372
|
+
|
|
373
|
+
def __init__(self, R, basis_keys=None, element_class=None, category=None,
|
|
374
|
+
prefix=None, names=None, **kwds):
|
|
375
|
+
r"""
|
|
376
|
+
TESTS::
|
|
377
|
+
|
|
378
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
379
|
+
|
|
380
|
+
sage: F.category()
|
|
381
|
+
Category of finite dimensional vector spaces with basis over Rational Field
|
|
382
|
+
|
|
383
|
+
One may specify the category this module belongs to::
|
|
384
|
+
|
|
385
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'], category=AlgebrasWithBasis(QQ))
|
|
386
|
+
sage: F.category()
|
|
387
|
+
Category of finite dimensional algebras with basis over Rational Field
|
|
388
|
+
|
|
389
|
+
sage: F = CombinatorialFreeModule(GF(3), ['a','b','c'], # needs sage.rings.finite_rings
|
|
390
|
+
....: category=(Modules(GF(3)).WithBasis(), Semigroups()))
|
|
391
|
+
sage: F.category() # needs sage.rings.finite_rings
|
|
392
|
+
Join of Category of finite semigroups
|
|
393
|
+
and Category of finite dimensional vector spaces with basis over Finite Field of size 3
|
|
394
|
+
|
|
395
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'], category=FiniteDimensionalModulesWithBasis(QQ))
|
|
396
|
+
sage: F.basis()
|
|
397
|
+
Finite family {'a': B['a'], 'b': B['b'], 'c': B['c']}
|
|
398
|
+
sage: F.category()
|
|
399
|
+
Category of finite dimensional vector spaces with basis over Rational Field
|
|
400
|
+
|
|
401
|
+
sage: TestSuite(F).run()
|
|
402
|
+
|
|
403
|
+
TESTS:
|
|
404
|
+
|
|
405
|
+
Regression test for :issue:`10127`: ``self._indices`` needs to be
|
|
406
|
+
set early enough, in case the initialization of the categories
|
|
407
|
+
use ``self.basis().keys()``. This occurred on several occasions
|
|
408
|
+
in non trivial constructions. In the following example,
|
|
409
|
+
:class:`AlgebrasWithBasis` constructs ``Homset(self,self)`` to
|
|
410
|
+
extend by bilinearity method ``product_on_basis``, which in
|
|
411
|
+
turn triggers ``self._repr_()``::
|
|
412
|
+
|
|
413
|
+
sage: class MyAlgebra(CombinatorialFreeModule):
|
|
414
|
+
....: def _repr_(self):
|
|
415
|
+
....: return "MyAlgebra on %s" % (self.basis().keys())
|
|
416
|
+
....: def product_on_basis(self, i, j):
|
|
417
|
+
....: pass
|
|
418
|
+
sage: MyAlgebra(ZZ, ZZ, category=AlgebrasWithBasis(QQ))
|
|
419
|
+
MyAlgebra on Integer Ring
|
|
420
|
+
|
|
421
|
+
A simpler example would be welcome!
|
|
422
|
+
|
|
423
|
+
We check that unknown options are caught::
|
|
424
|
+
|
|
425
|
+
sage: CombinatorialFreeModule(ZZ, [1,2,3], keyy=2)
|
|
426
|
+
Traceback (most recent call last):
|
|
427
|
+
...
|
|
428
|
+
ValueError: keyy is not a valid print option.
|
|
429
|
+
"""
|
|
430
|
+
# Make sure R is a ring with unit element
|
|
431
|
+
from sage.categories.rings import Rings
|
|
432
|
+
if R not in Rings():
|
|
433
|
+
raise TypeError("argument R must be a ring")
|
|
434
|
+
|
|
435
|
+
if element_class is not None:
|
|
436
|
+
self.Element = element_class
|
|
437
|
+
|
|
438
|
+
# The following is to ensure that basis keys is indeed a parent.
|
|
439
|
+
# tuple/list are converted to FiniteEnumeratedSet and set/frozenset to
|
|
440
|
+
# Set
|
|
441
|
+
# (e.g. root systems passes lists)
|
|
442
|
+
basis_keys = Sets()(basis_keys, enumerated_set=True)
|
|
443
|
+
|
|
444
|
+
# This is needed for the Cartesian product
|
|
445
|
+
# TODO: Remove this duplication from __classcall_private__
|
|
446
|
+
names, basis_keys, prefix = parse_indices_names(names, basis_keys, prefix, kwds)
|
|
447
|
+
if prefix is None:
|
|
448
|
+
prefix = "B"
|
|
449
|
+
|
|
450
|
+
# ignore the optional 'key' since it only affects CachedRepresentation
|
|
451
|
+
kwds.pop('key', None)
|
|
452
|
+
if 'monomial_key' in kwds:
|
|
453
|
+
kwds['sorting_key'] = kwds.pop('monomial_key')
|
|
454
|
+
if 'monomial_reverse' in kwds:
|
|
455
|
+
kwds['sorting_reverse'] = kwds.pop('monomial_reverse')
|
|
456
|
+
IndexedGenerators.__init__(self, basis_keys, prefix, names=names, **kwds)
|
|
457
|
+
|
|
458
|
+
if category is None:
|
|
459
|
+
category = ModulesWithBasis(R)
|
|
460
|
+
elif isinstance(category, tuple):
|
|
461
|
+
category = Category.join(category)
|
|
462
|
+
if basis_keys in Sets().Finite():
|
|
463
|
+
category = category.FiniteDimensional()
|
|
464
|
+
|
|
465
|
+
Parent.__init__(self, base=R, category=category, names=names)
|
|
466
|
+
|
|
467
|
+
self._order = None
|
|
468
|
+
|
|
469
|
+
def construction(self):
|
|
470
|
+
"""
|
|
471
|
+
The construction functor and base ring for ``self``.
|
|
472
|
+
|
|
473
|
+
EXAMPLES::
|
|
474
|
+
|
|
475
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'], category=AlgebrasWithBasis(QQ))
|
|
476
|
+
sage: F.construction()
|
|
477
|
+
(VectorFunctor, Rational Field)
|
|
478
|
+
"""
|
|
479
|
+
# Try to take it from the category
|
|
480
|
+
c = super().construction()
|
|
481
|
+
if c is not None:
|
|
482
|
+
return c
|
|
483
|
+
if self.__class__.__base__ != CombinatorialFreeModule:
|
|
484
|
+
# The construction is not suitable for subclasses
|
|
485
|
+
return None
|
|
486
|
+
from sage.categories.pushout import VectorFunctor
|
|
487
|
+
return VectorFunctor(None, True, None, with_basis='standard',
|
|
488
|
+
basis_keys=self.basis().keys()), self.base_ring()
|
|
489
|
+
|
|
490
|
+
def change_ring(self, R):
|
|
491
|
+
r"""
|
|
492
|
+
Return the base change of ``self`` to `R`.
|
|
493
|
+
|
|
494
|
+
EXAMPLES::
|
|
495
|
+
|
|
496
|
+
sage: F = CombinatorialFreeModule(ZZ, ['a','b','c']); F
|
|
497
|
+
Free module generated by {'a', 'b', 'c'} over Integer Ring
|
|
498
|
+
sage: F_QQ = F.change_ring(QQ); F_QQ
|
|
499
|
+
Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
500
|
+
sage: F_QQ.change_ring(ZZ) == F
|
|
501
|
+
True
|
|
502
|
+
|
|
503
|
+
sage: T = F.tensor(F); T
|
|
504
|
+
Free module generated by {'a', 'b', 'c'} over Integer Ring
|
|
505
|
+
# Free module generated by {'a', 'b', 'c'} over Integer Ring
|
|
506
|
+
sage: T.change_ring(QQ)
|
|
507
|
+
Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
508
|
+
# Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
509
|
+
|
|
510
|
+
sage: G = CombinatorialFreeModule(ZZ, ['x','y']); G
|
|
511
|
+
Free module generated by {'x', 'y'} over Integer Ring
|
|
512
|
+
sage: T = F.cartesian_product(G); T
|
|
513
|
+
Free module generated by {'a', 'b', 'c'} over Integer Ring
|
|
514
|
+
(+) Free module generated by {'x', 'y'} over Integer Ring
|
|
515
|
+
sage: T.change_ring(QQ)
|
|
516
|
+
Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
517
|
+
(+) Free module generated by {'x', 'y'} over Rational Field
|
|
518
|
+
"""
|
|
519
|
+
if R is self.base_ring():
|
|
520
|
+
return self
|
|
521
|
+
construction = self.construction()
|
|
522
|
+
if construction is not None:
|
|
523
|
+
functor, args = construction
|
|
524
|
+
from sage.categories.pushout import VectorFunctor
|
|
525
|
+
if isinstance(functor, VectorFunctor):
|
|
526
|
+
return functor(R)
|
|
527
|
+
from sage.categories.tensor import TensorProductFunctor
|
|
528
|
+
from sage.categories.cartesian_product import CartesianProductFunctor
|
|
529
|
+
if isinstance(functor, (TensorProductFunctor, CartesianProductFunctor)):
|
|
530
|
+
return functor([f.change_ring(R) for f in args])
|
|
531
|
+
raise NotImplementedError('the method change_ring() has not yet been implemented')
|
|
532
|
+
|
|
533
|
+
# For backwards compatibility
|
|
534
|
+
_repr_term = IndexedGenerators._repr_generator
|
|
535
|
+
_latex_term = IndexedGenerators._latex_generator
|
|
536
|
+
|
|
537
|
+
def _ascii_art_term(self, m):
|
|
538
|
+
r"""
|
|
539
|
+
Return an ascii art representation of the term indexed by ``m``.
|
|
540
|
+
|
|
541
|
+
TESTS::
|
|
542
|
+
|
|
543
|
+
sage: R = NonCommutativeSymmetricFunctions(QQ).R() # needs sage.combinat
|
|
544
|
+
sage: ascii_art(R.one()) # indirect doctest # needs sage.combinat
|
|
545
|
+
1
|
|
546
|
+
"""
|
|
547
|
+
try:
|
|
548
|
+
if m == self.one_basis():
|
|
549
|
+
return AsciiArt(["1"])
|
|
550
|
+
except Exception:
|
|
551
|
+
pass
|
|
552
|
+
return IndexedGenerators._ascii_art_generator(self, m)
|
|
553
|
+
|
|
554
|
+
def _unicode_art_term(self, m):
|
|
555
|
+
r"""
|
|
556
|
+
Return an unicode art representation of the term indexed by ``m``.
|
|
557
|
+
|
|
558
|
+
TESTS::
|
|
559
|
+
|
|
560
|
+
sage: R = NonCommutativeSymmetricFunctions(QQ).R() # needs sage.combinat
|
|
561
|
+
sage: unicode_art(R.one()) # indirect doctest # needs sage.combinat
|
|
562
|
+
1
|
|
563
|
+
"""
|
|
564
|
+
try:
|
|
565
|
+
if m == self.one_basis():
|
|
566
|
+
return UnicodeArt(["1"])
|
|
567
|
+
except Exception:
|
|
568
|
+
pass
|
|
569
|
+
return IndexedGenerators._unicode_art_generator(self, m)
|
|
570
|
+
|
|
571
|
+
# mostly for backward compatibility
|
|
572
|
+
@lazy_attribute
|
|
573
|
+
def _element_class(self):
|
|
574
|
+
"""
|
|
575
|
+
TESTS::
|
|
576
|
+
|
|
577
|
+
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
|
|
578
|
+
sage: F._element_class
|
|
579
|
+
<class 'sage.combinat.free_module.CombinatorialFreeModule_with_category.element_class'>
|
|
580
|
+
"""
|
|
581
|
+
return self.element_class
|
|
582
|
+
|
|
583
|
+
def _an_element_(self):
|
|
584
|
+
"""
|
|
585
|
+
EXAMPLES::
|
|
586
|
+
|
|
587
|
+
sage: CombinatorialFreeModule(QQ, ("a", "b", "c")).an_element()
|
|
588
|
+
2*B['a'] + 2*B['b'] + 3*B['c']
|
|
589
|
+
sage: CombinatorialFreeModule(QQ, ("a", "b", "c"))._an_element_()
|
|
590
|
+
2*B['a'] + 2*B['b'] + 3*B['c']
|
|
591
|
+
sage: CombinatorialFreeModule(QQ, ()).an_element()
|
|
592
|
+
0
|
|
593
|
+
sage: CombinatorialFreeModule(QQ, ZZ).an_element()
|
|
594
|
+
3*B[-1] + B[0] + 3*B[1]
|
|
595
|
+
sage: CombinatorialFreeModule(QQ, RR).an_element()
|
|
596
|
+
B[1.00000000000000]
|
|
597
|
+
"""
|
|
598
|
+
# Try a couple heuristics to build a not completely trivial
|
|
599
|
+
# element, while handling cases where R.an_element is not
|
|
600
|
+
# implemented, or R has no iterator, or R has few elements.
|
|
601
|
+
x = self.zero()
|
|
602
|
+
I = self.basis().keys()
|
|
603
|
+
R = self.base_ring()
|
|
604
|
+
try:
|
|
605
|
+
x = x + self.monomial(I.an_element())
|
|
606
|
+
except Exception:
|
|
607
|
+
pass
|
|
608
|
+
try:
|
|
609
|
+
g = iter(self.basis().keys())
|
|
610
|
+
for c in range(1, 4):
|
|
611
|
+
x = x + self.term(next(g), R(c))
|
|
612
|
+
except Exception:
|
|
613
|
+
pass
|
|
614
|
+
return x
|
|
615
|
+
|
|
616
|
+
# What semantic do we want for containment?
|
|
617
|
+
# Accepting anything that can be coerced is not reasonable, especially
|
|
618
|
+
# if we allow coercion from the enumerated set.
|
|
619
|
+
# Accepting anything that can be converted is an option, but that would
|
|
620
|
+
# be expensive. So far, x in self if x.parent() == self
|
|
621
|
+
|
|
622
|
+
def __contains__(self, x):
|
|
623
|
+
"""
|
|
624
|
+
TESTS::
|
|
625
|
+
|
|
626
|
+
sage: F = CombinatorialFreeModule(QQ,["a", "b"])
|
|
627
|
+
sage: G = CombinatorialFreeModule(ZZ,["a", "b"])
|
|
628
|
+
sage: F.monomial("a") in F
|
|
629
|
+
True
|
|
630
|
+
sage: G.monomial("a") in F
|
|
631
|
+
False
|
|
632
|
+
sage: "a" in F
|
|
633
|
+
False
|
|
634
|
+
sage: 5/3 in F
|
|
635
|
+
False
|
|
636
|
+
"""
|
|
637
|
+
return parent(x) == self # is self?
|
|
638
|
+
|
|
639
|
+
def _element_constructor_(self, x):
|
|
640
|
+
"""
|
|
641
|
+
Convert ``x`` into ``self``.
|
|
642
|
+
|
|
643
|
+
EXAMPLES::
|
|
644
|
+
|
|
645
|
+
sage: F = CombinatorialFreeModule(QQ, ["a", "b"])
|
|
646
|
+
sage: F(F.monomial("a")) # indirect doctest
|
|
647
|
+
B['a']
|
|
648
|
+
|
|
649
|
+
Do not rely on the following feature which may be removed in the future::
|
|
650
|
+
|
|
651
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ,3) # needs sage.combinat
|
|
652
|
+
sage: QS3([2,3,1]) # indirect doctest # needs sage.combinat
|
|
653
|
+
[2, 3, 1]
|
|
654
|
+
|
|
655
|
+
instead, use::
|
|
656
|
+
|
|
657
|
+
sage: P = QS3.basis().keys() # needs sage.combinat
|
|
658
|
+
sage: QS3.monomial(P([2,3,1])) # indirect doctest # needs sage.combinat
|
|
659
|
+
[2, 3, 1]
|
|
660
|
+
|
|
661
|
+
or::
|
|
662
|
+
|
|
663
|
+
sage: B = QS3.basis() # needs sage.combinat
|
|
664
|
+
sage: B[P([2,3,1])] # needs sage.combinat
|
|
665
|
+
[2, 3, 1]
|
|
666
|
+
|
|
667
|
+
TODO: The symmetric group algebra (and in general,
|
|
668
|
+
combinatorial free modules on word-like object could instead
|
|
669
|
+
provide an appropriate short-hand syntax QS3[2,3,1]).
|
|
670
|
+
|
|
671
|
+
Rationale: this conversion is ambiguous in situations like::
|
|
672
|
+
|
|
673
|
+
sage: F = CombinatorialFreeModule(QQ,[0,1])
|
|
674
|
+
|
|
675
|
+
Is ``0`` the zero of the base ring, or the index of a basis
|
|
676
|
+
element? I.e. should the result be ``0`` or ``B[0]``?
|
|
677
|
+
|
|
678
|
+
sage: F = CombinatorialFreeModule(QQ,[0,1])
|
|
679
|
+
sage: F(0) # this feature may eventually disappear
|
|
680
|
+
0
|
|
681
|
+
sage: F(1)
|
|
682
|
+
Traceback (most recent call last):
|
|
683
|
+
...
|
|
684
|
+
TypeError: do not know how to make x (= 1) an element of Free module generated by ... over Rational Field
|
|
685
|
+
|
|
686
|
+
It is preferable not to rely either on the above, and instead, use::
|
|
687
|
+
|
|
688
|
+
sage: F.zero()
|
|
689
|
+
0
|
|
690
|
+
|
|
691
|
+
Note that, on the other hand, conversions from the ground ring
|
|
692
|
+
are systematically defined (and mathematically meaningful) for
|
|
693
|
+
algebras.
|
|
694
|
+
|
|
695
|
+
A coercion between free modules with the same indices exists
|
|
696
|
+
whenever a coercion map is defined between their base rings::
|
|
697
|
+
|
|
698
|
+
sage: F = CombinatorialFreeModule(ZZ, ["a", "b"]); F.rename('F')
|
|
699
|
+
sage: G = CombinatorialFreeModule(QQ, ["a", "b"]); G.rename('G')
|
|
700
|
+
sage: G(F.monomial("a"))
|
|
701
|
+
B['a']
|
|
702
|
+
sage: G(-3*F.monomial("a"))
|
|
703
|
+
-3*B['a']
|
|
704
|
+
|
|
705
|
+
Otherwise, there is no conversion between distinct free modules::
|
|
706
|
+
|
|
707
|
+
sage: H = CombinatorialFreeModule(ZZ, ["a", "b", "c"]); H.rename('H')
|
|
708
|
+
sage: H(F.monomial("a"))
|
|
709
|
+
Traceback (most recent call last):
|
|
710
|
+
...
|
|
711
|
+
TypeError: do not know how to make x (= B['a']) an element of self (=H)
|
|
712
|
+
|
|
713
|
+
Here is a real life example illustrating that this yielded
|
|
714
|
+
mathematically wrong results::
|
|
715
|
+
|
|
716
|
+
sage: # needs sage.combinat
|
|
717
|
+
sage: S = SymmetricFunctions(QQ)
|
|
718
|
+
sage: s = S.s(); p = S.p()
|
|
719
|
+
sage: ss = tensor([s,s]); pp = tensor([p,p])
|
|
720
|
+
sage: a = tensor((s[2],s[2]))
|
|
721
|
+
|
|
722
|
+
The following originally used to yield ``p[[2]] # p[[2]]``, and if
|
|
723
|
+
there was no natural coercion between ``s`` and ``p``, this would
|
|
724
|
+
raise a :exc:`NotImplementedError`.
|
|
725
|
+
Since :issue:`15305`, this takes the
|
|
726
|
+
coercion between ``s`` and ``p`` and lifts it to the tensor product. ::
|
|
727
|
+
|
|
728
|
+
sage: pp(a) # needs sage.combinat
|
|
729
|
+
1/4*p[1, 1] # p[1, 1] + 1/4*p[1, 1] # p[2] + 1/4*p[2] # p[1, 1] + 1/4*p[2] # p[2]
|
|
730
|
+
|
|
731
|
+
General extensions of the ground ring should probably be reintroduced
|
|
732
|
+
at some point, but via coercions, and with stronger sanity
|
|
733
|
+
checks (ensuring that the codomain is really obtained by
|
|
734
|
+
extending the scalar of the domain; checking that they share
|
|
735
|
+
the same class is not sufficient).
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
TESTS:
|
|
739
|
+
|
|
740
|
+
Conversion from the ground ring is implemented for algebras::
|
|
741
|
+
|
|
742
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ,3) # needs sage.combinat
|
|
743
|
+
sage: QS3(2) # needs sage.combinat
|
|
744
|
+
2*[1, 2, 3]
|
|
745
|
+
"""
|
|
746
|
+
R = self.base_ring()
|
|
747
|
+
|
|
748
|
+
# Coerce ints to Integers
|
|
749
|
+
if isinstance(x, int):
|
|
750
|
+
x = Integer(x)
|
|
751
|
+
|
|
752
|
+
if x in R:
|
|
753
|
+
if x == 0:
|
|
754
|
+
return self.zero()
|
|
755
|
+
else:
|
|
756
|
+
raise TypeError("do not know how to make x (= %s) an element of %s" % (x, self))
|
|
757
|
+
# x is an element of the basis enumerated set;
|
|
758
|
+
# This is a very ugly way of testing this
|
|
759
|
+
elif ((hasattr(self._indices, 'element_class') and
|
|
760
|
+
isinstance(self._indices.element_class, type) and
|
|
761
|
+
isinstance(x, self._indices.element_class)) or
|
|
762
|
+
parent(x) == self._indices):
|
|
763
|
+
return self.monomial(x)
|
|
764
|
+
elif x in self._indices:
|
|
765
|
+
return self.monomial(self._indices(x))
|
|
766
|
+
else:
|
|
767
|
+
if hasattr(self, '_coerce_end'):
|
|
768
|
+
try:
|
|
769
|
+
return self._coerce_end(x)
|
|
770
|
+
except TypeError:
|
|
771
|
+
pass
|
|
772
|
+
raise TypeError("do not know how to make x (= %s) an element of self (=%s)" % (x, self))
|
|
773
|
+
|
|
774
|
+
def _convert_map_from_(self, S):
|
|
775
|
+
"""
|
|
776
|
+
Implement the conversion from formal sums.
|
|
777
|
+
|
|
778
|
+
EXAMPLES::
|
|
779
|
+
|
|
780
|
+
sage: E = CombinatorialFreeModule(QQ, ["a", "b", "c"])
|
|
781
|
+
sage: f = FormalSum([[2, "a"], [3, "b"]]); f
|
|
782
|
+
2*a + 3*b
|
|
783
|
+
sage: E._convert_map_from_(f.parent())
|
|
784
|
+
Generic morphism:
|
|
785
|
+
From: Abelian Group of all Formal Finite Sums over Integer Ring
|
|
786
|
+
To: Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
787
|
+
sage: E(f)
|
|
788
|
+
2*B['a'] + 3*B['b']
|
|
789
|
+
|
|
790
|
+
sage: E._convert_map_from_(ZZ)
|
|
791
|
+
"""
|
|
792
|
+
from sage.structure.formal_sum import FormalSums
|
|
793
|
+
K = self.base_ring()
|
|
794
|
+
if isinstance(S, FormalSums) and K.has_coerce_map_from(S.base_ring()):
|
|
795
|
+
G = self.basis().keys()
|
|
796
|
+
return SetMorphism(S.Hom(self, category=self.category() | S.category()),
|
|
797
|
+
lambda x: self.sum_of_terms((G(g), K(c))
|
|
798
|
+
for c, g in x))
|
|
799
|
+
|
|
800
|
+
def _first_ngens(self, n):
|
|
801
|
+
"""
|
|
802
|
+
Used by the preparser for ``F.<x> = ...``.
|
|
803
|
+
|
|
804
|
+
EXAMPLES::
|
|
805
|
+
|
|
806
|
+
sage: C = CombinatorialFreeModule(QQ, ZZ)
|
|
807
|
+
sage: C._first_ngens(3)
|
|
808
|
+
(B[0], B[1], B[-1])
|
|
809
|
+
|
|
810
|
+
sage: R.<x,y> = FreeAlgebra(QQ, 2) # needs sage.combinat
|
|
811
|
+
sage: x,y # needs sage.combinat
|
|
812
|
+
(x, y)
|
|
813
|
+
"""
|
|
814
|
+
try:
|
|
815
|
+
# Try gens first for compatibility with classes that
|
|
816
|
+
# rely on this (e.g., FreeAlgebra)
|
|
817
|
+
return tuple(self.gens())[:n]
|
|
818
|
+
except (AttributeError, ValueError, TypeError):
|
|
819
|
+
pass
|
|
820
|
+
B = self.basis()
|
|
821
|
+
it = iter(self._indices)
|
|
822
|
+
return tuple(B[next(it)] for i in range(n))
|
|
823
|
+
|
|
824
|
+
def _coerce_map_from_(self, R):
|
|
825
|
+
"""
|
|
826
|
+
Return ``True`` if there is a coercion map from ``R`` into ``self``.
|
|
827
|
+
|
|
828
|
+
There exists a coercion map from:
|
|
829
|
+
|
|
830
|
+
- a free module whose base ring coerces into the base ring of
|
|
831
|
+
``self``, and which has the same indices as ``self``
|
|
832
|
+
|
|
833
|
+
EXAMPLES::
|
|
834
|
+
|
|
835
|
+
sage: C = CombinatorialFreeModule(ZZ, Set([1,2]))
|
|
836
|
+
sage: CQ = CombinatorialFreeModule(QQ, Set([1,2]))
|
|
837
|
+
sage: CQ.has_coerce_map_from(C)
|
|
838
|
+
True
|
|
839
|
+
sage: c = C.monomial(2)
|
|
840
|
+
sage: cq = CQ(c); cq
|
|
841
|
+
B[2]
|
|
842
|
+
sage: cq.leading_coefficient().parent()
|
|
843
|
+
Rational Field
|
|
844
|
+
sage: C.has_coerce_map_from(CQ)
|
|
845
|
+
False
|
|
846
|
+
|
|
847
|
+
sage: # needs sage.rings.finite_rings
|
|
848
|
+
sage: CF2 = CombinatorialFreeModule(GF(2), Set([1,2]))
|
|
849
|
+
sage: CF2.has_coerce_map_from(C)
|
|
850
|
+
True
|
|
851
|
+
sage: c = C.monomial(1)
|
|
852
|
+
sage: CF2(2*c)
|
|
853
|
+
0
|
|
854
|
+
sage: CF2(3*c)
|
|
855
|
+
B[1]
|
|
856
|
+
"""
|
|
857
|
+
if isinstance(R, CombinatorialFreeModule):
|
|
858
|
+
try:
|
|
859
|
+
CR = R.base_extend(self.base_ring())
|
|
860
|
+
except (NotImplementedError, TypeError):
|
|
861
|
+
pass
|
|
862
|
+
else:
|
|
863
|
+
if CR == self:
|
|
864
|
+
return lambda parent, x: self._from_dict(x._monomial_coefficients,
|
|
865
|
+
coerce=True, remove_zeros=True)
|
|
866
|
+
return super()._coerce_map_from_(R)
|
|
867
|
+
|
|
868
|
+
def dimension(self):
|
|
869
|
+
"""
|
|
870
|
+
Return the dimension of the free module (which is given
|
|
871
|
+
by the number of elements in the basis).
|
|
872
|
+
|
|
873
|
+
EXAMPLES::
|
|
874
|
+
|
|
875
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
|
|
876
|
+
sage: F.dimension()
|
|
877
|
+
3
|
|
878
|
+
sage: F.basis().cardinality()
|
|
879
|
+
3
|
|
880
|
+
sage: F.basis().keys().cardinality()
|
|
881
|
+
3
|
|
882
|
+
|
|
883
|
+
Rank is available as a synonym::
|
|
884
|
+
|
|
885
|
+
sage: F.rank()
|
|
886
|
+
3
|
|
887
|
+
|
|
888
|
+
::
|
|
889
|
+
|
|
890
|
+
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat
|
|
891
|
+
sage: s.dimension() # needs sage.combinat
|
|
892
|
+
+Infinity
|
|
893
|
+
"""
|
|
894
|
+
return self._indices.cardinality()
|
|
895
|
+
|
|
896
|
+
rank = dimension
|
|
897
|
+
|
|
898
|
+
def is_exact(self):
|
|
899
|
+
r"""
|
|
900
|
+
Return ``True`` if elements of ``self`` have exact representations,
|
|
901
|
+
which is true of ``self`` if and only if it is true of
|
|
902
|
+
``self.basis().keys()`` and ``self.base_ring()``.
|
|
903
|
+
|
|
904
|
+
EXAMPLES::
|
|
905
|
+
|
|
906
|
+
sage: GroupAlgebra(GL(3, GF(7))).is_exact() # needs sage.groups sage.rings.finite_rings
|
|
907
|
+
True
|
|
908
|
+
sage: GroupAlgebra(GL(3, GF(7)), RR).is_exact() # needs sage.groups sage.rings.finite_rings
|
|
909
|
+
False
|
|
910
|
+
sage: GroupAlgebra(GL(3, pAdicRing(7))).is_exact() # not implemented, needs sage.groups sage.rings.padics
|
|
911
|
+
False
|
|
912
|
+
"""
|
|
913
|
+
# The index set may not have a check for exactness
|
|
914
|
+
# Assume the index set is exact if we cannot check
|
|
915
|
+
try:
|
|
916
|
+
if not self.basis().keys().is_exact():
|
|
917
|
+
return False
|
|
918
|
+
except AttributeError:
|
|
919
|
+
pass
|
|
920
|
+
return self.base_ring().is_exact()
|
|
921
|
+
|
|
922
|
+
def set_order(self, order):
|
|
923
|
+
"""
|
|
924
|
+
Set the order of the elements of the basis.
|
|
925
|
+
|
|
926
|
+
If :meth:`set_order` has not been called, then the ordering is
|
|
927
|
+
the one used in the generation of the elements of ``self``'s
|
|
928
|
+
associated enumerated set.
|
|
929
|
+
|
|
930
|
+
.. WARNING::
|
|
931
|
+
|
|
932
|
+
Many cached methods depend on this order, in
|
|
933
|
+
particular for constructing subspaces and quotients.
|
|
934
|
+
Changing the order after some computations have been
|
|
935
|
+
cached does not invalidate the cache, and is likely to
|
|
936
|
+
introduce inconsistencies.
|
|
937
|
+
|
|
938
|
+
EXAMPLES::
|
|
939
|
+
|
|
940
|
+
sage: # needs sage.combinat
|
|
941
|
+
sage: QS2 = SymmetricGroupAlgebra(QQ,2)
|
|
942
|
+
sage: b = list(QS2.basis().keys())
|
|
943
|
+
sage: b.reverse()
|
|
944
|
+
sage: QS2.set_order(b)
|
|
945
|
+
sage: QS2.get_order()
|
|
946
|
+
[[2, 1], [1, 2]]
|
|
947
|
+
"""
|
|
948
|
+
self._order = order
|
|
949
|
+
from sage.combinat.ranker import rank_from_list
|
|
950
|
+
self._rank_basis = rank_from_list(self._order)
|
|
951
|
+
|
|
952
|
+
@cached_method
|
|
953
|
+
def get_order(self):
|
|
954
|
+
"""
|
|
955
|
+
Return the order of the elements in the basis.
|
|
956
|
+
|
|
957
|
+
EXAMPLES::
|
|
958
|
+
|
|
959
|
+
sage: QS2 = SymmetricGroupAlgebra(QQ,2) # needs sage.combinat
|
|
960
|
+
sage: QS2.get_order() # note: order changed on 2009-03-13 # needs sage.combinat
|
|
961
|
+
[[2, 1], [1, 2]]
|
|
962
|
+
"""
|
|
963
|
+
if self._order is None:
|
|
964
|
+
self.set_order(self.basis().keys().list())
|
|
965
|
+
return self._order
|
|
966
|
+
|
|
967
|
+
def get_order_key(self):
|
|
968
|
+
"""
|
|
969
|
+
Return a comparison key on the basis indices that is
|
|
970
|
+
compatible with the current term order.
|
|
971
|
+
|
|
972
|
+
EXAMPLES::
|
|
973
|
+
|
|
974
|
+
sage: A = FiniteDimensionalAlgebrasWithBasis(QQ).example()
|
|
975
|
+
sage: A.set_order(['x', 'y', 'a', 'b'])
|
|
976
|
+
sage: Akey = A.get_order_key()
|
|
977
|
+
sage: sorted(A.basis().keys(), key=Akey)
|
|
978
|
+
['x', 'y', 'a', 'b']
|
|
979
|
+
sage: A.set_order(list(reversed(A.basis().keys())))
|
|
980
|
+
sage: Akey = A.get_order_key()
|
|
981
|
+
sage: sorted(A.basis().keys(), key=Akey)
|
|
982
|
+
['b', 'a', 'y', 'x']
|
|
983
|
+
"""
|
|
984
|
+
self.get_order()
|
|
985
|
+
return self._order_key
|
|
986
|
+
|
|
987
|
+
def _order_key(self, x):
|
|
988
|
+
"""
|
|
989
|
+
Return a key for `x` compatible with the term order.
|
|
990
|
+
|
|
991
|
+
INPUT:
|
|
992
|
+
|
|
993
|
+
- ``x`` -- indices of the basis of ``self``
|
|
994
|
+
|
|
995
|
+
EXAMPLES::
|
|
996
|
+
|
|
997
|
+
sage: A = CombinatorialFreeModule(QQ, ['x','y','a','b'])
|
|
998
|
+
sage: A.set_order(['x', 'y', 'a', 'b'])
|
|
999
|
+
sage: A._order_key('x')
|
|
1000
|
+
0
|
|
1001
|
+
sage: A._order_key('y')
|
|
1002
|
+
1
|
|
1003
|
+
sage: A._order_key('a')
|
|
1004
|
+
2
|
|
1005
|
+
"""
|
|
1006
|
+
return self._rank_basis(x)
|
|
1007
|
+
|
|
1008
|
+
def from_vector(self, vector, order=None, coerce=True):
|
|
1009
|
+
"""
|
|
1010
|
+
Build an element of ``self`` from a (sparse) vector.
|
|
1011
|
+
|
|
1012
|
+
.. SEEALSO:: :meth:`get_order`, :meth:`CombinatorialFreeModule.Element._vector_`
|
|
1013
|
+
|
|
1014
|
+
EXAMPLES::
|
|
1015
|
+
|
|
1016
|
+
sage: # needs sage.combinat
|
|
1017
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
1018
|
+
sage: b = QS3.from_vector(vector((2, 0, 0, 0, 0, 4))); b
|
|
1019
|
+
2*[1, 2, 3] + 4*[3, 2, 1]
|
|
1020
|
+
sage: a = 2*QS3([1,2,3]) + 4*QS3([3,2,1])
|
|
1021
|
+
sage: a == b
|
|
1022
|
+
True
|
|
1023
|
+
"""
|
|
1024
|
+
if order is None:
|
|
1025
|
+
order = self.get_order()
|
|
1026
|
+
if not coerce or vector.base_ring() is self.base_ring():
|
|
1027
|
+
return self._from_dict({order[i]: c for i, c in vector.items()},
|
|
1028
|
+
coerce=False)
|
|
1029
|
+
R = self.base_ring()
|
|
1030
|
+
return self._from_dict({order[i]: R(c) for i, c in vector.items() if R(c)},
|
|
1031
|
+
coerce=False, remove_zeros=False)
|
|
1032
|
+
|
|
1033
|
+
def sum(self, iter_of_elements):
|
|
1034
|
+
"""
|
|
1035
|
+
Return the sum of all elements in ``iter_of_elements``.
|
|
1036
|
+
|
|
1037
|
+
Overrides method inherited from commutative additive monoid as it
|
|
1038
|
+
is much faster on dicts directly.
|
|
1039
|
+
|
|
1040
|
+
INPUT:
|
|
1041
|
+
|
|
1042
|
+
- ``iter_of_elements`` -- iterator of elements of ``self``
|
|
1043
|
+
|
|
1044
|
+
EXAMPLES::
|
|
1045
|
+
|
|
1046
|
+
sage: F = CombinatorialFreeModule(QQ,[1,2])
|
|
1047
|
+
sage: f = F.an_element(); f
|
|
1048
|
+
2*B[1] + 2*B[2]
|
|
1049
|
+
sage: F.sum( f for _ in range(5) )
|
|
1050
|
+
10*B[1] + 10*B[2]
|
|
1051
|
+
"""
|
|
1052
|
+
D = blas.sum(element._monomial_coefficients for element in iter_of_elements)
|
|
1053
|
+
return self._from_dict(D, remove_zeros=False)
|
|
1054
|
+
|
|
1055
|
+
def linear_combination(self, iter_of_elements_coeff, factor_on_left=True):
|
|
1056
|
+
r"""
|
|
1057
|
+
Return the linear combination `\lambda_1 v_1 + \cdots +
|
|
1058
|
+
\lambda_k v_k` (resp. the linear combination `v_1 \lambda_1 +
|
|
1059
|
+
\cdots + v_k \lambda_k`) where ``iter_of_elements_coeff`` iterates
|
|
1060
|
+
through the sequence `((v_1, \lambda_1), ..., (v_k, \lambda_k))`.
|
|
1061
|
+
|
|
1062
|
+
INPUT:
|
|
1063
|
+
|
|
1064
|
+
- ``iter_of_elements_coeff`` -- iterator of pairs ``(element, coeff)``
|
|
1065
|
+
with ``element`` in ``self`` and ``coeff`` in ``self.base_ring()``
|
|
1066
|
+
|
|
1067
|
+
- ``factor_on_left`` -- (optional) if ``True``, the coefficients are
|
|
1068
|
+
multiplied from the left if ``False``, the coefficients are
|
|
1069
|
+
multiplied from the right
|
|
1070
|
+
|
|
1071
|
+
EXAMPLES::
|
|
1072
|
+
|
|
1073
|
+
sage: F = CombinatorialFreeModule(QQ, [1,2])
|
|
1074
|
+
sage: f = F.an_element(); f
|
|
1075
|
+
2*B[1] + 2*B[2]
|
|
1076
|
+
sage: F.linear_combination( (f,i) for i in range(5) )
|
|
1077
|
+
20*B[1] + 20*B[2]
|
|
1078
|
+
"""
|
|
1079
|
+
return self._from_dict(blas.linear_combination(((element._monomial_coefficients, coeff)
|
|
1080
|
+
for element, coeff in iter_of_elements_coeff),
|
|
1081
|
+
factor_on_left=factor_on_left),
|
|
1082
|
+
remove_zeros=False)
|
|
1083
|
+
|
|
1084
|
+
def term(self, index, coeff=None):
|
|
1085
|
+
"""
|
|
1086
|
+
Construct a term in ``self``.
|
|
1087
|
+
|
|
1088
|
+
INPUT:
|
|
1089
|
+
|
|
1090
|
+
- ``index`` -- the index of a basis element
|
|
1091
|
+
- ``coeff`` -- an element of the coefficient ring (default: one)
|
|
1092
|
+
|
|
1093
|
+
EXAMPLES::
|
|
1094
|
+
|
|
1095
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
|
|
1096
|
+
sage: F.term('a',3)
|
|
1097
|
+
3*B['a']
|
|
1098
|
+
sage: F.term('a')
|
|
1099
|
+
B['a']
|
|
1100
|
+
|
|
1101
|
+
Design: should this do coercion on the coefficient ring?
|
|
1102
|
+
"""
|
|
1103
|
+
if coeff is None:
|
|
1104
|
+
coeff = self.base_ring().one()
|
|
1105
|
+
return self._from_dict({index: coeff})
|
|
1106
|
+
|
|
1107
|
+
def _monomial(self, index):
|
|
1108
|
+
"""
|
|
1109
|
+
TESTS::
|
|
1110
|
+
|
|
1111
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
|
|
1112
|
+
sage: F._monomial('a')
|
|
1113
|
+
B['a']
|
|
1114
|
+
"""
|
|
1115
|
+
return self._from_dict({index: self.base_ring().one()}, remove_zeros=False)
|
|
1116
|
+
|
|
1117
|
+
@lazy_attribute
|
|
1118
|
+
def monomial(self):
|
|
1119
|
+
"""
|
|
1120
|
+
Return the basis element indexed by ``i``.
|
|
1121
|
+
|
|
1122
|
+
INPUT:
|
|
1123
|
+
|
|
1124
|
+
- ``i`` -- an element of the index set
|
|
1125
|
+
|
|
1126
|
+
EXAMPLES::
|
|
1127
|
+
|
|
1128
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
|
|
1129
|
+
sage: F.monomial('a')
|
|
1130
|
+
B['a']
|
|
1131
|
+
|
|
1132
|
+
``F.monomial`` is in fact (almost) a map::
|
|
1133
|
+
|
|
1134
|
+
sage: F.monomial
|
|
1135
|
+
Term map from {'a', 'b', 'c'} to Free module generated by {'a', 'b', 'c'} over Rational Field
|
|
1136
|
+
"""
|
|
1137
|
+
# Should use a real Map, as soon as combinatorial_classes are enumerated sets, and therefore parents
|
|
1138
|
+
from sage.categories.poor_man_map import PoorManMap
|
|
1139
|
+
return PoorManMap(self._monomial, domain=self._indices, codomain=self, name="Term map")
|
|
1140
|
+
|
|
1141
|
+
def _sum_of_monomials(self, indices):
|
|
1142
|
+
"""
|
|
1143
|
+
TESTS::
|
|
1144
|
+
|
|
1145
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
|
|
1146
|
+
sage: F._sum_of_monomials(['a', 'b', 'b'])
|
|
1147
|
+
B['a'] + 2*B['b']
|
|
1148
|
+
sage: F = CombinatorialFreeModule(GF(3), ['a', 'b', 'c']) # needs sage.rings.finite_rings
|
|
1149
|
+
sage: F._sum_of_monomials(['a', 'b', 'b', 'b']) # needs sage.rings.finite_rings
|
|
1150
|
+
B['a']
|
|
1151
|
+
"""
|
|
1152
|
+
R = self.base_ring()
|
|
1153
|
+
ret = blas.sum_of_monomials(indices, R.one())
|
|
1154
|
+
return self.element_class(self, ret)
|
|
1155
|
+
|
|
1156
|
+
def sum_of_terms(self, terms, distinct=False):
|
|
1157
|
+
"""
|
|
1158
|
+
Construct a sum of terms of ``self``.
|
|
1159
|
+
|
|
1160
|
+
INPUT:
|
|
1161
|
+
|
|
1162
|
+
- ``terms`` -- list (or iterable) of pairs ``(index, coeff)``
|
|
1163
|
+
- ``distinct`` -- boolean (default: ``False``); whether the indices are
|
|
1164
|
+
guaranteed to be distinct
|
|
1165
|
+
|
|
1166
|
+
EXAMPLES::
|
|
1167
|
+
|
|
1168
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
|
|
1169
|
+
sage: F.sum_of_terms([('a',2), ('c',3)])
|
|
1170
|
+
2*B['a'] + 3*B['c']
|
|
1171
|
+
|
|
1172
|
+
If ``distinct`` is True, then the construction is optimized::
|
|
1173
|
+
|
|
1174
|
+
sage: F.sum_of_terms([('a',2), ('c',3)], distinct = True)
|
|
1175
|
+
2*B['a'] + 3*B['c']
|
|
1176
|
+
|
|
1177
|
+
.. WARNING::
|
|
1178
|
+
|
|
1179
|
+
Use ``distinct=True`` only if you are sure that the
|
|
1180
|
+
indices are indeed distinct::
|
|
1181
|
+
|
|
1182
|
+
sage: F.sum_of_terms([('a',2), ('a',3)], distinct = True)
|
|
1183
|
+
3*B['a']
|
|
1184
|
+
|
|
1185
|
+
Extreme case::
|
|
1186
|
+
|
|
1187
|
+
sage: F.sum_of_terms([])
|
|
1188
|
+
0
|
|
1189
|
+
"""
|
|
1190
|
+
if distinct:
|
|
1191
|
+
return self._from_dict(dict(terms))
|
|
1192
|
+
return self._from_dict(blas.sum_of_terms(terms), remove_zeros=False)
|
|
1193
|
+
|
|
1194
|
+
@cached_method
|
|
1195
|
+
def zero(self):
|
|
1196
|
+
"""
|
|
1197
|
+
EXAMPLES::
|
|
1198
|
+
|
|
1199
|
+
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
|
|
1200
|
+
sage: F.zero()
|
|
1201
|
+
0
|
|
1202
|
+
"""
|
|
1203
|
+
return self._from_dict({}, remove_zeros=False)
|
|
1204
|
+
|
|
1205
|
+
def _from_dict(self, d, coerce=False, remove_zeros=True):
|
|
1206
|
+
r"""
|
|
1207
|
+
Construct an element of ``self`` from an ``{index: coefficient}``
|
|
1208
|
+
dictionary.
|
|
1209
|
+
|
|
1210
|
+
INPUT:
|
|
1211
|
+
|
|
1212
|
+
- ``d`` -- dictionary ``{index: coeff}`` where each ``index`` is
|
|
1213
|
+
the index of a basis element and each ``coeff`` belongs to the
|
|
1214
|
+
coefficient ring ``self.base_ring()``
|
|
1215
|
+
|
|
1216
|
+
- ``coerce`` -- boolean (default: ``False``); whether to coerce
|
|
1217
|
+
the coefficients ``coeff`` to the coefficient ring
|
|
1218
|
+
|
|
1219
|
+
- ``remove_zeros`` -- boolean (default: ``True``); if some
|
|
1220
|
+
coefficients ``coeff`` may be zero and should therefore be removed
|
|
1221
|
+
|
|
1222
|
+
EXAMPLES::
|
|
1223
|
+
|
|
1224
|
+
sage: # needs sage.combinat
|
|
1225
|
+
sage: e = SymmetricFunctions(QQ).elementary()
|
|
1226
|
+
sage: s = SymmetricFunctions(QQ).schur()
|
|
1227
|
+
sage: a = e([2,1]) + e([1,1,1]); a
|
|
1228
|
+
e[1, 1, 1] + e[2, 1]
|
|
1229
|
+
sage: s._from_dict(a.monomial_coefficients())
|
|
1230
|
+
s[1, 1, 1] + s[2, 1]
|
|
1231
|
+
|
|
1232
|
+
If the optional argument ``coerce`` is ``True``, then the
|
|
1233
|
+
coefficients are coerced into the base ring of ``self``::
|
|
1234
|
+
|
|
1235
|
+
sage: # needs sage.combinat
|
|
1236
|
+
sage: part = Partition([2,1])
|
|
1237
|
+
sage: d = {part: 1}
|
|
1238
|
+
sage: a = s._from_dict(d, coerce=True); a
|
|
1239
|
+
s[2, 1]
|
|
1240
|
+
sage: a.coefficient(part).parent()
|
|
1241
|
+
Rational Field
|
|
1242
|
+
|
|
1243
|
+
With ``remove_zeros=True``, zero coefficients are removed::
|
|
1244
|
+
|
|
1245
|
+
sage: s._from_dict({part: 0}) # needs sage.combinat
|
|
1246
|
+
0
|
|
1247
|
+
|
|
1248
|
+
.. WARNING::
|
|
1249
|
+
|
|
1250
|
+
With ``remove_zeros=True``, it is assumed that no
|
|
1251
|
+
coefficient of the dictionary is zero. Otherwise, this may
|
|
1252
|
+
lead to illegal results::
|
|
1253
|
+
|
|
1254
|
+
sage: list(s._from_dict({part: 0}, remove_zeros=False)) # needs sage.combinat
|
|
1255
|
+
[([2, 1], 0)]
|
|
1256
|
+
"""
|
|
1257
|
+
assert isinstance(d, dict)
|
|
1258
|
+
if coerce:
|
|
1259
|
+
R = self.base_ring()
|
|
1260
|
+
d = {key: R(coeff) for key, coeff in d.items()}
|
|
1261
|
+
if remove_zeros:
|
|
1262
|
+
d = {key: coeff for key, coeff in d.items() if coeff}
|
|
1263
|
+
return self.element_class(self, d)
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
class CombinatorialFreeModule_Tensor(CombinatorialFreeModule):
|
|
1267
|
+
"""
|
|
1268
|
+
Tensor Product of Free Modules.
|
|
1269
|
+
|
|
1270
|
+
EXAMPLES:
|
|
1271
|
+
|
|
1272
|
+
We construct two free modules, assign them short names, and construct their tensor product::
|
|
1273
|
+
|
|
1274
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename('F')
|
|
1275
|
+
sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename('G')
|
|
1276
|
+
sage: T = tensor([F, G]); T
|
|
1277
|
+
F # G
|
|
1278
|
+
|
|
1279
|
+
sage: T.category()
|
|
1280
|
+
Category of tensor products of
|
|
1281
|
+
finite dimensional modules with basis over Integer Ring
|
|
1282
|
+
|
|
1283
|
+
sage: T.construction() # todo: not implemented
|
|
1284
|
+
[tensor, ]
|
|
1285
|
+
|
|
1286
|
+
T is a free module, with same base ring as F and G::
|
|
1287
|
+
|
|
1288
|
+
sage: T.base_ring()
|
|
1289
|
+
Integer Ring
|
|
1290
|
+
|
|
1291
|
+
The basis of T is indexed by tuples of basis indices of F and G::
|
|
1292
|
+
|
|
1293
|
+
sage: T.basis().keys()
|
|
1294
|
+
Image of Cartesian product of {1, 2}, {3, 4}
|
|
1295
|
+
by The map <class 'tuple'> from Cartesian product of {1, 2}, {3, 4}
|
|
1296
|
+
sage: T.basis().keys().list()
|
|
1297
|
+
[(1, 3), (1, 4), (2, 3), (2, 4)]
|
|
1298
|
+
|
|
1299
|
+
FIXME: Should elements of a CartesianProduct be tuples (making them hashable)?
|
|
1300
|
+
|
|
1301
|
+
Here are the basis elements themselves::
|
|
1302
|
+
|
|
1303
|
+
sage: T.basis().cardinality()
|
|
1304
|
+
4
|
|
1305
|
+
sage: list(T.basis())
|
|
1306
|
+
[B[1] # B[3], B[1] # B[4], B[2] # B[3], B[2] # B[4]]
|
|
1307
|
+
|
|
1308
|
+
The tensor product is associative and flattens sub tensor products::
|
|
1309
|
+
|
|
1310
|
+
sage: H = CombinatorialFreeModule(ZZ, [5,6]); H.rename('H')
|
|
1311
|
+
sage: tensor([F, tensor([G, H])])
|
|
1312
|
+
F # G # H
|
|
1313
|
+
sage: tensor([tensor([F, G]), H])
|
|
1314
|
+
F # G # H
|
|
1315
|
+
sage: tensor([F, G, H])
|
|
1316
|
+
F # G # H
|
|
1317
|
+
|
|
1318
|
+
We now compute the tensor product of elements of free modules::
|
|
1319
|
+
|
|
1320
|
+
sage: f = F.monomial(1) + 2 * F.monomial(2)
|
|
1321
|
+
sage: g = 2*G.monomial(3) + G.monomial(4)
|
|
1322
|
+
sage: h = H.monomial(5) + H.monomial(6)
|
|
1323
|
+
sage: tensor([f, g])
|
|
1324
|
+
2*B[1] # B[3] + B[1] # B[4] + 4*B[2] # B[3] + 2*B[2] # B[4]
|
|
1325
|
+
|
|
1326
|
+
Again, the tensor product is associative on elements::
|
|
1327
|
+
|
|
1328
|
+
sage: tensor([f, tensor([g, h])]) == tensor([f, g, h])
|
|
1329
|
+
True
|
|
1330
|
+
sage: tensor([tensor([f, g]), h]) == tensor([f, g, h])
|
|
1331
|
+
True
|
|
1332
|
+
|
|
1333
|
+
Note further that the tensor product spaces need not preexist::
|
|
1334
|
+
|
|
1335
|
+
sage: t = tensor([f, g, h])
|
|
1336
|
+
sage: t.parent()
|
|
1337
|
+
F # G # H
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
TESTS::
|
|
1341
|
+
|
|
1342
|
+
sage: tensor([tensor([F, G]), H]) == tensor([F, G, H])
|
|
1343
|
+
True
|
|
1344
|
+
sage: tensor([F, tensor([G, H])]) == tensor([F, G, H])
|
|
1345
|
+
True
|
|
1346
|
+
"""
|
|
1347
|
+
@staticmethod
|
|
1348
|
+
def __classcall_private__(cls, modules, **options):
|
|
1349
|
+
"""
|
|
1350
|
+
TESTS::
|
|
1351
|
+
|
|
1352
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2])
|
|
1353
|
+
sage: G = CombinatorialFreeModule(ZZ, [3,4])
|
|
1354
|
+
sage: H = CombinatorialFreeModule(ZZ, [4])
|
|
1355
|
+
sage: tensor([tensor([F, G]), H]) == tensor([F, G, H])
|
|
1356
|
+
True
|
|
1357
|
+
sage: tensor([F, tensor([G, H])]) == tensor([F, G, H])
|
|
1358
|
+
True
|
|
1359
|
+
|
|
1360
|
+
Check that :issue:`19608` is fixed::
|
|
1361
|
+
|
|
1362
|
+
sage: T = tensor([F, G, H])
|
|
1363
|
+
sage: T in Modules(ZZ).FiniteDimensional()
|
|
1364
|
+
True
|
|
1365
|
+
"""
|
|
1366
|
+
assert (len(modules) > 0)
|
|
1367
|
+
R = modules[0].base_ring()
|
|
1368
|
+
assert (all(module in ModulesWithBasis(R)) for module in modules)
|
|
1369
|
+
# should check the base ring
|
|
1370
|
+
# flatten the list of modules so that tensor(A, tensor(B,C)) gets rewritten into tensor(A, B, C)
|
|
1371
|
+
modules = sum([module._sets if isinstance(module, CombinatorialFreeModule_Tensor) else (module,) for module in modules], ())
|
|
1372
|
+
if all('FiniteDimensional' in M.category().axioms() for M in modules):
|
|
1373
|
+
options['category'] = options['category'].FiniteDimensional()
|
|
1374
|
+
return super(CombinatorialFreeModule.Tensor, cls).__classcall__(cls, modules, **options)
|
|
1375
|
+
|
|
1376
|
+
def __init__(self, modules, **options):
|
|
1377
|
+
"""
|
|
1378
|
+
TESTS::
|
|
1379
|
+
|
|
1380
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2]); F
|
|
1381
|
+
F
|
|
1382
|
+
"""
|
|
1383
|
+
self._sets = modules
|
|
1384
|
+
indices = CartesianProduct_iters(*[module.basis().keys()
|
|
1385
|
+
for module in modules]).map(tuple, is_injective=True)
|
|
1386
|
+
CombinatorialFreeModule.__init__(self, modules[0].base_ring(), indices, **options)
|
|
1387
|
+
# the following is not the best option, but it's better than nothing.
|
|
1388
|
+
if 'tensor_symbol' in options:
|
|
1389
|
+
self._print_options['tensor_symbol'] = options['tensor_symbol']
|
|
1390
|
+
|
|
1391
|
+
def _repr_(self):
|
|
1392
|
+
r"""
|
|
1393
|
+
This is customizable by setting
|
|
1394
|
+
``self.print_options('tensor_symbol'=...)``.
|
|
1395
|
+
|
|
1396
|
+
TESTS::
|
|
1397
|
+
|
|
1398
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2,3])
|
|
1399
|
+
sage: G = CombinatorialFreeModule(ZZ, [1,2,3,8])
|
|
1400
|
+
sage: F.rename('F')
|
|
1401
|
+
sage: G.rename('G')
|
|
1402
|
+
sage: T = tensor([F, G])
|
|
1403
|
+
sage: T # indirect doctest
|
|
1404
|
+
F # G
|
|
1405
|
+
sage: T.print_options(tensor_symbol=' @ ') # note the spaces
|
|
1406
|
+
sage: T # indirect doctest
|
|
1407
|
+
F @ G
|
|
1408
|
+
|
|
1409
|
+
To avoid a side\--effect on another doctest, we revert the change::
|
|
1410
|
+
|
|
1411
|
+
sage: T.print_options(tensor_symbol=' # ')
|
|
1412
|
+
"""
|
|
1413
|
+
from sage.categories.tensor import tensor
|
|
1414
|
+
if hasattr(self, "_print_options"):
|
|
1415
|
+
symb = self._print_options['tensor_symbol']
|
|
1416
|
+
if symb is None:
|
|
1417
|
+
symb = tensor.symbol
|
|
1418
|
+
else:
|
|
1419
|
+
symb = tensor.symbol
|
|
1420
|
+
return symb.join("%s" % module for module in self._sets)
|
|
1421
|
+
# TODO: make this overridable by setting _name
|
|
1422
|
+
|
|
1423
|
+
def tensor_factors(self):
|
|
1424
|
+
"""
|
|
1425
|
+
Return the tensor factors of this tensor product.
|
|
1426
|
+
|
|
1427
|
+
EXAMPLES::
|
|
1428
|
+
|
|
1429
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2])
|
|
1430
|
+
sage: F.rename('F')
|
|
1431
|
+
sage: G = CombinatorialFreeModule(ZZ, [3,4])
|
|
1432
|
+
sage: G.rename('G')
|
|
1433
|
+
sage: T = tensor([F, G]); T
|
|
1434
|
+
F # G
|
|
1435
|
+
sage: T.tensor_factors()
|
|
1436
|
+
(F, G)
|
|
1437
|
+
"""
|
|
1438
|
+
return self._sets
|
|
1439
|
+
|
|
1440
|
+
def _ascii_art_(self, term):
|
|
1441
|
+
"""
|
|
1442
|
+
TESTS::
|
|
1443
|
+
|
|
1444
|
+
sage: R = NonCommutativeSymmetricFunctions(QQ).R() # needs sage.combinat
|
|
1445
|
+
sage: Partitions.options(diagram_str='#', convention='french') # needs sage.combinat
|
|
1446
|
+
sage: s = ascii_art(tensor((R[1,2], R[3,1,2]))); s # needs sage.combinat
|
|
1447
|
+
R # R
|
|
1448
|
+
# ###
|
|
1449
|
+
## #
|
|
1450
|
+
##
|
|
1451
|
+
|
|
1452
|
+
Check that the breakpoints are correct (:issue:`29202`)::
|
|
1453
|
+
|
|
1454
|
+
sage: s._breakpoints # needs sage.combinat
|
|
1455
|
+
[6]
|
|
1456
|
+
"""
|
|
1457
|
+
if hasattr(self, "_print_options"):
|
|
1458
|
+
symb = self._print_options['tensor_symbol']
|
|
1459
|
+
if symb is None:
|
|
1460
|
+
symb = tensor.symbol
|
|
1461
|
+
else:
|
|
1462
|
+
symb = tensor.symbol
|
|
1463
|
+
return ascii_art(*(module._ascii_art_term(t)
|
|
1464
|
+
for module, t in zip(self._sets, term)),
|
|
1465
|
+
sep=AsciiArt([symb], breakpoints=[len(symb)]))
|
|
1466
|
+
|
|
1467
|
+
_ascii_art_term = _ascii_art_
|
|
1468
|
+
|
|
1469
|
+
def _unicode_art_(self, term):
|
|
1470
|
+
"""
|
|
1471
|
+
TESTS::
|
|
1472
|
+
|
|
1473
|
+
sage: R = NonCommutativeSymmetricFunctions(QQ).R() # needs sage.combinat
|
|
1474
|
+
sage: Partitions.options(diagram_str='#', convention='french') # needs sage.combinat
|
|
1475
|
+
sage: s = unicode_art(tensor((R[1,2], R[3,1,2]))); s # needs sage.combinat
|
|
1476
|
+
R ⊗ R
|
|
1477
|
+
┌┐ ┌┬┬┐
|
|
1478
|
+
├┼┐ └┴┼┤
|
|
1479
|
+
└┴┘ ├┼┐
|
|
1480
|
+
└┴┘
|
|
1481
|
+
|
|
1482
|
+
Check that the breakpoints are correct (:issue:`29202`)::
|
|
1483
|
+
|
|
1484
|
+
sage: s._breakpoints # needs sage.combinat
|
|
1485
|
+
[7]
|
|
1486
|
+
"""
|
|
1487
|
+
if hasattr(self, "_print_options"):
|
|
1488
|
+
symb = self._print_options['tensor_symbol']
|
|
1489
|
+
if symb is None:
|
|
1490
|
+
symb = tensor.unicode_symbol
|
|
1491
|
+
else:
|
|
1492
|
+
symb = tensor.unicode_symbol
|
|
1493
|
+
return unicode_art(*(module._unicode_art_term(t)
|
|
1494
|
+
for module, t in zip(self._sets, term)),
|
|
1495
|
+
sep=UnicodeArt([symb], breakpoints=[len(symb)]))
|
|
1496
|
+
|
|
1497
|
+
_unicode_art_term = _unicode_art_
|
|
1498
|
+
|
|
1499
|
+
def _latex_(self):
|
|
1500
|
+
r"""
|
|
1501
|
+
TESTS::
|
|
1502
|
+
|
|
1503
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2,3])
|
|
1504
|
+
sage: G = CombinatorialFreeModule(ZZ, [1,2,3,8])
|
|
1505
|
+
sage: F.rename('F')
|
|
1506
|
+
sage: G.rename('G')
|
|
1507
|
+
sage: latex(tensor([F, F, G])) # indirect doctest
|
|
1508
|
+
\text{\texttt{F}} \otimes \text{\texttt{F}} \otimes \text{\texttt{G}}
|
|
1509
|
+
sage: F._latex_ = lambda : "F"
|
|
1510
|
+
sage: G._latex_ = lambda : "G"
|
|
1511
|
+
sage: latex(tensor([F, F, G])) # indirect doctest
|
|
1512
|
+
F \otimes F \otimes G
|
|
1513
|
+
"""
|
|
1514
|
+
from sage.misc.latex import latex
|
|
1515
|
+
symb = " \\otimes "
|
|
1516
|
+
return symb.join("%s" % latex(module) for module in self._sets)
|
|
1517
|
+
|
|
1518
|
+
def _repr_term(self, term):
|
|
1519
|
+
"""
|
|
1520
|
+
TESTS::
|
|
1521
|
+
|
|
1522
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2,3], prefix='F')
|
|
1523
|
+
sage: G = CombinatorialFreeModule(ZZ, [1,2,3,4], prefix='G')
|
|
1524
|
+
sage: f = F.monomial(1) + 2 * F.monomial(2)
|
|
1525
|
+
sage: g = 2*G.monomial(3) + G.monomial(4)
|
|
1526
|
+
sage: tensor([f, g]) # indirect doctest
|
|
1527
|
+
2*F[1] # G[3] + F[1] # G[4] + 4*F[2] # G[3] + 2*F[2] # G[4]
|
|
1528
|
+
"""
|
|
1529
|
+
if hasattr(self, "_print_options"):
|
|
1530
|
+
symb = self._print_options['tensor_symbol']
|
|
1531
|
+
if symb is None:
|
|
1532
|
+
symb = tensor.symbol
|
|
1533
|
+
else:
|
|
1534
|
+
symb = tensor.symbol
|
|
1535
|
+
return symb.join(module._repr_term(t) for (module, t) in zip(self._sets, term))
|
|
1536
|
+
|
|
1537
|
+
def _latex_term(self, term):
|
|
1538
|
+
r"""
|
|
1539
|
+
TESTS::
|
|
1540
|
+
|
|
1541
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2,3], prefix='x')
|
|
1542
|
+
sage: G = CombinatorialFreeModule(ZZ, [1,2,3,4], prefix='y')
|
|
1543
|
+
sage: f = F.monomial(1) + 2 * F.monomial(2)
|
|
1544
|
+
sage: g = 2*G.monomial(3) + G.monomial(4)
|
|
1545
|
+
sage: latex(tensor([f, g])) # indirect doctest
|
|
1546
|
+
2 x_{1} \otimes y_{3} + x_{1} \otimes y_{4} + 4 x_{2} \otimes y_{3} + 2 x_{2} \otimes y_{4}
|
|
1547
|
+
"""
|
|
1548
|
+
symb = " \\otimes "
|
|
1549
|
+
return symb.join(module._latex_term(t) for (module, t) in zip(self._sets, term))
|
|
1550
|
+
|
|
1551
|
+
@cached_method
|
|
1552
|
+
def tensor_constructor(self, modules):
|
|
1553
|
+
r"""
|
|
1554
|
+
INPUT:
|
|
1555
|
+
|
|
1556
|
+
- ``modules`` -- tuple `(F_1,\dots,F_n)` of
|
|
1557
|
+
free modules whose tensor product is self
|
|
1558
|
+
|
|
1559
|
+
Returns the canonical multilinear morphism from
|
|
1560
|
+
`F_1 \times \dots \times F_n` to `F_1 \otimes \dots \otimes F_n`
|
|
1561
|
+
|
|
1562
|
+
EXAMPLES::
|
|
1563
|
+
|
|
1564
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename('F')
|
|
1565
|
+
sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename('G')
|
|
1566
|
+
sage: H = CombinatorialFreeModule(ZZ, [5,6]); H.rename('H')
|
|
1567
|
+
|
|
1568
|
+
sage: f = F.monomial(1) + 2*F.monomial(2)
|
|
1569
|
+
sage: g = 2*G.monomial(3) + G.monomial(4)
|
|
1570
|
+
sage: h = H.monomial(5) + H.monomial(6)
|
|
1571
|
+
sage: FG = tensor([F, G])
|
|
1572
|
+
sage: phi_fg = FG.tensor_constructor((F, G))
|
|
1573
|
+
sage: phi_fg(f, g)
|
|
1574
|
+
2*B[1] # B[3] + B[1] # B[4] + 4*B[2] # B[3] + 2*B[2] # B[4]
|
|
1575
|
+
|
|
1576
|
+
sage: FGH = tensor([F, G, H])
|
|
1577
|
+
sage: phi_fgh = FGH.tensor_constructor((F, G, H))
|
|
1578
|
+
sage: phi_fgh(f, g, h)
|
|
1579
|
+
2*B[1] # B[3] # B[5] + 2*B[1] # B[3] # B[6] + B[1] # B[4] # B[5]
|
|
1580
|
+
+ B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6]
|
|
1581
|
+
+ 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6]
|
|
1582
|
+
|
|
1583
|
+
sage: phi_fg_h = FGH.tensor_constructor((FG, H))
|
|
1584
|
+
sage: phi_fg_h(phi_fg(f, g), h)
|
|
1585
|
+
2*B[1] # B[3] # B[5] + 2*B[1] # B[3] # B[6] + B[1] # B[4] # B[5]
|
|
1586
|
+
+ B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6]
|
|
1587
|
+
+ 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6]
|
|
1588
|
+
"""
|
|
1589
|
+
assert (module in ModulesWithBasis(self.base_ring()) for module in modules)
|
|
1590
|
+
assert (tensor(modules) == self)
|
|
1591
|
+
# a list l such that l[i] is True if modules[i] is readily a tensor product
|
|
1592
|
+
is_tensor = [isinstance(module, CombinatorialFreeModule_Tensor) for module in modules]
|
|
1593
|
+
# the tensor_constructor, on basis elements
|
|
1594
|
+
result = self.monomial * CartesianProductWithFlattening(is_tensor)
|
|
1595
|
+
# TODO: make this into an element of Hom( A x B, C ) when those will exist
|
|
1596
|
+
for i in range(len(modules)):
|
|
1597
|
+
result = modules[i]._module_morphism(result, position=i,
|
|
1598
|
+
codomain=self)
|
|
1599
|
+
return result
|
|
1600
|
+
|
|
1601
|
+
def _tensor_of_elements(self, elements):
|
|
1602
|
+
"""
|
|
1603
|
+
Return the tensor product of the specified elements.
|
|
1604
|
+
The result should be in ``self``.
|
|
1605
|
+
|
|
1606
|
+
EXAMPLES::
|
|
1607
|
+
|
|
1608
|
+
sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename('F')
|
|
1609
|
+
sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename('G')
|
|
1610
|
+
sage: H = CombinatorialFreeModule(ZZ, [5,6]); H.rename('H')
|
|
1611
|
+
|
|
1612
|
+
sage: f = F.monomial(1) + 2 * F.monomial(2)
|
|
1613
|
+
sage: g = 2*G.monomial(3) + G.monomial(4)
|
|
1614
|
+
sage: h = H.monomial(5) + H.monomial(6)
|
|
1615
|
+
|
|
1616
|
+
sage: GH = tensor([G, H])
|
|
1617
|
+
sage: gh = GH._tensor_of_elements([g, h]); gh
|
|
1618
|
+
2*B[3] # B[5] + 2*B[3] # B[6] + B[4] # B[5] + B[4] # B[6]
|
|
1619
|
+
|
|
1620
|
+
sage: FGH = tensor([F, G, H])
|
|
1621
|
+
sage: FGH._tensor_of_elements([f, g, h])
|
|
1622
|
+
2*B[1] # B[3] # B[5] + 2*B[1] # B[3] # B[6] + B[1] # B[4] # B[5]
|
|
1623
|
+
+ B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6]
|
|
1624
|
+
+ 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6]
|
|
1625
|
+
|
|
1626
|
+
sage: FGH._tensor_of_elements([f, gh])
|
|
1627
|
+
2*B[1] # B[3] # B[5] + 2*B[1] # B[3] # B[6] + B[1] # B[4] # B[5]
|
|
1628
|
+
+ B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6]
|
|
1629
|
+
+ 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6]
|
|
1630
|
+
"""
|
|
1631
|
+
return self.tensor_constructor(tuple(element.parent() for element in elements))(*elements)
|
|
1632
|
+
|
|
1633
|
+
def _coerce_map_from_(self, R):
|
|
1634
|
+
"""
|
|
1635
|
+
Return ``True`` if there is a coercion from ``R`` into ``self`` and
|
|
1636
|
+
``False`` otherwise. The things that coerce into ``self`` are:
|
|
1637
|
+
|
|
1638
|
+
- Anything with a coercion into ``self.base_ring()``.
|
|
1639
|
+
|
|
1640
|
+
- A tensor algebra whose factors have a coercion into the
|
|
1641
|
+
corresponding factors of ``self``.
|
|
1642
|
+
|
|
1643
|
+
TESTS::
|
|
1644
|
+
|
|
1645
|
+
sage: C = CombinatorialFreeModule(ZZ, ZZ)
|
|
1646
|
+
sage: C2 = CombinatorialFreeModule(ZZ, NN)
|
|
1647
|
+
sage: M = C.module_morphism(lambda x: C2.monomial(abs(x)), codomain=C2)
|
|
1648
|
+
sage: M.register_as_coercion()
|
|
1649
|
+
sage: C2(C.basis()[3])
|
|
1650
|
+
B[3]
|
|
1651
|
+
sage: C2(C.basis()[3] + C.basis()[-3])
|
|
1652
|
+
2*B[3]
|
|
1653
|
+
sage: S = C.tensor(C)
|
|
1654
|
+
sage: S2 = C2.tensor(C2)
|
|
1655
|
+
sage: S2.has_coerce_map_from(S)
|
|
1656
|
+
True
|
|
1657
|
+
sage: S.has_coerce_map_from(S2)
|
|
1658
|
+
False
|
|
1659
|
+
sage: S.an_element()
|
|
1660
|
+
3*B[0] # B[-1] + 2*B[0] # B[0] + 2*B[0] # B[1]
|
|
1661
|
+
sage: S2(S.an_element())
|
|
1662
|
+
2*B[0] # B[0] + 5*B[0] # B[1]
|
|
1663
|
+
|
|
1664
|
+
::
|
|
1665
|
+
|
|
1666
|
+
sage: C = CombinatorialFreeModule(ZZ, Set([1,2]))
|
|
1667
|
+
sage: D = CombinatorialFreeModule(ZZ, Set([2,4]))
|
|
1668
|
+
sage: f = C.module_morphism(on_basis=lambda x: D.monomial(2*x), codomain=D)
|
|
1669
|
+
sage: f.register_as_coercion()
|
|
1670
|
+
sage: T = tensor((C,C))
|
|
1671
|
+
sage: p = D.an_element()
|
|
1672
|
+
sage: T(tensor((p,p)))
|
|
1673
|
+
Traceback (most recent call last):
|
|
1674
|
+
...
|
|
1675
|
+
NotImplementedError
|
|
1676
|
+
sage: T = tensor((D,D))
|
|
1677
|
+
sage: p = C.an_element()
|
|
1678
|
+
sage: T(tensor((p,p)))
|
|
1679
|
+
4*B[2] # B[2] + 4*B[2] # B[4] + 4*B[4] # B[2] + 4*B[4] # B[4]
|
|
1680
|
+
"""
|
|
1681
|
+
if ((R in ModulesWithBasis(self.base_ring()).TensorProducts() or
|
|
1682
|
+
R in GradedAlgebrasWithBasis(self.base_ring()).SignedTensorProducts())
|
|
1683
|
+
and isinstance(R, CombinatorialFreeModule_Tensor)
|
|
1684
|
+
and len(R._sets) == len(self._sets)
|
|
1685
|
+
and all(self._sets[i].has_coerce_map_from(M)
|
|
1686
|
+
for i, M in enumerate(R._sets))):
|
|
1687
|
+
modules = R._sets
|
|
1688
|
+
vector_map = [self._sets[i]._internal_coerce_map_from(M)
|
|
1689
|
+
for i, M in enumerate(modules)]
|
|
1690
|
+
return R.module_morphism(lambda x: self._tensor_of_elements(
|
|
1691
|
+
[vector_map[i](M.monomial(x[i]))
|
|
1692
|
+
for i, M in enumerate(modules)]), codomain=self)
|
|
1693
|
+
|
|
1694
|
+
return super()._coerce_map_from_(R)
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
class CartesianProductWithFlattening:
|
|
1698
|
+
"""
|
|
1699
|
+
A class for Cartesian product constructor, with partial flattening
|
|
1700
|
+
"""
|
|
1701
|
+
|
|
1702
|
+
def __init__(self, flatten):
|
|
1703
|
+
"""
|
|
1704
|
+
INPUT:
|
|
1705
|
+
|
|
1706
|
+
- ``flatten`` -- tuple of booleans
|
|
1707
|
+
|
|
1708
|
+
This constructs a callable which accepts ``len(flatten)``
|
|
1709
|
+
arguments, and builds a tuple out them. When ``flatten[i]``,
|
|
1710
|
+
the `i`-th argument itself should be a tuple which is flattened
|
|
1711
|
+
in the result.
|
|
1712
|
+
|
|
1713
|
+
sage: from sage.combinat.free_module import CartesianProductWithFlattening
|
|
1714
|
+
sage: CartesianProductWithFlattening([True, False, True, True])
|
|
1715
|
+
<sage.combinat.free_module.CartesianProductWithFlattening object at ...>
|
|
1716
|
+
"""
|
|
1717
|
+
self._flatten = flatten
|
|
1718
|
+
|
|
1719
|
+
def __call__(self, *indices):
|
|
1720
|
+
"""
|
|
1721
|
+
EXAMPLES::
|
|
1722
|
+
|
|
1723
|
+
sage: from sage.combinat.free_module import CartesianProductWithFlattening
|
|
1724
|
+
sage: cp = CartesianProductWithFlattening([True, False, True, True])
|
|
1725
|
+
sage: cp((1,2), (3,4), (5,6), (7,8))
|
|
1726
|
+
(1, 2, (3, 4), 5, 6, 7, 8)
|
|
1727
|
+
sage: cp((1,2,3), 4, (5,6), (7,8))
|
|
1728
|
+
(1, 2, 3, 4, 5, 6, 7, 8)
|
|
1729
|
+
"""
|
|
1730
|
+
return sum((i if flatten else (i,)
|
|
1731
|
+
for (i, flatten) in zip(indices, self._flatten)), ())
|
|
1732
|
+
|
|
1733
|
+
|
|
1734
|
+
# TODO: find a way to avoid this hack to allow for cross references
|
|
1735
|
+
CombinatorialFreeModule.Tensor = CombinatorialFreeModule_Tensor
|
|
1736
|
+
|
|
1737
|
+
|
|
1738
|
+
class CombinatorialFreeModule_CartesianProduct(CombinatorialFreeModule):
|
|
1739
|
+
"""
|
|
1740
|
+
An implementation of Cartesian products of modules with basis.
|
|
1741
|
+
|
|
1742
|
+
EXAMPLES:
|
|
1743
|
+
|
|
1744
|
+
We construct two free modules, assign them short names, and construct their Cartesian product::
|
|
1745
|
+
|
|
1746
|
+
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename('F')
|
|
1747
|
+
sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename('G')
|
|
1748
|
+
sage: H = CombinatorialFreeModule(ZZ, [4,7]); H.rename('H')
|
|
1749
|
+
sage: S = cartesian_product([F, G])
|
|
1750
|
+
sage: S
|
|
1751
|
+
F (+) G
|
|
1752
|
+
sage: S.basis()
|
|
1753
|
+
Lazy family (Term map
|
|
1754
|
+
from Disjoint union of Family ({4, 5}, {4, 6})
|
|
1755
|
+
to F (+) G(i))_{i in Disjoint union of Family ({4, 5}, {4, 6})}
|
|
1756
|
+
|
|
1757
|
+
Note that the indices of the basis elements of F and G intersect non
|
|
1758
|
+
trivially. This is handled by forcing the union to be disjoint::
|
|
1759
|
+
|
|
1760
|
+
sage: list(S.basis())
|
|
1761
|
+
[B[(0, 4)], B[(0, 5)], B[(1, 4)], B[(1, 6)]]
|
|
1762
|
+
|
|
1763
|
+
We now compute the Cartesian product of elements of free modules::
|
|
1764
|
+
|
|
1765
|
+
sage: f = F.monomial(4) + 2*F.monomial(5)
|
|
1766
|
+
sage: g = 2*G.monomial(4) + G.monomial(6)
|
|
1767
|
+
sage: h = H.monomial(4) + H.monomial(7)
|
|
1768
|
+
sage: cartesian_product([f, g])
|
|
1769
|
+
B[(0, 4)] + 2*B[(0, 5)] + 2*B[(1, 4)] + B[(1, 6)]
|
|
1770
|
+
sage: cartesian_product([f, g, h])
|
|
1771
|
+
B[(0, 4)] + 2*B[(0, 5)] + 2*B[(1, 4)] + B[(1, 6)] + B[(2, 4)] + B[(2, 7)]
|
|
1772
|
+
sage: cartesian_product([f, g, h]).parent()
|
|
1773
|
+
F (+) G (+) H
|
|
1774
|
+
|
|
1775
|
+
TODO: choose an appropriate semantic for Cartesian products of Cartesian products (associativity?)::
|
|
1776
|
+
|
|
1777
|
+
sage: S = cartesian_product([cartesian_product([F, G]), H]) # todo: not implemented
|
|
1778
|
+
F (+) G (+) H
|
|
1779
|
+
"""
|
|
1780
|
+
@staticmethod
|
|
1781
|
+
def __classcall_private__(cls, modules, category, **options):
|
|
1782
|
+
"""
|
|
1783
|
+
Dispatch to the appropriate class based on the input.
|
|
1784
|
+
|
|
1785
|
+
EXAMPLES::
|
|
1786
|
+
|
|
1787
|
+
sage: # needs sage.combinat sage.groups
|
|
1788
|
+
sage: Q = RootSystem(['A',3]).root_space(GF(3))
|
|
1789
|
+
sage: W = WeylGroup(['A',3], prefix='s')
|
|
1790
|
+
sage: CP = cartesian_product([Q, W])
|
|
1791
|
+
sage: type(CP)
|
|
1792
|
+
<class 'sage.sets.cartesian_product.CartesianProduct_with_category'>
|
|
1793
|
+
"""
|
|
1794
|
+
R = modules[0].base_ring()
|
|
1795
|
+
Cat = ModulesWithBasis(R)
|
|
1796
|
+
if any(module not in Cat for module in modules):
|
|
1797
|
+
from sage.sets.cartesian_product import CartesianProduct
|
|
1798
|
+
return CartesianProduct(modules, category, **options)
|
|
1799
|
+
return super().__classcall__(cls, modules, category=category, **options)
|
|
1800
|
+
|
|
1801
|
+
def __init__(self, modules, **options):
|
|
1802
|
+
r"""
|
|
1803
|
+
TESTS::
|
|
1804
|
+
|
|
1805
|
+
sage: F = CombinatorialFreeModule(ZZ, [2,4,5])
|
|
1806
|
+
sage: G = CombinatorialFreeModule(ZZ, [2,4,7])
|
|
1807
|
+
sage: C = cartesian_product([F, G]) ; C
|
|
1808
|
+
Free module generated by {2, 4, 5} over Integer Ring (+) Free module generated by {2, 4, 7} over Integer Ring
|
|
1809
|
+
sage: TestSuite(C).run()
|
|
1810
|
+
"""
|
|
1811
|
+
assert len(modules) # TODO: generalize to a family or tuple
|
|
1812
|
+
R = modules[0].base_ring()
|
|
1813
|
+
assert all(module in ModulesWithBasis(R) for module in modules)
|
|
1814
|
+
# should check the base ring
|
|
1815
|
+
self._sets = modules
|
|
1816
|
+
CombinatorialFreeModule.__init__(self, R,
|
|
1817
|
+
DisjointUnionEnumeratedSets(
|
|
1818
|
+
[module.basis().keys() for module in modules], keepkey=True),
|
|
1819
|
+
**options)
|
|
1820
|
+
|
|
1821
|
+
def _sets_keys(self):
|
|
1822
|
+
"""
|
|
1823
|
+
In waiting for ``self._sets.keys()``.
|
|
1824
|
+
|
|
1825
|
+
TESTS::
|
|
1826
|
+
|
|
1827
|
+
sage: F = CombinatorialFreeModule(ZZ, [2,4,5])
|
|
1828
|
+
sage: G = CombinatorialFreeModule(ZZ, [2,4,7])
|
|
1829
|
+
sage: CP = cartesian_product([F, G])
|
|
1830
|
+
sage: CP._sets_keys()
|
|
1831
|
+
[0, 1]
|
|
1832
|
+
"""
|
|
1833
|
+
return list(range(len(self._sets)))
|
|
1834
|
+
|
|
1835
|
+
def _repr_(self):
|
|
1836
|
+
"""
|
|
1837
|
+
TESTS::
|
|
1838
|
+
|
|
1839
|
+
sage: F = CombinatorialFreeModule(ZZ, [2,4,5])
|
|
1840
|
+
sage: CP = cartesian_product([F, F]); CP # indirect doctest
|
|
1841
|
+
Free module generated by {2, 4, 5} over Integer Ring (+) Free module generated by {2, 4, 5} over Integer Ring
|
|
1842
|
+
sage: F.rename('F'); CP
|
|
1843
|
+
F (+) F
|
|
1844
|
+
"""
|
|
1845
|
+
from sage.categories.cartesian_product import cartesian_product
|
|
1846
|
+
return cartesian_product.symbol.join("%s" % module
|
|
1847
|
+
for module in self._sets)
|
|
1848
|
+
# TODO: make this overridable by setting _name
|
|
1849
|
+
|
|
1850
|
+
@cached_method
|
|
1851
|
+
def cartesian_embedding(self, i):
|
|
1852
|
+
"""
|
|
1853
|
+
Return the natural embedding morphism of the ``i``-th
|
|
1854
|
+
Cartesian factor (summand) of ``self`` into ``self``.
|
|
1855
|
+
|
|
1856
|
+
INPUT:
|
|
1857
|
+
|
|
1858
|
+
- ``i`` -- integer
|
|
1859
|
+
|
|
1860
|
+
EXAMPLES::
|
|
1861
|
+
|
|
1862
|
+
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename('F')
|
|
1863
|
+
sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename('G')
|
|
1864
|
+
sage: S = cartesian_product([F, G])
|
|
1865
|
+
sage: phi = S.cartesian_embedding(0)
|
|
1866
|
+
sage: phi(F.monomial(4) + 2 * F.monomial(5))
|
|
1867
|
+
B[(0, 4)] + 2*B[(0, 5)]
|
|
1868
|
+
sage: phi(F.monomial(4) + 2 * F.monomial(6)).parent() == S
|
|
1869
|
+
True
|
|
1870
|
+
|
|
1871
|
+
TESTS::
|
|
1872
|
+
|
|
1873
|
+
sage: phi(G.monomial(4))
|
|
1874
|
+
Traceback (most recent call last):
|
|
1875
|
+
...
|
|
1876
|
+
AssertionError
|
|
1877
|
+
"""
|
|
1878
|
+
assert i in self._sets_keys()
|
|
1879
|
+
return self._sets[i]._module_morphism(lambda t: self.monomial((i, t)),
|
|
1880
|
+
codomain=self)
|
|
1881
|
+
|
|
1882
|
+
summand_embedding = cartesian_embedding
|
|
1883
|
+
|
|
1884
|
+
@cached_method
|
|
1885
|
+
def cartesian_projection(self, i):
|
|
1886
|
+
"""
|
|
1887
|
+
Return the natural projection onto the `i`-th Cartesian factor
|
|
1888
|
+
(summand) of ``self``.
|
|
1889
|
+
|
|
1890
|
+
INPUT:
|
|
1891
|
+
|
|
1892
|
+
- ``i`` -- integer
|
|
1893
|
+
|
|
1894
|
+
EXAMPLES::
|
|
1895
|
+
|
|
1896
|
+
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename('F')
|
|
1897
|
+
sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename('G')
|
|
1898
|
+
sage: S = cartesian_product([F, G])
|
|
1899
|
+
sage: x = S.monomial((0,4)) + 2 * S.monomial((0,5)) + 3 * S.monomial((1,6))
|
|
1900
|
+
sage: S.cartesian_projection(0)(x)
|
|
1901
|
+
B[4] + 2*B[5]
|
|
1902
|
+
sage: S.cartesian_projection(1)(x)
|
|
1903
|
+
3*B[6]
|
|
1904
|
+
sage: S.cartesian_projection(0)(x).parent() == F
|
|
1905
|
+
True
|
|
1906
|
+
sage: S.cartesian_projection(1)(x).parent() == G
|
|
1907
|
+
True
|
|
1908
|
+
"""
|
|
1909
|
+
assert i in self._sets_keys()
|
|
1910
|
+
module = self._sets[i]
|
|
1911
|
+
return self._module_morphism(lambda j_t: module.monomial(j_t[1]) if i == j_t[0] else module.zero(), codomain=module)
|
|
1912
|
+
|
|
1913
|
+
summand_projection = cartesian_projection
|
|
1914
|
+
|
|
1915
|
+
def _cartesian_product_of_elements(self, elements):
|
|
1916
|
+
"""
|
|
1917
|
+
Return the Cartesian product of the elements.
|
|
1918
|
+
|
|
1919
|
+
INPUT:
|
|
1920
|
+
|
|
1921
|
+
- ``elements`` -- an iterable (e.g. tuple, list) with one element of
|
|
1922
|
+
each Cartesian factor of ``self``
|
|
1923
|
+
|
|
1924
|
+
EXAMPLES::
|
|
1925
|
+
|
|
1926
|
+
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename('F')
|
|
1927
|
+
sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename('G')
|
|
1928
|
+
sage: S = cartesian_product([F, G])
|
|
1929
|
+
sage: f = F.monomial(4) + 2*F.monomial(5)
|
|
1930
|
+
sage: g = 2*G.monomial(4) + G.monomial(6)
|
|
1931
|
+
sage: S._cartesian_product_of_elements([f, g])
|
|
1932
|
+
B[(0, 4)] + 2*B[(0, 5)] + 2*B[(1, 4)] + B[(1, 6)]
|
|
1933
|
+
sage: S._cartesian_product_of_elements([f, g]).parent() == S
|
|
1934
|
+
True
|
|
1935
|
+
|
|
1936
|
+
TESTS:
|
|
1937
|
+
|
|
1938
|
+
The ``elements`` can be a generator as in :issue:`31453`::
|
|
1939
|
+
|
|
1940
|
+
sage: from sage.categories.magmatic_algebras import (
|
|
1941
|
+
....: MagmaticAlgebras)
|
|
1942
|
+
sage: class TrivialCFM(CombinatorialFreeModule):
|
|
1943
|
+
....: def __init__(self):
|
|
1944
|
+
....: c = MagmaticAlgebras(QQ).WithBasis().Unital()
|
|
1945
|
+
....: super().__init__(QQ,[1],category=c)
|
|
1946
|
+
....: def one(self):
|
|
1947
|
+
....: return self.monomial(0)
|
|
1948
|
+
sage: c1 = TrivialCFM()
|
|
1949
|
+
sage: c1.one()
|
|
1950
|
+
B[0]
|
|
1951
|
+
sage: CP = cartesian_product([c1,c1])
|
|
1952
|
+
sage: CP.one()
|
|
1953
|
+
B[(0, 0)] + B[(1, 0)]
|
|
1954
|
+
"""
|
|
1955
|
+
return self.sum(self.summand_embedding(i)(element_i)
|
|
1956
|
+
for (i, element_i) in zip(self._sets_keys(),
|
|
1957
|
+
elements))
|
|
1958
|
+
|
|
1959
|
+
def cartesian_factors(self):
|
|
1960
|
+
"""
|
|
1961
|
+
Return the factors of the Cartesian product.
|
|
1962
|
+
|
|
1963
|
+
EXAMPLES::
|
|
1964
|
+
|
|
1965
|
+
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename('F')
|
|
1966
|
+
sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename('G')
|
|
1967
|
+
sage: S = cartesian_product([F, G])
|
|
1968
|
+
sage: S.cartesian_factors()
|
|
1969
|
+
(F, G)
|
|
1970
|
+
"""
|
|
1971
|
+
return self._sets
|
|
1972
|
+
|
|
1973
|
+
class Element(CombinatorialFreeModule.Element): # TODO: get rid of this inheritance
|
|
1974
|
+
pass
|
|
1975
|
+
|
|
1976
|
+
|
|
1977
|
+
CombinatorialFreeModule.CartesianProduct = CombinatorialFreeModule_CartesianProduct
|