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,2208 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
# sage.doctest: needs sage.rings.finite_rings
|
|
3
|
+
r"""
|
|
4
|
+
Ore modules
|
|
5
|
+
|
|
6
|
+
Let `R` be a commutative ring, `\theta : K \to K` by a ring
|
|
7
|
+
endomorphism and `\partial : K \to K` be a `\theta`-derivation,
|
|
8
|
+
that is an additive map satisfying the following axiom
|
|
9
|
+
|
|
10
|
+
.. MATH::
|
|
11
|
+
|
|
12
|
+
\partial(x y) = \theta(x) \partial(y) + \partial(x) y
|
|
13
|
+
|
|
14
|
+
A Ore module over `(R, \theta, \partial)` is a `R`-module `M`
|
|
15
|
+
equipped with a additive `f : M \to M` such that
|
|
16
|
+
|
|
17
|
+
.. MATH::
|
|
18
|
+
|
|
19
|
+
f(a x) = \theta(a) f(x) + \partial(a) x
|
|
20
|
+
|
|
21
|
+
Such a map `f` is called a pseudomorphism.
|
|
22
|
+
|
|
23
|
+
Equivalently, a Ore module is a module over the (noncommutative)
|
|
24
|
+
Ore polynomial ring `\mathcal S = R[X; \theta, \partial]`.
|
|
25
|
+
|
|
26
|
+
.. RUBRIC:: Defining Ore modules
|
|
27
|
+
|
|
28
|
+
SageMath provides support for creating and manipulating Ore
|
|
29
|
+
modules that are finite free over the base ring `R`.
|
|
30
|
+
|
|
31
|
+
To start with, the method
|
|
32
|
+
:meth:`sage.rings.polynomial.ore_polynomial_ring.OrePolynomialRing.quotient_module`
|
|
33
|
+
creates the quotient `\mathcal S/ \mathcal S P`, endowed with its structure
|
|
34
|
+
of `\mathcal S`-module, that is its structure of Ore module::
|
|
35
|
+
|
|
36
|
+
sage: K.<z> = GF(5^3)
|
|
37
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
38
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
39
|
+
sage: M
|
|
40
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
41
|
+
|
|
42
|
+
Classical methods are available and we can work with elements in
|
|
43
|
+
`M` as we do usually for vectors in finite free modules::
|
|
44
|
+
|
|
45
|
+
sage: M.basis()
|
|
46
|
+
[(1, 0), (0, 1)]
|
|
47
|
+
|
|
48
|
+
sage: v = M((z, z^2)); v
|
|
49
|
+
(z, z^2)
|
|
50
|
+
sage: z*v
|
|
51
|
+
(z^2, 2*z + 2)
|
|
52
|
+
|
|
53
|
+
The Ore action (or equivalently the structure of `\mathcal S`-module)
|
|
54
|
+
is also easily accessible::
|
|
55
|
+
|
|
56
|
+
sage: X*v
|
|
57
|
+
(3*z^2 + 2*z, 2*z^2 + 4*z + 4)
|
|
58
|
+
|
|
59
|
+
The method :meth:`sage.modules.ore_module.OreModule.pseudohom`
|
|
60
|
+
returns the map `f` defining the action of `X`::
|
|
61
|
+
|
|
62
|
+
sage: M.pseudohom()
|
|
63
|
+
Free module pseudomorphism (twisted by z |--> z^5) defined by the matrix
|
|
64
|
+
[ 0 1]
|
|
65
|
+
[4*z 0]
|
|
66
|
+
Domain: Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
67
|
+
Codomain: Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
68
|
+
|
|
69
|
+
A useful feature is the possibility to give chosen names to the vectors
|
|
70
|
+
of the canonical basis. This is easily done as follows::
|
|
71
|
+
|
|
72
|
+
sage: N.<u,v,w> = S.quotient_module(X^3 + z*X + 1)
|
|
73
|
+
sage: N
|
|
74
|
+
Ore module <u, v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
75
|
+
sage: N.basis()
|
|
76
|
+
[u, v, w]
|
|
77
|
+
|
|
78
|
+
Alternatively, one can pass in the argument ``names``; this
|
|
79
|
+
could be useful in particular when we want to name the vectors
|
|
80
|
+
basis `e_0, e_1, \ldots`::
|
|
81
|
+
|
|
82
|
+
sage: A = S.quotient_module(X^11 + z, names='e')
|
|
83
|
+
sage: A
|
|
84
|
+
Ore module <e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
85
|
+
sage: A.basis()
|
|
86
|
+
[e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10]
|
|
87
|
+
|
|
88
|
+
Do not forget to use the method :meth:`inject_variables` to get the
|
|
89
|
+
`e_i` in your namespace::
|
|
90
|
+
|
|
91
|
+
sage: e0
|
|
92
|
+
Traceback (most recent call last):
|
|
93
|
+
...
|
|
94
|
+
NameError: name 'e0' is not defined
|
|
95
|
+
sage: A.inject_variables()
|
|
96
|
+
Defining e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10
|
|
97
|
+
sage: e0
|
|
98
|
+
e0
|
|
99
|
+
|
|
100
|
+
.. RUBRIC:: Submodules and quotients
|
|
101
|
+
|
|
102
|
+
SageMath provides facilities for creating submodules and quotient
|
|
103
|
+
modules of Ore modules.
|
|
104
|
+
First of all, we define the Ore module `\mathcal S/\mathcal S P^2`
|
|
105
|
+
(for some Ore polynomials `P`), which is obviously not simple::
|
|
106
|
+
|
|
107
|
+
sage: P = X^2 + z*X + 1
|
|
108
|
+
sage: U = S.quotient_module(P^2, names='u')
|
|
109
|
+
sage: U.inject_variables()
|
|
110
|
+
Defining u0, u1, u2, u3
|
|
111
|
+
|
|
112
|
+
We now build the submodule `\mathcal S P / \mathcal S P^2` using
|
|
113
|
+
the method :meth:`sage.modules.ore_module.OreModule.span`::
|
|
114
|
+
|
|
115
|
+
sage: V = U.span(P*u0)
|
|
116
|
+
sage: V
|
|
117
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
118
|
+
sage: V.basis()
|
|
119
|
+
[u0 + (z^2+2*z+2)*u2 + 4*z*u3,
|
|
120
|
+
u1 + (2*z^2+4*z+4)*u2 + u3]
|
|
121
|
+
|
|
122
|
+
We underline that the span is really the `\mathcal S`-span and
|
|
123
|
+
not the `R`-span (as otherwise, it will not be a Ore module).
|
|
124
|
+
|
|
125
|
+
As before, one can use the attributes ``names`` to give explicit
|
|
126
|
+
names to the basis vectors::
|
|
127
|
+
|
|
128
|
+
sage: V = U.span(P*u0, names='v')
|
|
129
|
+
sage: V
|
|
130
|
+
Ore module <v0, v1> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
131
|
+
sage: V.inject_variables()
|
|
132
|
+
Defining v0, v1
|
|
133
|
+
sage: v0
|
|
134
|
+
v0
|
|
135
|
+
sage: U(v0)
|
|
136
|
+
u0 + (z^2+2*z+2)*u2 + 4*z*u3
|
|
137
|
+
|
|
138
|
+
A coercion map from `V` to `U` is automatically created.
|
|
139
|
+
Hence, we can safely combine vectors in `V` and vectors in `U` in a
|
|
140
|
+
single expression::
|
|
141
|
+
|
|
142
|
+
sage: v0 - u0
|
|
143
|
+
(z^2+2*z+2)*u2 + 4*z*u3
|
|
144
|
+
|
|
145
|
+
We can create the quotient `U/V` using a similar syntax::
|
|
146
|
+
|
|
147
|
+
sage: W = U.quo(P*u0)
|
|
148
|
+
sage: W
|
|
149
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
150
|
+
sage: W.basis()
|
|
151
|
+
[u2, u3]
|
|
152
|
+
|
|
153
|
+
We see that SageMath reuses by default the names of the representatives
|
|
154
|
+
to denote the vectors in the quotient `U/V`. This behaviour can be
|
|
155
|
+
overridden by providing explicit names using the attributes ``names``.
|
|
156
|
+
|
|
157
|
+
Shortcuts for creating quotients are also available::
|
|
158
|
+
|
|
159
|
+
sage: U / (P*u0)
|
|
160
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
161
|
+
sage: U/V
|
|
162
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
163
|
+
|
|
164
|
+
.. RUBRIC:: Morphisms of Ore modules
|
|
165
|
+
|
|
166
|
+
For a tutorial on morphisms of Ore modules, we refer to
|
|
167
|
+
:mod:`sage.modules.ore_module_morphism`.
|
|
168
|
+
|
|
169
|
+
AUTHOR:
|
|
170
|
+
|
|
171
|
+
- Xavier Caruso (2024-10)
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
# ***************************************************************************
|
|
175
|
+
# Copyright (C) 2024 Xavier Caruso <xavier.caruso@normalesup.org>
|
|
176
|
+
#
|
|
177
|
+
# This program is free software: you can redistribute it and/or modify
|
|
178
|
+
# it under the terms of the GNU General Public License as published by
|
|
179
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
180
|
+
# (at your option) any later version.
|
|
181
|
+
# https://www.gnu.org/licenses/
|
|
182
|
+
# ***************************************************************************
|
|
183
|
+
|
|
184
|
+
import operator
|
|
185
|
+
|
|
186
|
+
from sage.misc.latex import latex
|
|
187
|
+
from sage.misc.latex import latex_variable_name
|
|
188
|
+
from sage.structure.sequence import Sequence
|
|
189
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
190
|
+
|
|
191
|
+
from sage.categories.action import Action
|
|
192
|
+
from sage.categories.fields import Fields
|
|
193
|
+
from sage.categories.ore_modules import OreModules
|
|
194
|
+
|
|
195
|
+
from sage.matrix.matrix0 import Matrix
|
|
196
|
+
from sage.matrix.constructor import matrix
|
|
197
|
+
from sage.matrix.special import identity_matrix
|
|
198
|
+
|
|
199
|
+
from sage.rings.polynomial.ore_polynomial_element import OrePolynomial
|
|
200
|
+
from sage.modules.free_module import FreeModule_ambient
|
|
201
|
+
from sage.modules.free_module_element import FreeModuleElement_generic_dense
|
|
202
|
+
from sage.modules.ore_module_element import OreModuleElement
|
|
203
|
+
|
|
204
|
+
# Action by left multiplication on Ore modules
|
|
205
|
+
##############################################
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class ScalarAction(Action):
|
|
209
|
+
r"""
|
|
210
|
+
Action by scalar multiplication on Ore modules.
|
|
211
|
+
"""
|
|
212
|
+
def _act_(self, a, x):
|
|
213
|
+
r"""
|
|
214
|
+
Return the result of the action of `a` on `x`.
|
|
215
|
+
|
|
216
|
+
INPUT:
|
|
217
|
+
|
|
218
|
+
- ``a`` -- a scalar in the base ring
|
|
219
|
+
|
|
220
|
+
- ``x`` -- a vector in a Ore module
|
|
221
|
+
|
|
222
|
+
EXAMPLES::
|
|
223
|
+
|
|
224
|
+
sage: K.<z> = GF(5^3)
|
|
225
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
226
|
+
sage: M.<e0,e1> = S.quotient_module(X^2 + z) # indirect doctest
|
|
227
|
+
sage: z*e0 # indirect doctest
|
|
228
|
+
z*e0
|
|
229
|
+
"""
|
|
230
|
+
return x._rmul_(a)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class OreAction(Action):
|
|
234
|
+
r"""
|
|
235
|
+
Action by left multiplication of Ore polynomial rings
|
|
236
|
+
over Ore modules.
|
|
237
|
+
"""
|
|
238
|
+
def _act_(self, P, x):
|
|
239
|
+
r"""
|
|
240
|
+
Return the result of the action of `P` on `x`.
|
|
241
|
+
|
|
242
|
+
INPUT:
|
|
243
|
+
|
|
244
|
+
- ``P`` -- a Ore polynomial
|
|
245
|
+
|
|
246
|
+
- ``x`` -- a vector in a Ore module
|
|
247
|
+
|
|
248
|
+
EXAMPLES::
|
|
249
|
+
|
|
250
|
+
sage: K.<z> = GF(5^3)
|
|
251
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
252
|
+
sage: M.<e0,e1> = S.quotient_module(X^2 + z) # indirect doctest
|
|
253
|
+
sage: X*e0 # indirect doctest
|
|
254
|
+
e1
|
|
255
|
+
"""
|
|
256
|
+
ans = P[0]*x
|
|
257
|
+
y = x
|
|
258
|
+
for i in range(1, P.degree() + 1):
|
|
259
|
+
y = y.image()
|
|
260
|
+
ans += y._rmul_(P[i])
|
|
261
|
+
return ans
|
|
262
|
+
|
|
263
|
+
# Generic class for Ore modules
|
|
264
|
+
###############################
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def normalize_names(names, rank):
|
|
268
|
+
r"""
|
|
269
|
+
Return a normalized form of ``names``.
|
|
270
|
+
|
|
271
|
+
INPUT:
|
|
272
|
+
|
|
273
|
+
- ``names`` -- a string, a list of strings or ``None``
|
|
274
|
+
|
|
275
|
+
- ``rank`` -- the number of names to normalize
|
|
276
|
+
|
|
277
|
+
EXAMPLES::
|
|
278
|
+
|
|
279
|
+
sage: from sage.modules.ore_module import normalize_names
|
|
280
|
+
|
|
281
|
+
When ``names`` is a string, indices are added::
|
|
282
|
+
|
|
283
|
+
sage: normalize_names('e', 3)
|
|
284
|
+
('e0', 'e1', 'e2')
|
|
285
|
+
|
|
286
|
+
When ``names`` is a list or a tuple, it remains untouched
|
|
287
|
+
except that it is always casted to a tuple (in order to be
|
|
288
|
+
hashable and serve as a key)::
|
|
289
|
+
|
|
290
|
+
sage: normalize_names(['u', 'v', 'w'], 3)
|
|
291
|
+
('u', 'v', 'w')
|
|
292
|
+
|
|
293
|
+
Similarly, when ``names`` is ``None``, nothing is returned::
|
|
294
|
+
|
|
295
|
+
sage: normalize_names(None, 3)
|
|
296
|
+
|
|
297
|
+
If the number of names is not equal to ``rank``, an error
|
|
298
|
+
is raised::
|
|
299
|
+
|
|
300
|
+
sage: normalize_names(['u', 'v', 'w'], 2)
|
|
301
|
+
Traceback (most recent call last):
|
|
302
|
+
...
|
|
303
|
+
ValueError: the number of given names does not match the rank of the Ore module
|
|
304
|
+
"""
|
|
305
|
+
if names is None:
|
|
306
|
+
pass
|
|
307
|
+
elif isinstance(names, (list, tuple)):
|
|
308
|
+
if rank != len(names):
|
|
309
|
+
raise ValueError("the number of given names does not match the rank of the Ore module")
|
|
310
|
+
names = tuple([str(name) for name in names])
|
|
311
|
+
elif isinstance(names, str):
|
|
312
|
+
names = tuple([names + str(i) for i in range(rank)])
|
|
313
|
+
else:
|
|
314
|
+
raise ValueError("names must be a string or a list/tuple of strings")
|
|
315
|
+
return names
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class OreModule(UniqueRepresentation, FreeModule_ambient):
|
|
319
|
+
r"""
|
|
320
|
+
Generic class for Ore modules.
|
|
321
|
+
"""
|
|
322
|
+
Element = OreModuleElement
|
|
323
|
+
|
|
324
|
+
def __classcall_private__(cls, mat, twist, names=None, category=None):
|
|
325
|
+
r"""
|
|
326
|
+
Normalize the input before passing it to the init function
|
|
327
|
+
(useful to ensure the uniqueness assumption).
|
|
328
|
+
|
|
329
|
+
INPUT:
|
|
330
|
+
|
|
331
|
+
- ``mat`` -- the matrix defining the action of the Ore variable
|
|
332
|
+
|
|
333
|
+
- ``twist`` -- the twisting morphism/derivation
|
|
334
|
+
|
|
335
|
+
- ``names`` (default: ``None``) -- a string of a list of strings,
|
|
336
|
+
the names of the vector of the canonical basis; if ``None``,
|
|
337
|
+
elements are represented as vectors in `K^d`
|
|
338
|
+
|
|
339
|
+
- ``category`` (default: ``None``) -- the category of this
|
|
340
|
+
Ore module
|
|
341
|
+
|
|
342
|
+
TESTS::
|
|
343
|
+
|
|
344
|
+
sage: K.<z> = GF(5^3)
|
|
345
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
346
|
+
sage: P = X^2 + z
|
|
347
|
+
|
|
348
|
+
sage: M1 = S.quotient_module(P)
|
|
349
|
+
sage: M2 = S.quotient_module(P, names='e')
|
|
350
|
+
sage: M3.<e0,e1> = S.quotient_module(P)
|
|
351
|
+
|
|
352
|
+
sage: M1 is M2
|
|
353
|
+
False
|
|
354
|
+
sage: M2 is M3
|
|
355
|
+
True
|
|
356
|
+
"""
|
|
357
|
+
base = mat.base_ring()
|
|
358
|
+
if category is None:
|
|
359
|
+
category = OreModules(base, twist)
|
|
360
|
+
rank = mat.nrows()
|
|
361
|
+
if mat.ncols() != rank:
|
|
362
|
+
raise ValueError("matrix must be square")
|
|
363
|
+
names = normalize_names(names, rank)
|
|
364
|
+
return cls.__classcall__(cls, mat, category._ore, names, category)
|
|
365
|
+
|
|
366
|
+
def __init__(self, mat, ore, names, category) -> None:
|
|
367
|
+
r"""
|
|
368
|
+
Initialize this Ore module.
|
|
369
|
+
|
|
370
|
+
INPUT:
|
|
371
|
+
|
|
372
|
+
- ``mat`` -- the matrix defining the action of the Ore variable
|
|
373
|
+
|
|
374
|
+
- ``ore`` -- the underlying Ore polynomial ring
|
|
375
|
+
|
|
376
|
+
- ``names`` -- a string of a list of strings,
|
|
377
|
+
the names of the vector of the canonical basis; if ``None``,
|
|
378
|
+
elements are represented as vectors in `K^d`
|
|
379
|
+
|
|
380
|
+
- ``category`` -- the category of this Ore module
|
|
381
|
+
|
|
382
|
+
TESTS::
|
|
383
|
+
|
|
384
|
+
sage: K.<z> = GF(5^3)
|
|
385
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
386
|
+
sage: M = S.quotient_module(X^2 + z) # indirect doctest
|
|
387
|
+
sage: type(M)
|
|
388
|
+
<class 'sage.modules.ore_module.OreModule_with_category'>
|
|
389
|
+
|
|
390
|
+
sage: TestSuite(M).run()
|
|
391
|
+
"""
|
|
392
|
+
base = mat.base_ring()
|
|
393
|
+
rank = mat.nrows()
|
|
394
|
+
FreeModule_ambient.__init__(self, base, rank, category=category)
|
|
395
|
+
self.register_action(ScalarAction(base, self, True, operator.mul))
|
|
396
|
+
self._ore = ore
|
|
397
|
+
self._ore_category = category
|
|
398
|
+
self._names = names
|
|
399
|
+
if names is not None:
|
|
400
|
+
self._latex_names = [latex_variable_name(name) for name in names]
|
|
401
|
+
self._submodule_class = OreSubmodule
|
|
402
|
+
self._quotientModule_class = OreQuotientModule
|
|
403
|
+
self._pseudohom = FreeModule_ambient.pseudohom(self, mat, ore, codomain=self)
|
|
404
|
+
|
|
405
|
+
def _repr_(self) -> str:
|
|
406
|
+
r"""
|
|
407
|
+
Return a string representation of this Ore module.
|
|
408
|
+
|
|
409
|
+
TESTS::
|
|
410
|
+
|
|
411
|
+
sage: K.<z> = GF(5^3)
|
|
412
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
413
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
414
|
+
sage: M._repr_()
|
|
415
|
+
'Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5'
|
|
416
|
+
sage: N = S.quotient_module(X^2 + z, names='e')
|
|
417
|
+
sage: N._repr_()
|
|
418
|
+
'Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5'
|
|
419
|
+
|
|
420
|
+
::
|
|
421
|
+
|
|
422
|
+
sage: K.<z> = Frac(GF(17)['z'])
|
|
423
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
424
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
425
|
+
sage: M._repr_()
|
|
426
|
+
'Ore module of rank 2 over Fraction Field of Univariate Polynomial Ring in z over Finite Field of size 17 twisted by d/dz'
|
|
427
|
+
"""
|
|
428
|
+
s = "Ore module "
|
|
429
|
+
if self._names is None:
|
|
430
|
+
s += "of rank %s " % self.rank()
|
|
431
|
+
else:
|
|
432
|
+
s += "<" + ", ".join(self._names) + "> "
|
|
433
|
+
s += "over %s %s" % (self.base_ring(), self._ore._repr_twist())
|
|
434
|
+
return s
|
|
435
|
+
|
|
436
|
+
def _latex_(self) -> str:
|
|
437
|
+
r"""
|
|
438
|
+
Return a LaTeX representation of this Ore module.
|
|
439
|
+
|
|
440
|
+
TESTS::
|
|
441
|
+
|
|
442
|
+
sage: K.<z> = GF(5^3)
|
|
443
|
+
sage: Frob = K.frobenius_endomorphism()
|
|
444
|
+
sage: S.<X> = OrePolynomialRing(K, Frob)
|
|
445
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
446
|
+
sage: latex(M)
|
|
447
|
+
\texttt{Ore module of rank } 2\texttt{ over } \Bold{F}_{5^{3}} \texttt{ twisted by } z \mapsto z^{5}
|
|
448
|
+
sage: N = S.quotient_module(X^2 + z, names='e')
|
|
449
|
+
sage: latex(N)
|
|
450
|
+
\left<e_{0}, e_{1}\right>_{\Bold{F}_{5^{3}} , z \mapsto z^{5} }
|
|
451
|
+
|
|
452
|
+
::
|
|
453
|
+
|
|
454
|
+
sage: T.<Y> = OrePolynomialRing(K, Frob^3, polcast=False)
|
|
455
|
+
sage: M = T.quotient_module(Y^2 + z^2)
|
|
456
|
+
sage: latex(M)
|
|
457
|
+
\texttt{Ore module of rank } 2\texttt{ over } \Bold{F}_{5^{3}}\texttt{ untwisted}
|
|
458
|
+
"""
|
|
459
|
+
if self._names is None:
|
|
460
|
+
s = "\\texttt{Ore module of rank } %s" % self.rank()
|
|
461
|
+
s += "\\texttt{ over } %s" % latex(self.base_ring())
|
|
462
|
+
twist = self._ore._latex_twist()
|
|
463
|
+
if twist == "":
|
|
464
|
+
s += "\\texttt{ untwisted}"
|
|
465
|
+
else:
|
|
466
|
+
s += "\\texttt{ twisted by }" + twist
|
|
467
|
+
else:
|
|
468
|
+
s = "\\left<" + ", ".join(self._latex_names) + "\\right>"
|
|
469
|
+
s += "_{%s" % latex(self.base_ring())
|
|
470
|
+
twist = self._ore._latex_twist()
|
|
471
|
+
if twist != "":
|
|
472
|
+
s += "," + twist
|
|
473
|
+
s += "}"
|
|
474
|
+
return s
|
|
475
|
+
|
|
476
|
+
def _repr_element(self, x) -> str:
|
|
477
|
+
r"""
|
|
478
|
+
Return a string representation of the element `x` in
|
|
479
|
+
this Ore module.
|
|
480
|
+
|
|
481
|
+
EXAMPLES::
|
|
482
|
+
|
|
483
|
+
sage: K.<z> = GF(5^3)
|
|
484
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
485
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
486
|
+
sage: M((z, z^2)) # indirect doctest
|
|
487
|
+
(z, z^2)
|
|
488
|
+
"""
|
|
489
|
+
return FreeModuleElement_generic_dense._repr_(x)
|
|
490
|
+
|
|
491
|
+
def _latex_element(self, x) -> str:
|
|
492
|
+
r"""
|
|
493
|
+
Return a LaTeX representation of the element `x` in
|
|
494
|
+
this Ore module.
|
|
495
|
+
|
|
496
|
+
EXAMPLES::
|
|
497
|
+
|
|
498
|
+
sage: K.<z> = GF(5^3)
|
|
499
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
500
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
501
|
+
sage: v = M((z, z^2))
|
|
502
|
+
sage: latex(v) # indirect doctest
|
|
503
|
+
\left(z,\,z^{2}\right)
|
|
504
|
+
"""
|
|
505
|
+
return FreeModuleElement_generic_dense._latex_(x)
|
|
506
|
+
|
|
507
|
+
def _coerce_map_from_(self, S):
|
|
508
|
+
r"""
|
|
509
|
+
Return a coercion map from `M` to ``self``, or ``None``.
|
|
510
|
+
|
|
511
|
+
This method always returns ``None``; all coercions between
|
|
512
|
+
Ore modules are currently handled using the method
|
|
513
|
+
:meth:`register_coercion`.
|
|
514
|
+
|
|
515
|
+
TESTS::
|
|
516
|
+
|
|
517
|
+
sage: K.<z> = GF(5^3)
|
|
518
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
519
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
520
|
+
sage: N = M.span((X + z)*v)
|
|
521
|
+
|
|
522
|
+
sage: M._coerce_map_from_(N)
|
|
523
|
+
sage: M.coerce_map_from(N)
|
|
524
|
+
Ore module morphism:
|
|
525
|
+
From: Ore module of rank 1 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
526
|
+
To: Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
527
|
+
"""
|
|
528
|
+
pass
|
|
529
|
+
|
|
530
|
+
def is_zero(self) -> bool:
|
|
531
|
+
r"""
|
|
532
|
+
Return ``True`` if this Ore module is reduced to zero.
|
|
533
|
+
|
|
534
|
+
EXAMPLES::
|
|
535
|
+
|
|
536
|
+
sage: K.<z> = GF(5^3)
|
|
537
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
538
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
539
|
+
sage: M
|
|
540
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
541
|
+
sage: M.is_zero()
|
|
542
|
+
False
|
|
543
|
+
|
|
544
|
+
sage: Q = M.quo(M)
|
|
545
|
+
sage: Q.is_zero()
|
|
546
|
+
True
|
|
547
|
+
"""
|
|
548
|
+
return self.rank() == 0
|
|
549
|
+
|
|
550
|
+
def rename_basis(self, names, coerce=False):
|
|
551
|
+
r"""
|
|
552
|
+
Return the same Ore module with the given naming
|
|
553
|
+
for the vectors in its distinguished basis.
|
|
554
|
+
|
|
555
|
+
INPUT:
|
|
556
|
+
|
|
557
|
+
- ``names`` -- a string or a list of strings, the
|
|
558
|
+
new names
|
|
559
|
+
|
|
560
|
+
- ``coerce`` (default: ``False``) -- a boolean; if
|
|
561
|
+
``True``, a coercion map from this Ore module to
|
|
562
|
+
renamed version is set
|
|
563
|
+
|
|
564
|
+
EXAMPLES::
|
|
565
|
+
|
|
566
|
+
sage: K.<z> = GF(5^3)
|
|
567
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
568
|
+
sage: M = S.quotient_module(X^2 + z)
|
|
569
|
+
sage: M
|
|
570
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
571
|
+
|
|
572
|
+
sage: Me = M.rename_basis('e')
|
|
573
|
+
sage: Me
|
|
574
|
+
Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
575
|
+
|
|
576
|
+
Now compare how elements are displayed::
|
|
577
|
+
|
|
578
|
+
sage: M.random_element() # random
|
|
579
|
+
(3*z^2 + 4*z + 2, 3*z^2 + z)
|
|
580
|
+
sage: Me.random_element() # random
|
|
581
|
+
(2*z+4)*e0 + (z^2+4*z+4)*e1
|
|
582
|
+
|
|
583
|
+
At this point, there is no coercion map between ``M``
|
|
584
|
+
and ``Me``. Therefore, adding elements in both parents
|
|
585
|
+
results in an error::
|
|
586
|
+
|
|
587
|
+
sage: M.random_element() + Me.random_element()
|
|
588
|
+
Traceback (most recent call last):
|
|
589
|
+
...
|
|
590
|
+
TypeError: unsupported operand parent(s) for +:
|
|
591
|
+
'Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5' and
|
|
592
|
+
'Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5'
|
|
593
|
+
|
|
594
|
+
In order to set this coercion, one should define ``Me``
|
|
595
|
+
by passing the extra argument ``coerce=True``::
|
|
596
|
+
|
|
597
|
+
sage: Me = M.rename_basis('e', coerce=True)
|
|
598
|
+
sage: M.random_element() + Me.random_element() # random
|
|
599
|
+
2*z^2*e0 + (z^2+z+4)*e1
|
|
600
|
+
|
|
601
|
+
.. WARNING::
|
|
602
|
+
|
|
603
|
+
Use ``coerce=True`` with extreme caution. Indeed,
|
|
604
|
+
setting inappropriate coercion maps may result in a
|
|
605
|
+
circular path in the coercion graph which, in turn,
|
|
606
|
+
could eventually break the coercion system.
|
|
607
|
+
|
|
608
|
+
Note that the bracket construction also works::
|
|
609
|
+
|
|
610
|
+
sage: M.<v,w> = M.rename_basis()
|
|
611
|
+
sage: M
|
|
612
|
+
Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
613
|
+
|
|
614
|
+
In this case, `v` and `w` are automatically defined::
|
|
615
|
+
|
|
616
|
+
sage: v + w
|
|
617
|
+
v + w
|
|
618
|
+
"""
|
|
619
|
+
rank = self.rank()
|
|
620
|
+
names = normalize_names(names, rank)
|
|
621
|
+
cls = self.__class__
|
|
622
|
+
M = cls.__classcall__(cls, self._pseudohom._matrix,
|
|
623
|
+
self._ore, names, self._ore_category)
|
|
624
|
+
if coerce:
|
|
625
|
+
mat = identity_matrix(self.base_ring(), rank)
|
|
626
|
+
id = self.hom(mat, codomain=M)
|
|
627
|
+
M._unset_coercions_used()
|
|
628
|
+
M.register_coercion(id)
|
|
629
|
+
return M
|
|
630
|
+
|
|
631
|
+
def pseudohom(self):
|
|
632
|
+
r"""
|
|
633
|
+
Return the pseudomorphism giving the action of the Ore
|
|
634
|
+
variable on this Ore module.
|
|
635
|
+
|
|
636
|
+
EXAMPLES::
|
|
637
|
+
|
|
638
|
+
sage: K.<z> = GF(5^3)
|
|
639
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
640
|
+
sage: P = X^3 + z*X^2 - z^2*X + (z+2)
|
|
641
|
+
sage: M = S.quotient_module(P)
|
|
642
|
+
sage: M.pseudohom()
|
|
643
|
+
Free module pseudomorphism (twisted by z |--> z^5) defined by the matrix
|
|
644
|
+
[ 0 1 0]
|
|
645
|
+
[ 0 0 1]
|
|
646
|
+
[4*z + 3 z^2 4*z]
|
|
647
|
+
Domain: Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
648
|
+
Codomain: Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
649
|
+
|
|
650
|
+
.. SEEALSO::
|
|
651
|
+
|
|
652
|
+
:meth:`matrix`
|
|
653
|
+
"""
|
|
654
|
+
return self._pseudohom
|
|
655
|
+
|
|
656
|
+
def ore_ring(self, names='x', action=True):
|
|
657
|
+
r"""
|
|
658
|
+
Return the underlying Ore polynomial ring.
|
|
659
|
+
|
|
660
|
+
INPUT:
|
|
661
|
+
|
|
662
|
+
- ``names`` (default: ``x``) -- a string, the name
|
|
663
|
+
of the variable
|
|
664
|
+
|
|
665
|
+
- ``action`` (default: ``True``) -- a boolean; if
|
|
666
|
+
``True``, an action of the Ore polynomial ring on
|
|
667
|
+
the Ore module is set
|
|
668
|
+
|
|
669
|
+
EXAMPLES::
|
|
670
|
+
|
|
671
|
+
sage: K.<a> = GF(5^3)
|
|
672
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
673
|
+
sage: M.<e1,e2> = S.quotient_module(X^2 - a)
|
|
674
|
+
sage: M.ore_ring()
|
|
675
|
+
Ore Polynomial Ring in x over Finite Field in a of size 5^3 twisted by a |--> a^5
|
|
676
|
+
|
|
677
|
+
We can use a different variable name::
|
|
678
|
+
|
|
679
|
+
sage: M.ore_ring('Y')
|
|
680
|
+
Ore Polynomial Ring in Y over Finite Field in a of size 5^3 twisted by a |--> a^5
|
|
681
|
+
|
|
682
|
+
Alternatively, one can use the following shortcut::
|
|
683
|
+
|
|
684
|
+
sage: T.<Z> = M.ore_ring()
|
|
685
|
+
sage: T
|
|
686
|
+
Ore Polynomial Ring in Z over Finite Field in a of size 5^3 twisted by a |--> a^5
|
|
687
|
+
|
|
688
|
+
In all the above cases, an action of the returned Ore polynomial
|
|
689
|
+
ring on `M` is registered::
|
|
690
|
+
|
|
691
|
+
sage: Z*e1
|
|
692
|
+
e2
|
|
693
|
+
sage: Z*e2
|
|
694
|
+
a*e1
|
|
695
|
+
|
|
696
|
+
Specifying ``action=False`` prevents this to happen::
|
|
697
|
+
|
|
698
|
+
sage: T.<U> = M.ore_ring(action=False)
|
|
699
|
+
sage: U*e1
|
|
700
|
+
Traceback (most recent call last):
|
|
701
|
+
...
|
|
702
|
+
TypeError: unsupported operand parent(s) for *:
|
|
703
|
+
'Ore Polynomial Ring in U over Finite Field in a of size 5^3 twisted by a |--> a^5' and
|
|
704
|
+
'Ore module <e1, e2> over Finite Field in a of size 5^3 twisted by a |--> a^5'
|
|
705
|
+
"""
|
|
706
|
+
S = self._ore_category.ore_ring(names)
|
|
707
|
+
if action:
|
|
708
|
+
self._unset_coercions_used()
|
|
709
|
+
self.register_action(OreAction(S, self, True, operator.mul))
|
|
710
|
+
return S
|
|
711
|
+
|
|
712
|
+
def twisting_morphism(self):
|
|
713
|
+
r"""
|
|
714
|
+
Return the twisting morphism corresponding to this Ore module.
|
|
715
|
+
|
|
716
|
+
EXAMPLES::
|
|
717
|
+
|
|
718
|
+
sage: K.<z> = GF(5^3)
|
|
719
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
720
|
+
sage: M = S.quotient_module(X + z)
|
|
721
|
+
sage: M.twisting_morphism()
|
|
722
|
+
Frobenius endomorphism z |--> z^5 on Finite Field in z of size 5^3
|
|
723
|
+
|
|
724
|
+
When the twisting morphism is trivial (that is, the identity),
|
|
725
|
+
nothing is returned::
|
|
726
|
+
|
|
727
|
+
sage: R.<t> = QQ[]
|
|
728
|
+
sage: T.<Y> = OrePolynomialRing(R, R.derivation())
|
|
729
|
+
sage: M = T.quotient_module(Y + t^2)
|
|
730
|
+
sage: M.twisting_morphism()
|
|
731
|
+
|
|
732
|
+
.. SEEALSO::
|
|
733
|
+
|
|
734
|
+
:meth:`twisting_derivation`
|
|
735
|
+
"""
|
|
736
|
+
return self._ore.twisting_morphism()
|
|
737
|
+
|
|
738
|
+
def twisting_derivation(self):
|
|
739
|
+
r"""
|
|
740
|
+
Return the twisting derivation corresponding to this Ore module.
|
|
741
|
+
|
|
742
|
+
EXAMPLES::
|
|
743
|
+
|
|
744
|
+
sage: R.<t> = QQ[]
|
|
745
|
+
sage: T.<Y> = OrePolynomialRing(R, R.derivation())
|
|
746
|
+
sage: M = T.quotient_module(Y + t^2)
|
|
747
|
+
sage: M.twisting_derivation()
|
|
748
|
+
d/dt
|
|
749
|
+
|
|
750
|
+
When the twisting derivation in zero, nothing is returned::
|
|
751
|
+
|
|
752
|
+
sage: K.<z> = GF(5^3)
|
|
753
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
754
|
+
sage: M = S.quotient_module(X + z)
|
|
755
|
+
sage: M.twisting_derivation()
|
|
756
|
+
|
|
757
|
+
.. SEEALSO::
|
|
758
|
+
|
|
759
|
+
:meth:`twisting_morphism`
|
|
760
|
+
"""
|
|
761
|
+
return self._ore.twisting_derivation()
|
|
762
|
+
|
|
763
|
+
def matrix(self):
|
|
764
|
+
r"""
|
|
765
|
+
Return the matrix giving the action of the Ore variable
|
|
766
|
+
on this Ore module.
|
|
767
|
+
|
|
768
|
+
EXAMPLES::
|
|
769
|
+
|
|
770
|
+
sage: K.<z> = GF(5^3)
|
|
771
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
772
|
+
sage: P = X^3 + z*X^2 - z^2*X + (z+2)
|
|
773
|
+
sage: M = S.quotient_module(P)
|
|
774
|
+
sage: M.matrix()
|
|
775
|
+
[ 0 1 0]
|
|
776
|
+
[ 0 0 1]
|
|
777
|
+
[4*z + 3 z^2 4*z]
|
|
778
|
+
|
|
779
|
+
We recognize the companion matrix attached to the Ore
|
|
780
|
+
polynomial `P`. This is of course not a coincidence given
|
|
781
|
+
that the pseudomorphism corresponds to the left multiplication
|
|
782
|
+
|
|
783
|
+
.. SEEALSO::
|
|
784
|
+
|
|
785
|
+
:meth:`pseudohom`
|
|
786
|
+
"""
|
|
787
|
+
return self._pseudohom.matrix()
|
|
788
|
+
|
|
789
|
+
def basis(self) -> list:
|
|
790
|
+
r"""
|
|
791
|
+
Return the canonical basis of this Ore module.
|
|
792
|
+
|
|
793
|
+
EXAMPLES::
|
|
794
|
+
|
|
795
|
+
sage: K.<z> = GF(5^3)
|
|
796
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
797
|
+
sage: M = S.quotient_module(X^3 - z)
|
|
798
|
+
sage: M.basis()
|
|
799
|
+
[(1, 0, 0), (0, 1, 0), (0, 0, 1)]
|
|
800
|
+
"""
|
|
801
|
+
rank = self.rank()
|
|
802
|
+
zero = self.base_ring().zero()
|
|
803
|
+
one = self.base_ring().one()
|
|
804
|
+
coeffs = [zero] * rank
|
|
805
|
+
B = []
|
|
806
|
+
for i in range(rank):
|
|
807
|
+
coeffs[i] = one
|
|
808
|
+
B.append(self(coeffs))
|
|
809
|
+
coeffs[i] = zero
|
|
810
|
+
return B
|
|
811
|
+
|
|
812
|
+
def gens(self) -> list:
|
|
813
|
+
r"""
|
|
814
|
+
Return the canonical basis of this Ore module.
|
|
815
|
+
|
|
816
|
+
EXAMPLES::
|
|
817
|
+
|
|
818
|
+
sage: K.<z> = GF(5^3)
|
|
819
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
820
|
+
sage: M = S.quotient_module(X^3 - z)
|
|
821
|
+
sage: M.gens()
|
|
822
|
+
[(1, 0, 0), (0, 1, 0), (0, 0, 1)]
|
|
823
|
+
"""
|
|
824
|
+
return self.basis()
|
|
825
|
+
|
|
826
|
+
def gen(self, i):
|
|
827
|
+
r"""
|
|
828
|
+
Return the `i`-th vector of the canonical basis
|
|
829
|
+
of this Ore module.
|
|
830
|
+
|
|
831
|
+
EXAMPLES::
|
|
832
|
+
|
|
833
|
+
sage: K.<z> = GF(5^3)
|
|
834
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
835
|
+
sage: M = S.quotient_module(X^3 - z)
|
|
836
|
+
sage: M.gen(0)
|
|
837
|
+
(1, 0, 0)
|
|
838
|
+
sage: M.gen(1)
|
|
839
|
+
(0, 1, 0)
|
|
840
|
+
sage: M.gen(2)
|
|
841
|
+
(0, 0, 1)
|
|
842
|
+
sage: M.gen(3)
|
|
843
|
+
Traceback (most recent call last):
|
|
844
|
+
...
|
|
845
|
+
IndexError: generator is not defined
|
|
846
|
+
"""
|
|
847
|
+
rank = self.rank()
|
|
848
|
+
if i < 0 or i >= rank:
|
|
849
|
+
raise IndexError("generator is not defined")
|
|
850
|
+
zero = self.base_ring().zero()
|
|
851
|
+
one = self.base_ring().one()
|
|
852
|
+
coeffs = [zero] * rank
|
|
853
|
+
coeffs[i] = one
|
|
854
|
+
return self(coeffs)
|
|
855
|
+
|
|
856
|
+
def _an_element_(self):
|
|
857
|
+
r"""
|
|
858
|
+
Return an element of this Ore module.
|
|
859
|
+
|
|
860
|
+
EXAMPLES:
|
|
861
|
+
|
|
862
|
+
When the Ore module is not zero, the returned element
|
|
863
|
+
is the first vector of the distinguished basis::
|
|
864
|
+
|
|
865
|
+
sage: K.<t> = Frac(QQ['t'])
|
|
866
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
867
|
+
sage: M.<u,v> = S.quotient_module(X^2 - t)
|
|
868
|
+
sage: M.an_element()
|
|
869
|
+
u
|
|
870
|
+
|
|
871
|
+
On the contrary, when the Ore module vanishes, the
|
|
872
|
+
returned element is of course zero::
|
|
873
|
+
|
|
874
|
+
sage: N = M / u
|
|
875
|
+
sage: N
|
|
876
|
+
Ore module of rank 0 over Fraction Field of Univariate Polynomial Ring in t over Rational Field twisted by d/dt
|
|
877
|
+
sage: N.an_element()
|
|
878
|
+
0
|
|
879
|
+
"""
|
|
880
|
+
if self.rank() > 0:
|
|
881
|
+
return self.gen(0)
|
|
882
|
+
return self.zero()
|
|
883
|
+
|
|
884
|
+
def random_element(self, *args, **kwds):
|
|
885
|
+
r"""
|
|
886
|
+
Return a random element in this Ore module.
|
|
887
|
+
|
|
888
|
+
Extra arguments are passed to the random generator
|
|
889
|
+
of the base ring.
|
|
890
|
+
|
|
891
|
+
EXAMPLES::
|
|
892
|
+
|
|
893
|
+
sage: A.<t> = QQ['t']
|
|
894
|
+
sage: S.<X> = OrePolynomialRing(A, A.derivation())
|
|
895
|
+
sage: M = S.quotient_module(X^3 - t, names='e')
|
|
896
|
+
sage: M.random_element() # random
|
|
897
|
+
(-1/2*t^2 - 3/4*t + 3/2)*e0 + (-3/2*t^2 - 3*t + 4)*e1 + (-6*t + 2)*e2
|
|
898
|
+
|
|
899
|
+
sage: M.random_element(degree=5) # random
|
|
900
|
+
(4*t^5 - 1/2*t^4 + 3/2*t^3 + 6*t^2 - t - 1/10)*e0 + (19/3*t^5 - t^3 - t^2 + 1)*e1 + (t^5 + 4*t^4 + 4*t^2 + 1/3*t - 33)*e2
|
|
901
|
+
"""
|
|
902
|
+
K = self.base_ring()
|
|
903
|
+
r = self.rank()
|
|
904
|
+
vs = [K.random_element(*args, **kwds) for _ in range(r)]
|
|
905
|
+
return self(vs)
|
|
906
|
+
|
|
907
|
+
def module(self):
|
|
908
|
+
r"""
|
|
909
|
+
Return the underlying free module of this Ore module.
|
|
910
|
+
|
|
911
|
+
EXAMPLES::
|
|
912
|
+
|
|
913
|
+
sage: A.<t> = QQ['t']
|
|
914
|
+
sage: S.<X> = OrePolynomialRing(A, A.derivation())
|
|
915
|
+
sage: M = S.quotient_module(X^3 - t)
|
|
916
|
+
sage: M
|
|
917
|
+
Ore module of rank 3 over Univariate Polynomial Ring in t over Rational Field twisted by d/dt
|
|
918
|
+
|
|
919
|
+
sage: M.module()
|
|
920
|
+
Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in t over Rational Field
|
|
921
|
+
"""
|
|
922
|
+
return self.base_ring() ** self.rank()
|
|
923
|
+
|
|
924
|
+
def _Hom_(self, codomain, category):
|
|
925
|
+
r"""
|
|
926
|
+
Return the space of Ore morphisms from this Ore module
|
|
927
|
+
to ``codomain``.
|
|
928
|
+
|
|
929
|
+
INPUT:
|
|
930
|
+
|
|
931
|
+
- ``codomain`` -- a Ore module
|
|
932
|
+
|
|
933
|
+
- ``category`` -- the category in which the morphisms are
|
|
934
|
+
|
|
935
|
+
TESTS::
|
|
936
|
+
|
|
937
|
+
sage: K.<z> = GF(5^3)
|
|
938
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
939
|
+
sage: M = S.quotient_module(X^2 - z)
|
|
940
|
+
sage: N = S.quotient_module(X^3 - z)
|
|
941
|
+
|
|
942
|
+
sage: Hom(M, N) # indirect doctest
|
|
943
|
+
Set of Morphisms
|
|
944
|
+
from Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
945
|
+
to Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
946
|
+
in Category of enumerated finite dimensional Ore modules with basis over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
947
|
+
|
|
948
|
+
::
|
|
949
|
+
|
|
950
|
+
sage: End(M) # indirect doctest
|
|
951
|
+
Set of Morphisms
|
|
952
|
+
from Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
953
|
+
to Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
954
|
+
in Category of enumerated finite dimensional Ore modules with basis over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
955
|
+
"""
|
|
956
|
+
from sage.modules.ore_module_homspace import OreModule_homspace
|
|
957
|
+
return OreModule_homspace(self, codomain)
|
|
958
|
+
|
|
959
|
+
def hom(self, im_gens, codomain=None):
|
|
960
|
+
r"""
|
|
961
|
+
Return the morphism from this Ore module to ``codomain``
|
|
962
|
+
defined by ``im_gens``.
|
|
963
|
+
|
|
964
|
+
INPUT:
|
|
965
|
+
|
|
966
|
+
- ``im_gens`` -- a datum defining the morphism to build;
|
|
967
|
+
it could either a list, a tuple, a dictionary or a morphism
|
|
968
|
+
of Ore modules
|
|
969
|
+
|
|
970
|
+
- ``codomain`` (default: ``None``) -- a Ore module, the
|
|
971
|
+
codomain of the morphism; if ``None``, it is inferred from
|
|
972
|
+
``im_gens``
|
|
973
|
+
|
|
974
|
+
EXAMPLES::
|
|
975
|
+
|
|
976
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
977
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
978
|
+
sage: P = X^3 + 2*t*X^2 + (t^2 + 2)*X + t
|
|
979
|
+
sage: Q = t*X^2 - X + 1
|
|
980
|
+
|
|
981
|
+
sage: U = S.quotient_module(P, names='u')
|
|
982
|
+
sage: U.inject_variables()
|
|
983
|
+
Defining u0, u1, u2
|
|
984
|
+
sage: V = S.quotient_module(P*Q, names='v')
|
|
985
|
+
sage: V.inject_variables()
|
|
986
|
+
Defining v0, v1, v2, v3, v4
|
|
987
|
+
|
|
988
|
+
The first method for creating a morphism from `U` to `V` is
|
|
989
|
+
to explicitly write down its matrix in the canonical bases::
|
|
990
|
+
|
|
991
|
+
sage: mat = matrix(3, 5, [1, 4, t, 0, 0,
|
|
992
|
+
....: 0, 1, 0, t, 0,
|
|
993
|
+
....: 0, 0, 1, 1, t])
|
|
994
|
+
sage: f = U.hom(mat, codomain=V)
|
|
995
|
+
sage: f
|
|
996
|
+
Ore module morphism:
|
|
997
|
+
From: Ore module <u0, u1, u2> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
998
|
+
To: Ore module <v0, v1, v2, v3, v4> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
999
|
+
|
|
1000
|
+
This method is however not really convenient because it
|
|
1001
|
+
requires to compute beforehand all the entries of the
|
|
1002
|
+
defining matrix.
|
|
1003
|
+
Instead, we can pass the list of images of the generators::
|
|
1004
|
+
|
|
1005
|
+
sage: g = U.hom([Q*v0, X*Q*v0, X^2*Q*v0])
|
|
1006
|
+
sage: g
|
|
1007
|
+
Ore module morphism:
|
|
1008
|
+
From: Ore module <u0, u1, u2> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1009
|
+
To: Ore module <v0, v1, v2, v3, v4> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1010
|
+
sage: g.matrix()
|
|
1011
|
+
[1 4 t 0 0]
|
|
1012
|
+
[0 1 0 t 0]
|
|
1013
|
+
[0 0 1 1 t]
|
|
1014
|
+
|
|
1015
|
+
One can even give the values of the morphism on a smaller
|
|
1016
|
+
set as soon as the latter generates the domain as Ore module.
|
|
1017
|
+
The syntax uses dictionaries as follows::
|
|
1018
|
+
|
|
1019
|
+
sage: h = U.hom({u0: Q*v0})
|
|
1020
|
+
sage: h
|
|
1021
|
+
Ore module morphism:
|
|
1022
|
+
From: Ore module <u0, u1, u2> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1023
|
+
To: Ore module <v0, v1, v2, v3, v4> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1024
|
+
sage: g == h
|
|
1025
|
+
True
|
|
1026
|
+
|
|
1027
|
+
Finally ``im_gens`` can also be itself a Ore morphism, in which
|
|
1028
|
+
case SageMath tries to cast it into a morphism with the requested
|
|
1029
|
+
domains and codomains.
|
|
1030
|
+
As an example below, we restrict `g` to a subspace::
|
|
1031
|
+
|
|
1032
|
+
sage: C.<c0,c1> = U.span((X + t)*u0)
|
|
1033
|
+
sage: gC = C.hom(g)
|
|
1034
|
+
sage: gC
|
|
1035
|
+
Ore module morphism:
|
|
1036
|
+
From: Ore module <c0, c1> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1037
|
+
To: Ore module <v0, v1, v2, v3, v4> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1038
|
+
|
|
1039
|
+
sage: g(c0) == gC(c0)
|
|
1040
|
+
True
|
|
1041
|
+
sage: g(c1) == gC(c1)
|
|
1042
|
+
True
|
|
1043
|
+
|
|
1044
|
+
TESTS::
|
|
1045
|
+
|
|
1046
|
+
sage: U.hom(0)
|
|
1047
|
+
Traceback (most recent call last):
|
|
1048
|
+
...
|
|
1049
|
+
ValueError: im_gens must be a list, a tuple, a dictionary, a matrix or a Ore module morphism
|
|
1050
|
+
|
|
1051
|
+
sage: U.hom([Q*v0])
|
|
1052
|
+
Traceback (most recent call last):
|
|
1053
|
+
...
|
|
1054
|
+
ValueError: wrong number of generators
|
|
1055
|
+
|
|
1056
|
+
sage: U.hom({u0: Q*v0, u1: Q*v0})
|
|
1057
|
+
Traceback (most recent call last):
|
|
1058
|
+
...
|
|
1059
|
+
ValueError: does not define a morphism of Ore modules
|
|
1060
|
+
|
|
1061
|
+
sage: U.hom({(X+t)*u0: (X+t)*Q*v0})
|
|
1062
|
+
Traceback (most recent call last):
|
|
1063
|
+
...
|
|
1064
|
+
ValueError: does not define a morphism of Ore modules
|
|
1065
|
+
"""
|
|
1066
|
+
from sage.modules.ore_module_morphism import OreModuleMorphism
|
|
1067
|
+
if codomain is None:
|
|
1068
|
+
if isinstance(im_gens, Matrix):
|
|
1069
|
+
codomain = self
|
|
1070
|
+
elif isinstance(im_gens, OreModuleMorphism):
|
|
1071
|
+
codomain = im_gens.codomain()
|
|
1072
|
+
elif isinstance(im_gens, (list, tuple)):
|
|
1073
|
+
codomain = Sequence(im_gens).universe()
|
|
1074
|
+
elif isinstance(im_gens, dict):
|
|
1075
|
+
codomain = Sequence(im_gens.values()).universe()
|
|
1076
|
+
else:
|
|
1077
|
+
raise ValueError("im_gens must be a list, a tuple, a dictionary, a matrix or a Ore module morphism")
|
|
1078
|
+
H = self.Hom(codomain)
|
|
1079
|
+
return H(im_gens)
|
|
1080
|
+
|
|
1081
|
+
def multiplication_map(self, P):
|
|
1082
|
+
r"""
|
|
1083
|
+
Return the multiplication by `P` acting on this Ore module.
|
|
1084
|
+
|
|
1085
|
+
INPUT:
|
|
1086
|
+
|
|
1087
|
+
- ``P`` -- a scalar in the base ring, or a Ore polynomial
|
|
1088
|
+
|
|
1089
|
+
EXAMPLES::
|
|
1090
|
+
|
|
1091
|
+
sage: K.<a> = GF(7^5)
|
|
1092
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1093
|
+
sage: P = X^3 + a*X^2 + X - a^2
|
|
1094
|
+
sage: M = S.quotient_module(P)
|
|
1095
|
+
|
|
1096
|
+
We define the scalar multiplication by an element in the base ring::
|
|
1097
|
+
|
|
1098
|
+
sage: f = M.multiplication_map(3)
|
|
1099
|
+
sage: f
|
|
1100
|
+
Ore module endomorphism of Ore module of rank 3 over Finite Field in a of size 7^5 twisted by a |--> a^7
|
|
1101
|
+
sage: f.matrix()
|
|
1102
|
+
[3 0 0]
|
|
1103
|
+
[0 3 0]
|
|
1104
|
+
[0 0 3]
|
|
1105
|
+
|
|
1106
|
+
Be careful that an element in the base ring defines a Ore morphism
|
|
1107
|
+
if and only if it is fixed by the twisting morphisms and killed by
|
|
1108
|
+
the derivation (otherwise the multiplication by this element does
|
|
1109
|
+
not commute with the Ore action).
|
|
1110
|
+
In SageMath, attempting to create the multiplication by an element
|
|
1111
|
+
which does not fulfill these requirements leads to an error::
|
|
1112
|
+
|
|
1113
|
+
sage: M.multiplication_map(a)
|
|
1114
|
+
Traceback (most recent call last):
|
|
1115
|
+
...
|
|
1116
|
+
ValueError: does not define a morphism of Ore modules
|
|
1117
|
+
|
|
1118
|
+
As soon as it defines a Ore morphism, one can also build the left
|
|
1119
|
+
multiplication by an Ore polynomial::
|
|
1120
|
+
|
|
1121
|
+
sage: g = M.multiplication_map(X^5)
|
|
1122
|
+
sage: g
|
|
1123
|
+
Ore module endomorphism of Ore module of rank 3 over Finite Field in a of size 7^5 twisted by a |--> a^7
|
|
1124
|
+
sage: g.matrix()
|
|
1125
|
+
[ 3*a^4 + 3*a^3 + 6*a^2 + 5*a 4*a^4 + 5*a^3 + 2*a^2 + 6 6*a^4 + 6*a^3 + a^2 + 4]
|
|
1126
|
+
[ a^2 + 3 5*a^4 + 5*a^3 + 6*a^2 + 4*a + 1 a^3 + 5*a^2 + 4]
|
|
1127
|
+
[6*a^4 + 6*a^3 + 3*a^2 + 3*a + 1 4*a^4 + 2*a^3 + 3*a + 5 6*a^4 + 6*a^3 + 2*a^2 + 5*a + 2]
|
|
1128
|
+
|
|
1129
|
+
We check that the characteristic polynomial of `g` is the reduced
|
|
1130
|
+
norm of the Ore polynomial `P` we started with (this is a classical
|
|
1131
|
+
property)::
|
|
1132
|
+
|
|
1133
|
+
sage: g.charpoly()
|
|
1134
|
+
x^3 + 4*x^2 + 2*x + 5
|
|
1135
|
+
sage: P.reduced_norm(var='x')
|
|
1136
|
+
x^3 + 4*x^2 + 2*x + 5
|
|
1137
|
+
"""
|
|
1138
|
+
if isinstance(P, OrePolynomial):
|
|
1139
|
+
S = P.parent()
|
|
1140
|
+
ore = self._ore
|
|
1141
|
+
if S._morphism != ore._morphism or S._derivation != ore._derivation:
|
|
1142
|
+
raise ValueError("twist does not match")
|
|
1143
|
+
action = OreAction(S, self, True, operator.mul)
|
|
1144
|
+
M = matrix([action._act_(P, x).list() for x in self.basis()])
|
|
1145
|
+
else:
|
|
1146
|
+
P = self.base_ring()(P)
|
|
1147
|
+
r = self.rank()
|
|
1148
|
+
M = matrix(r, r, P)
|
|
1149
|
+
H = self.Hom(self)
|
|
1150
|
+
return H(M)
|
|
1151
|
+
|
|
1152
|
+
def identity_morphism(self):
|
|
1153
|
+
r"""
|
|
1154
|
+
Return the identity morphism of this Ore module.
|
|
1155
|
+
|
|
1156
|
+
EXAMPLES::
|
|
1157
|
+
|
|
1158
|
+
sage: K.<a> = GF(7^5)
|
|
1159
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1160
|
+
sage: M.<u,v> = S.quotient_module(X^2 + a*X + a^2)
|
|
1161
|
+
sage: id = M.identity_morphism()
|
|
1162
|
+
sage: id
|
|
1163
|
+
Ore module endomorphism of Ore module <u, v> over Finite Field in a of size 7^5 twisted by a |--> a^7
|
|
1164
|
+
|
|
1165
|
+
sage: id(u)
|
|
1166
|
+
u
|
|
1167
|
+
sage: id(v)
|
|
1168
|
+
v
|
|
1169
|
+
"""
|
|
1170
|
+
H = self.Hom(self)
|
|
1171
|
+
one = self.base_ring().one()
|
|
1172
|
+
return H(one)
|
|
1173
|
+
|
|
1174
|
+
def _span(self, gens):
|
|
1175
|
+
r"""
|
|
1176
|
+
Return a matrix whose lines form a basis over the base field
|
|
1177
|
+
of the submodule of this Ore module generated over the Ore
|
|
1178
|
+
ring by ``gens``.
|
|
1179
|
+
|
|
1180
|
+
INPUT:
|
|
1181
|
+
|
|
1182
|
+
- ``gens`` -- a list of vectors or submodules of this Ore module
|
|
1183
|
+
|
|
1184
|
+
TESTS::
|
|
1185
|
+
|
|
1186
|
+
sage: K.<a> = GF(7^5)
|
|
1187
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1188
|
+
sage: P = X^2 + a
|
|
1189
|
+
sage: Q = X^3 + a^2*X + 1
|
|
1190
|
+
sage: M = S.quotient_module(P*Q, names='e')
|
|
1191
|
+
sage: M.inject_variables()
|
|
1192
|
+
Defining e0, e1, e2, e3, e4
|
|
1193
|
+
|
|
1194
|
+
sage: M._span([Q*e0])
|
|
1195
|
+
[ 1 0 a^4 + 5*a^3 + 6*a^2 + a 1 6*a^2]
|
|
1196
|
+
[ 0 1 2*a^4 + 6*a^2 + 2*a + 3 0 1]
|
|
1197
|
+
|
|
1198
|
+
sage: M._span([Q*e0, e1])
|
|
1199
|
+
[1 0 0 0 0]
|
|
1200
|
+
[0 1 0 0 0]
|
|
1201
|
+
[0 0 1 0 0]
|
|
1202
|
+
[0 0 0 1 0]
|
|
1203
|
+
[0 0 0 0 1]
|
|
1204
|
+
|
|
1205
|
+
sage: N = M.span(Q*e0)
|
|
1206
|
+
sage: M._span([N, e2])
|
|
1207
|
+
[1 0 0 0 0]
|
|
1208
|
+
[0 1 0 0 0]
|
|
1209
|
+
[0 0 1 0 0]
|
|
1210
|
+
[0 0 0 1 0]
|
|
1211
|
+
[0 0 0 0 1]
|
|
1212
|
+
"""
|
|
1213
|
+
base = self.base_ring()
|
|
1214
|
+
rank = self.rank()
|
|
1215
|
+
f = self._pseudohom
|
|
1216
|
+
if not isinstance(gens, (list, tuple)):
|
|
1217
|
+
gens = [gens]
|
|
1218
|
+
rows = []
|
|
1219
|
+
for gen in gens:
|
|
1220
|
+
if isinstance(gen, OreModule):
|
|
1221
|
+
incl = self.coerce_map_from(gen)
|
|
1222
|
+
if incl is None:
|
|
1223
|
+
raise ValueError("not canonically a submodule")
|
|
1224
|
+
rows += incl._matrix.rows()
|
|
1225
|
+
elif isinstance(gen, OreModuleElement):
|
|
1226
|
+
rows.append(self(gen).list())
|
|
1227
|
+
if len(rows) < 2*rank:
|
|
1228
|
+
zero = rank * [base.zero()]
|
|
1229
|
+
rows += (2*rank - len(rows)) * [zero]
|
|
1230
|
+
M = matrix(base, rows)
|
|
1231
|
+
M.echelonize()
|
|
1232
|
+
oldr = 0
|
|
1233
|
+
r = M.rank()
|
|
1234
|
+
iter = 1
|
|
1235
|
+
while r > oldr:
|
|
1236
|
+
for i in range(r):
|
|
1237
|
+
v = M.row(i)
|
|
1238
|
+
for _ in range(iter):
|
|
1239
|
+
v = f(v)
|
|
1240
|
+
v = v.list()
|
|
1241
|
+
for j in range(rank):
|
|
1242
|
+
M[i+r, j] = v[j]
|
|
1243
|
+
M.echelonize()
|
|
1244
|
+
oldr = r
|
|
1245
|
+
r = M.rank()
|
|
1246
|
+
iter *= 2
|
|
1247
|
+
return M.matrix_from_rows(range(r))
|
|
1248
|
+
|
|
1249
|
+
def span(self, gens, names=None):
|
|
1250
|
+
r"""
|
|
1251
|
+
Return the submodule of this Ore module generated (over the
|
|
1252
|
+
underlying Ore ring) by ``gens``.
|
|
1253
|
+
|
|
1254
|
+
INPUT:
|
|
1255
|
+
|
|
1256
|
+
- ``gens`` -- a list of vectors or submodules of this Ore module
|
|
1257
|
+
|
|
1258
|
+
- ``names`` (default: ``None``) -- the name of the vectors in a
|
|
1259
|
+
basis of this submodule
|
|
1260
|
+
|
|
1261
|
+
EXAMPLES::
|
|
1262
|
+
|
|
1263
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1264
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1265
|
+
sage: P = X^2 + t*X + 1
|
|
1266
|
+
sage: M = S.quotient_module(P^3, names='e')
|
|
1267
|
+
sage: M.inject_variables()
|
|
1268
|
+
Defining e0, e1, e2, e3, e4, e5
|
|
1269
|
+
|
|
1270
|
+
We create the submodule `M P`::
|
|
1271
|
+
|
|
1272
|
+
sage: MP = M.span([P*e0])
|
|
1273
|
+
sage: MP
|
|
1274
|
+
Ore module of rank 4 over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1275
|
+
sage: MP.basis()
|
|
1276
|
+
[e0 + (t^4+t^2+3)*e4 + t^3*e5,
|
|
1277
|
+
e1 + (4*t^3+2*t)*e4 + (4*t^2+3)*e5,
|
|
1278
|
+
e2 + (2*t^2+2)*e4 + 2*t*e5,
|
|
1279
|
+
e3 + 4*t*e4 + 4*e5]
|
|
1280
|
+
|
|
1281
|
+
When there is only one generator, encapsulating it in a list is
|
|
1282
|
+
not necessary; one can equally write::
|
|
1283
|
+
|
|
1284
|
+
sage: MP = M.span(P*e0)
|
|
1285
|
+
|
|
1286
|
+
If one wants, one can give names to the basis of the submodule using
|
|
1287
|
+
the attribute ``names``::
|
|
1288
|
+
|
|
1289
|
+
sage: MP2 = M.span(P^2*e0, names='u')
|
|
1290
|
+
sage: MP2.inject_variables()
|
|
1291
|
+
Defining u0, u1
|
|
1292
|
+
sage: MP2.basis()
|
|
1293
|
+
[u0, u1]
|
|
1294
|
+
|
|
1295
|
+
sage: M(u0)
|
|
1296
|
+
e0 + (t^2+4)*e2 + 3*t^3*e3 + (t^2+1)*e4 + 3*t*e5
|
|
1297
|
+
|
|
1298
|
+
Note that a coercion map from the submodule to the ambient module
|
|
1299
|
+
is automatically set::
|
|
1300
|
+
|
|
1301
|
+
sage: M.has_coerce_map_from(MP2)
|
|
1302
|
+
True
|
|
1303
|
+
|
|
1304
|
+
Therefore, combining elements of ``M`` and ``MP2`` in the same
|
|
1305
|
+
expression perfectly works::
|
|
1306
|
+
|
|
1307
|
+
sage: t*u0 + e1
|
|
1308
|
+
t*e0 + e1 + (t^3+4*t)*e2 + 3*t^4*e3 + (t^3+t)*e4 + 3*t^2*e5
|
|
1309
|
+
|
|
1310
|
+
Here is an example with multiple generators::
|
|
1311
|
+
|
|
1312
|
+
sage: MM = M.span([MP2, P*e1])
|
|
1313
|
+
sage: MM.basis()
|
|
1314
|
+
[e0, e1, e2, e3, e4, e5]
|
|
1315
|
+
|
|
1316
|
+
In this case, we obtain the whole space.
|
|
1317
|
+
|
|
1318
|
+
Creating submodules of submodules is also allowed::
|
|
1319
|
+
|
|
1320
|
+
sage: N = MP.span(P^2*e0)
|
|
1321
|
+
sage: N
|
|
1322
|
+
Ore module of rank 2 over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1323
|
+
sage: N.basis()
|
|
1324
|
+
[e0 + (t^2+4)*e2 + 3*t^3*e3 + (t^2+1)*e4 + 3*t*e5,
|
|
1325
|
+
e1 + (4*t^2+4)*e3 + 3*t*e4 + 4*e5]
|
|
1326
|
+
|
|
1327
|
+
.. SEEALSO::
|
|
1328
|
+
|
|
1329
|
+
:meth:`quotient`
|
|
1330
|
+
"""
|
|
1331
|
+
gens = self._span(gens)
|
|
1332
|
+
return self._submodule_class(self, gens, names=names)
|
|
1333
|
+
|
|
1334
|
+
def quotient(self, sub, names=None, check=True):
|
|
1335
|
+
r"""
|
|
1336
|
+
Return the quotient of this Ore module by the submodule
|
|
1337
|
+
generated (over the underlying Ore ring) by ``gens``.
|
|
1338
|
+
|
|
1339
|
+
INPUT:
|
|
1340
|
+
|
|
1341
|
+
- ``gens`` -- a list of vectors or submodules of this Ore module
|
|
1342
|
+
|
|
1343
|
+
- ``names`` (default: ``None``) -- the name of the vectors in a
|
|
1344
|
+
basis of the quotient
|
|
1345
|
+
|
|
1346
|
+
- ``check`` (default: ``True``) -- a boolean, ignored
|
|
1347
|
+
|
|
1348
|
+
EXAMPLES::
|
|
1349
|
+
|
|
1350
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1351
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1352
|
+
sage: P = X^2 + t*X + 1
|
|
1353
|
+
sage: M = S.quotient_module(P^3, names='e')
|
|
1354
|
+
sage: M.inject_variables()
|
|
1355
|
+
Defining e0, e1, e2, e3, e4, e5
|
|
1356
|
+
|
|
1357
|
+
We create the quotient `M/MP`::
|
|
1358
|
+
|
|
1359
|
+
sage: modP = M.quotient(P*e0)
|
|
1360
|
+
sage: modP
|
|
1361
|
+
Ore module of rank 2 over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1362
|
+
|
|
1363
|
+
As a shortcut, we can write ``quo`` instead of ``quotient`` or even
|
|
1364
|
+
use the ``/`` operator::
|
|
1365
|
+
|
|
1366
|
+
sage: modP = M / (P*e0)
|
|
1367
|
+
sage: modP
|
|
1368
|
+
Ore module of rank 2 over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1369
|
+
|
|
1370
|
+
By default, the vectors in the quotient have the same names as their
|
|
1371
|
+
representatives in `M`::
|
|
1372
|
+
|
|
1373
|
+
sage: modP.basis()
|
|
1374
|
+
[e4, e5]
|
|
1375
|
+
|
|
1376
|
+
One can override this behavior by setting the attributes ``names``::
|
|
1377
|
+
|
|
1378
|
+
sage: modP = M.quo(P*e0, names='u')
|
|
1379
|
+
sage: modP.inject_variables()
|
|
1380
|
+
Defining u0, u1
|
|
1381
|
+
sage: modP.basis()
|
|
1382
|
+
[u0, u1]
|
|
1383
|
+
|
|
1384
|
+
Note that a coercion map from the initial Ore module to its quotient
|
|
1385
|
+
is automatically set. As a consequence, combining elements of ``M``
|
|
1386
|
+
and ``modP`` in the same formula works::
|
|
1387
|
+
|
|
1388
|
+
sage: t*u0 + e1
|
|
1389
|
+
(t^3+4*t)*u0 + (t^2+2)*u1
|
|
1390
|
+
|
|
1391
|
+
One can combine the construction of quotients and submodules without
|
|
1392
|
+
trouble. For instance, here we build the space `M P / M P^2`::
|
|
1393
|
+
|
|
1394
|
+
sage: modP2 = M / (P^2*e0)
|
|
1395
|
+
sage: N = modP2.span(P*e0)
|
|
1396
|
+
sage: N
|
|
1397
|
+
Ore module of rank 2 over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1398
|
+
sage: N.basis()
|
|
1399
|
+
[e2 + (2*t^2+2)*e4 + 2*t*e5,
|
|
1400
|
+
e3 + 4*t*e4 + 4*e5]
|
|
1401
|
+
|
|
1402
|
+
.. SEEALSO::
|
|
1403
|
+
|
|
1404
|
+
:meth:`quo`, :meth:`span`
|
|
1405
|
+
"""
|
|
1406
|
+
gens = self._span(sub)
|
|
1407
|
+
return self._quotientModule_class(self, gens, names=names)
|
|
1408
|
+
|
|
1409
|
+
quo = quotient
|
|
1410
|
+
|
|
1411
|
+
def __eq__(self, other) -> bool:
|
|
1412
|
+
r"""
|
|
1413
|
+
Return ``True`` if this Ore module is the same than ``other``.
|
|
1414
|
+
|
|
1415
|
+
TESTS:
|
|
1416
|
+
|
|
1417
|
+
Different names lead to different parents::
|
|
1418
|
+
|
|
1419
|
+
sage: K.<a> = GF(7^5)
|
|
1420
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1421
|
+
sage: M.<u,v> = S.quotient_module(X^2 + a*X + a^2)
|
|
1422
|
+
sage: N.<e0,e1> = S.quotient_module(X^2 + a*X + a^2)
|
|
1423
|
+
sage: M == N
|
|
1424
|
+
False
|
|
1425
|
+
|
|
1426
|
+
However, different syntaxes resulting in the same names lead
|
|
1427
|
+
to the same parent::
|
|
1428
|
+
|
|
1429
|
+
sage: N2 = S.quotient_module(X^2 + a*X + a^2, names='e')
|
|
1430
|
+
sage: N == N2
|
|
1431
|
+
True
|
|
1432
|
+
"""
|
|
1433
|
+
return self is other
|
|
1434
|
+
|
|
1435
|
+
def __hash__(self) -> int:
|
|
1436
|
+
r"""
|
|
1437
|
+
Return a hash of this Ore module.
|
|
1438
|
+
|
|
1439
|
+
TESTS::
|
|
1440
|
+
|
|
1441
|
+
sage: K.<z> = GF(5^3)
|
|
1442
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1443
|
+
sage: M = S.quotient_module(X^3 - z)
|
|
1444
|
+
sage: hash(M) # random
|
|
1445
|
+
128873304640624
|
|
1446
|
+
"""
|
|
1447
|
+
return id(self)
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
# Submodules
|
|
1451
|
+
############
|
|
1452
|
+
|
|
1453
|
+
class OreSubmodule(OreModule):
|
|
1454
|
+
r"""
|
|
1455
|
+
Class for submodules of Ore modules.
|
|
1456
|
+
"""
|
|
1457
|
+
def __classcall_private__(cls, ambient, gens, names):
|
|
1458
|
+
r"""
|
|
1459
|
+
Normalize the input before passing it to the init function
|
|
1460
|
+
(useful to ensure the uniqueness assupmtion).
|
|
1461
|
+
|
|
1462
|
+
INPUT:
|
|
1463
|
+
|
|
1464
|
+
- ``ambient`` -- a Ore module, the ambient module where
|
|
1465
|
+
this submodule sits
|
|
1466
|
+
|
|
1467
|
+
- ``gens`` -- a list of generators (formatted as coordinates
|
|
1468
|
+
vectors) of this submodule
|
|
1469
|
+
|
|
1470
|
+
- ``names`` -- the name of the vectors of the basis of
|
|
1471
|
+
the submodule, or ``None``
|
|
1472
|
+
|
|
1473
|
+
TESTS::
|
|
1474
|
+
|
|
1475
|
+
sage: K.<z> = GF(5^3)
|
|
1476
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1477
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
1478
|
+
sage: N1 = M.span((X + z)*v)
|
|
1479
|
+
sage: N2 = M.span((X + z^5)*w)
|
|
1480
|
+
sage: N1 is N2
|
|
1481
|
+
True
|
|
1482
|
+
|
|
1483
|
+
::
|
|
1484
|
+
|
|
1485
|
+
sage: R.<t> = QQ[]
|
|
1486
|
+
sage: S.<X> = OrePolynomialRing(R, R.derivation())
|
|
1487
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1488
|
+
sage: M.span((X + t)*v)
|
|
1489
|
+
Traceback (most recent call last):
|
|
1490
|
+
...
|
|
1491
|
+
NotImplementedError: Ore submodules are currently only implemented over fields
|
|
1492
|
+
"""
|
|
1493
|
+
base = ambient.base_ring()
|
|
1494
|
+
if base not in Fields():
|
|
1495
|
+
raise NotImplementedError("Ore submodules are currently only implemented over fields")
|
|
1496
|
+
if isinstance(gens, Matrix):
|
|
1497
|
+
basis = gens
|
|
1498
|
+
else:
|
|
1499
|
+
basis = matrix(base, gens)
|
|
1500
|
+
basis = basis.echelon_form()
|
|
1501
|
+
basis.set_immutable()
|
|
1502
|
+
rank = basis.rank()
|
|
1503
|
+
if basis.nrows() != rank:
|
|
1504
|
+
basis = basis.matrix_from_rows(range(rank))
|
|
1505
|
+
names = normalize_names(names, rank)
|
|
1506
|
+
return cls.__classcall__(cls, ambient, basis, names)
|
|
1507
|
+
|
|
1508
|
+
def __init__(self, ambient, basis, names) -> None:
|
|
1509
|
+
r"""
|
|
1510
|
+
Initialize this Ore submodule.
|
|
1511
|
+
|
|
1512
|
+
INPUT:
|
|
1513
|
+
|
|
1514
|
+
- ``ambient`` -- a Ore module, the ambient module where
|
|
1515
|
+
this submodule sits
|
|
1516
|
+
|
|
1517
|
+
- ``basis`` -- the echelon basis of this submodule
|
|
1518
|
+
|
|
1519
|
+
- ``names`` -- the name of the vectors of the basis of
|
|
1520
|
+
the submodule, or ``None``
|
|
1521
|
+
|
|
1522
|
+
TESTS::
|
|
1523
|
+
|
|
1524
|
+
sage: K.<z> = GF(5^3)
|
|
1525
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1526
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
1527
|
+
sage: N = M.span((X + z)*v) # indirect doctest
|
|
1528
|
+
sage: type(N)
|
|
1529
|
+
<class 'sage.modules.ore_module.OreSubmodule_with_category'>
|
|
1530
|
+
|
|
1531
|
+
sage: TestSuite(N).run()
|
|
1532
|
+
"""
|
|
1533
|
+
from sage.modules.ore_module_morphism import OreModuleRetraction
|
|
1534
|
+
base = ambient.base_ring()
|
|
1535
|
+
self._ambient = ambient
|
|
1536
|
+
self._basis = basis
|
|
1537
|
+
rows = [basis.solve_left(ambient(x).image()) for x in basis.rows()]
|
|
1538
|
+
OreModule.__init__(self, matrix(base, rows),
|
|
1539
|
+
ambient.ore_ring(action=False),
|
|
1540
|
+
names, ambient._ore_category)
|
|
1541
|
+
coerce = self.hom(basis, codomain=ambient)
|
|
1542
|
+
ambient.register_coercion(coerce)
|
|
1543
|
+
self._inject = coerce.__copy__()
|
|
1544
|
+
self.register_conversion(OreModuleRetraction(ambient, self))
|
|
1545
|
+
|
|
1546
|
+
def _repr_element(self, x) -> str:
|
|
1547
|
+
r"""
|
|
1548
|
+
Return a string representation of ``x``.
|
|
1549
|
+
|
|
1550
|
+
By default, elements in a Ore submodule are printed as their
|
|
1551
|
+
images in the ambient module.
|
|
1552
|
+
|
|
1553
|
+
TESTS::
|
|
1554
|
+
|
|
1555
|
+
sage: K.<z> = GF(5^3)
|
|
1556
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1557
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
1558
|
+
sage: N = M.span((X + z)*v)
|
|
1559
|
+
sage: N.an_element() # indirect doctest
|
|
1560
|
+
v + (3*z^2+4)*w
|
|
1561
|
+
"""
|
|
1562
|
+
return self._ambient(x)._repr_()
|
|
1563
|
+
|
|
1564
|
+
def _latex_element(self, x) -> str:
|
|
1565
|
+
r"""
|
|
1566
|
+
Return a LaTeX representation of ``x``.
|
|
1567
|
+
|
|
1568
|
+
By default, elements in a Ore submodule are rendered as their
|
|
1569
|
+
images in the ambient module.
|
|
1570
|
+
|
|
1571
|
+
TESTS::
|
|
1572
|
+
|
|
1573
|
+
sage: K.<z> = GF(5^3)
|
|
1574
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1575
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
1576
|
+
sage: N = M.span((X + z)*v)
|
|
1577
|
+
sage: latex(N.an_element()) # indirect doctest
|
|
1578
|
+
v + \left(3 z^{2} + 4\right) w
|
|
1579
|
+
"""
|
|
1580
|
+
return self._ambient(x)._latex_()
|
|
1581
|
+
|
|
1582
|
+
def ambient(self):
|
|
1583
|
+
r"""
|
|
1584
|
+
Return the ambient Ore module in which this submodule lives.
|
|
1585
|
+
|
|
1586
|
+
EXAMPLES::
|
|
1587
|
+
|
|
1588
|
+
sage: K.<z> = GF(5^3)
|
|
1589
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1590
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
1591
|
+
sage: N = M.span((X + z)*v)
|
|
1592
|
+
sage: N.ambient()
|
|
1593
|
+
Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1594
|
+
sage: N.ambient() is M
|
|
1595
|
+
True
|
|
1596
|
+
"""
|
|
1597
|
+
return self._ambient
|
|
1598
|
+
|
|
1599
|
+
def rename_basis(self, names, coerce=False):
|
|
1600
|
+
r"""
|
|
1601
|
+
Return the same Ore module with the given naming
|
|
1602
|
+
for the vectors in its distinguished basis.
|
|
1603
|
+
|
|
1604
|
+
INPUT:
|
|
1605
|
+
|
|
1606
|
+
- ``names`` -- a string or a list of strings, the
|
|
1607
|
+
new names
|
|
1608
|
+
|
|
1609
|
+
- ``coerce`` (default: ``False``) -- a boolean; if
|
|
1610
|
+
``True``, a coercion map from this Ore module to
|
|
1611
|
+
renamed version is set
|
|
1612
|
+
|
|
1613
|
+
EXAMPLES::
|
|
1614
|
+
|
|
1615
|
+
sage: K.<z> = GF(5^3)
|
|
1616
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1617
|
+
sage: M = S.quotient_module(X^2 + z^2)
|
|
1618
|
+
sage: M
|
|
1619
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1620
|
+
|
|
1621
|
+
sage: Me = M.rename_basis('e')
|
|
1622
|
+
sage: Me
|
|
1623
|
+
Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1624
|
+
|
|
1625
|
+
Now compare how elements are displayed::
|
|
1626
|
+
|
|
1627
|
+
sage: M.random_element() # random
|
|
1628
|
+
(3*z^2 + 4*z + 2, 3*z^2 + z)
|
|
1629
|
+
sage: Me.random_element() # random
|
|
1630
|
+
(2*z + 4)*e0 + (z^2 + 4*z + 4)*e1
|
|
1631
|
+
|
|
1632
|
+
At this point, there is no coercion map between ``M``
|
|
1633
|
+
and ``Me``. Therefore, adding elements in both parents
|
|
1634
|
+
results in an error::
|
|
1635
|
+
|
|
1636
|
+
sage: M.random_element() + Me.random_element()
|
|
1637
|
+
Traceback (most recent call last):
|
|
1638
|
+
...
|
|
1639
|
+
TypeError: unsupported operand parent(s) for +:
|
|
1640
|
+
'Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5' and
|
|
1641
|
+
'Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5'
|
|
1642
|
+
|
|
1643
|
+
In order to set this coercion, one should define ``Me``
|
|
1644
|
+
by passing the extra argument ``coerce=True``::
|
|
1645
|
+
|
|
1646
|
+
sage: Me = M.rename_basis('e', coerce=True)
|
|
1647
|
+
sage: M.random_element() + Me.random_element() # random
|
|
1648
|
+
2*z^2*e0 + (z^2 + z + 4)*e1
|
|
1649
|
+
|
|
1650
|
+
.. WARNING::
|
|
1651
|
+
|
|
1652
|
+
Use ``coerce=True`` with extreme caution. Indeed,
|
|
1653
|
+
setting inappropriate coercion maps may result in a
|
|
1654
|
+
circular path in the coercion graph which, in turn,
|
|
1655
|
+
could eventually break the coercion system.
|
|
1656
|
+
|
|
1657
|
+
Note that the bracket construction also works::
|
|
1658
|
+
|
|
1659
|
+
sage: M.<v,w> = M.rename_basis()
|
|
1660
|
+
sage: M
|
|
1661
|
+
Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1662
|
+
|
|
1663
|
+
In this case, `v` and `w` are automatically defined::
|
|
1664
|
+
|
|
1665
|
+
sage: v + w
|
|
1666
|
+
v + w
|
|
1667
|
+
|
|
1668
|
+
TESTS::
|
|
1669
|
+
|
|
1670
|
+
sage: K.<z> = GF(5^3)
|
|
1671
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1672
|
+
sage: P = X + z
|
|
1673
|
+
sage: A.<v,w> = S.quotient_module(P^2)
|
|
1674
|
+
sage: M = A.span(P*v)
|
|
1675
|
+
sage: Me = M.rename_basis('e', coerce=True)
|
|
1676
|
+
sage: M.an_element() + Me.an_element()
|
|
1677
|
+
2*e0
|
|
1678
|
+
"""
|
|
1679
|
+
rank = self.rank()
|
|
1680
|
+
names = normalize_names(names, rank)
|
|
1681
|
+
cls = self.__class__
|
|
1682
|
+
M = cls.__classcall__(cls, self._ambient, self._basis, names)
|
|
1683
|
+
if coerce:
|
|
1684
|
+
mat = identity_matrix(self.base_ring(), rank)
|
|
1685
|
+
id = self.hom(mat, codomain=M)
|
|
1686
|
+
M._unset_coercions_used()
|
|
1687
|
+
M.register_coercion(id)
|
|
1688
|
+
return M
|
|
1689
|
+
|
|
1690
|
+
def injection_morphism(self):
|
|
1691
|
+
r"""
|
|
1692
|
+
Return the inclusion of this submodule in the ambient space.
|
|
1693
|
+
|
|
1694
|
+
EXAMPLES::
|
|
1695
|
+
|
|
1696
|
+
sage: K.<z> = GF(5^3)
|
|
1697
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1698
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
1699
|
+
sage: N = M.span((X + z)*v)
|
|
1700
|
+
sage: N.injection_morphism()
|
|
1701
|
+
Ore module morphism:
|
|
1702
|
+
From: Ore module of rank 1 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1703
|
+
To: Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1704
|
+
"""
|
|
1705
|
+
return self._inject
|
|
1706
|
+
|
|
1707
|
+
def morphism_restriction(self, f):
|
|
1708
|
+
r"""
|
|
1709
|
+
Return the restriction of `f` to this submodule.
|
|
1710
|
+
|
|
1711
|
+
EXAMPLES::
|
|
1712
|
+
|
|
1713
|
+
sage: K.<z> = GF(5^3)
|
|
1714
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1715
|
+
sage: M.<v,w> = S.quotient_module((X + z)^2)
|
|
1716
|
+
sage: N = M.span((X + z)*v)
|
|
1717
|
+
|
|
1718
|
+
sage: f = M.multiplication_map(X^3)
|
|
1719
|
+
sage: f
|
|
1720
|
+
Ore module endomorphism of Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1721
|
+
|
|
1722
|
+
sage: g = N.morphism_restriction(f)
|
|
1723
|
+
sage: g
|
|
1724
|
+
Ore module morphism:
|
|
1725
|
+
From: Ore module of rank 1 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1726
|
+
To: Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1727
|
+
sage: g.matrix()
|
|
1728
|
+
[ 3 4*z^2 + 2]
|
|
1729
|
+
|
|
1730
|
+
TESTS::
|
|
1731
|
+
|
|
1732
|
+
sage: N.morphism_restriction(g)
|
|
1733
|
+
Traceback (most recent call last):
|
|
1734
|
+
...
|
|
1735
|
+
ValueError: the domain of the morphism must be the ambient space
|
|
1736
|
+
"""
|
|
1737
|
+
if f.domain() is not self._ambient:
|
|
1738
|
+
raise ValueError("the domain of the morphism must be the ambient space")
|
|
1739
|
+
return f * self._inject
|
|
1740
|
+
|
|
1741
|
+
def morphism_corestriction(self, f):
|
|
1742
|
+
r"""
|
|
1743
|
+
If the image of `f` is contained in this submodule,
|
|
1744
|
+
return the corresponding corestriction of `f`.
|
|
1745
|
+
|
|
1746
|
+
EXAMPLES::
|
|
1747
|
+
|
|
1748
|
+
sage: K.<z> = GF(5^3)
|
|
1749
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
1750
|
+
sage: P = X + z
|
|
1751
|
+
sage: M.<v,w> = S.quotient_module(P^2)
|
|
1752
|
+
sage: N = M.span(P*v)
|
|
1753
|
+
|
|
1754
|
+
sage: f = M.hom({v: P*v})
|
|
1755
|
+
sage: f
|
|
1756
|
+
Ore module endomorphism of Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1757
|
+
|
|
1758
|
+
sage: g = N.morphism_corestriction(f)
|
|
1759
|
+
sage: g
|
|
1760
|
+
Ore module morphism:
|
|
1761
|
+
From: Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1762
|
+
To: Ore module of rank 1 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
1763
|
+
sage: g.matrix()
|
|
1764
|
+
[ z]
|
|
1765
|
+
[4*z^2]
|
|
1766
|
+
|
|
1767
|
+
When the image of the morphism is not contained in this submodule,
|
|
1768
|
+
an error is raised::
|
|
1769
|
+
|
|
1770
|
+
sage: h = M.multiplication_map(X^3)
|
|
1771
|
+
sage: N.morphism_corestriction(h)
|
|
1772
|
+
Traceback (most recent call last):
|
|
1773
|
+
...
|
|
1774
|
+
ValueError: the image of the morphism is not contained in this submodule
|
|
1775
|
+
|
|
1776
|
+
TESTS::
|
|
1777
|
+
|
|
1778
|
+
sage: N.morphism_corestriction(g)
|
|
1779
|
+
Traceback (most recent call last):
|
|
1780
|
+
...
|
|
1781
|
+
ValueError: the codomain of the morphism must be the ambient space
|
|
1782
|
+
"""
|
|
1783
|
+
if f.codomain() is not self._ambient:
|
|
1784
|
+
raise ValueError("the codomain of the morphism must be the ambient space")
|
|
1785
|
+
rows = []
|
|
1786
|
+
basis = self._basis
|
|
1787
|
+
try:
|
|
1788
|
+
rows = [basis.solve_left(y) for y in f._matrix.rows()]
|
|
1789
|
+
except ValueError:
|
|
1790
|
+
raise ValueError("the image of the morphism is not contained in this submodule")
|
|
1791
|
+
return f.domain().hom(rows, codomain=self)
|
|
1792
|
+
|
|
1793
|
+
_hom_change_domain = morphism_restriction
|
|
1794
|
+
_hom_change_codomain = morphism_corestriction
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
# Quotients
|
|
1798
|
+
###########
|
|
1799
|
+
|
|
1800
|
+
class OreQuotientModule(OreModule):
|
|
1801
|
+
r"""
|
|
1802
|
+
Class for quotients of Ore modules.
|
|
1803
|
+
"""
|
|
1804
|
+
def __classcall_private__(cls, cover, gens, names):
|
|
1805
|
+
r"""
|
|
1806
|
+
Normalize the input before passing it to the init function
|
|
1807
|
+
(useful to ensure the uniqueness assumption).
|
|
1808
|
+
|
|
1809
|
+
INPUT:
|
|
1810
|
+
|
|
1811
|
+
- ``cover`` -- a Ore module, the cover module of this
|
|
1812
|
+
quotient
|
|
1813
|
+
|
|
1814
|
+
- ``gens`` -- a list of generators (formatted as coordinates
|
|
1815
|
+
vectors) of the submodule by which we quotient out
|
|
1816
|
+
|
|
1817
|
+
- ``names`` -- the name of the vectors of the basis of
|
|
1818
|
+
the quotient, or ``None``
|
|
1819
|
+
|
|
1820
|
+
TESTS::
|
|
1821
|
+
|
|
1822
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1823
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1824
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1825
|
+
sage: Q1 = M.quo((X + t)*v)
|
|
1826
|
+
sage: Q2 = M.quo(v + (X + t)*w)
|
|
1827
|
+
sage: Q1 is Q2
|
|
1828
|
+
True
|
|
1829
|
+
|
|
1830
|
+
::
|
|
1831
|
+
|
|
1832
|
+
sage: R.<t> = QQ[]
|
|
1833
|
+
sage: S.<X> = OrePolynomialRing(R, R.derivation())
|
|
1834
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1835
|
+
sage: M.quo((X + t)*v)
|
|
1836
|
+
Traceback (most recent call last):
|
|
1837
|
+
...
|
|
1838
|
+
NotImplementedError: quotient of Ore modules are currently only implemented over fields
|
|
1839
|
+
"""
|
|
1840
|
+
base = cover.base_ring()
|
|
1841
|
+
if base not in Fields():
|
|
1842
|
+
raise NotImplementedError("quotient of Ore modules are currently only implemented over fields")
|
|
1843
|
+
if isinstance(gens, Matrix):
|
|
1844
|
+
basis = gens
|
|
1845
|
+
else:
|
|
1846
|
+
basis = matrix(base, gens)
|
|
1847
|
+
basis = basis.echelon_form()
|
|
1848
|
+
basis.set_immutable()
|
|
1849
|
+
rank = basis.rank()
|
|
1850
|
+
if basis.nrows() != rank:
|
|
1851
|
+
basis = basis.matrix_from_rows(range(rank))
|
|
1852
|
+
names = normalize_names(names, cover.rank() - rank)
|
|
1853
|
+
return cls.__classcall__(cls, cover, basis, names)
|
|
1854
|
+
|
|
1855
|
+
def __init__(self, cover, basis, names) -> None:
|
|
1856
|
+
r"""
|
|
1857
|
+
Initialize this Ore quotient.
|
|
1858
|
+
|
|
1859
|
+
INPUT:
|
|
1860
|
+
|
|
1861
|
+
- ``cover`` -- a Ore module, the cover module of this
|
|
1862
|
+
quotient
|
|
1863
|
+
|
|
1864
|
+
- ``basis`` -- the echelon basis of the submodule
|
|
1865
|
+
defining the quotient
|
|
1866
|
+
|
|
1867
|
+
- ``names`` -- the name of the vectors of the basis of
|
|
1868
|
+
the submodule, or ``None``
|
|
1869
|
+
|
|
1870
|
+
TESTS::
|
|
1871
|
+
|
|
1872
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1873
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1874
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1875
|
+
sage: Q = M.quo((X + t)*v) # indirect doctest
|
|
1876
|
+
sage: type(Q)
|
|
1877
|
+
<class 'sage.modules.ore_module.OreQuotientModule_with_category'>
|
|
1878
|
+
|
|
1879
|
+
sage: TestSuite(N).run()
|
|
1880
|
+
"""
|
|
1881
|
+
from sage.modules.ore_module_morphism import OreModuleSection
|
|
1882
|
+
self._cover = cover
|
|
1883
|
+
d = cover.rank()
|
|
1884
|
+
base = cover.base_ring()
|
|
1885
|
+
self._relations = basis
|
|
1886
|
+
pivots = basis.pivots()
|
|
1887
|
+
r = basis.rank()
|
|
1888
|
+
coerce = matrix(base, d, d-r)
|
|
1889
|
+
indices = []
|
|
1890
|
+
i = 0
|
|
1891
|
+
for j in range(d):
|
|
1892
|
+
if i < r and pivots[i] == j:
|
|
1893
|
+
i += 1
|
|
1894
|
+
else:
|
|
1895
|
+
indices.append(j)
|
|
1896
|
+
coerce[j, j-i] = base.one()
|
|
1897
|
+
for i in range(r):
|
|
1898
|
+
for j in range(d-r):
|
|
1899
|
+
coerce[pivots[i], j] = -basis[i, indices[j]]
|
|
1900
|
+
rows = [cover.gen(i).image() * coerce for i in indices]
|
|
1901
|
+
OreModule.__init__(self, matrix(base, rows),
|
|
1902
|
+
cover.ore_ring(action=False),
|
|
1903
|
+
names, cover._ore_category)
|
|
1904
|
+
self._indices = indices
|
|
1905
|
+
self._project = coerce = cover.hom(coerce, codomain=self)
|
|
1906
|
+
self.register_coercion(coerce)
|
|
1907
|
+
cover.register_conversion(OreModuleSection(self, cover))
|
|
1908
|
+
|
|
1909
|
+
def _repr_element(self, x) -> str:
|
|
1910
|
+
r"""
|
|
1911
|
+
Return a string representation of `x`.
|
|
1912
|
+
|
|
1913
|
+
By default, elements in a Ore quotient are printed as
|
|
1914
|
+
their (canonical) representatives.
|
|
1915
|
+
|
|
1916
|
+
TESTS::
|
|
1917
|
+
|
|
1918
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1919
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1920
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1921
|
+
sage: Q = M.quo((X + t)*v)
|
|
1922
|
+
sage: Q.an_element() # indirect doctest
|
|
1923
|
+
w
|
|
1924
|
+
"""
|
|
1925
|
+
M = self._cover
|
|
1926
|
+
indices = self._indices
|
|
1927
|
+
base = self.base_ring()
|
|
1928
|
+
coords = M.rank() * [base.zero()]
|
|
1929
|
+
for i in range(self.rank()):
|
|
1930
|
+
coords[indices[i]] = x[i]
|
|
1931
|
+
return M(coords)._repr_()
|
|
1932
|
+
|
|
1933
|
+
def _latex_element(self, x) -> str:
|
|
1934
|
+
r"""
|
|
1935
|
+
Return a LaTeX representation of `x`.
|
|
1936
|
+
|
|
1937
|
+
By default, elements in a Ore quotient are rendered as
|
|
1938
|
+
their (canonical) representatives with a bar.
|
|
1939
|
+
|
|
1940
|
+
TESTS::
|
|
1941
|
+
|
|
1942
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1943
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1944
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1945
|
+
sage: Q = M.quo((X + t)*v)
|
|
1946
|
+
sage: latex(Q.an_element()) # indirect doctest
|
|
1947
|
+
\overline{w}
|
|
1948
|
+
"""
|
|
1949
|
+
M = self._cover
|
|
1950
|
+
indices = self._indices
|
|
1951
|
+
base = self.base_ring()
|
|
1952
|
+
coords = M.rank() * [base.zero()]
|
|
1953
|
+
for i in range(self.rank()):
|
|
1954
|
+
coords[indices[i]] = x[i]
|
|
1955
|
+
return "\\overline{%s}" % M(coords)._latex_()
|
|
1956
|
+
|
|
1957
|
+
def cover(self):
|
|
1958
|
+
r"""
|
|
1959
|
+
If this quotient in `M/N`, return `M`.
|
|
1960
|
+
|
|
1961
|
+
EXAMPLES::
|
|
1962
|
+
|
|
1963
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1964
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1965
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1966
|
+
sage: N = M.quo((X + t)*v)
|
|
1967
|
+
|
|
1968
|
+
sage: N.cover()
|
|
1969
|
+
Ore module <v, w> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1970
|
+
sage: N.cover() is M
|
|
1971
|
+
True
|
|
1972
|
+
|
|
1973
|
+
.. SEEALSO::
|
|
1974
|
+
|
|
1975
|
+
:meth:`relations`
|
|
1976
|
+
"""
|
|
1977
|
+
return self._cover
|
|
1978
|
+
|
|
1979
|
+
def relations(self, names=None):
|
|
1980
|
+
r"""
|
|
1981
|
+
If this quotient in `M/N`, return `N`.
|
|
1982
|
+
|
|
1983
|
+
INPUT:
|
|
1984
|
+
|
|
1985
|
+
- ``names`` -- the names of the vectors of the basis
|
|
1986
|
+
of `N`, or ``None``
|
|
1987
|
+
|
|
1988
|
+
EXAMPLES::
|
|
1989
|
+
|
|
1990
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
1991
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
1992
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
1993
|
+
sage: Q = M.quo((X + t)*v)
|
|
1994
|
+
|
|
1995
|
+
sage: N = Q.relations()
|
|
1996
|
+
sage: N
|
|
1997
|
+
Ore module of rank 1 over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
1998
|
+
sage: (X + t)*v in N
|
|
1999
|
+
True
|
|
2000
|
+
sage: Q == M/N
|
|
2001
|
+
True
|
|
2002
|
+
|
|
2003
|
+
It is also possible to define names for the basis elements
|
|
2004
|
+
of `N`::
|
|
2005
|
+
|
|
2006
|
+
sage: N.<u> = Q.relations()
|
|
2007
|
+
sage: N
|
|
2008
|
+
Ore module <u> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2009
|
+
sage: M(u)
|
|
2010
|
+
v + 1/t*w
|
|
2011
|
+
|
|
2012
|
+
.. SEEALSO::
|
|
2013
|
+
|
|
2014
|
+
:meth:`relations`
|
|
2015
|
+
"""
|
|
2016
|
+
return self._submodule_class(self._cover, self._relations, names=names)
|
|
2017
|
+
|
|
2018
|
+
def rename_basis(self, names, coerce=False):
|
|
2019
|
+
r"""
|
|
2020
|
+
Return the same Ore module with the given naming
|
|
2021
|
+
for the vectors in its distinguished basis.
|
|
2022
|
+
|
|
2023
|
+
INPUT:
|
|
2024
|
+
|
|
2025
|
+
- ``names`` -- a string or a list of strings, the
|
|
2026
|
+
new names
|
|
2027
|
+
|
|
2028
|
+
- ``coerce`` (default: ``False``) -- a boolean; if
|
|
2029
|
+
``True``, a coercion map from this Ore module to
|
|
2030
|
+
the renamed version is set
|
|
2031
|
+
|
|
2032
|
+
EXAMPLES::
|
|
2033
|
+
|
|
2034
|
+
sage: K.<z> = GF(5^3)
|
|
2035
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
2036
|
+
sage: M = S.quotient_module(X^2 + z*X + 1)
|
|
2037
|
+
sage: M
|
|
2038
|
+
Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
2039
|
+
|
|
2040
|
+
sage: Me = M.rename_basis('e')
|
|
2041
|
+
sage: Me
|
|
2042
|
+
Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
2043
|
+
|
|
2044
|
+
Now compare how elements are displayed::
|
|
2045
|
+
|
|
2046
|
+
sage: M.random_element() # random
|
|
2047
|
+
(3*z^2 + 4*z + 2, 3*z^2 + z)
|
|
2048
|
+
sage: Me.random_element() # random
|
|
2049
|
+
(2*z + 4)*e0 + (z^2 + 4*z + 4)*e1
|
|
2050
|
+
|
|
2051
|
+
At this point, there is no coercion map between ``M``
|
|
2052
|
+
and ``Me``. Therefore, adding elements in both parents
|
|
2053
|
+
results in an error::
|
|
2054
|
+
|
|
2055
|
+
sage: M.random_element() + Me.random_element()
|
|
2056
|
+
Traceback (most recent call last):
|
|
2057
|
+
...
|
|
2058
|
+
TypeError: unsupported operand parent(s) for +:
|
|
2059
|
+
'Ore module of rank 2 over Finite Field in z of size 5^3 twisted by z |--> z^5' and
|
|
2060
|
+
'Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5'
|
|
2061
|
+
|
|
2062
|
+
In order to set this coercion, one should define ``Me``
|
|
2063
|
+
by passing the extra argument ``coerce=True``::
|
|
2064
|
+
|
|
2065
|
+
sage: Me = M.rename_basis('e', coerce=True)
|
|
2066
|
+
sage: M.random_element() + Me.random_element() # random
|
|
2067
|
+
2*z^2*e0 + (z^2 + z + 4)*e1
|
|
2068
|
+
|
|
2069
|
+
.. WARNING::
|
|
2070
|
+
|
|
2071
|
+
Use ``coerce=True`` with extreme caution. Indeed,
|
|
2072
|
+
setting inappropriate coercion maps may result in a
|
|
2073
|
+
circular path in the coercion graph which, in turn,
|
|
2074
|
+
could eventually break the coercion system.
|
|
2075
|
+
|
|
2076
|
+
Note that the bracket construction also works::
|
|
2077
|
+
|
|
2078
|
+
sage: M.<v,w> = M.rename_basis()
|
|
2079
|
+
sage: M
|
|
2080
|
+
Ore module <v, w> over Finite Field in z of size 5^3 twisted by z |--> z^5
|
|
2081
|
+
|
|
2082
|
+
In this case, `v` and `w` are automatically defined::
|
|
2083
|
+
|
|
2084
|
+
sage: v + w
|
|
2085
|
+
v + w
|
|
2086
|
+
|
|
2087
|
+
TESTS::
|
|
2088
|
+
|
|
2089
|
+
sage: K.<z> = GF(5^3)
|
|
2090
|
+
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
|
|
2091
|
+
sage: P = X + z
|
|
2092
|
+
sage: A.<v,w> = S.quotient_module(P^2)
|
|
2093
|
+
sage: M = A.quo(P*v)
|
|
2094
|
+
sage: Me = M.rename_basis('e', coerce=True)
|
|
2095
|
+
sage: M.an_element() + Me.an_element()
|
|
2096
|
+
2*e0
|
|
2097
|
+
|
|
2098
|
+
"""
|
|
2099
|
+
rank = self.rank()
|
|
2100
|
+
names = normalize_names(names, rank)
|
|
2101
|
+
cls = self.__class__
|
|
2102
|
+
M = cls.__classcall__(cls, self._cover, self._relations, names)
|
|
2103
|
+
if coerce:
|
|
2104
|
+
mat = identity_matrix(self.base_ring(), rank)
|
|
2105
|
+
id = self.hom(mat, codomain=M)
|
|
2106
|
+
M._unset_coercions_used()
|
|
2107
|
+
M.register_coercion(id)
|
|
2108
|
+
return M
|
|
2109
|
+
|
|
2110
|
+
def projection_morphism(self):
|
|
2111
|
+
r"""
|
|
2112
|
+
Return the projection from the cover module to this quotient.
|
|
2113
|
+
|
|
2114
|
+
EXAMPLES::
|
|
2115
|
+
|
|
2116
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
2117
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
2118
|
+
sage: M.<v,w> = S.quotient_module((X + t)^2)
|
|
2119
|
+
sage: Q = M.quo((X + t)*v)
|
|
2120
|
+
sage: Q.projection_morphism()
|
|
2121
|
+
Ore module morphism:
|
|
2122
|
+
From: Ore module <v, w> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2123
|
+
To: Ore module of rank 1 over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2124
|
+
"""
|
|
2125
|
+
return self._project
|
|
2126
|
+
|
|
2127
|
+
def morphism_quotient(self, f):
|
|
2128
|
+
r"""
|
|
2129
|
+
If this quotient in `M/N` and `f : M \to X` is a morphism
|
|
2130
|
+
vanishing on `N`, return the induced map `M/N \to X`.
|
|
2131
|
+
|
|
2132
|
+
EXAMPLES::
|
|
2133
|
+
|
|
2134
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
2135
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
2136
|
+
sage: P = X + t
|
|
2137
|
+
sage: M.<v,w> = S.quotient_module(P^2)
|
|
2138
|
+
sage: Q.<wbar> = M.quo(P*v)
|
|
2139
|
+
|
|
2140
|
+
sage: f = M.hom({v: P*v})
|
|
2141
|
+
sage: f
|
|
2142
|
+
Ore module endomorphism of Ore module <v, w> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2143
|
+
sage: g = Q.morphism_quotient(f)
|
|
2144
|
+
sage: g
|
|
2145
|
+
Ore module morphism:
|
|
2146
|
+
From: Ore module <wbar> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2147
|
+
To: Ore module <v, w> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2148
|
+
|
|
2149
|
+
When the given morphism does not vanish on `N`, an error is raised::
|
|
2150
|
+
|
|
2151
|
+
sage: h = M.multiplication_map(X^5)
|
|
2152
|
+
sage: h
|
|
2153
|
+
Ore module endomorphism of Ore module <v, w> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2154
|
+
sage: Q.morphism_quotient(h)
|
|
2155
|
+
Traceback (most recent call last):
|
|
2156
|
+
...
|
|
2157
|
+
ValueError: the morphism does not factor through this quotient
|
|
2158
|
+
|
|
2159
|
+
TESTS::
|
|
2160
|
+
|
|
2161
|
+
sage: Q.morphism_quotient(g)
|
|
2162
|
+
Traceback (most recent call last):
|
|
2163
|
+
...
|
|
2164
|
+
ValueError: the domain of the morphism must be the cover ring
|
|
2165
|
+
"""
|
|
2166
|
+
if f.domain() is not self._cover:
|
|
2167
|
+
raise ValueError("the domain of the morphism must be the cover ring")
|
|
2168
|
+
Z = self._relations * f._matrix
|
|
2169
|
+
if not Z.is_zero():
|
|
2170
|
+
raise ValueError("the morphism does not factor through this quotient")
|
|
2171
|
+
mat = f._matrix.matrix_from_rows(self._indices)
|
|
2172
|
+
return self.hom(mat, codomain=f.codomain())
|
|
2173
|
+
|
|
2174
|
+
def morphism_modulo(self, f):
|
|
2175
|
+
r"""
|
|
2176
|
+
If this quotient in `M/N` and `f : X \to M` is a morphism,
|
|
2177
|
+
return the induced map `X \to M/N`.
|
|
2178
|
+
|
|
2179
|
+
EXAMPLES::
|
|
2180
|
+
|
|
2181
|
+
sage: K.<t> = Frac(GF(5)['t'])
|
|
2182
|
+
sage: S.<X> = OrePolynomialRing(K, K.derivation())
|
|
2183
|
+
sage: P = X + t
|
|
2184
|
+
sage: M.<v,w> = S.quotient_module(P^2)
|
|
2185
|
+
sage: Q.<wbar> = M.quo(P*v)
|
|
2186
|
+
|
|
2187
|
+
sage: f = M.multiplication_map(X^5)
|
|
2188
|
+
sage: f
|
|
2189
|
+
Ore module endomorphism of Ore module <v, w> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2190
|
+
sage: g = Q.morphism_modulo(f)
|
|
2191
|
+
sage: g
|
|
2192
|
+
Ore module morphism:
|
|
2193
|
+
From: Ore module <v, w> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2194
|
+
To: Ore module <wbar> over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 twisted by d/dt
|
|
2195
|
+
|
|
2196
|
+
TESTS::
|
|
2197
|
+
|
|
2198
|
+
sage: Q.morphism_modulo(g)
|
|
2199
|
+
Traceback (most recent call last):
|
|
2200
|
+
...
|
|
2201
|
+
ValueError: the codomain of the morphism must be the cover ring
|
|
2202
|
+
"""
|
|
2203
|
+
if f.codomain() is not self._cover:
|
|
2204
|
+
raise ValueError("the codomain of the morphism must be the cover ring")
|
|
2205
|
+
return self._project * f
|
|
2206
|
+
|
|
2207
|
+
_hom_change_domain = morphism_quotient
|
|
2208
|
+
_hom_change_codomain = morphism_modulo
|