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,1636 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
r"""
|
|
3
|
+
Morphisms of modules with a basis
|
|
4
|
+
|
|
5
|
+
This module contains a hierarchy of classes for morphisms of modules
|
|
6
|
+
with a basis (category :class:`Modules.WithBasis`):
|
|
7
|
+
|
|
8
|
+
- :class:`ModuleMorphism`
|
|
9
|
+
- :class:`ModuleMorphismByLinearity`
|
|
10
|
+
- :class:`ModuleMorphismFromMatrix`
|
|
11
|
+
- :class:`ModuleMorphismFromFunction`
|
|
12
|
+
- :class:`TriangularModuleMorphism`
|
|
13
|
+
- :class:`TriangularModuleMorphismByLinearity`
|
|
14
|
+
- :class:`TriangularModuleMorphismFromFunction`
|
|
15
|
+
|
|
16
|
+
These are internal classes; it is recommended *not* to use them
|
|
17
|
+
directly, and instead to construct morphisms through the
|
|
18
|
+
:meth:`ModulesWithBasis.ParentMethods.module_morphism` method of the
|
|
19
|
+
domain, or through the homset. See the former for an overview
|
|
20
|
+
of the possible arguments.
|
|
21
|
+
|
|
22
|
+
EXAMPLES:
|
|
23
|
+
|
|
24
|
+
We construct a morphism through the method
|
|
25
|
+
:meth:`ModulesWithBasis.ParentMethods.module_morphism`, by specifying
|
|
26
|
+
the image of each element of the distinguished basis::
|
|
27
|
+
|
|
28
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); x = X.basis()
|
|
29
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); y = Y.basis()
|
|
30
|
+
sage: on_basis = lambda i: Y.monomial(i) + 2*Y.monomial(i+1)
|
|
31
|
+
|
|
32
|
+
sage: phi1 = X.module_morphism(on_basis, codomain=Y)
|
|
33
|
+
sage: phi1(x[1])
|
|
34
|
+
B[1] + 2*B[2]
|
|
35
|
+
|
|
36
|
+
sage: phi1
|
|
37
|
+
Generic morphism:
|
|
38
|
+
From: Free module generated by {1, 2, 3} over Rational Field
|
|
39
|
+
To: Free module generated by {1, 2, 3, 4} over Rational Field
|
|
40
|
+
sage: phi1.parent()
|
|
41
|
+
Set of Morphisms from Free module generated by {1, 2, 3} over Rational Field to Free module generated by {1, 2, 3, 4} over Rational Field in Category of finite dimensional vector spaces with basis over Rational Field
|
|
42
|
+
sage: phi1.__class__
|
|
43
|
+
<class 'sage.modules.with_basis.morphism.ModuleMorphismByLinearity_with_category'>
|
|
44
|
+
|
|
45
|
+
Constructing the same morphism from the homset::
|
|
46
|
+
|
|
47
|
+
sage: H = Hom(X,Y)
|
|
48
|
+
sage: phi2 = H(on_basis=on_basis)
|
|
49
|
+
sage: phi1 == phi2
|
|
50
|
+
True
|
|
51
|
+
|
|
52
|
+
Constructing the same morphism directly using the class; no backward
|
|
53
|
+
compatibility is guaranteed in this case::
|
|
54
|
+
|
|
55
|
+
sage: from sage.modules.with_basis.morphism import ModuleMorphismByLinearity
|
|
56
|
+
sage: phi3 = ModuleMorphismByLinearity(X, on_basis, codomain=Y)
|
|
57
|
+
sage: phi3 == phi1
|
|
58
|
+
True
|
|
59
|
+
|
|
60
|
+
.. WARNING::
|
|
61
|
+
|
|
62
|
+
The hierarchy of classes implemented in this module is one of the
|
|
63
|
+
first non-trivial hierarchies of classes for morphisms. It is
|
|
64
|
+
hitting a couple scaling issues:
|
|
65
|
+
|
|
66
|
+
- There are many independent properties from which module
|
|
67
|
+
morphisms can get code (being defined by linearity, from a
|
|
68
|
+
matrix, or a function; being triangular, being diagonal,
|
|
69
|
+
...). How to mitigate the class hierarchy growth?
|
|
70
|
+
|
|
71
|
+
This will become even more stringent as more properties are
|
|
72
|
+
added (e.g. being defined from generators for an algebra
|
|
73
|
+
morphism, ...)
|
|
74
|
+
|
|
75
|
+
Categories, whose primary purpose is to provide infrastructure
|
|
76
|
+
for handling such large hierarchy of classes, can't help at this
|
|
77
|
+
point: there is no category whose morphisms are triangular
|
|
78
|
+
morphisms, and it's not clear such a category would be sensible.
|
|
79
|
+
|
|
80
|
+
- How to properly handle ``__init__`` method calls and
|
|
81
|
+
multiple inheritance?
|
|
82
|
+
|
|
83
|
+
- Who should be in charge of setting the default category: the
|
|
84
|
+
classes themselves, or
|
|
85
|
+
:meth:`ModulesWithBasis.ParentMethods.module_morphism`?
|
|
86
|
+
|
|
87
|
+
Because of this, the hierarchy of classes, and the specific APIs,
|
|
88
|
+
is likely to be refactored as better infrastructure and best
|
|
89
|
+
practices emerge.
|
|
90
|
+
|
|
91
|
+
AUTHORS:
|
|
92
|
+
|
|
93
|
+
- Nicolas M. Thiery (2008-2015)
|
|
94
|
+
|
|
95
|
+
- Jason Bandlow and Florent Hivert (2010): Triangular Morphisms
|
|
96
|
+
|
|
97
|
+
- Christian Stump (2010): :issue:`9648` module_morphism's to a wider class
|
|
98
|
+
of codomains
|
|
99
|
+
|
|
100
|
+
Before :issue:`8678`, this hierarchy of classes used to be in
|
|
101
|
+
sage.categories.modules_with_basis; see :issue:`8678` for the complete log.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
# ****************************************************************************
|
|
105
|
+
# Copyright (C) 2015 Nicolas M. Thiery <nthiery at users.sf.net>
|
|
106
|
+
#
|
|
107
|
+
# This program is free software: you can redistribute it and/or modify
|
|
108
|
+
# it under the terms of the GNU General Public License as published by
|
|
109
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
110
|
+
# (at your option) any later version.
|
|
111
|
+
# https://www.gnu.org/licenses/
|
|
112
|
+
# ****************************************************************************
|
|
113
|
+
|
|
114
|
+
from sage.categories.fields import Fields
|
|
115
|
+
from sage.categories.modules import Modules
|
|
116
|
+
from sage.misc.call import attrcall
|
|
117
|
+
# The identity function would deserve a more canonical location
|
|
118
|
+
from sage.misc.c3_controlled import identity
|
|
119
|
+
from sage.categories.commutative_additive_semigroups import CommutativeAdditiveSemigroups
|
|
120
|
+
from sage.categories.homset import Hom
|
|
121
|
+
from sage.categories.modules_with_basis import ModulesWithBasis
|
|
122
|
+
from sage.categories.morphism import SetMorphism, Morphism
|
|
123
|
+
from sage.categories.sets_cat import Sets
|
|
124
|
+
from sage.categories.sets_with_partial_maps import SetsWithPartialMaps
|
|
125
|
+
from sage.structure.richcmp import op_EQ, op_NE
|
|
126
|
+
from sage.structure.element import Matrix
|
|
127
|
+
from sage.structure.sage_object import SageObject
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class ModuleMorphism(Morphism):
|
|
131
|
+
"""
|
|
132
|
+
The top abstract base class for module with basis morphisms.
|
|
133
|
+
|
|
134
|
+
INPUT:
|
|
135
|
+
|
|
136
|
+
- ``domain`` -- a parent in ``ModulesWithBasis(...)``
|
|
137
|
+
- ``codomain`` -- a parent in ``Modules(...)``
|
|
138
|
+
- ``category`` -- a category or ``None`` (default: ``None``)
|
|
139
|
+
- ``affine`` -- whether we define an affine module morphism
|
|
140
|
+
(default: ``False``)
|
|
141
|
+
|
|
142
|
+
Construct a module morphism from ``domain`` to ``codomain`` in the
|
|
143
|
+
category ``category``. By default, the category is the first of
|
|
144
|
+
``Modules(R).WithBasis().FiniteDimensional()``,
|
|
145
|
+
``Modules(R).WithBasis()``, ``Modules(R)``,
|
|
146
|
+
``CommutativeAdditiveMonoids()`` that contains both the domain and
|
|
147
|
+
the codomain. If initializing an affine morphism, then `Sets()` is
|
|
148
|
+
used instead.
|
|
149
|
+
|
|
150
|
+
.. SEEALSO::
|
|
151
|
+
|
|
152
|
+
- :meth:`ModulesWithBasis.ParentMethods.module_morphism` for
|
|
153
|
+
usage information and examples;
|
|
154
|
+
- :mod:`sage.modules.with_basis.morphism` for a technical
|
|
155
|
+
overview of the classes for module morphisms;
|
|
156
|
+
- :class:`ModuleMorphismFromFunction` and
|
|
157
|
+
:class:`TriangularModuleMorphism`.
|
|
158
|
+
|
|
159
|
+
The role of this class is minimal: it provides an :meth:`__init__`
|
|
160
|
+
method which:
|
|
161
|
+
|
|
162
|
+
- handles the choice of the default category
|
|
163
|
+
- handles the proper inheritance from categories by updating the
|
|
164
|
+
class of ``self`` upon construction.
|
|
165
|
+
"""
|
|
166
|
+
def __init__(self, domain, codomain=None, category=None, affine=False):
|
|
167
|
+
"""
|
|
168
|
+
Initialization of module morphisms.
|
|
169
|
+
|
|
170
|
+
TESTS::
|
|
171
|
+
|
|
172
|
+
sage: X = CombinatorialFreeModule(ZZ, [-2, -1, 1, 2])
|
|
173
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1, 2])
|
|
174
|
+
sage: from sage.modules.with_basis.morphism import ModuleMorphismByLinearity
|
|
175
|
+
sage: phi = ModuleMorphismByLinearity(X, on_basis=Y.monomial * abs)
|
|
176
|
+
sage: TestSuite(phi).run()
|
|
177
|
+
"""
|
|
178
|
+
if category is None:
|
|
179
|
+
if domain not in ModulesWithBasis:
|
|
180
|
+
raise ValueError("domain(=%s) should be a module with basis" % codomain)
|
|
181
|
+
base_ring = domain.base_ring()
|
|
182
|
+
|
|
183
|
+
if not hasattr(codomain, 'base_ring'):
|
|
184
|
+
raise ValueError("codomain(=%s) needs to have a base_ring attribute" % codomain)
|
|
185
|
+
# codomain should be a module over base_ring
|
|
186
|
+
# The natural test would be ``codomains in Modules(base_ring)``
|
|
187
|
+
# But this is not properly implemented yet::
|
|
188
|
+
#
|
|
189
|
+
# sage: CC in Modules(QQ)
|
|
190
|
+
# False
|
|
191
|
+
# sage: QQ in Modules(QQ)
|
|
192
|
+
# False
|
|
193
|
+
# sage: CC[x] in Modules(QQ)
|
|
194
|
+
# False
|
|
195
|
+
|
|
196
|
+
# The test below is a bit more restrictive
|
|
197
|
+
if (not codomain.base_ring().has_coerce_map_from(base_ring)) \
|
|
198
|
+
and (not codomain.has_coerce_map_from(base_ring)):
|
|
199
|
+
raise ValueError("codomain(=%s) should be a module over the base ring of the domain(=%s)" % (codomain, domain))
|
|
200
|
+
|
|
201
|
+
if affine:
|
|
202
|
+
# We don't yet have a category whose morphisms are affine morphisms
|
|
203
|
+
category = Sets()
|
|
204
|
+
else:
|
|
205
|
+
C = Modules(base_ring)
|
|
206
|
+
for D in [C.WithBasis().FiniteDimensional(),
|
|
207
|
+
C.WithBasis(),
|
|
208
|
+
C,
|
|
209
|
+
# QQ is not in Modules(QQ)!
|
|
210
|
+
CommutativeAdditiveSemigroups()]:
|
|
211
|
+
if codomain in D and domain in D:
|
|
212
|
+
category = D
|
|
213
|
+
break
|
|
214
|
+
if category is None:
|
|
215
|
+
raise ValueError("codomain=(%s) should at least be a commutative additive semigroup")
|
|
216
|
+
|
|
217
|
+
H = Hom(domain, codomain, category=category)
|
|
218
|
+
Morphism.__init__(self, H)
|
|
219
|
+
|
|
220
|
+
# If needed, this creates the element class from the concrete
|
|
221
|
+
# class (ModuleMorphismByLinearity, DiagonalModuleMorphism,
|
|
222
|
+
# ...) and the abstract classes from the categories.
|
|
223
|
+
#
|
|
224
|
+
# The category infrastructure handles this automatically for
|
|
225
|
+
# parents with a single element class. But for now we still
|
|
226
|
+
# need to do it by hand here, since H may have many different
|
|
227
|
+
# element classes
|
|
228
|
+
if not issubclass(self.__class__, H._abstract_element_class):
|
|
229
|
+
self.__class__ = H.__make_element_class__(self.__class__)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class ModuleMorphismFromFunction(ModuleMorphism, SetMorphism):
|
|
233
|
+
"""
|
|
234
|
+
A class for module morphisms implemented by a plain function.
|
|
235
|
+
|
|
236
|
+
INPUT:
|
|
237
|
+
|
|
238
|
+
- ``domain``, ``codomain``, ``category`` -- as for :class:`ModuleMorphism`
|
|
239
|
+
|
|
240
|
+
- ``function`` -- any function or callable from domain to codomain
|
|
241
|
+
|
|
242
|
+
.. SEEALSO::
|
|
243
|
+
|
|
244
|
+
- :meth:`ModulesWithBasis.ParentMethods.module_morphism` for
|
|
245
|
+
usage information and examples;
|
|
246
|
+
- :mod:`sage.modules.with_basis.morphism` for a technical
|
|
247
|
+
overview of the classes for module morphisms;
|
|
248
|
+
- :class:`ModuleMorphismFromFunction` and
|
|
249
|
+
:class:`TriangularModuleMorphism`.
|
|
250
|
+
"""
|
|
251
|
+
|
|
252
|
+
def __init__(self, domain, function, codomain=None, category=None):
|
|
253
|
+
"""
|
|
254
|
+
TESTS::
|
|
255
|
+
|
|
256
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename('X'); x = X.basis()
|
|
257
|
+
sage: from sage.modules.with_basis.morphism import ModuleMorphismFromFunction
|
|
258
|
+
sage: def f(x): return 3*x
|
|
259
|
+
sage: import __main__; __main__.f = f # Fake f being defined in a python module
|
|
260
|
+
sage: phi = ModuleMorphismFromFunction(X, f, codomain=X)
|
|
261
|
+
sage: phi(x[1])
|
|
262
|
+
3*B[1]
|
|
263
|
+
sage: TestSuite(phi).run()
|
|
264
|
+
"""
|
|
265
|
+
# Caveat: This calls Morphism.__init__ twice ...
|
|
266
|
+
ModuleMorphism.__init__(self, domain, codomain, category=category)
|
|
267
|
+
SetMorphism.__init__(self, self.parent(), function)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class ModuleMorphismByLinearity(ModuleMorphism):
|
|
271
|
+
"""
|
|
272
|
+
A class for module morphisms obtained by extending a function by linearity.
|
|
273
|
+
|
|
274
|
+
INPUT:
|
|
275
|
+
|
|
276
|
+
- ``domain``, ``codomain``, ``category`` -- as for :class:`ModuleMorphism`
|
|
277
|
+
- ``on_basis`` -- a function which accepts indices of the basis of
|
|
278
|
+
``domain`` as ``position``-th argument
|
|
279
|
+
- ``codomain`` -- a parent in ``Modules(...)``
|
|
280
|
+
(default: ``on_basis.codomain()``)
|
|
281
|
+
- ``position`` -- nonnegative integer (default: 0)
|
|
282
|
+
- ``zero`` -- the zero of the codomain (defaults: ``codomain.zero()``)
|
|
283
|
+
|
|
284
|
+
.. SEEALSO::
|
|
285
|
+
|
|
286
|
+
- :meth:`ModulesWithBasis.ParentMethods.module_morphism` for
|
|
287
|
+
usage information and examples;
|
|
288
|
+
- :mod:`sage.modules.with_basis.morphism` for a technical
|
|
289
|
+
overview of the classes for module morphisms;
|
|
290
|
+
- :class:`ModuleMorphismFromFunction` and
|
|
291
|
+
:class:`TriangularModuleMorphism`.
|
|
292
|
+
|
|
293
|
+
.. NOTE::
|
|
294
|
+
|
|
295
|
+
``on_basis`` may alternatively be provided in derived classes
|
|
296
|
+
by passing ``None`` as argument, and implementing or setting
|
|
297
|
+
the attribute ``_on_basis``
|
|
298
|
+
"""
|
|
299
|
+
def __init__(self, domain, on_basis=None, codomain=None, category=None,
|
|
300
|
+
position=0, zero=None):
|
|
301
|
+
"""
|
|
302
|
+
TESTS::
|
|
303
|
+
|
|
304
|
+
sage: X = CombinatorialFreeModule(ZZ, [-2, -1, 1, 2])
|
|
305
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1, 2])
|
|
306
|
+
sage: from sage.modules.with_basis.morphism import ModuleMorphismByLinearity
|
|
307
|
+
sage: phi = ModuleMorphismByLinearity(X, on_basis=Y.monomial * abs)
|
|
308
|
+
|
|
309
|
+
sage: TestSuite(phi).run()
|
|
310
|
+
"""
|
|
311
|
+
# Might want to assert that domain is a module with basis
|
|
312
|
+
base_ring = domain.base_ring()
|
|
313
|
+
|
|
314
|
+
if codomain is None and hasattr(on_basis, 'codomain'):
|
|
315
|
+
codomain = on_basis.codomain()
|
|
316
|
+
if zero is None:
|
|
317
|
+
zero = codomain.zero()
|
|
318
|
+
self._zero = zero
|
|
319
|
+
self._position = position
|
|
320
|
+
if on_basis is not None:
|
|
321
|
+
self._on_basis = on_basis
|
|
322
|
+
|
|
323
|
+
self._is_module_with_basis_over_same_base_ring = \
|
|
324
|
+
codomain in ModulesWithBasis(base_ring) and zero == codomain.zero()
|
|
325
|
+
|
|
326
|
+
ModuleMorphism.__init__(self, domain, codomain,
|
|
327
|
+
category=category,
|
|
328
|
+
affine=(zero != codomain.zero()))
|
|
329
|
+
|
|
330
|
+
def _richcmp_(self, other, op):
|
|
331
|
+
r"""
|
|
332
|
+
Return whether this morphism and ``other`` satisfy ``op``.
|
|
333
|
+
|
|
334
|
+
TESTS::
|
|
335
|
+
|
|
336
|
+
sage: X = CombinatorialFreeModule(ZZ, [-2, -1, 1, 2])
|
|
337
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1, 2])
|
|
338
|
+
sage: f = X.module_morphism(on_basis=Y.monomial * abs)
|
|
339
|
+
sage: g = X.module_morphism(on_basis=Y.monomial * abs)
|
|
340
|
+
sage: h1 = X.module_morphism(on_basis=X.monomial * abs)
|
|
341
|
+
sage: h2 = X.module_morphism(on_basis=X.monomial * factorial)
|
|
342
|
+
sage: h3 = X.module_morphism(on_basis=Y.monomial * abs, category=Modules(ZZ))
|
|
343
|
+
sage: f == g, f == h1, f == h2, f == h3, f == 1, 1 == f
|
|
344
|
+
(True, False, False, False, False, False)
|
|
345
|
+
"""
|
|
346
|
+
if op == op_EQ:
|
|
347
|
+
return (self.__class__ is other.__class__
|
|
348
|
+
and self._zero == other._zero
|
|
349
|
+
and self._on_basis == other._on_basis
|
|
350
|
+
and self._position == other._position
|
|
351
|
+
and self._is_module_with_basis_over_same_base_ring == other._is_module_with_basis_over_same_base_ring)
|
|
352
|
+
if op == op_NE:
|
|
353
|
+
return not (self == other)
|
|
354
|
+
return NotImplemented
|
|
355
|
+
|
|
356
|
+
def on_basis(self):
|
|
357
|
+
"""
|
|
358
|
+
Return the action of this morphism on basis elements, as per
|
|
359
|
+
:meth:`ModulesWithBasis.Homsets.ElementMethods.on_basis`.
|
|
360
|
+
|
|
361
|
+
OUTPUT:
|
|
362
|
+
|
|
363
|
+
- a function from the indices of the basis of the domain to the
|
|
364
|
+
codomain
|
|
365
|
+
|
|
366
|
+
EXAMPLES::
|
|
367
|
+
|
|
368
|
+
sage: X = CombinatorialFreeModule(ZZ, [-2, -1, 1, 2])
|
|
369
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1, 2])
|
|
370
|
+
sage: phi_on_basis = Y.monomial * abs
|
|
371
|
+
sage: phi = sage.modules.with_basis.morphism.ModuleMorphismByLinearity(X, on_basis = phi_on_basis, codomain=Y)
|
|
372
|
+
sage: x = X.basis()
|
|
373
|
+
sage: phi.on_basis()(-2)
|
|
374
|
+
B[2]
|
|
375
|
+
sage: phi.on_basis() == phi_on_basis
|
|
376
|
+
True
|
|
377
|
+
"""
|
|
378
|
+
return self._on_basis
|
|
379
|
+
|
|
380
|
+
def __call__(self, *args):
|
|
381
|
+
r"""
|
|
382
|
+
Apply this morphism to ``*args``.
|
|
383
|
+
|
|
384
|
+
EXAMPLES::
|
|
385
|
+
|
|
386
|
+
sage: X = CombinatorialFreeModule(ZZ, [-2, -1, 1, 2])
|
|
387
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1, 2])
|
|
388
|
+
sage: def phi_on_basis(i): return Y.monomial(abs(i))
|
|
389
|
+
sage: phi = sage.modules.with_basis.morphism.ModuleMorphismByLinearity(X, on_basis = Y.monomial * abs, codomain=Y)
|
|
390
|
+
sage: x = X.basis()
|
|
391
|
+
sage: phi(x[1]), phi(x[-2]), phi(x[1] + 3 * x[-2])
|
|
392
|
+
(B[1], B[2], B[1] + 3*B[2])
|
|
393
|
+
|
|
394
|
+
.. TODO::
|
|
395
|
+
|
|
396
|
+
Add more tests for multi-parameter module morphisms.
|
|
397
|
+
"""
|
|
398
|
+
before = args[0:self._position]
|
|
399
|
+
after = args[self._position + 1:len(args)]
|
|
400
|
+
x = args[self._position]
|
|
401
|
+
assert x.parent() is self.domain()
|
|
402
|
+
|
|
403
|
+
mc = x.monomial_coefficients(copy=False)
|
|
404
|
+
if self._is_module_with_basis_over_same_base_ring:
|
|
405
|
+
return self.codomain().linear_combination(
|
|
406
|
+
(self._on_basis(*(before + (index,) + after)), coeff)
|
|
407
|
+
for (index, coeff) in mc.items())
|
|
408
|
+
else:
|
|
409
|
+
return sum((coeff * self._on_basis(*(before + (index,) + after))
|
|
410
|
+
for (index, coeff) in mc.items()), self._zero)
|
|
411
|
+
|
|
412
|
+
# As per the specs of Map, we should in fact implement _call_.
|
|
413
|
+
# However we currently need to abuse Map.__call__ (which strict
|
|
414
|
+
# type checking) for multi-parameter module morphisms
|
|
415
|
+
# To be cleaned up
|
|
416
|
+
_call_ = __call__
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
class TriangularModuleMorphism(ModuleMorphism):
|
|
420
|
+
r"""
|
|
421
|
+
An abstract class for triangular module morphisms.
|
|
422
|
+
|
|
423
|
+
Let `X` and `Y` be modules over the same base ring, with
|
|
424
|
+
distinguished bases `F` indexed by `I` and `G` indexed by `J`,
|
|
425
|
+
respectively.
|
|
426
|
+
|
|
427
|
+
A module morphism `\phi` from `X` to `Y` is *triangular* if its
|
|
428
|
+
representing matrix in the distinguished bases of `X` and `Y` is
|
|
429
|
+
upper triangular (echelon form).
|
|
430
|
+
|
|
431
|
+
More precisely, `\phi` is *upper triangular* w.r.t. a total order
|
|
432
|
+
`<` on `J` if, for any `j\in J`, there exists at most one index
|
|
433
|
+
`i\in I` such that the leading support of `\phi(F_i)` is `j` (see
|
|
434
|
+
:meth:`leading_support()`). We denote by `r(j)` this index,
|
|
435
|
+
setting `r(j)` to ``None`` if it does not exist.
|
|
436
|
+
|
|
437
|
+
*Lower triangular* morphisms are defined similarly, taking the
|
|
438
|
+
trailing support instead (see :meth:`trailing_support()`).
|
|
439
|
+
|
|
440
|
+
A triangular morphism is *unitriangular* if all its pivots
|
|
441
|
+
(i.e. coefficient of `j` in each `\phi(F[r(j)])`) are `1`.
|
|
442
|
+
|
|
443
|
+
INPUT:
|
|
444
|
+
|
|
445
|
+
- ``domain`` -- a module with basis `X`
|
|
446
|
+
- ``codomain`` -- a module with basis `Y` (default: `X`)
|
|
447
|
+
- ``category`` -- a category, as for :class:`ModuleMorphism`
|
|
448
|
+
|
|
449
|
+
- ``triangular`` -- ``'upper'`` or ``'lower'`` (default: ``'upper'``)
|
|
450
|
+
- ``unitriangular`` -- boolean (default: ``False``)
|
|
451
|
+
As a shorthand, one may use ``unitriangular='lower'``
|
|
452
|
+
for ``triangular='lower', unitriangular=True``.
|
|
453
|
+
|
|
454
|
+
- ``key`` -- a comparison key on `J`
|
|
455
|
+
(default: the usual comparison of elements of `J`)
|
|
456
|
+
|
|
457
|
+
- ``inverse_on_support`` -- a function `J \to I\cup \{None\}`
|
|
458
|
+
implementing `r` (default: the identity function).
|
|
459
|
+
If set to "compute", the values of `r(j)` are precomputed by
|
|
460
|
+
running through the index set `I` of the basis of the
|
|
461
|
+
domain. This of course requires the domain to be finite
|
|
462
|
+
dimensional.
|
|
463
|
+
|
|
464
|
+
- ``invertible`` -- boolean or ``None`` (default: ``None``); can
|
|
465
|
+
be set to specify that `\phi` is known to be (or not to be)
|
|
466
|
+
invertible. If the domain and codomain share the same indexing
|
|
467
|
+
set, this is by default automatically set to ``True`` if
|
|
468
|
+
``inverse_on_support`` is the identity, or in the finite
|
|
469
|
+
dimensional case.
|
|
470
|
+
|
|
471
|
+
.. SEEALSO::
|
|
472
|
+
|
|
473
|
+
- :meth:`ModulesWithBasis.ParentMethods.module_morphism` for
|
|
474
|
+
usage information and examples;
|
|
475
|
+
- :mod:`sage.modules.with_basis.morphism` for a technical
|
|
476
|
+
overview of the classes for module morphisms;
|
|
477
|
+
- :class:`ModuleMorphismFromFunction` and
|
|
478
|
+
:class:`TriangularModuleMorphism`.
|
|
479
|
+
|
|
480
|
+
OUTPUT: a morphism from `X` to `Y`
|
|
481
|
+
|
|
482
|
+
.. WARNING::
|
|
483
|
+
|
|
484
|
+
This class is meant to be used as a complement for a concrete
|
|
485
|
+
morphism class. In particular, the :meth:`__init__` method
|
|
486
|
+
focuses on setting up the data structure describing the
|
|
487
|
+
triangularity of the morphism. It purposely does *not* call
|
|
488
|
+
:meth:`ModuleMorphism.__init__` which should be called
|
|
489
|
+
(directly or indirectly) beforehand.
|
|
490
|
+
|
|
491
|
+
EXAMPLES:
|
|
492
|
+
|
|
493
|
+
We construct and invert an upper unitriangular module morphism between
|
|
494
|
+
two free `\QQ`-modules::
|
|
495
|
+
|
|
496
|
+
sage: I = range(1,200)
|
|
497
|
+
sage: X = CombinatorialFreeModule(QQ, I); X.rename('X'); x = X.basis()
|
|
498
|
+
sage: Y = CombinatorialFreeModule(QQ, I); Y.rename('Y'); y = Y.basis()
|
|
499
|
+
sage: ut = Y.sum_of_monomials * divisors # This * is map composition.
|
|
500
|
+
sage: phi = X.module_morphism(ut, unitriangular='upper', codomain=Y)
|
|
501
|
+
sage: phi(x[2])
|
|
502
|
+
B[1] + B[2]
|
|
503
|
+
sage: phi(x[6])
|
|
504
|
+
B[1] + B[2] + B[3] + B[6]
|
|
505
|
+
sage: phi(x[30])
|
|
506
|
+
B[1] + B[2] + B[3] + B[5] + B[6] + B[10] + B[15] + B[30]
|
|
507
|
+
sage: phi.preimage(y[2])
|
|
508
|
+
-B[1] + B[2]
|
|
509
|
+
sage: phi.preimage(y[6])
|
|
510
|
+
B[1] - B[2] - B[3] + B[6]
|
|
511
|
+
sage: phi.preimage(y[30])
|
|
512
|
+
-B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30]
|
|
513
|
+
sage: (phi^-1)(y[30])
|
|
514
|
+
-B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30]
|
|
515
|
+
|
|
516
|
+
A lower triangular (but not unitriangular) morphism::
|
|
517
|
+
|
|
518
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
519
|
+
sage: def lt(i): return sum(j*x[j] for j in range(i, 4))
|
|
520
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=X)
|
|
521
|
+
sage: phi(x[2])
|
|
522
|
+
2*B[2] + 3*B[3]
|
|
523
|
+
sage: phi.preimage(x[2])
|
|
524
|
+
1/2*B[2] - 1/2*B[3]
|
|
525
|
+
sage: phi(phi.preimage(x[2]))
|
|
526
|
+
B[2]
|
|
527
|
+
|
|
528
|
+
Using the ``key`` keyword, we can use triangularity even if
|
|
529
|
+
the map becomes triangular only after a permutation of the basis::
|
|
530
|
+
|
|
531
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
532
|
+
sage: def ut(i): return (x[1] + x[2] if i == 1 else x[2] + (x[3] if i == 3 else 0))
|
|
533
|
+
sage: perm = [0, 2, 1, 3]
|
|
534
|
+
sage: phi = X.module_morphism(ut, triangular='upper', codomain=X,
|
|
535
|
+
....: key=lambda a: perm[a])
|
|
536
|
+
sage: [phi(x[i]) for i in range(1, 4)]
|
|
537
|
+
[B[1] + B[2], B[2], B[2] + B[3]]
|
|
538
|
+
sage: [phi.preimage(x[i]) for i in range(1, 4)]
|
|
539
|
+
[B[1] - B[2], B[2], -B[2] + B[3]]
|
|
540
|
+
|
|
541
|
+
The same works in the lower-triangular case::
|
|
542
|
+
|
|
543
|
+
sage: def lt(i): return (x[1] + x[2] + x[3] if i == 2 else x[i])
|
|
544
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=X,
|
|
545
|
+
....: key=lambda a: perm[a])
|
|
546
|
+
sage: [phi(x[i]) for i in range(1, 4)]
|
|
547
|
+
[B[1], B[1] + B[2] + B[3], B[3]]
|
|
548
|
+
sage: [phi.preimage(x[i]) for i in range(1, 4)]
|
|
549
|
+
[B[1], -B[1] + B[2] - B[3], B[3]]
|
|
550
|
+
|
|
551
|
+
An injective but not surjective morphism cannot be inverted,
|
|
552
|
+
but the ``inverse_on_support`` keyword allows Sage to find a
|
|
553
|
+
partial inverse::
|
|
554
|
+
|
|
555
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); x = X.basis()
|
|
556
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4,5]); y = Y.basis()
|
|
557
|
+
sage: ult = lambda i: sum( y[j] for j in range(i+1,6) )
|
|
558
|
+
sage: phi = X.module_morphism(ult, unitriangular='lower', codomain=Y,
|
|
559
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
560
|
+
sage: phi(x[2])
|
|
561
|
+
B[3] + B[4] + B[5]
|
|
562
|
+
sage: phi.preimage(y[3])
|
|
563
|
+
B[2] - B[3]
|
|
564
|
+
|
|
565
|
+
The ``inverse_on_support`` keyword can also be used if the
|
|
566
|
+
bases of the domain and the codomain are identical but one of
|
|
567
|
+
them has to be permuted in order to render the morphism
|
|
568
|
+
triangular. For example::
|
|
569
|
+
|
|
570
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
571
|
+
sage: def ut(i):
|
|
572
|
+
....: return (x[3] if i == 1 else x[1] if i == 2
|
|
573
|
+
....: else x[1] + x[2])
|
|
574
|
+
sage: def perm(i):
|
|
575
|
+
....: return (2 if i == 1 else 3 if i == 2 else 1)
|
|
576
|
+
sage: phi = X.module_morphism(ut, triangular='upper', codomain=X,
|
|
577
|
+
....: inverse_on_support=perm)
|
|
578
|
+
sage: [phi(x[i]) for i in range(1, 4)]
|
|
579
|
+
[B[3], B[1], B[1] + B[2]]
|
|
580
|
+
sage: [phi.preimage(x[i]) for i in range(1, 4)]
|
|
581
|
+
[B[2], -B[2] + B[3], B[1]]
|
|
582
|
+
|
|
583
|
+
The same works if the permutation induces lower triangularity::
|
|
584
|
+
|
|
585
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
586
|
+
sage: def lt(i):
|
|
587
|
+
....: return (x[3] if i == 1 else x[2] if i == 2
|
|
588
|
+
....: else x[1] + x[2])
|
|
589
|
+
sage: def perm(i):
|
|
590
|
+
....: return 4 - i
|
|
591
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=X,
|
|
592
|
+
....: inverse_on_support=perm)
|
|
593
|
+
sage: [phi(x[i]) for i in range(1, 4)]
|
|
594
|
+
[B[3], B[2], B[1] + B[2]]
|
|
595
|
+
sage: [phi.preimage(x[i]) for i in range(1, 4)]
|
|
596
|
+
[-B[2] + B[3], B[2], B[1]]
|
|
597
|
+
|
|
598
|
+
In the finite dimensional case, one can ask Sage to recover
|
|
599
|
+
``inverse_on_support`` by a precomputation::
|
|
600
|
+
|
|
601
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); x = X.basis()
|
|
602
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3, 4]); y = Y.basis()
|
|
603
|
+
sage: ut = lambda i: sum( y[j] for j in range(1,i+2) )
|
|
604
|
+
sage: phi = X.module_morphism(ut, triangular='upper', codomain=Y,
|
|
605
|
+
....: inverse_on_support='compute')
|
|
606
|
+
sage: tx = "{} {} {}"
|
|
607
|
+
sage: for j in Y.basis().keys():
|
|
608
|
+
....: i = phi._inverse_on_support(j)
|
|
609
|
+
....: print(tx.format(j, i, phi(x[i]) if i is not None else None))
|
|
610
|
+
1 None None
|
|
611
|
+
2 1 B[1] + B[2]
|
|
612
|
+
3 2 B[1] + B[2] + B[3]
|
|
613
|
+
4 3 B[1] + B[2] + B[3] + B[4]
|
|
614
|
+
|
|
615
|
+
The ``inverse_on_basis`` and ``key`` keywords can be combined::
|
|
616
|
+
|
|
617
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
618
|
+
sage: x = X.basis()
|
|
619
|
+
sage: def ut(i):
|
|
620
|
+
....: return (2*x[2] + 3*x[3] if i == 1
|
|
621
|
+
....: else x[1] + x[2] + x[3] if i == 2
|
|
622
|
+
....: else 4*x[2])
|
|
623
|
+
sage: def perm(i):
|
|
624
|
+
....: return (2 if i == 1 else 3 if i == 2 else 1)
|
|
625
|
+
sage: perverse_key = lambda a: (a - 2) % 3
|
|
626
|
+
sage: phi = X.module_morphism(ut, triangular='upper', codomain=X,
|
|
627
|
+
....: inverse_on_support=perm, key=perverse_key)
|
|
628
|
+
sage: [phi(x[i]) for i in range(1, 4)]
|
|
629
|
+
[2*B[2] + 3*B[3], B[1] + B[2] + B[3], 4*B[2]]
|
|
630
|
+
sage: [phi.preimage(x[i]) for i in range(1, 4)]
|
|
631
|
+
[-1/3*B[1] + B[2] - 1/12*B[3], 1/4*B[3], 1/3*B[1] - 1/6*B[3]]
|
|
632
|
+
"""
|
|
633
|
+
def __init__(self, triangular='upper', unitriangular=False,
|
|
634
|
+
key=None, inverse=None, inverse_on_support=identity, invertible=None):
|
|
635
|
+
"""
|
|
636
|
+
TESTS::
|
|
637
|
+
|
|
638
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
639
|
+
sage: def lt(i): return sum(j*x[j] for j in range(i, 4))
|
|
640
|
+
sage: import __main__; __main__.lt = lt # Fake lt being defined in a python module
|
|
641
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=X)
|
|
642
|
+
sage: phi.__class__
|
|
643
|
+
<class 'sage.modules.with_basis.morphism.TriangularModuleMorphismByLinearity_with_category'>
|
|
644
|
+
sage: phi._invertible
|
|
645
|
+
True
|
|
646
|
+
sage: TestSuite(phi).run()
|
|
647
|
+
|
|
648
|
+
With the option ``compute``::
|
|
649
|
+
|
|
650
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=X,
|
|
651
|
+
....: inverse_on_support='compute')
|
|
652
|
+
sage: TestSuite(phi).run(skip=["_test_pickling"])
|
|
653
|
+
|
|
654
|
+
Pickling works in Python3 (:issue:`17957`)::
|
|
655
|
+
|
|
656
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=X,
|
|
657
|
+
....: inverse_on_support='compute')
|
|
658
|
+
sage: loads(dumps(phi))
|
|
659
|
+
Generic endomorphism of X
|
|
660
|
+
sage: phi._inverse_on_support
|
|
661
|
+
<built-in method get of dict object at ...>
|
|
662
|
+
sage: ldp = loads(dumps(phi._inverse_on_support))
|
|
663
|
+
sage: [ldp(i) == phi._inverse_on_support(i) for i in range(1, 4)]
|
|
664
|
+
[True, True, True]
|
|
665
|
+
"""
|
|
666
|
+
if key is not None:
|
|
667
|
+
self._key_kwds = {"key": key}
|
|
668
|
+
else:
|
|
669
|
+
self._key_kwds = {}
|
|
670
|
+
|
|
671
|
+
if triangular == "upper":
|
|
672
|
+
self._dominant_item = attrcall("leading_item", **self._key_kwds)
|
|
673
|
+
else:
|
|
674
|
+
self._dominant_item = attrcall("trailing_item", **self._key_kwds)
|
|
675
|
+
# We store those two just be able to pass them down to the inverse function
|
|
676
|
+
self._triangular = triangular
|
|
677
|
+
|
|
678
|
+
domain = self.domain()
|
|
679
|
+
codomain = self.codomain()
|
|
680
|
+
on_basis = self.on_basis()
|
|
681
|
+
self._unitriangular = unitriangular
|
|
682
|
+
self._inverse = inverse
|
|
683
|
+
|
|
684
|
+
if inverse_on_support == "compute":
|
|
685
|
+
inverse_on_support = {self._dominant_item(on_basis(i))[0]: i
|
|
686
|
+
for i in self.domain().basis().keys()
|
|
687
|
+
}.get
|
|
688
|
+
|
|
689
|
+
self._inverse_on_support = inverse_on_support
|
|
690
|
+
|
|
691
|
+
if invertible is None and (domain.basis().keys() == codomain.basis().keys()) and \
|
|
692
|
+
(self._inverse_on_support == identity or domain in Modules.FiniteDimensional):
|
|
693
|
+
invertible = True
|
|
694
|
+
self._invertible = invertible
|
|
695
|
+
|
|
696
|
+
def _richcmp_(self, other, op):
|
|
697
|
+
r"""
|
|
698
|
+
Return whether this morphism and ``other`` satisfy ``op``.
|
|
699
|
+
|
|
700
|
+
TESTS::
|
|
701
|
+
|
|
702
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
703
|
+
sage: def ut(i): return (x[1] + x[2] if i == 1 else x[2] + (x[3] if i == 3 else 0))
|
|
704
|
+
sage: perm = [0, 2, 1, 3]
|
|
705
|
+
sage: our_key = lambda a: perm[a]
|
|
706
|
+
sage: phi = X.module_morphism(ut, triangular='upper', codomain=X, key=our_key)
|
|
707
|
+
sage: def ut2(i): return (x[1] + 7*x[2] if i == 1 else x[2] + (x[3] if i == 3 else 0))
|
|
708
|
+
sage: phi2 = X.module_morphism(ut2, triangular='upper', codomain=X, key=our_key)
|
|
709
|
+
sage: def lt(i): return (x[1] + x[2] + x[3] if i == 2 else x[i])
|
|
710
|
+
sage: psi = X.module_morphism(lt, triangular='lower', codomain=X, key=our_key)
|
|
711
|
+
sage: phi == phi
|
|
712
|
+
True
|
|
713
|
+
sage: phi == phi2
|
|
714
|
+
False
|
|
715
|
+
sage: phi == psi
|
|
716
|
+
False
|
|
717
|
+
"""
|
|
718
|
+
if op == op_EQ:
|
|
719
|
+
return (self.__class__ is other.__class__
|
|
720
|
+
and self._triangular == other._triangular
|
|
721
|
+
and self._unitriangular == other._unitriangular
|
|
722
|
+
and self._inverse_on_support == other._inverse_on_support
|
|
723
|
+
and self._invertible == other._invertible
|
|
724
|
+
and self._dominant_item == other._dominant_item)
|
|
725
|
+
if op == op_NE:
|
|
726
|
+
return not (self == other)
|
|
727
|
+
return NotImplemented
|
|
728
|
+
|
|
729
|
+
def _test_triangular(self, **options):
|
|
730
|
+
"""
|
|
731
|
+
Test that ``self`` is actually triangular.
|
|
732
|
+
|
|
733
|
+
See also: :class:`sage.misc.sage_unittest.TestSuite`.
|
|
734
|
+
|
|
735
|
+
EXAMPLES::
|
|
736
|
+
|
|
737
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); x = X.basis()
|
|
738
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); y = Y.basis()
|
|
739
|
+
sage: lt = lambda i: sum( y[j] for j in range(i,4) )
|
|
740
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y)
|
|
741
|
+
sage: phi._test_triangular()
|
|
742
|
+
|
|
743
|
+
sage: lt = lambda i: sum( y[j] for j in range(i+1,4) )
|
|
744
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y)
|
|
745
|
+
sage: phi._test_triangular()
|
|
746
|
+
Traceback (most recent call last):
|
|
747
|
+
...
|
|
748
|
+
AssertionError: morphism is not triangular on 1
|
|
749
|
+
|
|
750
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); x = X.basis()
|
|
751
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4,5]); y = Y.basis()
|
|
752
|
+
sage: ult = lambda i: sum( y[j] for j in range(i+1,6) )
|
|
753
|
+
sage: phi = X.module_morphism(ult, unitriangular='lower', codomain=Y,
|
|
754
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
755
|
+
sage: phi._test_triangular()
|
|
756
|
+
|
|
757
|
+
sage: ult = lambda i: sum( 2*y[j] for j in range(i+1,6) )
|
|
758
|
+
sage: phi = X.module_morphism(ult, unitriangular='lower', codomain=Y,
|
|
759
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
760
|
+
sage: phi._test_triangular()
|
|
761
|
+
Traceback (most recent call last):
|
|
762
|
+
...
|
|
763
|
+
AssertionError: morphism is not unitriangular on 1
|
|
764
|
+
"""
|
|
765
|
+
from sage.misc.lazy_format import LazyFormat
|
|
766
|
+
tester = self._tester(**options)
|
|
767
|
+
on_basis = self.on_basis()
|
|
768
|
+
for x in self.domain().basis().keys().some_elements():
|
|
769
|
+
# is there any better set to use ?
|
|
770
|
+
bs, co = self._dominant_item(on_basis(x))
|
|
771
|
+
if self._unitriangular:
|
|
772
|
+
tester.assertEqual(co, self.domain().base_ring().one(),
|
|
773
|
+
LazyFormat("morphism is not unitriangular on %s") % x)
|
|
774
|
+
xback = self._inverse_on_support(bs)
|
|
775
|
+
tester.assertEqual(x, xback,
|
|
776
|
+
LazyFormat("morphism is not triangular on %s") % x)
|
|
777
|
+
|
|
778
|
+
def __invert__(self):
|
|
779
|
+
"""
|
|
780
|
+
Return the triangular morphism which is the inverse of ``self``.
|
|
781
|
+
|
|
782
|
+
Raises an error if ``self`` is not invertible.
|
|
783
|
+
|
|
784
|
+
TESTS::
|
|
785
|
+
|
|
786
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); x = X.basis()
|
|
787
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); y = Y.basis()
|
|
788
|
+
sage: uut = lambda i: sum( y[j] for j in range(1,i+1)) # uni-upper
|
|
789
|
+
sage: ult = lambda i: sum( y[j] for j in range(i,4) ) # uni-lower
|
|
790
|
+
sage: ut = lambda i: sum(j*y[j] for j in range(1,i+1)) # upper
|
|
791
|
+
sage: lt = lambda i: sum(j*y[j] for j in range(i,4 )) # lower
|
|
792
|
+
sage: f_uut = X.module_morphism(uut, codomain=Y,
|
|
793
|
+
....: unitriangular='upper')
|
|
794
|
+
sage: f_ult = X.module_morphism(ult, codomain=Y,
|
|
795
|
+
....: unitriangular='lower')
|
|
796
|
+
sage: f_ut = X.module_morphism(ut, codomain=Y, triangular='upper')
|
|
797
|
+
sage: f_lt = X.module_morphism(lt, codomain=Y, triangular='lower')
|
|
798
|
+
sage: (~f_uut)(y[2])
|
|
799
|
+
-B[1] + B[2]
|
|
800
|
+
sage: (~f_ult)(y[2])
|
|
801
|
+
B[2] - B[3]
|
|
802
|
+
sage: (~f_ut)(y[2])
|
|
803
|
+
-1/2*B[1] + 1/2*B[2]
|
|
804
|
+
sage: (~f_lt)(y[2])
|
|
805
|
+
1/2*B[2] - 1/2*B[3]
|
|
806
|
+
"""
|
|
807
|
+
if self._invertible is True:
|
|
808
|
+
return self.section()
|
|
809
|
+
elif self._invertible is False:
|
|
810
|
+
raise ValueError("Non invertible morphism")
|
|
811
|
+
else:
|
|
812
|
+
raise ValueError("Morphism not known to be invertible; see the invertible option of module_morphism")
|
|
813
|
+
|
|
814
|
+
def section(self):
|
|
815
|
+
"""
|
|
816
|
+
Return the section (partial inverse) of ``self``.
|
|
817
|
+
|
|
818
|
+
This returns a partial triangular morphism which is a section of
|
|
819
|
+
``self``. The section morphism raises a :exc:`ValueError` if
|
|
820
|
+
asked to apply on an element which is not in the image of ``self``.
|
|
821
|
+
|
|
822
|
+
EXAMPLES::
|
|
823
|
+
|
|
824
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); x = X.basis()
|
|
825
|
+
sage: X.rename('X')
|
|
826
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4,5]); y = Y.basis()
|
|
827
|
+
sage: ult = lambda i: sum( y[j] for j in range(i+1,6) ) # uni-lower
|
|
828
|
+
sage: phi = X.module_morphism(ult, triangular='lower', codomain=Y,
|
|
829
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
830
|
+
sage: ~phi
|
|
831
|
+
Traceback (most recent call last):
|
|
832
|
+
...
|
|
833
|
+
ValueError: Morphism not known to be invertible;
|
|
834
|
+
see the invertible option of module_morphism
|
|
835
|
+
sage: phiinv = phi.section()
|
|
836
|
+
sage: list(map(phiinv*phi, X.basis().list())) == X.basis().list()
|
|
837
|
+
True
|
|
838
|
+
sage: phiinv(Y.basis()[1])
|
|
839
|
+
Traceback (most recent call last):
|
|
840
|
+
...
|
|
841
|
+
ValueError: B[1] is not in the image
|
|
842
|
+
"""
|
|
843
|
+
if self._inverse is not None:
|
|
844
|
+
return self._inverse
|
|
845
|
+
if self._inverse_on_support == identity:
|
|
846
|
+
retract_dom = None
|
|
847
|
+
else:
|
|
848
|
+
on_basis = self.on_basis()
|
|
849
|
+
|
|
850
|
+
def retract_dom(i):
|
|
851
|
+
self._dominant_item(on_basis(i))[0]
|
|
852
|
+
|
|
853
|
+
if self._invertible:
|
|
854
|
+
return self.__class__(
|
|
855
|
+
domain=self.codomain(),
|
|
856
|
+
on_basis=self._invert_on_basis,
|
|
857
|
+
codomain=self.domain(), category=self.category_for(),
|
|
858
|
+
unitriangular=self._unitriangular, triangular=self._triangular,
|
|
859
|
+
inverse=self, inverse_on_support=retract_dom,
|
|
860
|
+
invertible=self._invertible, **self._key_kwds)
|
|
861
|
+
else:
|
|
862
|
+
return SetMorphism(Hom(self.codomain(), self.domain(),
|
|
863
|
+
SetsWithPartialMaps()),
|
|
864
|
+
self.preimage)
|
|
865
|
+
|
|
866
|
+
# This should be removed and optimized as soon as triangular
|
|
867
|
+
# morphisms not defined by linearity are available
|
|
868
|
+
# (the inverse should not be computed on the basis).
|
|
869
|
+
def _invert_on_basis(self, i):
|
|
870
|
+
r"""
|
|
871
|
+
Return the image, by the inverse of ``self``, of the basis element
|
|
872
|
+
indexed by ``i``.
|
|
873
|
+
|
|
874
|
+
TESTS::
|
|
875
|
+
|
|
876
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); x = X.basis()
|
|
877
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); y = Y.basis()
|
|
878
|
+
sage: ult = lambda i: sum( y[j] for j in range(i,4) ) # uni-lower
|
|
879
|
+
sage: phi = X.module_morphism(ult, triangular='lower', codomain=Y)
|
|
880
|
+
sage: phi._invert_on_basis(2)
|
|
881
|
+
B[2] - B[3]
|
|
882
|
+
"""
|
|
883
|
+
return self.preimage(self.codomain().monomial(i))
|
|
884
|
+
|
|
885
|
+
def preimage(self, f):
|
|
886
|
+
r"""
|
|
887
|
+
Return the preimage of `f` under ``self``.
|
|
888
|
+
|
|
889
|
+
EXAMPLES::
|
|
890
|
+
|
|
891
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); x = X.basis()
|
|
892
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); y = Y.basis()
|
|
893
|
+
sage: ult = lambda i: sum( y[j] for j in range(i,4) ) # uni-lower
|
|
894
|
+
sage: phi = X.module_morphism(ult, triangular='lower', codomain=Y)
|
|
895
|
+
sage: phi.preimage(y[1] + y[2])
|
|
896
|
+
B[1] - B[3]
|
|
897
|
+
|
|
898
|
+
The morphism need not be surjective. In the following example,
|
|
899
|
+
the codomain is of larger dimension than the domain::
|
|
900
|
+
|
|
901
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); x = X.basis()
|
|
902
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3, 4]); y = Y.basis()
|
|
903
|
+
sage: lt = lambda i: sum( y[j] for j in range(i,5) )
|
|
904
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y)
|
|
905
|
+
sage: phi.preimage(y[1] + y[2])
|
|
906
|
+
B[1] - B[3]
|
|
907
|
+
|
|
908
|
+
Here are examples using ``inverse_on_support`` to handle a
|
|
909
|
+
morphism that shifts the leading indices by `1`::
|
|
910
|
+
|
|
911
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); x = X.basis()
|
|
912
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3, 4, 5]); y = Y.basis()
|
|
913
|
+
sage: lt = lambda i: sum( y[j] for j in range(i+1,6) ) # lower
|
|
914
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y,
|
|
915
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
916
|
+
sage: phi(x[1])
|
|
917
|
+
B[2] + B[3] + B[4] + B[5]
|
|
918
|
+
sage: phi(x[3])
|
|
919
|
+
B[4] + B[5]
|
|
920
|
+
sage: phi.preimage(y[2] + y[3])
|
|
921
|
+
B[1] - B[3]
|
|
922
|
+
sage: phi(phi.preimage(y[2] + y[3])) == y[2] + y[3]
|
|
923
|
+
True
|
|
924
|
+
sage: el = x[1] + 3*x[2] + 2*x[3]
|
|
925
|
+
sage: phi.preimage(phi(el)) == el
|
|
926
|
+
True
|
|
927
|
+
|
|
928
|
+
sage: phi.preimage(y[1])
|
|
929
|
+
Traceback (most recent call last):
|
|
930
|
+
...
|
|
931
|
+
ValueError: B[1] is not in the image
|
|
932
|
+
sage: phi.preimage(y[4])
|
|
933
|
+
Traceback (most recent call last):
|
|
934
|
+
...
|
|
935
|
+
ValueError: B[4] is not in the image
|
|
936
|
+
|
|
937
|
+
Over a base ring like `\ZZ`, the morphism need not be
|
|
938
|
+
surjective even when the dimensions match::
|
|
939
|
+
|
|
940
|
+
sage: X = CombinatorialFreeModule(ZZ, [1, 2, 3]); x = X.basis()
|
|
941
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1, 2, 3]); y = Y.basis()
|
|
942
|
+
sage: lt = lambda i: sum( 2* y[j] for j in range(i,4) ) # lower
|
|
943
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y)
|
|
944
|
+
sage: phi.preimage(2*y[1] + 2*y[2])
|
|
945
|
+
B[1] - B[3]
|
|
946
|
+
|
|
947
|
+
The error message in case of failure could be more specific though::
|
|
948
|
+
|
|
949
|
+
sage: phi.preimage(y[1] + y[2])
|
|
950
|
+
Traceback (most recent call last):
|
|
951
|
+
...
|
|
952
|
+
TypeError: no conversion of this rational to integer
|
|
953
|
+
"""
|
|
954
|
+
F = self.domain()
|
|
955
|
+
G = self.codomain()
|
|
956
|
+
on_basis = self.on_basis()
|
|
957
|
+
if f not in G:
|
|
958
|
+
raise ValueError("f(={}) must be in the codomain of the morphism to have a preimage under the latter".format(f))
|
|
959
|
+
|
|
960
|
+
remainder = f
|
|
961
|
+
|
|
962
|
+
out = F.zero()
|
|
963
|
+
while not remainder.is_zero():
|
|
964
|
+
(j, c) = self._dominant_item(remainder)
|
|
965
|
+
|
|
966
|
+
j_preimage = self._inverse_on_support(j)
|
|
967
|
+
if j_preimage is None:
|
|
968
|
+
raise ValueError("{} is not in the image".format(f))
|
|
969
|
+
s = on_basis(j_preimage)
|
|
970
|
+
if not j == self._dominant_item(s)[0]:
|
|
971
|
+
raise ValueError("The morphism (={}) is not triangular at {}, and therefore a preimage cannot be computed".format(f, s))
|
|
972
|
+
|
|
973
|
+
if not self._unitriangular:
|
|
974
|
+
# What's the appropriate way to request an exact
|
|
975
|
+
# division within the base ring and get an error if
|
|
976
|
+
# this is not possible?
|
|
977
|
+
c = c.parent()(c / s[j])
|
|
978
|
+
|
|
979
|
+
# Before this was ``remainder -= s._lmul_(c)`` for speed, but
|
|
980
|
+
# not every module implements scalar multiplication this way.
|
|
981
|
+
remainder -= s * c
|
|
982
|
+
out += F.term(j_preimage, c)
|
|
983
|
+
|
|
984
|
+
return out
|
|
985
|
+
|
|
986
|
+
def coreduced(self, y):
|
|
987
|
+
r"""
|
|
988
|
+
Return `y` reduced w.r.t. the image of ``self``.
|
|
989
|
+
|
|
990
|
+
INPUT:
|
|
991
|
+
|
|
992
|
+
- ``self`` -- a triangular morphism over a field, or a
|
|
993
|
+
unitriangular morphism over a ring
|
|
994
|
+
- ``y`` -- an element of the codomain of ``self``
|
|
995
|
+
|
|
996
|
+
Suppose that ``self`` is a morphism from `X` to `Y`. Then, for
|
|
997
|
+
any `y \in Y`, the call ``self.coreduced(y)`` returns a
|
|
998
|
+
normal form for `y` in the quotient `Y / I` where `I` is the
|
|
999
|
+
image of ``self``.
|
|
1000
|
+
|
|
1001
|
+
EXAMPLES::
|
|
1002
|
+
|
|
1003
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); x = X.basis()
|
|
1004
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4,5]); y = Y.basis()
|
|
1005
|
+
sage: ult = lambda i: sum( y[j] for j in range(i+1,6) )
|
|
1006
|
+
sage: phi = X.module_morphism(ult, unitriangular='lower', codomain=Y,
|
|
1007
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1008
|
+
sage: [phi(v) for v in X.basis()]
|
|
1009
|
+
[B[2] + B[3] + B[4] + B[5],
|
|
1010
|
+
B[3] + B[4] + B[5],
|
|
1011
|
+
B[4] + B[5]]
|
|
1012
|
+
sage: [phi.coreduced(y[1]-2*y[4])]
|
|
1013
|
+
[B[1] + 2*B[5]]
|
|
1014
|
+
sage: [phi.coreduced(v) for v in y]
|
|
1015
|
+
[B[1], 0, 0, -B[5], B[5]]
|
|
1016
|
+
|
|
1017
|
+
Now with a non unitriangular morphism::
|
|
1018
|
+
|
|
1019
|
+
sage: lt = lambda i: sum( j*y[j] for j in range(i+1,6) )
|
|
1020
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y,
|
|
1021
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1022
|
+
sage: [phi(v) for v in X.basis()]
|
|
1023
|
+
[2*B[2] + 3*B[3] + 4*B[4] + 5*B[5],
|
|
1024
|
+
3*B[3] + 4*B[4] + 5*B[5],
|
|
1025
|
+
4*B[4] + 5*B[5]]
|
|
1026
|
+
sage: [phi.coreduced(y[1]-2*y[4])]
|
|
1027
|
+
[B[1] + 5/2*B[5]]
|
|
1028
|
+
sage: [phi.coreduced(v) for v in y]
|
|
1029
|
+
[B[1], 0, 0, -5/4*B[5], B[5]]
|
|
1030
|
+
|
|
1031
|
+
For general rings, this method is only implemented for
|
|
1032
|
+
unitriangular morphisms::
|
|
1033
|
+
|
|
1034
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); x = X.basis()
|
|
1035
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1,2,3,4,5]); y = Y.basis()
|
|
1036
|
+
sage: phi = X.module_morphism(ult, unitriangular='lower', codomain=Y,
|
|
1037
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1038
|
+
sage: [phi.coreduced(y[1]-2*y[4])]
|
|
1039
|
+
[B[1] + 2*B[5]]
|
|
1040
|
+
sage: [phi.coreduced(v) for v in y]
|
|
1041
|
+
[B[1], 0, 0, -B[5], B[5]]
|
|
1042
|
+
|
|
1043
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y,
|
|
1044
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1045
|
+
sage: [phi.coreduced(v) for v in y]
|
|
1046
|
+
Traceback (most recent call last):
|
|
1047
|
+
...
|
|
1048
|
+
NotImplementedError: coreduce for a triangular but not unitriangular morphism over a ring
|
|
1049
|
+
|
|
1050
|
+
.. NOTE:: Before :issue:`8678` this method used to be called co_reduced.
|
|
1051
|
+
"""
|
|
1052
|
+
G = self.codomain()
|
|
1053
|
+
if G.base_ring() not in Fields() and not self._unitriangular:
|
|
1054
|
+
raise NotImplementedError("coreduce for a triangular but not unitriangular morphism over a ring")
|
|
1055
|
+
on_basis = self.on_basis()
|
|
1056
|
+
assert y in G
|
|
1057
|
+
|
|
1058
|
+
result = G.zero()
|
|
1059
|
+
remainder = y
|
|
1060
|
+
|
|
1061
|
+
while not remainder.is_zero():
|
|
1062
|
+
(j, c) = self._dominant_item(remainder)
|
|
1063
|
+
j_preimage = self._inverse_on_support(j)
|
|
1064
|
+
if j_preimage is None:
|
|
1065
|
+
dom_term = G.term(j, c)
|
|
1066
|
+
remainder -= dom_term
|
|
1067
|
+
result += dom_term
|
|
1068
|
+
else:
|
|
1069
|
+
s = on_basis(j_preimage)
|
|
1070
|
+
assert j == self._dominant_item(s)[0]
|
|
1071
|
+
if not self._unitriangular:
|
|
1072
|
+
c = c / s[j] # the base ring is a field
|
|
1073
|
+
# Before this was ``remainder -= s._lmul_(c)`` for speed, but
|
|
1074
|
+
# not every module implements scalar multiplication this way.
|
|
1075
|
+
remainder -= s * c
|
|
1076
|
+
return result
|
|
1077
|
+
|
|
1078
|
+
def cokernel_basis_indices(self):
|
|
1079
|
+
r"""
|
|
1080
|
+
Return the indices of the natural monomial basis of the cokernel of ``self``.
|
|
1081
|
+
|
|
1082
|
+
INPUT:
|
|
1083
|
+
|
|
1084
|
+
- ``self`` -- a triangular morphism over a field or a
|
|
1085
|
+
unitriangular morphism over a ring, with a finite
|
|
1086
|
+
dimensional codomain.
|
|
1087
|
+
|
|
1088
|
+
OUTPUT:
|
|
1089
|
+
|
|
1090
|
+
A list `E` of indices of the basis `(B_e)_e` of the codomain
|
|
1091
|
+
of ``self`` so that `(B_e)_{e\in E}` forms a basis of a
|
|
1092
|
+
supplementary of the image set of ``self``.
|
|
1093
|
+
|
|
1094
|
+
Thinking of this triangular morphism as a row echelon matrix,
|
|
1095
|
+
this returns the complementary of the characteristic
|
|
1096
|
+
columns. Namely `E` is the set of indices which do not appear
|
|
1097
|
+
as leading support of some element of the image set of
|
|
1098
|
+
``self``.
|
|
1099
|
+
|
|
1100
|
+
EXAMPLES::
|
|
1101
|
+
|
|
1102
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); x = X.basis()
|
|
1103
|
+
sage: Y = CombinatorialFreeModule(ZZ, [1,2,3,4,5]); y = Y.basis()
|
|
1104
|
+
sage: uut = lambda i: sum( y[j] for j in range(i+1,6) ) # uni-upper
|
|
1105
|
+
sage: phi = X.module_morphism(uut, unitriangular='upper', codomain=Y,
|
|
1106
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1107
|
+
sage: phi.cokernel_basis_indices()
|
|
1108
|
+
[1, 5]
|
|
1109
|
+
|
|
1110
|
+
sage: phi = X.module_morphism(uut, triangular='upper', codomain=Y,
|
|
1111
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1112
|
+
sage: phi.cokernel_basis_indices()
|
|
1113
|
+
Traceback (most recent call last):
|
|
1114
|
+
...
|
|
1115
|
+
NotImplementedError: cokernel_basis_indices for a triangular but not unitriangular morphism over a ring
|
|
1116
|
+
|
|
1117
|
+
sage: Y = CombinatorialFreeModule(ZZ, NN); y = Y.basis()
|
|
1118
|
+
sage: phi = X.module_morphism(uut, unitriangular='upper', codomain=Y,
|
|
1119
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1120
|
+
sage: phi.cokernel_basis_indices()
|
|
1121
|
+
Traceback (most recent call last):
|
|
1122
|
+
...
|
|
1123
|
+
NotImplementedError: cokernel_basis_indices implemented only for morphisms with a finite dimensional codomain
|
|
1124
|
+
"""
|
|
1125
|
+
R = self.domain().base_ring()
|
|
1126
|
+
if R not in Fields() and not self._unitriangular:
|
|
1127
|
+
raise NotImplementedError("cokernel_basis_indices for a triangular but not unitriangular morphism over a ring")
|
|
1128
|
+
if self.codomain() not in Modules(R).FiniteDimensional():
|
|
1129
|
+
raise NotImplementedError("cokernel_basis_indices implemented only for morphisms with a finite dimensional codomain")
|
|
1130
|
+
return [i for i in self.codomain().basis().keys() if self._inverse_on_support(i) is None]
|
|
1131
|
+
|
|
1132
|
+
def cokernel_projection(self, category=None):
|
|
1133
|
+
"""
|
|
1134
|
+
Return a projection on the co-kernel of ``self``.
|
|
1135
|
+
|
|
1136
|
+
INPUT:
|
|
1137
|
+
|
|
1138
|
+
- ``category`` -- the category of the result
|
|
1139
|
+
|
|
1140
|
+
EXAMPLES::
|
|
1141
|
+
|
|
1142
|
+
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); x = X.basis()
|
|
1143
|
+
sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4,5]); y = Y.basis()
|
|
1144
|
+
sage: lt = lambda i: sum( y[j] for j in range(i+1,6) ) # lower
|
|
1145
|
+
sage: phi = X.module_morphism(lt, triangular='lower', codomain=Y,
|
|
1146
|
+
....: inverse_on_support=lambda i: i-1 if i in [2,3,4] else None)
|
|
1147
|
+
sage: phipro = phi.cokernel_projection()
|
|
1148
|
+
sage: phipro(y[1] + y[2])
|
|
1149
|
+
B[1]
|
|
1150
|
+
sage: all(phipro(phi(x)).is_zero() for x in X.basis())
|
|
1151
|
+
True
|
|
1152
|
+
sage: phipro(y[1])
|
|
1153
|
+
B[1]
|
|
1154
|
+
sage: phipro(y[4])
|
|
1155
|
+
-B[5]
|
|
1156
|
+
sage: phipro(y[5])
|
|
1157
|
+
B[5]
|
|
1158
|
+
"""
|
|
1159
|
+
codomain = self.codomain()
|
|
1160
|
+
category = ModulesWithBasis(codomain.base_ring()).or_subcategory(category)
|
|
1161
|
+
return codomain.module_morphism(function=self.coreduced,
|
|
1162
|
+
codomain=codomain, category=category)
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
class TriangularModuleMorphismByLinearity(ModuleMorphismByLinearity, TriangularModuleMorphism):
|
|
1166
|
+
r"""
|
|
1167
|
+
A concrete class for triangular module morphisms obtained by extending a function by linearity.
|
|
1168
|
+
|
|
1169
|
+
.. SEEALSO::
|
|
1170
|
+
|
|
1171
|
+
- :meth:`ModulesWithBasis.ParentMethods.module_morphism` for
|
|
1172
|
+
usage information and examples;
|
|
1173
|
+
- :mod:`sage.modules.with_basis.morphism` for a technical
|
|
1174
|
+
overview of the classes for module morphisms;
|
|
1175
|
+
- :class:`ModuleMorphismByLinearity` and
|
|
1176
|
+
:class:`TriangularModuleMorphism`.
|
|
1177
|
+
"""
|
|
1178
|
+
def __init__(self, domain, on_basis, codomain=None, category=None, **keywords):
|
|
1179
|
+
r"""
|
|
1180
|
+
TESTS::
|
|
1181
|
+
|
|
1182
|
+
sage: X = CombinatorialFreeModule(QQ, ZZ)
|
|
1183
|
+
sage: from sage.modules.with_basis.morphism import TriangularModuleMorphismByLinearity
|
|
1184
|
+
sage: def on_basis(i): return X.sum_of_monomials(range(i-2, i+1))
|
|
1185
|
+
sage: import __main__; __main__.on_basis = on_basis # Fake on_basis being defined in a python module
|
|
1186
|
+
sage: phi = TriangularModuleMorphismByLinearity(
|
|
1187
|
+
....: X, on_basis=on_basis, codomain=X)
|
|
1188
|
+
sage: TestSuite(phi).run(skip=["_test_nonzero_equal"])
|
|
1189
|
+
"""
|
|
1190
|
+
ModuleMorphismByLinearity.__init__(self, on_basis=on_basis,
|
|
1191
|
+
domain=domain, codomain=codomain, category=category)
|
|
1192
|
+
TriangularModuleMorphism.__init__(self, **keywords)
|
|
1193
|
+
|
|
1194
|
+
def _richcmp_(self, other, op):
|
|
1195
|
+
r"""
|
|
1196
|
+
Return whether this morphism and ``other`` satisfy ``op``.
|
|
1197
|
+
|
|
1198
|
+
TESTS::
|
|
1199
|
+
|
|
1200
|
+
sage: X = CombinatorialFreeModule(QQ, ZZ)
|
|
1201
|
+
sage: from sage.modules.with_basis.morphism import TriangularModuleMorphismByLinearity
|
|
1202
|
+
sage: def on_basis(i): return X.sum_of_monomials(range(i-2, i+1))
|
|
1203
|
+
sage: phi = TriangularModuleMorphismByLinearity(
|
|
1204
|
+
....: X, on_basis=on_basis, codomain=X)
|
|
1205
|
+
sage: phi == phi
|
|
1206
|
+
True
|
|
1207
|
+
"""
|
|
1208
|
+
if op == op_EQ:
|
|
1209
|
+
return (ModuleMorphismByLinearity._richcmp_(self, other, op)
|
|
1210
|
+
and TriangularModuleMorphism._richcmp_(self, other, op))
|
|
1211
|
+
if op == op_NE:
|
|
1212
|
+
return not (self == other)
|
|
1213
|
+
return NotImplemented
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
class TriangularModuleMorphismFromFunction(ModuleMorphismFromFunction, TriangularModuleMorphism):
|
|
1217
|
+
r"""
|
|
1218
|
+
A concrete class for triangular module morphisms implemented by a function.
|
|
1219
|
+
|
|
1220
|
+
.. SEEALSO::
|
|
1221
|
+
|
|
1222
|
+
- :meth:`ModulesWithBasis.ParentMethods.module_morphism` for
|
|
1223
|
+
usage information and examples;
|
|
1224
|
+
- :mod:`sage.modules.with_basis.morphism` for a technical
|
|
1225
|
+
overview of the classes for module morphisms;
|
|
1226
|
+
- :class:`ModuleMorphismFromFunction` and
|
|
1227
|
+
:class:`TriangularModuleMorphism`.
|
|
1228
|
+
"""
|
|
1229
|
+
def __init__(self, domain, function, codomain=None, category=None, **keywords):
|
|
1230
|
+
r"""
|
|
1231
|
+
TESTS::
|
|
1232
|
+
|
|
1233
|
+
sage: X = CombinatorialFreeModule(QQ, [0,1,2,3,4])
|
|
1234
|
+
sage: from sage.modules.with_basis.morphism import TriangularModuleMorphismFromFunction
|
|
1235
|
+
sage: def f(x): return x + X.term(0, sum(x.coefficients()))
|
|
1236
|
+
sage: import __main__; __main__.f = f # Fake f being defined in a python module
|
|
1237
|
+
sage: phi = TriangularModuleMorphismFromFunction(
|
|
1238
|
+
....: X, function=f, codomain=X)
|
|
1239
|
+
sage: TestSuite(phi).run()
|
|
1240
|
+
"""
|
|
1241
|
+
ModuleMorphismFromFunction.__init__(self, function=function,
|
|
1242
|
+
domain=domain, codomain=codomain,
|
|
1243
|
+
category=category)
|
|
1244
|
+
TriangularModuleMorphism.__init__(self, **keywords)
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
class ModuleMorphismFromMatrix(ModuleMorphismByLinearity):
|
|
1248
|
+
r"""
|
|
1249
|
+
A class for module morphisms built from a matrix in the
|
|
1250
|
+
distinguished bases of the domain and codomain.
|
|
1251
|
+
|
|
1252
|
+
.. SEEALSO::
|
|
1253
|
+
|
|
1254
|
+
- :meth:`ModulesWithBasis.ParentMethods.module_morphism`
|
|
1255
|
+
- :meth:`ModulesWithBasis.FiniteDimensional.MorphismMethods.matrix`
|
|
1256
|
+
|
|
1257
|
+
INPUT:
|
|
1258
|
+
|
|
1259
|
+
- ``domain``, ``codomain`` -- two finite dimensional modules over
|
|
1260
|
+
the same base ring `R` with basis `F` and `G`, respectively
|
|
1261
|
+
|
|
1262
|
+
- ``matrix`` -- a matrix with base ring `R` and dimensions
|
|
1263
|
+
matching that of `F` and `G`, respectively
|
|
1264
|
+
|
|
1265
|
+
- ``side`` -- ``'left'`` or ``'right'`` (default: ``'left'``)
|
|
1266
|
+
|
|
1267
|
+
If ``side`` is "left", this morphism is considered as
|
|
1268
|
+
acting on the left; i.e. each column of the matrix
|
|
1269
|
+
represents the image of an element of the basis of the
|
|
1270
|
+
domain.
|
|
1271
|
+
|
|
1272
|
+
- ``category`` -- a category or ``None`` (default: ``None``)
|
|
1273
|
+
|
|
1274
|
+
EXAMPLES::
|
|
1275
|
+
|
|
1276
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2]); X.rename('X'); x = X.basis()
|
|
1277
|
+
sage: Y = CombinatorialFreeModule(ZZ, [3,4]); Y.rename('Y'); y = Y.basis()
|
|
1278
|
+
sage: m = matrix([[1,2],[3,5]])
|
|
1279
|
+
sage: phi = X.module_morphism(matrix=m, codomain=Y)
|
|
1280
|
+
sage: phi.parent()
|
|
1281
|
+
Set of Morphisms from X to Y in Category of finite dimensional modules with basis over Integer Ring
|
|
1282
|
+
sage: phi.__class__
|
|
1283
|
+
<class 'sage.modules.with_basis.morphism.ModuleMorphismFromMatrix_with_category'>
|
|
1284
|
+
sage: phi(x[1])
|
|
1285
|
+
B[3] + 3*B[4]
|
|
1286
|
+
sage: phi(x[2])
|
|
1287
|
+
2*B[3] + 5*B[4]
|
|
1288
|
+
|
|
1289
|
+
sage: m = matrix([[1,2],[3,5]])
|
|
1290
|
+
sage: phi = X.module_morphism(matrix=m, codomain=Y, side='right',
|
|
1291
|
+
....: category=Modules(ZZ).WithBasis())
|
|
1292
|
+
sage: phi.parent()
|
|
1293
|
+
Set of Morphisms from X to Y
|
|
1294
|
+
in Category of modules with basis over Integer Ring
|
|
1295
|
+
sage: phi(x[1])
|
|
1296
|
+
B[3] + 2*B[4]
|
|
1297
|
+
sage: phi(x[2])
|
|
1298
|
+
3*B[3] + 5*B[4]
|
|
1299
|
+
|
|
1300
|
+
.. TODO::
|
|
1301
|
+
|
|
1302
|
+
Possibly implement rank, addition, multiplication, matrix,
|
|
1303
|
+
etc, from the stored matrix.
|
|
1304
|
+
"""
|
|
1305
|
+
def __init__(self, domain, matrix, codomain=None, category=None, side='left'):
|
|
1306
|
+
r"""
|
|
1307
|
+
Initialize ``self``.
|
|
1308
|
+
|
|
1309
|
+
TESTS::
|
|
1310
|
+
|
|
1311
|
+
sage: from sage.modules.with_basis.morphism import ModuleMorphismFromMatrix
|
|
1312
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2]); X.rename('X'); x = X.basis()
|
|
1313
|
+
sage: Y = CombinatorialFreeModule(ZZ, [3,4]); Y.rename('Y'); y = Y.basis()
|
|
1314
|
+
sage: m = matrix([[1,2],[3,5]])
|
|
1315
|
+
sage: phi = ModuleMorphismFromMatrix(matrix=m, domain=X, codomain=Y, side='right')
|
|
1316
|
+
sage: phi.__class__
|
|
1317
|
+
<class 'sage.modules.with_basis.morphism.ModuleMorphismFromMatrix_with_category'>
|
|
1318
|
+
sage: phi.matrix(side='right') == m
|
|
1319
|
+
True
|
|
1320
|
+
sage: TestSuite(phi).run(skip=["_test_pickling"])
|
|
1321
|
+
|
|
1322
|
+
Pickling works (:issue:`17957`) in Python 3::
|
|
1323
|
+
|
|
1324
|
+
sage: phi._on_basis
|
|
1325
|
+
<built-in method __getitem__ of dict object at ...>
|
|
1326
|
+
sage: loads(dumps(phi)) == phi
|
|
1327
|
+
True
|
|
1328
|
+
|
|
1329
|
+
The matrix is stored in the morphism, as if it was for an
|
|
1330
|
+
action on the right::
|
|
1331
|
+
|
|
1332
|
+
sage: phi._matrix
|
|
1333
|
+
[1 2]
|
|
1334
|
+
[3 5]
|
|
1335
|
+
|
|
1336
|
+
sage: phi = ModuleMorphismFromMatrix(matrix=m, side='left',
|
|
1337
|
+
....: domain=X, codomain=Y)
|
|
1338
|
+
sage: phi._matrix
|
|
1339
|
+
[1 3]
|
|
1340
|
+
[2 5]
|
|
1341
|
+
"""
|
|
1342
|
+
C = ModulesWithBasis(domain.base_ring()).FiniteDimensional()
|
|
1343
|
+
if domain not in C:
|
|
1344
|
+
raise ValueError("The domain %s should be finite dimensional" % domain)
|
|
1345
|
+
if codomain is None:
|
|
1346
|
+
raise ValueError("The codomain %s should be specified")
|
|
1347
|
+
if codomain not in C:
|
|
1348
|
+
raise ValueError("The codomain %s should be finite dimensional" % codomain)
|
|
1349
|
+
if not isinstance(matrix, Matrix):
|
|
1350
|
+
raise ValueError("matrix (=%s) should be a matrix" % matrix)
|
|
1351
|
+
import sage.combinat.ranker
|
|
1352
|
+
indices = tuple(domain.basis().keys())
|
|
1353
|
+
rank_domain = sage.combinat.ranker.rank_from_list(indices)
|
|
1354
|
+
if side == "left":
|
|
1355
|
+
matrix = matrix.transpose()
|
|
1356
|
+
if matrix.nrows() != len(indices):
|
|
1357
|
+
raise ValueError("The dimension of the matrix (%s) does not match with the dimension of the domain (%s)"
|
|
1358
|
+
% (matrix.nrows(), len(indices)))
|
|
1359
|
+
if matrix.ncols() != codomain.dimension():
|
|
1360
|
+
raise ValueError("The dimension of the matrix (%s) does not match with the dimension of the codomain (%s)"
|
|
1361
|
+
% (matrix.ncols(), codomain.dimension()))
|
|
1362
|
+
self._matrix = matrix
|
|
1363
|
+
d = {xt: codomain.from_vector(matrix.row(rank_domain(xt)))
|
|
1364
|
+
for xt in domain.basis().keys()}
|
|
1365
|
+
|
|
1366
|
+
ModuleMorphismByLinearity.__init__(self, on_basis=d.__getitem__,
|
|
1367
|
+
domain=domain, codomain=codomain,
|
|
1368
|
+
category=category)
|
|
1369
|
+
|
|
1370
|
+
def _richcmp_(self, other, op):
|
|
1371
|
+
r"""
|
|
1372
|
+
Return whether this morphism and ``other`` satisfy ``op``.
|
|
1373
|
+
|
|
1374
|
+
TESTS::
|
|
1375
|
+
|
|
1376
|
+
sage: from sage.modules.with_basis.morphism import ModuleMorphismFromMatrix
|
|
1377
|
+
sage: X = CombinatorialFreeModule(ZZ, [1,2]); X.rename('X'); x = X.basis()
|
|
1378
|
+
sage: Y = CombinatorialFreeModule(ZZ, [3,4]); Y.rename('Y'); y = Y.basis()
|
|
1379
|
+
sage: m = matrix([[1,2],[3,5]])
|
|
1380
|
+
sage: phi = ModuleMorphismFromMatrix(matrix=m, domain=X, codomain=Y, side='right')
|
|
1381
|
+
sage: phi2 = ModuleMorphismFromMatrix(matrix=m, domain=X, codomain=Y, side='right')
|
|
1382
|
+
sage: phi == phi2
|
|
1383
|
+
True
|
|
1384
|
+
sage: phi is phi2
|
|
1385
|
+
False
|
|
1386
|
+
sage: m2 = matrix([[1,2],[4,5]])
|
|
1387
|
+
sage: phi2 = ModuleMorphismFromMatrix(matrix=m2, domain=X, codomain=Y, side='right')
|
|
1388
|
+
sage: phi == phi2
|
|
1389
|
+
False
|
|
1390
|
+
"""
|
|
1391
|
+
if op == op_EQ:
|
|
1392
|
+
# We skip the on_basis check since the matrix defines the morphism
|
|
1393
|
+
return (self.__class__ is other.__class__
|
|
1394
|
+
and self._zero == other._zero
|
|
1395
|
+
and self._position == other._position
|
|
1396
|
+
and self._is_module_with_basis_over_same_base_ring == other._is_module_with_basis_over_same_base_ring
|
|
1397
|
+
and self._matrix == other._matrix)
|
|
1398
|
+
if op == op_NE:
|
|
1399
|
+
return not (self == other)
|
|
1400
|
+
return NotImplemented
|
|
1401
|
+
|
|
1402
|
+
|
|
1403
|
+
class DiagonalModuleMorphism(ModuleMorphismByLinearity):
|
|
1404
|
+
r"""
|
|
1405
|
+
A class for diagonal module morphisms.
|
|
1406
|
+
|
|
1407
|
+
See :meth:`ModulesWithBasis.ParentMethods.module_morphism`.
|
|
1408
|
+
|
|
1409
|
+
INPUT:
|
|
1410
|
+
|
|
1411
|
+
- ``domain``, ``codomain`` -- two modules with basis `F` and `G`,
|
|
1412
|
+
respectively
|
|
1413
|
+
- ``diagonal`` -- a function `d`
|
|
1414
|
+
|
|
1415
|
+
Assumptions:
|
|
1416
|
+
|
|
1417
|
+
- ``domain`` and ``codomain`` have the same base ring `R`,
|
|
1418
|
+
- their respective bases `F` and `G` have the same index set `I`,
|
|
1419
|
+
- `d` is a function `I \to R`.
|
|
1420
|
+
|
|
1421
|
+
Return the diagonal module morphism from ``domain`` to ``codomain``
|
|
1422
|
+
sending `F(i) \mapsto d(i) G(i)` for all `i \in I`.
|
|
1423
|
+
|
|
1424
|
+
By default, ``codomain`` is currently assumed to be ``domain``.
|
|
1425
|
+
(Todo: make a consistent choice with ``*ModuleMorphism``.)
|
|
1426
|
+
|
|
1427
|
+
.. TODO::
|
|
1428
|
+
|
|
1429
|
+
- Implement an optimized ``_call_()`` function.
|
|
1430
|
+
- Generalize to a mapcoeffs.
|
|
1431
|
+
- Generalize to a mapterms.
|
|
1432
|
+
|
|
1433
|
+
EXAMPLES::
|
|
1434
|
+
|
|
1435
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
1436
|
+
sage: phi = X.module_morphism(diagonal=factorial, codomain=X)
|
|
1437
|
+
sage: x = X.basis()
|
|
1438
|
+
sage: phi(x[1]), phi(x[2]), phi(x[3])
|
|
1439
|
+
(B[1], 2*B[2], 6*B[3])
|
|
1440
|
+
"""
|
|
1441
|
+
def __init__(self, domain, diagonal, codomain=None, category=None):
|
|
1442
|
+
r"""
|
|
1443
|
+
Initialize ``self``.
|
|
1444
|
+
|
|
1445
|
+
TESTS::
|
|
1446
|
+
|
|
1447
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
1448
|
+
sage: phi = X.module_morphism(diagonal=factorial, codomain=X)
|
|
1449
|
+
sage: phi.__class__
|
|
1450
|
+
<class 'sage.modules.with_basis.morphism.DiagonalModuleMorphism_with_category'>
|
|
1451
|
+
sage: TestSuite(phi).run()
|
|
1452
|
+
"""
|
|
1453
|
+
if codomain is None:
|
|
1454
|
+
raise ValueError("The codomain should be specified")
|
|
1455
|
+
if not (domain.basis().keys() == codomain.basis().keys() and
|
|
1456
|
+
domain.base_ring() == codomain.base_ring()):
|
|
1457
|
+
raise ValueError("The domain and codomain should have the same base ring "
|
|
1458
|
+
"and the same basis indexing")
|
|
1459
|
+
from collections.abc import Callable
|
|
1460
|
+
if not isinstance(diagonal, Callable):
|
|
1461
|
+
raise ValueError("diagonal (=%s) should be a function" % diagonal)
|
|
1462
|
+
if category is None:
|
|
1463
|
+
category = ModulesWithBasis(domain.base_ring())
|
|
1464
|
+
ModuleMorphismByLinearity.__init__(
|
|
1465
|
+
self, domain=domain, codomain=codomain, category=category)
|
|
1466
|
+
self._diagonal = diagonal
|
|
1467
|
+
|
|
1468
|
+
def _richcmp_(self, other, op):
|
|
1469
|
+
r"""
|
|
1470
|
+
Return whether this morphism and ``other`` satisfy ``op``.
|
|
1471
|
+
|
|
1472
|
+
TESTS::
|
|
1473
|
+
|
|
1474
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X')
|
|
1475
|
+
sage: phi = X.module_morphism(diagonal=factorial, codomain=X)
|
|
1476
|
+
sage: psi = X.module_morphism(diagonal=factorial, codomain=X)
|
|
1477
|
+
sage: phi == psi
|
|
1478
|
+
True
|
|
1479
|
+
sage: phi is psi
|
|
1480
|
+
False
|
|
1481
|
+
"""
|
|
1482
|
+
if op == op_EQ:
|
|
1483
|
+
return (self.__class__ is other.__class__
|
|
1484
|
+
and self._diagonal == other._diagonal)
|
|
1485
|
+
if op == op_NE:
|
|
1486
|
+
return not (self == other)
|
|
1487
|
+
return NotImplemented
|
|
1488
|
+
|
|
1489
|
+
def _on_basis(self, i):
|
|
1490
|
+
"""
|
|
1491
|
+
Return the image by ``self`` of the basis element indexed by ``i``.
|
|
1492
|
+
|
|
1493
|
+
TESTS::
|
|
1494
|
+
|
|
1495
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
1496
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); Y.rename('Y'); y = Y.basis()
|
|
1497
|
+
sage: phi = X.module_morphism(diagonal=factorial, codomain=X)
|
|
1498
|
+
sage: phi._on_basis(3)
|
|
1499
|
+
6*B[3]
|
|
1500
|
+
"""
|
|
1501
|
+
return self.codomain().term(i, self._diagonal(i))
|
|
1502
|
+
|
|
1503
|
+
def __invert__(self):
|
|
1504
|
+
r"""
|
|
1505
|
+
Return the inverse diagonal morphism.
|
|
1506
|
+
|
|
1507
|
+
EXAMPLES::
|
|
1508
|
+
|
|
1509
|
+
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename('X'); x = X.basis()
|
|
1510
|
+
sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); Y.rename('Y'); y = Y.basis()
|
|
1511
|
+
sage: phi = X.module_morphism(diagonal=factorial, codomain=X)
|
|
1512
|
+
sage: phi_inv = ~phi
|
|
1513
|
+
sage: phi_inv
|
|
1514
|
+
Generic endomorphism of Y
|
|
1515
|
+
sage: phi_inv(y[3])
|
|
1516
|
+
1/6*B[3]
|
|
1517
|
+
|
|
1518
|
+
Caveat: this inverse morphism is only well defined if
|
|
1519
|
+
`d(\lambda)` is always invertible in the base ring. This
|
|
1520
|
+
condition is *not* tested for, so using an ill defined inverse
|
|
1521
|
+
morphism will trigger arithmetic errors.
|
|
1522
|
+
"""
|
|
1523
|
+
return self.codomain().module_morphism(
|
|
1524
|
+
diagonal=pointwise_inverse_function(self._diagonal),
|
|
1525
|
+
codomain=self.domain(), category=self.category_for())
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
def pointwise_inverse_function(f):
|
|
1529
|
+
r"""
|
|
1530
|
+
Return the function `x \mapsto 1 / f(x)`.
|
|
1531
|
+
|
|
1532
|
+
INPUT:
|
|
1533
|
+
|
|
1534
|
+
- ``f`` -- a function
|
|
1535
|
+
|
|
1536
|
+
EXAMPLES::
|
|
1537
|
+
|
|
1538
|
+
sage: from sage.modules.with_basis.morphism import pointwise_inverse_function
|
|
1539
|
+
sage: def f(x): return x
|
|
1540
|
+
sage: g = pointwise_inverse_function(f)
|
|
1541
|
+
sage: g(1), g(2), g(3)
|
|
1542
|
+
(1, 1/2, 1/3)
|
|
1543
|
+
|
|
1544
|
+
:func:`pointwise_inverse_function` is an involution::
|
|
1545
|
+
|
|
1546
|
+
sage: f is pointwise_inverse_function(g)
|
|
1547
|
+
True
|
|
1548
|
+
|
|
1549
|
+
.. TODO::
|
|
1550
|
+
|
|
1551
|
+
This has nothing to do here!!! Should there be a library for
|
|
1552
|
+
pointwise operations on functions somewhere in Sage?
|
|
1553
|
+
"""
|
|
1554
|
+
if hasattr(f, "pointwise_inverse"):
|
|
1555
|
+
return f.pointwise_inverse()
|
|
1556
|
+
return PointwiseInverseFunction(f)
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
class PointwiseInverseFunction(SageObject):
|
|
1560
|
+
r"""
|
|
1561
|
+
A class for pointwise inverse functions.
|
|
1562
|
+
|
|
1563
|
+
The pointwise inverse function of a function `f` is the function
|
|
1564
|
+
sending every `x` to `1 / f(x)`.
|
|
1565
|
+
|
|
1566
|
+
EXAMPLES::
|
|
1567
|
+
|
|
1568
|
+
sage: from sage.modules.with_basis.morphism import PointwiseInverseFunction
|
|
1569
|
+
sage: f = PointwiseInverseFunction(factorial)
|
|
1570
|
+
sage: f(0), f(1), f(2), f(3)
|
|
1571
|
+
(1, 1, 1/2, 1/6)
|
|
1572
|
+
"""
|
|
1573
|
+
def __init__(self, f):
|
|
1574
|
+
"""
|
|
1575
|
+
TESTS::
|
|
1576
|
+
|
|
1577
|
+
sage: from sage.modules.with_basis.morphism import PointwiseInverseFunction
|
|
1578
|
+
sage: f = PointwiseInverseFunction(factorial)
|
|
1579
|
+
sage: f(0), f(1), f(2), f(3)
|
|
1580
|
+
(1, 1, 1/2, 1/6)
|
|
1581
|
+
sage: TestSuite(f).run()
|
|
1582
|
+
"""
|
|
1583
|
+
self._pointwise_inverse = f
|
|
1584
|
+
|
|
1585
|
+
def __eq__(self, other):
|
|
1586
|
+
r"""
|
|
1587
|
+
Return whether this function is equal to ``other``.
|
|
1588
|
+
|
|
1589
|
+
TESTS::
|
|
1590
|
+
|
|
1591
|
+
sage: from sage.modules.with_basis.morphism import PointwiseInverseFunction
|
|
1592
|
+
sage: f = PointwiseInverseFunction(factorial)
|
|
1593
|
+
sage: g = PointwiseInverseFunction(factorial)
|
|
1594
|
+
sage: f is g
|
|
1595
|
+
False
|
|
1596
|
+
sage: f == g
|
|
1597
|
+
True
|
|
1598
|
+
"""
|
|
1599
|
+
return (self.__class__ is other.__class__
|
|
1600
|
+
and self._pointwise_inverse == other._pointwise_inverse)
|
|
1601
|
+
|
|
1602
|
+
def __ne__(self, other):
|
|
1603
|
+
r"""
|
|
1604
|
+
Return whether this function is not equal to ``other``.
|
|
1605
|
+
|
|
1606
|
+
TESTS::
|
|
1607
|
+
|
|
1608
|
+
sage: from sage.modules.with_basis.morphism import PointwiseInverseFunction
|
|
1609
|
+
sage: f = PointwiseInverseFunction(factorial)
|
|
1610
|
+
sage: g = PointwiseInverseFunction(factorial)
|
|
1611
|
+
sage: f != g
|
|
1612
|
+
False
|
|
1613
|
+
"""
|
|
1614
|
+
return not (self == other)
|
|
1615
|
+
|
|
1616
|
+
def __call__(self, *args):
|
|
1617
|
+
"""
|
|
1618
|
+
TESTS::
|
|
1619
|
+
|
|
1620
|
+
sage: from sage.modules.with_basis.morphism import PointwiseInverseFunction
|
|
1621
|
+
sage: g = PointwiseInverseFunction(operator.mul)
|
|
1622
|
+
sage: g(5,7)
|
|
1623
|
+
1/35
|
|
1624
|
+
"""
|
|
1625
|
+
return ~(self._pointwise_inverse(*args))
|
|
1626
|
+
|
|
1627
|
+
def pointwise_inverse(self):
|
|
1628
|
+
"""
|
|
1629
|
+
TESTS::
|
|
1630
|
+
|
|
1631
|
+
sage: from sage.modules.with_basis.morphism import PointwiseInverseFunction
|
|
1632
|
+
sage: g = PointwiseInverseFunction(operator.mul)
|
|
1633
|
+
sage: g.pointwise_inverse() is operator.mul
|
|
1634
|
+
True
|
|
1635
|
+
"""
|
|
1636
|
+
return self._pointwise_inverse
|