passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.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 +808 -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-0cd532bd.so.1 +0 -0
- passagemath_modules.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-d8ebe4b5.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_modules.libs/libquadmath-bb76a5fc.so.0.0.0 +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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-x86_64-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-x86_64-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,1925 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
r"""
|
|
3
|
+
Multiplicative Abelian Groups
|
|
4
|
+
|
|
5
|
+
This module lets you compute with finitely generated Abelian groups of the form
|
|
6
|
+
|
|
7
|
+
.. MATH::
|
|
8
|
+
|
|
9
|
+
G = \ZZ^r \oplus \ZZ_{k_1} \oplus \cdots \oplus \ZZ_{k_t}
|
|
10
|
+
|
|
11
|
+
It is customary to denote the infinite cyclic group `\ZZ` as having
|
|
12
|
+
order `0`, so the data defining the Abelian group can be written as an
|
|
13
|
+
integer vector
|
|
14
|
+
|
|
15
|
+
.. MATH::
|
|
16
|
+
|
|
17
|
+
\vec{k} = (0, \dots, 0, k_1, \dots, k_t)
|
|
18
|
+
|
|
19
|
+
where there are `r` zeroes and `t` nonzero values. To construct this
|
|
20
|
+
Abelian group in Sage, you can either specify all entries of `\vec{k}`
|
|
21
|
+
or only the nonzero entries together with the total number of
|
|
22
|
+
generators::
|
|
23
|
+
|
|
24
|
+
sage: AbelianGroup([0,0,0,2,3])
|
|
25
|
+
Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3
|
|
26
|
+
sage: AbelianGroup(5, [2,3])
|
|
27
|
+
Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3
|
|
28
|
+
|
|
29
|
+
It is also legal to specify `1` as the order. The corresponding
|
|
30
|
+
generator will be the neutral element, but it will still take up an
|
|
31
|
+
index in the labelling of the generators::
|
|
32
|
+
|
|
33
|
+
sage: G = AbelianGroup([2,1,3], names='g')
|
|
34
|
+
sage: G.gens()
|
|
35
|
+
(g0, 1, g2)
|
|
36
|
+
|
|
37
|
+
Note that this presentation is not unique, for example
|
|
38
|
+
`\ZZ_6 \cong \ZZ_2 \times \ZZ_3`. The orders of the generators
|
|
39
|
+
`\vec{k}=(0,\dots,0,k_1,\dots, k_t)` has previously been called
|
|
40
|
+
invariants in Sage, even though they are not necessarily the (unique)
|
|
41
|
+
invariant factors of the group. You should now use
|
|
42
|
+
:meth:`~AbelianGroup_class.gens_orders` instead::
|
|
43
|
+
|
|
44
|
+
sage: J = AbelianGroup([2,0,3,2,4]); J
|
|
45
|
+
Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
|
|
46
|
+
sage: J.gens_orders() # use this instead
|
|
47
|
+
(2, 0, 3, 2, 4)
|
|
48
|
+
sage: J.invariants() # deprecated
|
|
49
|
+
(2, 0, 3, 2, 4)
|
|
50
|
+
sage: J.elementary_divisors() # these are the "invariant factors"
|
|
51
|
+
(2, 2, 12, 0)
|
|
52
|
+
sage: for i in range(J.ngens()):
|
|
53
|
+
....: print((i, J.gen(i), J.gen(i).order())) # or use this form
|
|
54
|
+
(0, f0, 2)
|
|
55
|
+
(1, f1, +Infinity)
|
|
56
|
+
(2, f2, 3)
|
|
57
|
+
(3, f3, 2)
|
|
58
|
+
(4, f4, 4)
|
|
59
|
+
|
|
60
|
+
Background on invariant factors and the Smith normal form
|
|
61
|
+
(according to section 4.1 of [Cohen1]_): An abelian group is a
|
|
62
|
+
group `A` for which there exists an exact sequence
|
|
63
|
+
`\ZZ^k \rightarrow \ZZ^\ell \rightarrow A \rightarrow 1`,
|
|
64
|
+
for some positive integers
|
|
65
|
+
`k,\ell` with `k\leq \ell`. For example, a finite abelian group has a
|
|
66
|
+
decomposition
|
|
67
|
+
|
|
68
|
+
.. MATH::
|
|
69
|
+
|
|
70
|
+
A = \langle a_1\rangle \times \dots \times \langle a_\ell\rangle ,
|
|
71
|
+
|
|
72
|
+
where `\mathrm{ord}(a_i)=p_i^{c_i}`, for some primes `p_i` and some
|
|
73
|
+
positive integers `c_i`, `i=1,...,\ell`. GAP calls the
|
|
74
|
+
list (ordered by size) of the `p_i^{c_i}` the *abelian invariants*.
|
|
75
|
+
In Sage they will be called *invariants*.
|
|
76
|
+
In this situation, `k=\ell` and `\phi: \ZZ^\ell \rightarrow A` is the map
|
|
77
|
+
`\phi(x_1,...,x_\ell) = a_1^{x_1}...a_\ell^{x_\ell}`,
|
|
78
|
+
for `(x_1,...,x_\ell)\in \ZZ^\ell`. The matrix of relations
|
|
79
|
+
`M:\ZZ^k \rightarrow \ZZ^\ell` is the matrix
|
|
80
|
+
whose rows generate the kernel of `\phi` as a `\ZZ`-module.
|
|
81
|
+
In other words, `M=(M_{ij})` is a `\ell\times \ell`
|
|
82
|
+
diagonal matrix with `M_{ii}=p_i^{c_i}`. Consider now the
|
|
83
|
+
subgroup `B\subset A` generated by
|
|
84
|
+
`b_1 = a_1^{f_{1,1}}...a_\ell^{f_{\ell,1}}`, ...,
|
|
85
|
+
`b_m = a_1^{f_{1,m}}...a_\ell^{f_{\ell,m}}`.
|
|
86
|
+
The kernel of the map `\phi_B: \ZZ^m \rightarrow B` defined by
|
|
87
|
+
`\phi_B(y_1,...,y_m) = b_1^{y_1}...b_m^{y_m}`,
|
|
88
|
+
for `(y_1,...,y_m)\in \ZZ^m`, is the kernel of the matrix
|
|
89
|
+
|
|
90
|
+
.. MATH::
|
|
91
|
+
|
|
92
|
+
F=
|
|
93
|
+
\left(
|
|
94
|
+
\begin{array}{cccc}
|
|
95
|
+
f_{11} & f_{12} & \dots & f_{1m}\\
|
|
96
|
+
f_{21} & f_{22} & \dots & f_{2m}\\
|
|
97
|
+
\vdots & & \ddots & \vdots \\
|
|
98
|
+
f_{\ell,1} & f_{\ell,2} & \dots & f_{\ell,m}
|
|
99
|
+
\end{array}
|
|
100
|
+
\right),
|
|
101
|
+
|
|
102
|
+
regarded as a map
|
|
103
|
+
`\ZZ^m\rightarrow (\ZZ/p_1^{c_1}\ZZ)\times ...\times (\ZZ/p_\ell^{c_\ell}\ZZ)`.
|
|
104
|
+
In particular, `B\cong \ZZ^m/\ker(F)`. If `B=A` then the
|
|
105
|
+
Smith normal form (SNF) of a generator matrix of
|
|
106
|
+
`\ker(F)` and the SNF of `M` are the same. The diagonal entries `s_i` of the
|
|
107
|
+
SNF `S = \mathrm{diag}[s_1,s_2,s_3, ... s_r,0,0,...0]`,
|
|
108
|
+
are called *determinantal divisors* of `F`.
|
|
109
|
+
where `r` is the rank. The *invariant factors* of `A` are:
|
|
110
|
+
|
|
111
|
+
.. MATH::
|
|
112
|
+
|
|
113
|
+
s_1, s_2/s_1, s_3/s_2, ... s_r/s_{r-1}.
|
|
114
|
+
|
|
115
|
+
Sage supports multiplicative abelian groups on any prescribed finite
|
|
116
|
+
number `n \geq 0` of generators. Use the :func:`AbelianGroup`
|
|
117
|
+
function to create an abelian group, and the
|
|
118
|
+
:meth:`~AbelianGroup_class.gen` and :meth:`~AbelianGroup_class.gens`
|
|
119
|
+
methods to obtain the corresponding generators. You can print the
|
|
120
|
+
generators as arbitrary strings using the optional ``names`` argument
|
|
121
|
+
to the :func:`AbelianGroup` function.
|
|
122
|
+
|
|
123
|
+
EXAMPLE 1:
|
|
124
|
+
|
|
125
|
+
We create an abelian group in zero or more variables; the syntax ``T(1)``
|
|
126
|
+
creates the identity element even in the rank zero case::
|
|
127
|
+
|
|
128
|
+
sage: T = AbelianGroup(0, [])
|
|
129
|
+
sage: T
|
|
130
|
+
Trivial Abelian group
|
|
131
|
+
sage: T.gens()
|
|
132
|
+
()
|
|
133
|
+
sage: T(1)
|
|
134
|
+
1
|
|
135
|
+
|
|
136
|
+
EXAMPLE 2:
|
|
137
|
+
|
|
138
|
+
An Abelian group uses a multiplicative representation of elements, but
|
|
139
|
+
the underlying representation is lists of integer exponents::
|
|
140
|
+
|
|
141
|
+
sage: F = AbelianGroup(5, [3,4,5,5,7], names = list("abcde"))
|
|
142
|
+
sage: F
|
|
143
|
+
Multiplicative Abelian group isomorphic to C3 x C4 x C5 x C5 x C7
|
|
144
|
+
sage: (a,b,c,d,e) = F.gens()
|
|
145
|
+
sage: a*b^2*e*d
|
|
146
|
+
a*b^2*d*e
|
|
147
|
+
sage: x = b^2*e*d*a^7
|
|
148
|
+
sage: x
|
|
149
|
+
a*b^2*d*e
|
|
150
|
+
sage: x.list()
|
|
151
|
+
[1, 2, 0, 1, 1]
|
|
152
|
+
|
|
153
|
+
REFERENCES:
|
|
154
|
+
|
|
155
|
+
.. [Cohen1] \H. Cohen, Advanced topics in computational number theory,
|
|
156
|
+
Springer, 2000.
|
|
157
|
+
|
|
158
|
+
.. [Cohen2] \H. Cohen, A course in computational algebraic number theory,
|
|
159
|
+
Springer, 1996.
|
|
160
|
+
|
|
161
|
+
.. [Rotman] \J. Rotman, An introduction to the theory of
|
|
162
|
+
groups, 4th ed, Springer, 1995.
|
|
163
|
+
|
|
164
|
+
.. WARNING::
|
|
165
|
+
|
|
166
|
+
Many basic properties for infinite abelian groups are not
|
|
167
|
+
implemented.
|
|
168
|
+
|
|
169
|
+
AUTHORS:
|
|
170
|
+
|
|
171
|
+
- William Stein, David Joyner (2008-12): added (user requested) is_cyclic,
|
|
172
|
+
fixed elementary_divisors.
|
|
173
|
+
|
|
174
|
+
- David Joyner (2006-03): (based on free abelian monoids by David
|
|
175
|
+
Kohel)
|
|
176
|
+
|
|
177
|
+
- David Joyner (2006-05) several significant bug fixes
|
|
178
|
+
|
|
179
|
+
- David Joyner (2006-08) trivial changes to docs, added random, fixed
|
|
180
|
+
bug in how invariants are recorded
|
|
181
|
+
|
|
182
|
+
- David Joyner (2006-10) added dual_group method
|
|
183
|
+
|
|
184
|
+
- David Joyner (2008-02) fixed serious bug in word_problem
|
|
185
|
+
|
|
186
|
+
- David Joyner (2008-03) fixed bug in trivial group case
|
|
187
|
+
|
|
188
|
+
- David Loeffler (2009-05) added subgroups method
|
|
189
|
+
|
|
190
|
+
- Volker Braun (2012-11) port to new Parent base. Use tuples for
|
|
191
|
+
immutables. Rename invariants to gens_orders.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
# ****************************************************************************
|
|
195
|
+
# Copyright (C) 2006 William Stein <wstein@gmail.com>
|
|
196
|
+
# Copyright (C) 2006 David Joyner <wdjoyner@gmail.com>
|
|
197
|
+
# Copyright (C) 2012 Volker Braun <vbraun.name@gmail.com>
|
|
198
|
+
#
|
|
199
|
+
# This program is free software: you can redistribute it and/or modify
|
|
200
|
+
# it under the terms of the GNU General Public License as published by
|
|
201
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
202
|
+
# (at your option) any later version.
|
|
203
|
+
# https://www.gnu.org/licenses/
|
|
204
|
+
# ****************************************************************************
|
|
205
|
+
from itertools import product
|
|
206
|
+
|
|
207
|
+
from sage.arith.functions import lcm
|
|
208
|
+
from sage.arith.misc import divisors, gcd
|
|
209
|
+
from sage.categories.groups import Groups
|
|
210
|
+
from sage.groups.abelian_gps.abelian_group_element import AbelianGroupElement
|
|
211
|
+
from sage.groups.group import AbelianGroup as AbelianGroupBase
|
|
212
|
+
from sage.matrix.constructor import matrix
|
|
213
|
+
from sage.matrix.special import diagonal_matrix
|
|
214
|
+
from sage.misc.cachefunc import cached_method
|
|
215
|
+
from sage.misc.misc_c import prod
|
|
216
|
+
from sage.misc.mrange import mrange
|
|
217
|
+
from sage.modules.free_module_element import vector
|
|
218
|
+
from sage.rings.infinity import infinity
|
|
219
|
+
from sage.rings.integer import Integer
|
|
220
|
+
from sage.rings.integer_ring import ZZ
|
|
221
|
+
from sage.structure.category_object import normalize_names
|
|
222
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# .. TODO::
|
|
226
|
+
|
|
227
|
+
# this uses perm groups - the AbelianGroupElement instance method
|
|
228
|
+
# uses a different implementation.
|
|
229
|
+
def word_problem(words, g, verbose=False):
|
|
230
|
+
r"""
|
|
231
|
+
`G` and `H` are abelian, `g` in `G`, `H` is a subgroup of `G` generated by
|
|
232
|
+
a list (words) of elements of `G`. If `g` is in `H`, return the expression
|
|
233
|
+
for `g` as a word in the elements of (words).
|
|
234
|
+
|
|
235
|
+
The 'word problem' for a finite abelian group `G` boils down to the
|
|
236
|
+
following matrix-vector analog of the Chinese remainder theorem.
|
|
237
|
+
|
|
238
|
+
Problem: Fix integers `1<n_1\leq n_2\leq ...\leq n_k`
|
|
239
|
+
(indeed, these `n_i` will all be prime powers), fix a
|
|
240
|
+
generating set `g_i=(a_{i1},...,a_{ik})` (with
|
|
241
|
+
`a_{ij}\in \mathrm{Z}/n_j\mathrm{Z}`), for `1\leq i\leq \ell`,
|
|
242
|
+
for the group `G`, and let `d = (d_1,...,d_k)` be
|
|
243
|
+
an element of the direct product
|
|
244
|
+
`\mathrm{Z}/n_1\mathrm{Z} \times ...\times \mathrm{Z}/n_k\mathrm{Z}`. Find, if they
|
|
245
|
+
exist, integers `c_1,...,c_\ell` such that
|
|
246
|
+
`c_1g_1+...+c_\ell g_\ell = d`. In other words, solve
|
|
247
|
+
the equation `cA=d` for `c\in \mathrm{Z}^\ell`, where
|
|
248
|
+
`A` is the matrix whose rows are the `g_i`'s. Of
|
|
249
|
+
course, it suffices to restrict the `c_i`'s to the range
|
|
250
|
+
`0\leq c_i\leq N-1`, where `N` denotes the least
|
|
251
|
+
common multiple of the integers `n_1,...,n_k`.
|
|
252
|
+
|
|
253
|
+
This function does not solve this directly, as perhaps it should.
|
|
254
|
+
Rather (for both speed and as a model for a similar function valid
|
|
255
|
+
for more general groups), it pushes it over to GAP, which has optimized
|
|
256
|
+
(non-deterministic) algorithms for the word problem. Essentially,
|
|
257
|
+
this function is a wrapper for the GAP function 'Factorization'.
|
|
258
|
+
|
|
259
|
+
EXAMPLES::
|
|
260
|
+
|
|
261
|
+
sage: # needs sage.libs.gap
|
|
262
|
+
sage: G.<a,b,c> = AbelianGroup(3, [2,3,4]); G
|
|
263
|
+
Multiplicative Abelian group isomorphic to C2 x C3 x C4
|
|
264
|
+
sage: w = word_problem([a*b,a*c], b*c); w # random
|
|
265
|
+
[[a*b, 1], [a*c, 1]]
|
|
266
|
+
sage: prod([x^i for x,i in w]) == b*c
|
|
267
|
+
True
|
|
268
|
+
sage: w = word_problem([a*c,c], a); w # random
|
|
269
|
+
[[a*c, 1], [c, -1]]
|
|
270
|
+
sage: prod([x^i for x,i in w]) == a
|
|
271
|
+
True
|
|
272
|
+
sage: word_problem([a*c,c], a, verbose=True) # random
|
|
273
|
+
a = (a*c)^1*(c)^-1
|
|
274
|
+
[[a*c, 1], [c, -1]]
|
|
275
|
+
|
|
276
|
+
::
|
|
277
|
+
|
|
278
|
+
sage: # needs sage.libs.gap
|
|
279
|
+
sage: A.<a,b,c,d,e> = AbelianGroup(5, [4, 5, 5, 7, 8])
|
|
280
|
+
sage: b1 = a^3*b*c*d^2*e^5
|
|
281
|
+
sage: b2 = a^2*b*c^2*d^3*e^3
|
|
282
|
+
sage: b3 = a^7*b^3*c^5*d^4*e^4
|
|
283
|
+
sage: b4 = a^3*b^2*c^2*d^3*e^5
|
|
284
|
+
sage: b5 = a^2*b^4*c^2*d^4*e^5
|
|
285
|
+
sage: w = word_problem([b1,b2,b3,b4,b5], e); w # random
|
|
286
|
+
[[a^3*b*c*d^2*e^5, 1], [a^2*b*c^2*d^3*e^3, 1],
|
|
287
|
+
[a^3*b^3*d^4*e^4, 3], [a^2*b^4*c^2*d^4*e^5, 1]]
|
|
288
|
+
sage: prod([x^i for x,i in w]) == e
|
|
289
|
+
True
|
|
290
|
+
sage: word_problem([a,b,c,d,e], e)
|
|
291
|
+
[[e, 1]]
|
|
292
|
+
sage: word_problem([a,b,c,d,e], b)
|
|
293
|
+
[[b, 1]]
|
|
294
|
+
|
|
295
|
+
.. WARNING::
|
|
296
|
+
|
|
297
|
+
1. Might have unpleasant effect when the word problem
|
|
298
|
+
cannot be solved.
|
|
299
|
+
|
|
300
|
+
2. Uses permutation groups, so may be slow when group is large.
|
|
301
|
+
The instance method word_problem of the class
|
|
302
|
+
AbelianGroupElement is implemented differently (wrapping
|
|
303
|
+
GAP's 'EpimorphismFromFreeGroup' and
|
|
304
|
+
'PreImagesRepresentative') and may be faster.
|
|
305
|
+
"""
|
|
306
|
+
from sage.libs.gap.libgap import libgap
|
|
307
|
+
A = libgap.AbelianGroup(g.parent().gens_orders())
|
|
308
|
+
gens = libgap.GeneratorsOfGroup(A)
|
|
309
|
+
|
|
310
|
+
gap_g = libgap.Product([gi**Li for gi, Li in zip(gens, g.list())])
|
|
311
|
+
|
|
312
|
+
gensH = [libgap.Product([gi**Li for gi, Li in zip(gens, w.list())])
|
|
313
|
+
for w in words]
|
|
314
|
+
H = libgap.Group(gensH)
|
|
315
|
+
|
|
316
|
+
x = libgap.Factorization(H, gap_g)
|
|
317
|
+
|
|
318
|
+
resu = libgap.ExtRepOfObj(x).sage() # (indice, power, indice, power, etc)
|
|
319
|
+
indices = resu[0::2]
|
|
320
|
+
powers = resu[1::2]
|
|
321
|
+
if verbose:
|
|
322
|
+
v = '*'.join('(%s)^%s' % (words[indi - 1], powi)
|
|
323
|
+
for indi, powi in zip(indices, powers))
|
|
324
|
+
print('%s = %s' % (g, v))
|
|
325
|
+
return [[words[indi - 1], powi] for indi, powi in zip(indices, powers)]
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def _normalize(n, gens_orders=None, names='f'):
|
|
329
|
+
"""
|
|
330
|
+
Helper function for :func:`AbelianGroup`. Beat some sense into the
|
|
331
|
+
arguments.
|
|
332
|
+
|
|
333
|
+
This function is also used by some descendents of
|
|
334
|
+
:class:`AbelianGroup_class`.
|
|
335
|
+
|
|
336
|
+
INPUT:
|
|
337
|
+
|
|
338
|
+
See :func:`AbelianGroup`.
|
|
339
|
+
|
|
340
|
+
OUTPUT:
|
|
341
|
+
|
|
342
|
+
Unique data for defining a :class:`AbelianGroup_class`. Raises an
|
|
343
|
+
exception if the input is invalid.
|
|
344
|
+
|
|
345
|
+
EXAMPLES::
|
|
346
|
+
|
|
347
|
+
sage: from sage.groups.abelian_gps.abelian_group import _normalize
|
|
348
|
+
sage: _normalize(5, [2,1,0], names='abc')
|
|
349
|
+
((0, 0, 2, 1, 0), 'abc')
|
|
350
|
+
sage: _normalize(5, (2.0, 1.0, 0/1), names=list('abc'))
|
|
351
|
+
((0, 0, 2, 1, 0), ('a', 'b', 'c'))
|
|
352
|
+
sage: _normalize([0,2,1,0], names='a')
|
|
353
|
+
((0, 2, 1, 0), 'a')
|
|
354
|
+
|
|
355
|
+
TESTS::
|
|
356
|
+
|
|
357
|
+
sage: _normalize(5, (2.0, 1.5, 0/1), names=list('abc'))
|
|
358
|
+
Traceback (most recent call last):
|
|
359
|
+
...
|
|
360
|
+
TypeError: Attempt to coerce non-integral RealNumber to Integer
|
|
361
|
+
sage: _normalize('1', '[2]', names='a')
|
|
362
|
+
Traceback (most recent call last):
|
|
363
|
+
...
|
|
364
|
+
TypeError: unable to convert '[' to an integer
|
|
365
|
+
sage: _normalize(3, 'str', names='a')
|
|
366
|
+
Traceback (most recent call last):
|
|
367
|
+
...
|
|
368
|
+
TypeError: unable to convert 's' to an integer
|
|
369
|
+
|
|
370
|
+
Verify that :issue:`38967` is fixed::
|
|
371
|
+
|
|
372
|
+
sage: AbelianGroup([-4])
|
|
373
|
+
Traceback (most recent call last):
|
|
374
|
+
...
|
|
375
|
+
ValueError: orders of generators cannot be negative but they are (-4,)
|
|
376
|
+
"""
|
|
377
|
+
if gens_orders is None:
|
|
378
|
+
if isinstance(n, (list, tuple)):
|
|
379
|
+
gens_orders = n
|
|
380
|
+
n = len(n)
|
|
381
|
+
else:
|
|
382
|
+
gens_orders = []
|
|
383
|
+
n = ZZ(n)
|
|
384
|
+
if len(gens_orders) < n:
|
|
385
|
+
gens_orders = [0] * (n - len(gens_orders)) + list(gens_orders)
|
|
386
|
+
gens_orders = tuple(ZZ(i) for i in gens_orders)
|
|
387
|
+
if any(i < 0 for i in gens_orders):
|
|
388
|
+
raise ValueError(f'orders of generators cannot be negative but they are {gens_orders}')
|
|
389
|
+
if len(gens_orders) > n:
|
|
390
|
+
raise ValueError('gens_orders (='+str(gens_orders)+') must have length n (='+str(n)+')')
|
|
391
|
+
if isinstance(names, list):
|
|
392
|
+
names = tuple(names)
|
|
393
|
+
return (gens_orders, names)
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def AbelianGroup(n, gens_orders=None, names='f'):
|
|
397
|
+
r"""
|
|
398
|
+
Create the multiplicative abelian group in `n` generators
|
|
399
|
+
with given orders of generators (which need not be prime powers).
|
|
400
|
+
|
|
401
|
+
INPUT:
|
|
402
|
+
|
|
403
|
+
- ``n`` -- integer (optional); if not specified, will be derived
|
|
404
|
+
from ``gens_orders``
|
|
405
|
+
|
|
406
|
+
- ``gens_orders`` -- list of nonnegative integers in the form
|
|
407
|
+
`[a_0, a_1, \dots, a_{n-1}]`, typically written in increasing
|
|
408
|
+
order. This list is padded with zeros if it has length less
|
|
409
|
+
than `n`. The orders of the commuting generators, with `0`
|
|
410
|
+
denoting an infinite cyclic factor.
|
|
411
|
+
|
|
412
|
+
- ``names`` -- (optional) names of generators
|
|
413
|
+
|
|
414
|
+
Alternatively, you can also give input in the form
|
|
415
|
+
``AbelianGroup(gens_orders, names='f')``, where the names keyword
|
|
416
|
+
argument must be explicitly named.
|
|
417
|
+
|
|
418
|
+
OUTPUT:
|
|
419
|
+
|
|
420
|
+
Abelian group with generators and invariant type. The default name
|
|
421
|
+
for generator ``A.i`` is ``fi``, as in GAP.
|
|
422
|
+
|
|
423
|
+
EXAMPLES::
|
|
424
|
+
|
|
425
|
+
sage: F = AbelianGroup(5, [5,5,7,8,9], names='abcde')
|
|
426
|
+
sage: F(1)
|
|
427
|
+
1
|
|
428
|
+
sage: (a, b, c, d, e) = F.gens()
|
|
429
|
+
sage: mul([ a, b, a, c, b, d, c, d ], F(1))
|
|
430
|
+
a^2*b^2*c^2*d^2
|
|
431
|
+
sage: d * b**2 * c**3
|
|
432
|
+
b^2*c^3*d
|
|
433
|
+
sage: F = AbelianGroup(3, [2]*3); F
|
|
434
|
+
Multiplicative Abelian group isomorphic to C2 x C2 x C2
|
|
435
|
+
sage: H = AbelianGroup([2,3], names='xy'); H
|
|
436
|
+
Multiplicative Abelian group isomorphic to C2 x C3
|
|
437
|
+
sage: AbelianGroup(5)
|
|
438
|
+
Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
|
|
439
|
+
sage: AbelianGroup(5).order()
|
|
440
|
+
+Infinity
|
|
441
|
+
|
|
442
|
+
Notice that `0`'s are prepended if necessary::
|
|
443
|
+
|
|
444
|
+
sage: G = AbelianGroup(5, [2,3,4]); G
|
|
445
|
+
Multiplicative Abelian group isomorphic to Z x Z x C2 x C3 x C4
|
|
446
|
+
sage: G.gens_orders()
|
|
447
|
+
(0, 0, 2, 3, 4)
|
|
448
|
+
|
|
449
|
+
The invariant list must not be longer than the number of generators::
|
|
450
|
+
|
|
451
|
+
sage: AbelianGroup(2, [2,3,4])
|
|
452
|
+
Traceback (most recent call last):
|
|
453
|
+
...
|
|
454
|
+
ValueError: gens_orders (=(2, 3, 4)) must have length n (=2)
|
|
455
|
+
"""
|
|
456
|
+
gens_orders, names = _normalize(n, gens_orders, names)
|
|
457
|
+
M = AbelianGroup_class(gens_orders, names)
|
|
458
|
+
return M
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def is_AbelianGroup(x):
|
|
462
|
+
"""
|
|
463
|
+
Return ``True`` if ``x`` is an Abelian group.
|
|
464
|
+
|
|
465
|
+
EXAMPLES::
|
|
466
|
+
|
|
467
|
+
sage: from sage.groups.abelian_gps.abelian_group import is_AbelianGroup
|
|
468
|
+
sage: F = AbelianGroup(5,[5,5,7,8,9], names=list("abcde")); F
|
|
469
|
+
Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
|
|
470
|
+
sage: is_AbelianGroup(F)
|
|
471
|
+
doctest:warning...
|
|
472
|
+
DeprecationWarning: the function is_AbelianGroup is deprecated;
|
|
473
|
+
use 'isinstance(..., AbelianGroup_class)' instead
|
|
474
|
+
See https://github.com/sagemath/sage/issues/37898 for details.
|
|
475
|
+
True
|
|
476
|
+
sage: is_AbelianGroup(AbelianGroup(7, [3]*7))
|
|
477
|
+
True
|
|
478
|
+
"""
|
|
479
|
+
from sage.misc.superseded import deprecation
|
|
480
|
+
deprecation(37898, "the function is_AbelianGroup is deprecated; use 'isinstance(..., AbelianGroup_class)' instead")
|
|
481
|
+
return isinstance(x, AbelianGroup_class)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
class AbelianGroup_class(UniqueRepresentation, AbelianGroupBase):
|
|
485
|
+
"""
|
|
486
|
+
The parent for Abelian groups with chosen generator orders.
|
|
487
|
+
|
|
488
|
+
.. WARNING::
|
|
489
|
+
|
|
490
|
+
You should use :func:`AbelianGroup` to construct Abelian
|
|
491
|
+
groups and not instantiate this class directly.
|
|
492
|
+
|
|
493
|
+
INPUT:
|
|
494
|
+
|
|
495
|
+
- ``generator_orders`` -- list of integers. The orders of the
|
|
496
|
+
(commuting) generators. Zero denotes an infinite cyclic
|
|
497
|
+
generator.
|
|
498
|
+
|
|
499
|
+
- ``names`` -- names of the group generators (optional)
|
|
500
|
+
|
|
501
|
+
EXAMPLES::
|
|
502
|
+
|
|
503
|
+
sage: Z2xZ3 = AbelianGroup([2,3])
|
|
504
|
+
sage: Z6 = AbelianGroup([6])
|
|
505
|
+
sage: Z2xZ3 is Z2xZ3, Z6 is Z6
|
|
506
|
+
(True, True)
|
|
507
|
+
sage: Z2xZ3 is Z6
|
|
508
|
+
False
|
|
509
|
+
sage: Z2xZ3 == Z6
|
|
510
|
+
False
|
|
511
|
+
sage: Z2xZ3.is_isomorphic(Z6)
|
|
512
|
+
True
|
|
513
|
+
|
|
514
|
+
sage: F = AbelianGroup(5,[5,5,7,8,9], names=list("abcde")); F
|
|
515
|
+
Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
|
|
516
|
+
sage: F = AbelianGroup(5,[2, 4, 12, 24, 120], names=list("abcde")); F
|
|
517
|
+
Multiplicative Abelian group isomorphic to C2 x C4 x C12 x C24 x C120
|
|
518
|
+
sage: F.elementary_divisors()
|
|
519
|
+
(2, 4, 12, 24, 120)
|
|
520
|
+
|
|
521
|
+
sage: F.category()
|
|
522
|
+
Category of finite enumerated commutative groups
|
|
523
|
+
|
|
524
|
+
TESTS::
|
|
525
|
+
|
|
526
|
+
sage: AbelianGroup([]).gens_orders()
|
|
527
|
+
()
|
|
528
|
+
sage: AbelianGroup([1]).gens_orders()
|
|
529
|
+
(1,)
|
|
530
|
+
sage: AbelianGroup([1,1]).gens_orders()
|
|
531
|
+
(1, 1)
|
|
532
|
+
sage: AbelianGroup(0).gens_orders()
|
|
533
|
+
()
|
|
534
|
+
"""
|
|
535
|
+
Element = AbelianGroupElement
|
|
536
|
+
|
|
537
|
+
def __init__(self, generator_orders, names, category=None):
|
|
538
|
+
"""
|
|
539
|
+
The Python constructor.
|
|
540
|
+
|
|
541
|
+
TESTS::
|
|
542
|
+
|
|
543
|
+
sage: G = AbelianGroup([0,5,0,7], names=list("abcd")); G
|
|
544
|
+
Multiplicative Abelian group isomorphic to Z x C5 x Z x C7
|
|
545
|
+
sage: TestSuite(G).run()
|
|
546
|
+
|
|
547
|
+
We check that :issue:`15140` is fixed::
|
|
548
|
+
|
|
549
|
+
sage: A = AbelianGroup([3,3])
|
|
550
|
+
sage: A.category()
|
|
551
|
+
Category of finite enumerated commutative groups
|
|
552
|
+
sage: A = AbelianGroup([3,0,7])
|
|
553
|
+
sage: A.category()
|
|
554
|
+
Category of infinite commutative groups
|
|
555
|
+
"""
|
|
556
|
+
assert isinstance(names, (str, tuple))
|
|
557
|
+
assert isinstance(generator_orders, tuple)
|
|
558
|
+
assert all(isinstance(order, Integer) for order in generator_orders)
|
|
559
|
+
self._gens_orders = generator_orders
|
|
560
|
+
n = len(generator_orders)
|
|
561
|
+
names = normalize_names(n, names)
|
|
562
|
+
self._assign_names(names)
|
|
563
|
+
if category is None:
|
|
564
|
+
category = Groups().Commutative()
|
|
565
|
+
if all(order > 0 for order in generator_orders):
|
|
566
|
+
category = category.Finite().Enumerated()
|
|
567
|
+
else:
|
|
568
|
+
category = category.Infinite()
|
|
569
|
+
AbelianGroupBase.__init__(self, category=category)
|
|
570
|
+
|
|
571
|
+
def is_isomorphic(left, right):
|
|
572
|
+
"""
|
|
573
|
+
Check whether ``left`` and ``right`` are isomorphic.
|
|
574
|
+
|
|
575
|
+
INPUT:
|
|
576
|
+
|
|
577
|
+
- ``right`` -- anything
|
|
578
|
+
|
|
579
|
+
OUTPUT: boolean; whether ``left`` and ``right`` are isomorphic as abelian groups
|
|
580
|
+
|
|
581
|
+
EXAMPLES::
|
|
582
|
+
|
|
583
|
+
sage: G1 = AbelianGroup([2,3,4,5])
|
|
584
|
+
sage: G2 = AbelianGroup([2,3,4,5,1])
|
|
585
|
+
sage: G1.is_isomorphic(G2)
|
|
586
|
+
True
|
|
587
|
+
"""
|
|
588
|
+
if not isinstance(right, AbelianGroup_class):
|
|
589
|
+
return False
|
|
590
|
+
return left.elementary_divisors() == right.elementary_divisors()
|
|
591
|
+
|
|
592
|
+
def is_subgroup(left, right):
|
|
593
|
+
"""
|
|
594
|
+
Test whether ``left`` is a subgroup of ``right``.
|
|
595
|
+
|
|
596
|
+
EXAMPLES::
|
|
597
|
+
|
|
598
|
+
sage: G = AbelianGroup([2,3,4,5])
|
|
599
|
+
sage: G.is_subgroup(G)
|
|
600
|
+
True
|
|
601
|
+
|
|
602
|
+
sage: H = G.subgroup([G.1]) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
603
|
+
sage: H.is_subgroup(G) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
604
|
+
True
|
|
605
|
+
|
|
606
|
+
sage: G.<a, b> = AbelianGroup(2)
|
|
607
|
+
sage: H.<c> = AbelianGroup(1)
|
|
608
|
+
sage: H < G
|
|
609
|
+
False
|
|
610
|
+
"""
|
|
611
|
+
for l in left.gens():
|
|
612
|
+
if l not in right:
|
|
613
|
+
return False
|
|
614
|
+
return True
|
|
615
|
+
|
|
616
|
+
__le__ = is_subgroup
|
|
617
|
+
|
|
618
|
+
def __ge__(left, right):
|
|
619
|
+
"""
|
|
620
|
+
Test whether ``right`` is a subgroup of ``left``.
|
|
621
|
+
|
|
622
|
+
EXAMPLES::
|
|
623
|
+
|
|
624
|
+
sage: G.<a, b> = AbelianGroup(2)
|
|
625
|
+
sage: H.<c> = AbelianGroup(1)
|
|
626
|
+
sage: G >= H
|
|
627
|
+
False
|
|
628
|
+
"""
|
|
629
|
+
return right <= left
|
|
630
|
+
|
|
631
|
+
def __lt__(left, right):
|
|
632
|
+
"""
|
|
633
|
+
Test whether ``left`` is a strict subgroup of ``right``.
|
|
634
|
+
|
|
635
|
+
EXAMPLES::
|
|
636
|
+
|
|
637
|
+
sage: G.<a, b> = AbelianGroup(2)
|
|
638
|
+
sage: H.<c> = AbelianGroup(1)
|
|
639
|
+
sage: H < G
|
|
640
|
+
False
|
|
641
|
+
"""
|
|
642
|
+
return left <= right and left != right
|
|
643
|
+
|
|
644
|
+
def __gt__(left, right):
|
|
645
|
+
"""
|
|
646
|
+
Test whether ``right`` is a strict subgroup of ``left``.
|
|
647
|
+
|
|
648
|
+
EXAMPLES::
|
|
649
|
+
|
|
650
|
+
sage: G.<a, b> = AbelianGroup(2)
|
|
651
|
+
sage: H.<c> = AbelianGroup(1)
|
|
652
|
+
sage: G > H
|
|
653
|
+
False
|
|
654
|
+
"""
|
|
655
|
+
return left >= right and left != right
|
|
656
|
+
|
|
657
|
+
def is_trivial(self):
|
|
658
|
+
"""
|
|
659
|
+
Return whether the group is trivial.
|
|
660
|
+
|
|
661
|
+
A group is trivial if it has precisely one element.
|
|
662
|
+
|
|
663
|
+
EXAMPLES::
|
|
664
|
+
|
|
665
|
+
sage: AbelianGroup([2, 3]).is_trivial()
|
|
666
|
+
False
|
|
667
|
+
sage: AbelianGroup([1, 1]).is_trivial()
|
|
668
|
+
True
|
|
669
|
+
"""
|
|
670
|
+
return self.elementary_divisors() == ()
|
|
671
|
+
|
|
672
|
+
def __bool__(self) -> bool:
|
|
673
|
+
"""
|
|
674
|
+
Return ``True`` if this group is nontrivial.
|
|
675
|
+
|
|
676
|
+
EXAMPLES::
|
|
677
|
+
|
|
678
|
+
sage: T = AbelianGroup([2, 3])
|
|
679
|
+
sage: bool(T) # indirect doctest
|
|
680
|
+
True
|
|
681
|
+
sage: bool(AbelianGroup([]))
|
|
682
|
+
False
|
|
683
|
+
sage: bool(AbelianGroup([1,1,1]))
|
|
684
|
+
False
|
|
685
|
+
"""
|
|
686
|
+
return not self.is_trivial()
|
|
687
|
+
|
|
688
|
+
@cached_method
|
|
689
|
+
def dual_group(self, names='X', base_ring=None):
|
|
690
|
+
"""
|
|
691
|
+
Return the dual group.
|
|
692
|
+
|
|
693
|
+
INPUT:
|
|
694
|
+
|
|
695
|
+
- ``names`` -- string or list of strings. The generator names
|
|
696
|
+
for the dual group
|
|
697
|
+
|
|
698
|
+
- ``base_ring`` -- the base ring; if ``None`` (default), then
|
|
699
|
+
a suitable cyclotomic field is picked automatically
|
|
700
|
+
|
|
701
|
+
OUTPUT: the :class:`dual abelian group <sage.groups.abelian_gps.dual_abelian_group.DualAbelianGroup_class>`
|
|
702
|
+
|
|
703
|
+
EXAMPLES::
|
|
704
|
+
|
|
705
|
+
sage: G = AbelianGroup([2])
|
|
706
|
+
sage: G.dual_group() # needs sage.rings.number_field
|
|
707
|
+
Dual of Abelian Group isomorphic to Z/2Z over Cyclotomic Field of order 2 and degree 1
|
|
708
|
+
sage: G.dual_group().gens() # needs sage.rings.number_field
|
|
709
|
+
(X,)
|
|
710
|
+
sage: G.dual_group(names='Z').gens() # needs sage.rings.number_field
|
|
711
|
+
(Z,)
|
|
712
|
+
|
|
713
|
+
sage: G.dual_group(base_ring=QQ)
|
|
714
|
+
Dual of Abelian Group isomorphic to Z/2Z over Rational Field
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
TESTS::
|
|
718
|
+
|
|
719
|
+
sage: H = AbelianGroup(1)
|
|
720
|
+
sage: H.dual_group()
|
|
721
|
+
Traceback (most recent call last):
|
|
722
|
+
...
|
|
723
|
+
ValueError: group must be finite
|
|
724
|
+
"""
|
|
725
|
+
from sage.groups.abelian_gps.dual_abelian_group import DualAbelianGroup_class
|
|
726
|
+
if not self.is_finite():
|
|
727
|
+
raise ValueError('group must be finite')
|
|
728
|
+
if base_ring is None:
|
|
729
|
+
from sage.rings.number_field.number_field import CyclotomicField
|
|
730
|
+
base_ring = CyclotomicField(lcm(self.gens_orders()))
|
|
731
|
+
return DualAbelianGroup_class(self, names=names, base_ring=base_ring)
|
|
732
|
+
|
|
733
|
+
@cached_method
|
|
734
|
+
def elementary_divisors(self):
|
|
735
|
+
r"""
|
|
736
|
+
Return the elementary divisors of the group, using Pari.
|
|
737
|
+
|
|
738
|
+
.. NOTE::
|
|
739
|
+
|
|
740
|
+
Here is another algorithm for computing the elementary divisors
|
|
741
|
+
`d_1, d_2, d_3, \ldots`, of a finite abelian group (where `d_1 | d_2 | d_3 | \ldots`
|
|
742
|
+
are composed of prime powers dividing the invariants of the group
|
|
743
|
+
in a way described below). Just factor the invariants `a_i` that
|
|
744
|
+
define the abelian group. Then the biggest `d_i` is the product
|
|
745
|
+
of the maximum prime powers dividing some `a_j`. In other words, the
|
|
746
|
+
largest `d_i` is the product of `p^v`, where
|
|
747
|
+
`v = \max(\mathrm{ord}_p(a_j) \text{ for all } j`).
|
|
748
|
+
Now divide out all those `p^v`'s into the list of invariants `a_i`,
|
|
749
|
+
and get a new list of "smaller invariants". Repeat the above procedure
|
|
750
|
+
on these "smaller invariants" to compute `d_{i-1}`, and so on.
|
|
751
|
+
(Thanks to Robert Miller for communicating this algorithm.)
|
|
752
|
+
|
|
753
|
+
OUTPUT: tuple of integers
|
|
754
|
+
|
|
755
|
+
EXAMPLES::
|
|
756
|
+
|
|
757
|
+
sage: G = AbelianGroup(2, [2,3])
|
|
758
|
+
sage: G.elementary_divisors()
|
|
759
|
+
(6,)
|
|
760
|
+
sage: G = AbelianGroup(1, [6])
|
|
761
|
+
sage: G.elementary_divisors()
|
|
762
|
+
(6,)
|
|
763
|
+
sage: G = AbelianGroup(2, [2,6])
|
|
764
|
+
sage: G
|
|
765
|
+
Multiplicative Abelian group isomorphic to C2 x C6
|
|
766
|
+
sage: G.gens_orders()
|
|
767
|
+
(2, 6)
|
|
768
|
+
sage: G.elementary_divisors()
|
|
769
|
+
(2, 6)
|
|
770
|
+
sage: J = AbelianGroup([1,3,5,12])
|
|
771
|
+
sage: J.elementary_divisors()
|
|
772
|
+
(3, 60)
|
|
773
|
+
sage: G = AbelianGroup(2, [0,6])
|
|
774
|
+
sage: G.elementary_divisors()
|
|
775
|
+
(6, 0)
|
|
776
|
+
sage: AbelianGroup([3,4,5]).elementary_divisors()
|
|
777
|
+
(60,)
|
|
778
|
+
"""
|
|
779
|
+
from sage.matrix.constructor import diagonal_matrix
|
|
780
|
+
ed = diagonal_matrix(ZZ, self.gens_orders()).elementary_divisors()
|
|
781
|
+
return tuple(d for d in ed if d != 1)
|
|
782
|
+
|
|
783
|
+
@cached_method
|
|
784
|
+
def exponent(self):
|
|
785
|
+
"""
|
|
786
|
+
Return the exponent of this abelian group.
|
|
787
|
+
|
|
788
|
+
EXAMPLES::
|
|
789
|
+
|
|
790
|
+
sage: G = AbelianGroup([2,3,7]); G
|
|
791
|
+
Multiplicative Abelian group isomorphic to C2 x C3 x C7
|
|
792
|
+
sage: G.exponent()
|
|
793
|
+
42
|
|
794
|
+
sage: G = AbelianGroup([2,4,6]); G
|
|
795
|
+
Multiplicative Abelian group isomorphic to C2 x C4 x C6
|
|
796
|
+
sage: G.exponent()
|
|
797
|
+
12
|
|
798
|
+
"""
|
|
799
|
+
return lcm(self.gens_orders())
|
|
800
|
+
|
|
801
|
+
def identity(self):
|
|
802
|
+
r"""
|
|
803
|
+
Return the identity element of this group.
|
|
804
|
+
|
|
805
|
+
EXAMPLES::
|
|
806
|
+
|
|
807
|
+
sage: G = AbelianGroup([2,2])
|
|
808
|
+
sage: e = G.identity()
|
|
809
|
+
sage: e
|
|
810
|
+
1
|
|
811
|
+
sage: g = G.gen(0)
|
|
812
|
+
sage: g*e
|
|
813
|
+
f0
|
|
814
|
+
sage: e*g
|
|
815
|
+
f0
|
|
816
|
+
"""
|
|
817
|
+
return self(1)
|
|
818
|
+
|
|
819
|
+
def _group_notation(self, eldv):
|
|
820
|
+
"""
|
|
821
|
+
Return abstract group notation for generator orders ``eldv``.
|
|
822
|
+
|
|
823
|
+
INPUT:
|
|
824
|
+
|
|
825
|
+
- ``eldv`` -- iterable of integers
|
|
826
|
+
|
|
827
|
+
OUTPUT: string
|
|
828
|
+
|
|
829
|
+
EXAMPLES::
|
|
830
|
+
|
|
831
|
+
sage: G = AbelianGroup([2,2])
|
|
832
|
+
sage: G._group_notation([0,1,2,3])
|
|
833
|
+
'Z x C1 x C2 x C3'
|
|
834
|
+
"""
|
|
835
|
+
v = []
|
|
836
|
+
for x in eldv:
|
|
837
|
+
if x:
|
|
838
|
+
v.append("C%s" % x)
|
|
839
|
+
else:
|
|
840
|
+
v.append("Z")
|
|
841
|
+
return ' x '.join(v)
|
|
842
|
+
|
|
843
|
+
def _latex_(self):
|
|
844
|
+
r"""
|
|
845
|
+
Return latex representation of this group.
|
|
846
|
+
|
|
847
|
+
EXAMPLES::
|
|
848
|
+
|
|
849
|
+
sage: F = AbelianGroup(10, [2]*10)
|
|
850
|
+
sage: F._latex_()
|
|
851
|
+
'$\\mathrm{AbelianGroup}( 10, (2, 2, 2, 2, 2, 2, 2, 2, 2, 2) )$'
|
|
852
|
+
"""
|
|
853
|
+
return r"$\mathrm{AbelianGroup}( %s, %s )$" % (self.ngens(),
|
|
854
|
+
self.gens_orders())
|
|
855
|
+
|
|
856
|
+
@cached_method
|
|
857
|
+
def _libgap_(self):
|
|
858
|
+
r"""
|
|
859
|
+
Return a GAP group corresponding to this group.
|
|
860
|
+
|
|
861
|
+
EXAMPLES::
|
|
862
|
+
|
|
863
|
+
sage: G = AbelianGroup([2,3,9])
|
|
864
|
+
sage: libgap(G) # needs sage.libs.gap
|
|
865
|
+
<pc group of size 54 with 3 generators>
|
|
866
|
+
|
|
867
|
+
The result is cached::
|
|
868
|
+
|
|
869
|
+
sage: libgap(G) is libgap(G) # needs sage.libs.gap
|
|
870
|
+
True
|
|
871
|
+
|
|
872
|
+
Requires the optional ``gap_packages`` for infinite groups::
|
|
873
|
+
|
|
874
|
+
sage: G = AbelianGroup(3, [0,3,4], names='abc')
|
|
875
|
+
sage: libgap(G) # optional - gap_package_polycyclic
|
|
876
|
+
Pcp-group with orders [ 0, 3, 4 ]
|
|
877
|
+
"""
|
|
878
|
+
from sage.libs.gap.libgap import libgap
|
|
879
|
+
|
|
880
|
+
if self.is_finite():
|
|
881
|
+
return libgap.AbelianGroup(self.gens_orders())
|
|
882
|
+
|
|
883
|
+
# Make sure to LoadPackage("Polycyclic") in gap
|
|
884
|
+
from sage.features.gap import GapPackage
|
|
885
|
+
GapPackage("polycyclic", spkg='gap_packages').require()
|
|
886
|
+
return libgap.AbelianPcpGroup(self.gens_orders())
|
|
887
|
+
|
|
888
|
+
def _gap_init_(self):
|
|
889
|
+
r"""
|
|
890
|
+
Return string that defines corresponding abelian group in GAP.
|
|
891
|
+
|
|
892
|
+
EXAMPLES::
|
|
893
|
+
|
|
894
|
+
sage: G = AbelianGroup([2,3,9])
|
|
895
|
+
sage: G._gap_init_()
|
|
896
|
+
'AbelianGroup([2, 3, 9])'
|
|
897
|
+
sage: gap(G) # needs sage.libs.gap
|
|
898
|
+
Group( [ f1, f2, f3 ] )
|
|
899
|
+
|
|
900
|
+
Requires the optional ``gap_packages`` for infinite groups::
|
|
901
|
+
|
|
902
|
+
sage: G = AbelianGroup(3,[0,3,4], names='abc'); G
|
|
903
|
+
Multiplicative Abelian group isomorphic to Z x C3 x C4
|
|
904
|
+
sage: G._gap_init_() # optional - gap_package_polycyclic
|
|
905
|
+
'AbelianPcpGroup([0, 3, 4])'
|
|
906
|
+
"""
|
|
907
|
+
if self.is_finite():
|
|
908
|
+
return 'AbelianGroup(%s)' % list(self.gens_orders())
|
|
909
|
+
|
|
910
|
+
from sage.features.gap import GapPackage
|
|
911
|
+
# Make sure to LoadPackage("Polycyclic") in gap
|
|
912
|
+
GapPackage("polycyclic", spkg='gap_packages').require()
|
|
913
|
+
return 'AbelianPcpGroup(%s)' % list(self.gens_orders())
|
|
914
|
+
|
|
915
|
+
def gen(self, i=0):
|
|
916
|
+
"""
|
|
917
|
+
The `i`-th generator of the abelian group.
|
|
918
|
+
|
|
919
|
+
EXAMPLES::
|
|
920
|
+
|
|
921
|
+
sage: F = AbelianGroup(5,[],names='a')
|
|
922
|
+
sage: F.0
|
|
923
|
+
a0
|
|
924
|
+
sage: F.2
|
|
925
|
+
a2
|
|
926
|
+
sage: F.gens_orders()
|
|
927
|
+
(0, 0, 0, 0, 0)
|
|
928
|
+
|
|
929
|
+
sage: G = AbelianGroup([2,1,3])
|
|
930
|
+
sage: G.gens()
|
|
931
|
+
(f0, 1, f2)
|
|
932
|
+
"""
|
|
933
|
+
n = self.ngens()
|
|
934
|
+
if i < 0 or i >= n:
|
|
935
|
+
raise IndexError("Argument i (= %s) must be between 0 and %s." % (i, n-1))
|
|
936
|
+
x = [0]*n
|
|
937
|
+
if self._gens_orders[i] != 1:
|
|
938
|
+
x[i] = 1
|
|
939
|
+
return self.element_class(self, x)
|
|
940
|
+
|
|
941
|
+
def gens(self) -> tuple:
|
|
942
|
+
"""
|
|
943
|
+
Return the generators of the group.
|
|
944
|
+
|
|
945
|
+
OUTPUT:
|
|
946
|
+
|
|
947
|
+
A tuple of group elements. The generators according to the
|
|
948
|
+
chosen :meth:`gens_orders`.
|
|
949
|
+
|
|
950
|
+
EXAMPLES::
|
|
951
|
+
|
|
952
|
+
sage: F = AbelianGroup(5, [3,2], names='abcde')
|
|
953
|
+
sage: F.gens()
|
|
954
|
+
(a, b, c, d, e)
|
|
955
|
+
sage: [g.order() for g in F.gens()]
|
|
956
|
+
[+Infinity, +Infinity, +Infinity, 3, 2]
|
|
957
|
+
"""
|
|
958
|
+
return tuple(self.gen(i) for i in range(self.ngens()))
|
|
959
|
+
|
|
960
|
+
def gens_orders(self):
|
|
961
|
+
"""
|
|
962
|
+
Return the orders of the cyclic factors that this group has
|
|
963
|
+
been defined with.
|
|
964
|
+
|
|
965
|
+
Use :meth:`elementary_divisors` if you are looking for an
|
|
966
|
+
invariant of the group.
|
|
967
|
+
|
|
968
|
+
OUTPUT: tuple of integers
|
|
969
|
+
|
|
970
|
+
EXAMPLES::
|
|
971
|
+
|
|
972
|
+
sage: Z2xZ3 = AbelianGroup([2,3])
|
|
973
|
+
sage: Z2xZ3.gens_orders()
|
|
974
|
+
(2, 3)
|
|
975
|
+
sage: Z2xZ3.elementary_divisors()
|
|
976
|
+
(6,)
|
|
977
|
+
|
|
978
|
+
sage: Z6 = AbelianGroup([6])
|
|
979
|
+
sage: Z6.gens_orders()
|
|
980
|
+
(6,)
|
|
981
|
+
sage: Z6.elementary_divisors()
|
|
982
|
+
(6,)
|
|
983
|
+
|
|
984
|
+
sage: Z2xZ3.is_isomorphic(Z6)
|
|
985
|
+
True
|
|
986
|
+
sage: Z2xZ3 is Z6
|
|
987
|
+
False
|
|
988
|
+
|
|
989
|
+
TESTS::
|
|
990
|
+
|
|
991
|
+
sage: F = AbelianGroup(3, [2], names='abc')
|
|
992
|
+
sage: list(map(type, F.gens_orders()))
|
|
993
|
+
[<class 'sage.rings.integer.Integer'>,
|
|
994
|
+
<class 'sage.rings.integer.Integer'>,
|
|
995
|
+
<class 'sage.rings.integer.Integer'>]
|
|
996
|
+
"""
|
|
997
|
+
return self._gens_orders
|
|
998
|
+
|
|
999
|
+
def invariants(self):
|
|
1000
|
+
"""
|
|
1001
|
+
Return the orders of the cyclic factors that this group has
|
|
1002
|
+
been defined with.
|
|
1003
|
+
|
|
1004
|
+
For historical reasons this has been called invariants in
|
|
1005
|
+
Sage, even though they are not necessarily the invariant
|
|
1006
|
+
factors of the group. Use :meth:`gens_orders` instead::
|
|
1007
|
+
|
|
1008
|
+
sage: J = AbelianGroup([2,0,3,2,4]); J
|
|
1009
|
+
Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
|
|
1010
|
+
sage: J.invariants() # deprecated
|
|
1011
|
+
(2, 0, 3, 2, 4)
|
|
1012
|
+
sage: J.gens_orders() # use this instead
|
|
1013
|
+
(2, 0, 3, 2, 4)
|
|
1014
|
+
sage: for i in range(J.ngens()):
|
|
1015
|
+
....: print((i, J.gen(i), J.gen(i).order())) # or this
|
|
1016
|
+
(0, f0, 2)
|
|
1017
|
+
(1, f1, +Infinity)
|
|
1018
|
+
(2, f2, 3)
|
|
1019
|
+
(3, f3, 2)
|
|
1020
|
+
(4, f4, 4)
|
|
1021
|
+
|
|
1022
|
+
Use :meth:`elementary_divisors` if you are looking for an
|
|
1023
|
+
invariant of the group.
|
|
1024
|
+
|
|
1025
|
+
OUTPUT: tuple of integers; zero means infinite cyclic factor
|
|
1026
|
+
|
|
1027
|
+
EXAMPLES::
|
|
1028
|
+
|
|
1029
|
+
sage: J = AbelianGroup([2,3])
|
|
1030
|
+
sage: J.invariants()
|
|
1031
|
+
(2, 3)
|
|
1032
|
+
sage: J.elementary_divisors()
|
|
1033
|
+
(6,)
|
|
1034
|
+
|
|
1035
|
+
TESTS::
|
|
1036
|
+
|
|
1037
|
+
sage: F = AbelianGroup(3, [2], names='abc')
|
|
1038
|
+
sage: list(map(type, F.gens_orders()))
|
|
1039
|
+
[<class 'sage.rings.integer.Integer'>,
|
|
1040
|
+
<class 'sage.rings.integer.Integer'>,
|
|
1041
|
+
<class 'sage.rings.integer.Integer'>]
|
|
1042
|
+
"""
|
|
1043
|
+
# TODO: deprecate
|
|
1044
|
+
return self.gens_orders()
|
|
1045
|
+
|
|
1046
|
+
def is_cyclic(self):
|
|
1047
|
+
"""
|
|
1048
|
+
Return ``True`` if the group is a cyclic group.
|
|
1049
|
+
|
|
1050
|
+
EXAMPLES::
|
|
1051
|
+
|
|
1052
|
+
sage: J = AbelianGroup([2,3])
|
|
1053
|
+
sage: J.gens_orders()
|
|
1054
|
+
(2, 3)
|
|
1055
|
+
sage: J.elementary_divisors()
|
|
1056
|
+
(6,)
|
|
1057
|
+
sage: J.is_cyclic()
|
|
1058
|
+
True
|
|
1059
|
+
sage: G = AbelianGroup([6])
|
|
1060
|
+
sage: G.gens_orders()
|
|
1061
|
+
(6,)
|
|
1062
|
+
sage: G.is_cyclic()
|
|
1063
|
+
True
|
|
1064
|
+
sage: H = AbelianGroup([2,2])
|
|
1065
|
+
sage: H.gens_orders()
|
|
1066
|
+
(2, 2)
|
|
1067
|
+
sage: H.is_cyclic()
|
|
1068
|
+
False
|
|
1069
|
+
sage: H = AbelianGroup([2,4])
|
|
1070
|
+
sage: H.elementary_divisors()
|
|
1071
|
+
(2, 4)
|
|
1072
|
+
sage: H.is_cyclic()
|
|
1073
|
+
False
|
|
1074
|
+
sage: H.permutation_group().is_cyclic() # needs sage.groups
|
|
1075
|
+
False
|
|
1076
|
+
sage: T = AbelianGroup([])
|
|
1077
|
+
sage: T.is_cyclic()
|
|
1078
|
+
True
|
|
1079
|
+
sage: T = AbelianGroup(1, [0]); T
|
|
1080
|
+
Multiplicative Abelian group isomorphic to Z
|
|
1081
|
+
sage: T.is_cyclic()
|
|
1082
|
+
True
|
|
1083
|
+
sage: B = AbelianGroup([3,4,5])
|
|
1084
|
+
sage: B.is_cyclic()
|
|
1085
|
+
True
|
|
1086
|
+
"""
|
|
1087
|
+
return len(self.elementary_divisors()) <= 1
|
|
1088
|
+
|
|
1089
|
+
@cached_method
|
|
1090
|
+
def ngens(self):
|
|
1091
|
+
"""
|
|
1092
|
+
The number of free generators of the abelian group.
|
|
1093
|
+
|
|
1094
|
+
EXAMPLES::
|
|
1095
|
+
|
|
1096
|
+
sage: F = AbelianGroup(10000)
|
|
1097
|
+
sage: F.ngens()
|
|
1098
|
+
10000
|
|
1099
|
+
"""
|
|
1100
|
+
return len(self.gens_orders())
|
|
1101
|
+
|
|
1102
|
+
@cached_method
|
|
1103
|
+
def order(self):
|
|
1104
|
+
"""
|
|
1105
|
+
Return the order of this group.
|
|
1106
|
+
|
|
1107
|
+
EXAMPLES::
|
|
1108
|
+
|
|
1109
|
+
sage: G = AbelianGroup(2, [2,3])
|
|
1110
|
+
sage: G.order()
|
|
1111
|
+
6
|
|
1112
|
+
sage: G = AbelianGroup(3, [2,3,0])
|
|
1113
|
+
sage: G.order()
|
|
1114
|
+
+Infinity
|
|
1115
|
+
"""
|
|
1116
|
+
length = prod(self.gens_orders())
|
|
1117
|
+
if length == 0:
|
|
1118
|
+
return infinity
|
|
1119
|
+
return length
|
|
1120
|
+
|
|
1121
|
+
cardinality = order
|
|
1122
|
+
|
|
1123
|
+
@cached_method
|
|
1124
|
+
def permutation_group(self):
|
|
1125
|
+
r"""
|
|
1126
|
+
Return the permutation group isomorphic to this abelian group.
|
|
1127
|
+
|
|
1128
|
+
If the invariants are `q_1, \ldots, q_n` then the
|
|
1129
|
+
generators of the permutation will be of order
|
|
1130
|
+
`q_1, \ldots, q_n`, respectively.
|
|
1131
|
+
|
|
1132
|
+
EXAMPLES::
|
|
1133
|
+
|
|
1134
|
+
sage: G = AbelianGroup(2,[2,3]); G
|
|
1135
|
+
Multiplicative Abelian group isomorphic to C2 x C3
|
|
1136
|
+
sage: G.permutation_group() # needs sage.groups
|
|
1137
|
+
Permutation Group with generators [(1,2), (3,4,5)]
|
|
1138
|
+
|
|
1139
|
+
TESTS:
|
|
1140
|
+
|
|
1141
|
+
Check that :issue:`25692` is fixed::
|
|
1142
|
+
|
|
1143
|
+
sage: G = AbelianGroup([0])
|
|
1144
|
+
sage: G.permutation_group()
|
|
1145
|
+
Traceback (most recent call last):
|
|
1146
|
+
...
|
|
1147
|
+
TypeError: Abelian group must be finite
|
|
1148
|
+
"""
|
|
1149
|
+
# GAP does not support infinite permutation groups
|
|
1150
|
+
if not self.is_finite():
|
|
1151
|
+
raise TypeError('Abelian group must be finite')
|
|
1152
|
+
from sage.groups.perm_gps.permgroup import PermutationGroup
|
|
1153
|
+
s = 'Image(IsomorphismPermGroup(%s))' % self._gap_init_()
|
|
1154
|
+
return PermutationGroup(gap_group=s)
|
|
1155
|
+
|
|
1156
|
+
def is_commutative(self):
|
|
1157
|
+
"""
|
|
1158
|
+
Return ``True`` since this group is commutative.
|
|
1159
|
+
|
|
1160
|
+
EXAMPLES::
|
|
1161
|
+
|
|
1162
|
+
sage: G = AbelianGroup([2,3,9, 0])
|
|
1163
|
+
sage: G.is_commutative()
|
|
1164
|
+
True
|
|
1165
|
+
sage: G.is_abelian()
|
|
1166
|
+
True
|
|
1167
|
+
"""
|
|
1168
|
+
return True
|
|
1169
|
+
|
|
1170
|
+
def random_element(self):
|
|
1171
|
+
"""
|
|
1172
|
+
Return a random element of this group.
|
|
1173
|
+
|
|
1174
|
+
EXAMPLES::
|
|
1175
|
+
|
|
1176
|
+
sage: G = AbelianGroup([2,3,9])
|
|
1177
|
+
sage: G.random_element().parent() is G
|
|
1178
|
+
True
|
|
1179
|
+
"""
|
|
1180
|
+
from sage.misc.prandom import randint
|
|
1181
|
+
result = self.one()
|
|
1182
|
+
for g in self.gens():
|
|
1183
|
+
order = g.order()
|
|
1184
|
+
if order is infinity:
|
|
1185
|
+
order = 42 # infinite order; randomly chosen maximum
|
|
1186
|
+
result *= g ** (randint(0, order))
|
|
1187
|
+
return result
|
|
1188
|
+
|
|
1189
|
+
def _repr_(self) -> str:
|
|
1190
|
+
"""
|
|
1191
|
+
Return a string representation of ``self``.
|
|
1192
|
+
|
|
1193
|
+
EXAMPLES::
|
|
1194
|
+
|
|
1195
|
+
sage: G = AbelianGroup([2,3,9])
|
|
1196
|
+
sage: G._repr_()
|
|
1197
|
+
'Multiplicative Abelian group isomorphic to C2 x C3 x C9'
|
|
1198
|
+
"""
|
|
1199
|
+
eldv = self.gens_orders()
|
|
1200
|
+
if len(eldv) == 0:
|
|
1201
|
+
return "Trivial Abelian group"
|
|
1202
|
+
g = self._group_notation(eldv)
|
|
1203
|
+
return "Multiplicative Abelian group isomorphic to " + g
|
|
1204
|
+
|
|
1205
|
+
def subgroup(self, gensH, names='f'):
|
|
1206
|
+
"""
|
|
1207
|
+
Create a subgroup of this group.
|
|
1208
|
+
|
|
1209
|
+
The "big" group must be defined using "named" generators.
|
|
1210
|
+
|
|
1211
|
+
INPUT:
|
|
1212
|
+
|
|
1213
|
+
- ``gensH`` -- list of elements which are products of the
|
|
1214
|
+
generators of the ambient abelian group `G` = ``self``
|
|
1215
|
+
|
|
1216
|
+
EXAMPLES::
|
|
1217
|
+
|
|
1218
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1219
|
+
sage: G.<a,b,c> = AbelianGroup(3, [2,3,4]); G
|
|
1220
|
+
Multiplicative Abelian group isomorphic to C2 x C3 x C4
|
|
1221
|
+
sage: H = G.subgroup([a*b,a]); H
|
|
1222
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a*b, a}
|
|
1223
|
+
sage: H < G
|
|
1224
|
+
True
|
|
1225
|
+
sage: F = G.subgroup([a,b^2])
|
|
1226
|
+
sage: F
|
|
1227
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
|
|
1228
|
+
sage: F.gens()
|
|
1229
|
+
(a, b^2)
|
|
1230
|
+
sage: F = AbelianGroup(5, [30,64,729], names=list("abcde"))
|
|
1231
|
+
sage: a,b,c,d,e = F.gens()
|
|
1232
|
+
sage: F.subgroup([a,b])
|
|
1233
|
+
Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b}
|
|
1234
|
+
sage: F.subgroup([c,e])
|
|
1235
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x C729
|
|
1236
|
+
generated by {c, e}
|
|
1237
|
+
"""
|
|
1238
|
+
G = self
|
|
1239
|
+
gensH = tuple(gensH)
|
|
1240
|
+
if isinstance(names, list):
|
|
1241
|
+
names = tuple(names)
|
|
1242
|
+
for h in gensH:
|
|
1243
|
+
if h not in G:
|
|
1244
|
+
raise TypeError('Subgroup generators must belong to the given group.')
|
|
1245
|
+
return self.Subgroup(self, gensH, names)
|
|
1246
|
+
|
|
1247
|
+
def list(self):
|
|
1248
|
+
"""
|
|
1249
|
+
Return tuple of all elements of this group.
|
|
1250
|
+
|
|
1251
|
+
EXAMPLES::
|
|
1252
|
+
|
|
1253
|
+
sage: G = AbelianGroup([2,3], names = "ab")
|
|
1254
|
+
sage: G.list()
|
|
1255
|
+
(1, b, b^2, a, a*b, a*b^2)
|
|
1256
|
+
|
|
1257
|
+
::
|
|
1258
|
+
|
|
1259
|
+
sage: G = AbelianGroup([]); G
|
|
1260
|
+
Trivial Abelian group
|
|
1261
|
+
sage: G.list()
|
|
1262
|
+
(1,)
|
|
1263
|
+
"""
|
|
1264
|
+
if not self.is_finite():
|
|
1265
|
+
raise NotImplementedError("group must be finite")
|
|
1266
|
+
return tuple(iter(self))
|
|
1267
|
+
|
|
1268
|
+
def __len__(self):
|
|
1269
|
+
"""
|
|
1270
|
+
Return the length of ``self``.
|
|
1271
|
+
|
|
1272
|
+
EXAMPLES::
|
|
1273
|
+
|
|
1274
|
+
sage: G = AbelianGroup(2,[2,3])
|
|
1275
|
+
sage: len(G)
|
|
1276
|
+
6
|
|
1277
|
+
sage: G = AbelianGroup(3,[2,3,0])
|
|
1278
|
+
sage: len(G)
|
|
1279
|
+
Traceback (most recent call last):
|
|
1280
|
+
...
|
|
1281
|
+
NotImplementedError: group must be finite
|
|
1282
|
+
"""
|
|
1283
|
+
length = prod(self.gens_orders())
|
|
1284
|
+
if length == 0:
|
|
1285
|
+
raise NotImplementedError("group must be finite")
|
|
1286
|
+
return int(length)
|
|
1287
|
+
|
|
1288
|
+
def __iter__(self):
|
|
1289
|
+
"""
|
|
1290
|
+
Return an iterator over the elements of this group.
|
|
1291
|
+
|
|
1292
|
+
EXAMPLES::
|
|
1293
|
+
|
|
1294
|
+
sage: G = AbelianGroup([2,3], names = "ab")
|
|
1295
|
+
sage: [a for a in G]
|
|
1296
|
+
[1, b, b^2, a, a*b, a*b^2]
|
|
1297
|
+
sage: L = list(G); L
|
|
1298
|
+
[1, b, b^2, a, a*b, a*b^2]
|
|
1299
|
+
|
|
1300
|
+
The returned list is a reference; mutating it does not allow the
|
|
1301
|
+
user to (accidentally?) alter the computed generators::
|
|
1302
|
+
|
|
1303
|
+
sage: L[0] = 0
|
|
1304
|
+
sage: list(G)
|
|
1305
|
+
[1, b, b^2, a, a*b, a*b^2]
|
|
1306
|
+
sage: G = AbelianGroup([1], names='a')
|
|
1307
|
+
sage: list(G)
|
|
1308
|
+
[1]
|
|
1309
|
+
sage: G = AbelianGroup([])
|
|
1310
|
+
sage: G.list()
|
|
1311
|
+
(1,)
|
|
1312
|
+
sage: list(G)
|
|
1313
|
+
[1]
|
|
1314
|
+
|
|
1315
|
+
We can also iterate over infinite groups::
|
|
1316
|
+
|
|
1317
|
+
sage: A = AbelianGroup([3,0,5,0])
|
|
1318
|
+
sage: for a in A:
|
|
1319
|
+
....: if a^2 == A([1, 2, 3, 4]):
|
|
1320
|
+
....: print(a, a^2)
|
|
1321
|
+
....: break
|
|
1322
|
+
f0^2*f1*f2^4*f3^2 f0*f1^2*f2^3*f3^4
|
|
1323
|
+
"""
|
|
1324
|
+
invs = self.gens_orders()
|
|
1325
|
+
if 0 not in invs:
|
|
1326
|
+
# The group is finite
|
|
1327
|
+
yield from map(self, mrange(invs))
|
|
1328
|
+
else:
|
|
1329
|
+
# A similar approach works for infinite groups.
|
|
1330
|
+
# (This would also work for finite groups, but is more complicated.)
|
|
1331
|
+
from sage.misc.mrange import cantor_product
|
|
1332
|
+
yield from map(self, cantor_product(*[range(n) if n
|
|
1333
|
+
else ZZ for n in invs]))
|
|
1334
|
+
|
|
1335
|
+
def number_of_subgroups(self, order=None):
|
|
1336
|
+
r"""
|
|
1337
|
+
Return the number of subgroups of this group, possibly only of a
|
|
1338
|
+
specific order.
|
|
1339
|
+
|
|
1340
|
+
INPUT:
|
|
1341
|
+
|
|
1342
|
+
- ``order`` -- (default: ``None``) find the number of subgroups of this
|
|
1343
|
+
order; if ``None``, this defaults to counting all subgroups
|
|
1344
|
+
|
|
1345
|
+
ALGORITHM:
|
|
1346
|
+
|
|
1347
|
+
An infinite group has infinitely many subgroups. All finite subgroups of
|
|
1348
|
+
any group are contained in the torsion subgroup, which for finitely
|
|
1349
|
+
generated abelian group is itself finite. Hence, we can assume the
|
|
1350
|
+
group is finite. A finite abelian group is isomorphic to a direct
|
|
1351
|
+
product of its Sylow subgroups, and so we can reduce the problem
|
|
1352
|
+
further to counting subgroups of finite abelian `p`-groups.
|
|
1353
|
+
|
|
1354
|
+
Assume a Sylow subgroup is a `p`-group of type `\lambda`, and using
|
|
1355
|
+
:func:`~sage.combinat.q_analogues.q_subgroups_of_abelian_group`
|
|
1356
|
+
sum the number of subgroups of type `\mu` in an abelian `p`-group of
|
|
1357
|
+
type `\lambda` for all `\mu` contained in `\lambda`.
|
|
1358
|
+
|
|
1359
|
+
EXAMPLES::
|
|
1360
|
+
|
|
1361
|
+
sage: AbelianGroup([2,0,0,3,0]).number_of_subgroups()
|
|
1362
|
+
+Infinity
|
|
1363
|
+
|
|
1364
|
+
sage: # needs sage.combinat
|
|
1365
|
+
sage: AbelianGroup([2,3]).number_of_subgroups()
|
|
1366
|
+
4
|
|
1367
|
+
sage: AbelianGroup([2,4,8]).number_of_subgroups()
|
|
1368
|
+
81
|
|
1369
|
+
sage: AbelianGroup([2,4,8]).number_of_subgroups(order=4)
|
|
1370
|
+
19
|
|
1371
|
+
sage: AbelianGroup([10,15,25,12]).number_of_subgroups()
|
|
1372
|
+
5760
|
|
1373
|
+
sage: AbelianGroup([10,15,25,12]).number_of_subgroups(order=45000)
|
|
1374
|
+
1
|
|
1375
|
+
sage: AbelianGroup([10,15,25,12]).number_of_subgroups(order=14)
|
|
1376
|
+
0
|
|
1377
|
+
|
|
1378
|
+
TESTS::
|
|
1379
|
+
|
|
1380
|
+
sage: # needs sage.combinat
|
|
1381
|
+
sage: AbelianGroup([]).number_of_subgroups()
|
|
1382
|
+
1
|
|
1383
|
+
sage: AbelianGroup([1,3,1]).number_of_subgroups()
|
|
1384
|
+
2
|
|
1385
|
+
sage: AbelianGroup([]).number_of_subgroups(order=2)
|
|
1386
|
+
0
|
|
1387
|
+
sage: AbelianGroup([1,3,1]).number_of_subgroups(order=2)
|
|
1388
|
+
0
|
|
1389
|
+
sage: AbelianGroup([1,3,0,1]).number_of_subgroups(order=3) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1390
|
+
1
|
|
1391
|
+
sage: AbelianGroup([1,3,1]).number_of_subgroups(order=-2)
|
|
1392
|
+
Traceback (most recent call last):
|
|
1393
|
+
...
|
|
1394
|
+
ValueError: subgroups order must be positive or None
|
|
1395
|
+
"""
|
|
1396
|
+
if not self.is_finite():
|
|
1397
|
+
if order is None:
|
|
1398
|
+
return infinity
|
|
1399
|
+
else:
|
|
1400
|
+
# Finite order subgroups are all contained in the torsion subgroup
|
|
1401
|
+
return self.torsion_subgroup().number_of_subgroups(order=order)
|
|
1402
|
+
|
|
1403
|
+
from itertools import chain
|
|
1404
|
+
from collections import defaultdict
|
|
1405
|
+
from sage.arith.misc import factor
|
|
1406
|
+
from sage.combinat.q_analogues import q_subgroups_of_abelian_group
|
|
1407
|
+
from sage.combinat.integer_lists import IntegerListsLex
|
|
1408
|
+
|
|
1409
|
+
# The group order is prod(p^e for (p,e) in primary_factors)
|
|
1410
|
+
primary_factors = list(chain.from_iterable(
|
|
1411
|
+
factor(ed) for ed in self.elementary_divisors()))
|
|
1412
|
+
sylow_types = defaultdict(list)
|
|
1413
|
+
for p, e in primary_factors:
|
|
1414
|
+
sylow_types[p].append(e)
|
|
1415
|
+
subgroups_orders_kwds = {}
|
|
1416
|
+
|
|
1417
|
+
if order is None:
|
|
1418
|
+
for p, p_exps in sylow_types.items():
|
|
1419
|
+
subgroups_orders_kwds[p] = {'max_sum': sum(p_exps)}
|
|
1420
|
+
else:
|
|
1421
|
+
order = Integer(order)
|
|
1422
|
+
if order < 1:
|
|
1423
|
+
raise ValueError('subgroups order must be positive or None')
|
|
1424
|
+
if not order.divides(self.order()):
|
|
1425
|
+
return Integer(0)
|
|
1426
|
+
order_exps = dict(factor(order))
|
|
1427
|
+
|
|
1428
|
+
for p in (set(sylow_types) - set(order_exps)):
|
|
1429
|
+
del sylow_types[p]
|
|
1430
|
+
for p in sylow_types:
|
|
1431
|
+
subgroups_orders_kwds[p] = {'n': order_exps[p]}
|
|
1432
|
+
|
|
1433
|
+
result = Integer(1)
|
|
1434
|
+
for p, p_exps in sylow_types.items():
|
|
1435
|
+
p_exps.sort(reverse=True)
|
|
1436
|
+
# The sum is over all partitions mu contained in p_exps whose size
|
|
1437
|
+
# is determined by subgroups_orders_kwds.
|
|
1438
|
+
result *= sum(q_subgroups_of_abelian_group(p_exps, mu, q=p)
|
|
1439
|
+
for mu in IntegerListsLex(max_slope=0,
|
|
1440
|
+
min_part=1,
|
|
1441
|
+
max_length=len(p_exps),
|
|
1442
|
+
ceiling=p_exps,
|
|
1443
|
+
element_constructor=list,
|
|
1444
|
+
**subgroups_orders_kwds[p]))
|
|
1445
|
+
return result
|
|
1446
|
+
|
|
1447
|
+
def subgroups(self, check=False):
|
|
1448
|
+
r"""
|
|
1449
|
+
Compute all the subgroups of this abelian group (which must be finite).
|
|
1450
|
+
|
|
1451
|
+
INPUT:
|
|
1452
|
+
|
|
1453
|
+
- ``check`` -- boolean; if ``True``, performs the same computation in
|
|
1454
|
+
GAP and checks that the number of subgroups generated is the
|
|
1455
|
+
same. (I don't know how to convert GAP's output back into
|
|
1456
|
+
Sage, so we don't actually compare the subgroups).
|
|
1457
|
+
|
|
1458
|
+
ALGORITHM:
|
|
1459
|
+
|
|
1460
|
+
If the group is cyclic, the problem is easy. Otherwise, write it as
|
|
1461
|
+
a direct product A x B, where B is cyclic. Compute the subgroups of
|
|
1462
|
+
A (by recursion).
|
|
1463
|
+
|
|
1464
|
+
Now, for every subgroup C of A x B, let G be its *projection onto*
|
|
1465
|
+
A and H its *intersection with* B. Then there is a well-defined
|
|
1466
|
+
homomorphism f: G -> B/H that sends a in G to the class mod H of b,
|
|
1467
|
+
where (a,b) is any element of C lifting a; and every subgroup C
|
|
1468
|
+
arises from a unique triple (G, H, f).
|
|
1469
|
+
|
|
1470
|
+
.. TODO::
|
|
1471
|
+
|
|
1472
|
+
This is *many orders of magnitude* slower than Magma. Consider
|
|
1473
|
+
using the much faster method
|
|
1474
|
+
:meth:`~AbelianGroup_class.number_of_subgroups` in case you only
|
|
1475
|
+
need the number of subgroups, possibly of a specific order.
|
|
1476
|
+
|
|
1477
|
+
EXAMPLES::
|
|
1478
|
+
|
|
1479
|
+
sage: AbelianGroup([2,3]).subgroups() # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1480
|
+
[Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {f0*f1^2},
|
|
1481
|
+
Multiplicative Abelian subgroup isomorphic to C2 generated by {f0},
|
|
1482
|
+
Multiplicative Abelian subgroup isomorphic to C3 generated by {f1},
|
|
1483
|
+
Trivial Abelian subgroup]
|
|
1484
|
+
sage: len(AbelianGroup([2,4,8]).subgroups()) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1485
|
+
81
|
|
1486
|
+
|
|
1487
|
+
TESTS::
|
|
1488
|
+
|
|
1489
|
+
sage: AbelianGroup([]).subgroups()
|
|
1490
|
+
[Trivial Abelian group]
|
|
1491
|
+
|
|
1492
|
+
Check that :issue:`14196` is fixed::
|
|
1493
|
+
|
|
1494
|
+
sage: B = AbelianGroup([1,2])
|
|
1495
|
+
sage: B.subgroups() # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1496
|
+
[Multiplicative Abelian subgroup isomorphic to C2 generated by {f1},
|
|
1497
|
+
Trivial Abelian subgroup]
|
|
1498
|
+
sage: B.subgroups(check=True) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1499
|
+
[Multiplicative Abelian subgroup isomorphic to C2 generated by {f1},
|
|
1500
|
+
Trivial Abelian subgroup]
|
|
1501
|
+
"""
|
|
1502
|
+
if not self.is_finite():
|
|
1503
|
+
raise ValueError("group must be finite")
|
|
1504
|
+
from sage.misc.verbose import verbose
|
|
1505
|
+
|
|
1506
|
+
if self.is_trivial():
|
|
1507
|
+
return [self]
|
|
1508
|
+
if self.ngens() == 1:
|
|
1509
|
+
n = self.gen(0).order()
|
|
1510
|
+
return [self.subgroup([self.gen(0)**i]) for i in divisors(n)]
|
|
1511
|
+
|
|
1512
|
+
v = self.gens_orders()
|
|
1513
|
+
A = AbelianGroup(v[:-1])
|
|
1514
|
+
x = v[-1]
|
|
1515
|
+
|
|
1516
|
+
Wsubs = A.subgroups()
|
|
1517
|
+
|
|
1518
|
+
subgps = []
|
|
1519
|
+
for G in Wsubs:
|
|
1520
|
+
ngens = len(G.gens())
|
|
1521
|
+
verbose("G = subgp generated by %s" % list(G.gens()))
|
|
1522
|
+
verbose("invariants are: %s" % [t.order() for t in G.gens()])
|
|
1523
|
+
for H in divisors(x):
|
|
1524
|
+
# H = the subgroup of *index* H.
|
|
1525
|
+
its = [range(0, H, H // gcd(H, G.gen(i).order()))
|
|
1526
|
+
for i in range(ngens)]
|
|
1527
|
+
for f in product(*its):
|
|
1528
|
+
verbose("using hom from G to C_%s sending gens to %s" % (H, f))
|
|
1529
|
+
new_sub = []
|
|
1530
|
+
for a in range(ngens):
|
|
1531
|
+
val = G.gen(a).list() + [f[a]]
|
|
1532
|
+
if any(l != 0 for l in val):
|
|
1533
|
+
new_sub.append(val)
|
|
1534
|
+
if H != x:
|
|
1535
|
+
new_sub.append([0] * A.ngens() + [H])
|
|
1536
|
+
subgps.append(self.subgroup_reduced(new_sub))
|
|
1537
|
+
|
|
1538
|
+
if check:
|
|
1539
|
+
verbose("Running Gap cross-check")
|
|
1540
|
+
from sage.libs.gap.libgap import libgap
|
|
1541
|
+
t = libgap(v).AbelianGroup().SubgroupsSolvableGroup().Size().sage()
|
|
1542
|
+
if t != len(subgps):
|
|
1543
|
+
raise ArithmeticError("For %s Gap finds %s subgroups, I found %s" % (v, t, len(subgps)))
|
|
1544
|
+
verbose("Gap check OK for %s: %s" % (v, t))
|
|
1545
|
+
return subgps
|
|
1546
|
+
|
|
1547
|
+
def subgroup_reduced(self, elts, verbose=False):
|
|
1548
|
+
r"""
|
|
1549
|
+
Given a list of lists of integers (corresponding to elements of
|
|
1550
|
+
``self``), find a set of independent generators for the subgroup
|
|
1551
|
+
generated by these elements, and return the subgroup with these as
|
|
1552
|
+
generators, forgetting the original generators.
|
|
1553
|
+
|
|
1554
|
+
This is used by the ``subgroups`` routine.
|
|
1555
|
+
|
|
1556
|
+
An error will be raised if the elements given are not linearly
|
|
1557
|
+
independent over `\QQ`.
|
|
1558
|
+
|
|
1559
|
+
EXAMPLES::
|
|
1560
|
+
|
|
1561
|
+
sage: G = AbelianGroup([4,4])
|
|
1562
|
+
sage: G.subgroup( [ G([1,0]), G([1,2]) ]) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1563
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C4
|
|
1564
|
+
generated by {f0, f0*f1^2}
|
|
1565
|
+
sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ]) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1566
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C4
|
|
1567
|
+
generated by {f0^2*f1^2, f0^3}
|
|
1568
|
+
"""
|
|
1569
|
+
from sage.matrix.constructor import matrix
|
|
1570
|
+
d = self.ngens()
|
|
1571
|
+
X = ZZ**d
|
|
1572
|
+
try:
|
|
1573
|
+
elt_lattice = X.submodule_with_basis(elts)
|
|
1574
|
+
except ValueError as e:
|
|
1575
|
+
# can't happen?
|
|
1576
|
+
print("Vectors not LI: {}".format(elts))
|
|
1577
|
+
raise e
|
|
1578
|
+
rel_lattice = X.span([X.gen(i) * self.gens_orders()[i] for i in range(d)])
|
|
1579
|
+
isect = elt_lattice.intersection(rel_lattice)
|
|
1580
|
+
mat = matrix([elt_lattice.coordinate_vector(x) for x in isect.gens()]).change_ring(ZZ)
|
|
1581
|
+
D, U, V = mat.smith_form()
|
|
1582
|
+
new_basis = [(elt_lattice.linear_combination_of_basis((~V).row(i)).list(), D[i, i]) for i in range(U.ncols())]
|
|
1583
|
+
return self.subgroup([self([x[0][i] % self.gens_orders()[i]
|
|
1584
|
+
for i in range(d)]) for x in new_basis if x[1] != 1])
|
|
1585
|
+
|
|
1586
|
+
def torsion_subgroup(self, n=None):
|
|
1587
|
+
"""
|
|
1588
|
+
Return the `n`-torsion subgroup of this abelian group when `n`
|
|
1589
|
+
is given, and the torsion subgroup otherwise.
|
|
1590
|
+
|
|
1591
|
+
The [`n`-]torsion subgroup consists of all elements whose order
|
|
1592
|
+
is finite [and divides `n`].
|
|
1593
|
+
|
|
1594
|
+
EXAMPLES::
|
|
1595
|
+
|
|
1596
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1597
|
+
sage: G = AbelianGroup([2, 3])
|
|
1598
|
+
sage: G.torsion_subgroup()
|
|
1599
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated
|
|
1600
|
+
by {f0, f1}
|
|
1601
|
+
sage: G = AbelianGroup([2, 0, 0, 3, 0])
|
|
1602
|
+
sage: G.torsion_subgroup()
|
|
1603
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated
|
|
1604
|
+
by {f0, f3}
|
|
1605
|
+
sage: G = AbelianGroup([])
|
|
1606
|
+
sage: G.torsion_subgroup()
|
|
1607
|
+
Trivial Abelian subgroup
|
|
1608
|
+
sage: G = AbelianGroup([0, 0])
|
|
1609
|
+
sage: G.torsion_subgroup()
|
|
1610
|
+
Trivial Abelian subgroup
|
|
1611
|
+
|
|
1612
|
+
::
|
|
1613
|
+
|
|
1614
|
+
sage: G = AbelianGroup([2, 2*3, 2*3*5, 0, 2*3*5*7, 2*3*5*7*11])
|
|
1615
|
+
sage: G.torsion_subgroup(5) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1616
|
+
Multiplicative Abelian subgroup isomorphic to C5 x C5 x C5
|
|
1617
|
+
generated by {f2^6, f4^42, f5^462}
|
|
1618
|
+
"""
|
|
1619
|
+
if n is None:
|
|
1620
|
+
torsion_generators = [g for g in self.gens() if g.order() != infinity]
|
|
1621
|
+
else:
|
|
1622
|
+
n = ZZ(n)
|
|
1623
|
+
if n <= 0:
|
|
1624
|
+
raise ValueError('n must be a positive integer')
|
|
1625
|
+
torsion_generators = []
|
|
1626
|
+
for g in self.gens():
|
|
1627
|
+
o = g.order()
|
|
1628
|
+
if o == infinity:
|
|
1629
|
+
continue
|
|
1630
|
+
d = n.gcd(o)
|
|
1631
|
+
torsion_generators.append(g**(o//d))
|
|
1632
|
+
return self.subgroup(torsion_generators)
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
class AbelianGroup_subgroup(AbelianGroup_class):
|
|
1636
|
+
"""
|
|
1637
|
+
Subgroup subclass of ``AbelianGroup_class``, so instance methods are
|
|
1638
|
+
inherited.
|
|
1639
|
+
|
|
1640
|
+
.. TODO::
|
|
1641
|
+
|
|
1642
|
+
There should be a way to coerce an element of a subgroup
|
|
1643
|
+
into the ambient group.
|
|
1644
|
+
"""
|
|
1645
|
+
def __init__(self, ambient, gens, names='f', category=None):
|
|
1646
|
+
"""
|
|
1647
|
+
EXAMPLES::
|
|
1648
|
+
|
|
1649
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1650
|
+
sage: F = AbelianGroup(5, [30,64,729], names=list("abcde"))
|
|
1651
|
+
sage: a,b,c,d,e = F.gens()
|
|
1652
|
+
sage: F.subgroup([a^3,b])
|
|
1653
|
+
Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a^3, b}
|
|
1654
|
+
sage: F.subgroup([c])
|
|
1655
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 generated by {c}
|
|
1656
|
+
sage: F.subgroup([a, c])
|
|
1657
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x Z generated by {a, c}
|
|
1658
|
+
sage: F.subgroup([a, b*c])
|
|
1659
|
+
Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b*c}
|
|
1660
|
+
sage: F.subgroup([b*c, d])
|
|
1661
|
+
Multiplicative Abelian subgroup isomorphic to C64 x Z generated by {b*c, d}
|
|
1662
|
+
sage: F.subgroup([a*b, c^6, d], names=list("xyz"))
|
|
1663
|
+
Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
|
|
1664
|
+
sage: H.<x,y,z> = F.subgroup([a*b, c^6, d]); H
|
|
1665
|
+
Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
|
|
1666
|
+
sage: G = F.subgroup([a*b, c^6, d], names=list("xyz")); G
|
|
1667
|
+
Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
|
|
1668
|
+
sage: x,y,z = G.gens()
|
|
1669
|
+
sage: x.order()
|
|
1670
|
+
+Infinity
|
|
1671
|
+
sage: y.order()
|
|
1672
|
+
5
|
|
1673
|
+
sage: z.order()
|
|
1674
|
+
64
|
|
1675
|
+
sage: A = AbelianGroup(5, [3, 5, 5, 7, 8], names='abcde')
|
|
1676
|
+
sage: a,b,c,d,e = A.gens()
|
|
1677
|
+
sage: A.subgroup([a,b])
|
|
1678
|
+
Multiplicative Abelian subgroup isomorphic to C3 x C5 generated by {a, b}
|
|
1679
|
+
sage: A.subgroup([a,b,c,d^2,e])
|
|
1680
|
+
Multiplicative Abelian subgroup isomorphic to C3 x C5 x C5 x C7 x C8 generated by {a, b, c, d^2, e}
|
|
1681
|
+
sage: A.subgroup([a, b, c, d^2, e^2])
|
|
1682
|
+
Multiplicative Abelian subgroup isomorphic to C3 x C4 x C5 x C5 x C7 generated by {a, b, c, d^2, e^2}
|
|
1683
|
+
sage: B = A.subgroup([a^3, b, c, d, e^2]); B
|
|
1684
|
+
Multiplicative Abelian subgroup isomorphic to C4 x C5 x C5 x C7 generated by {b, c, d, e^2}
|
|
1685
|
+
sage: B.gens_orders()
|
|
1686
|
+
(4, 5, 5, 7)
|
|
1687
|
+
sage: A = AbelianGroup(4,[1009, 2003, 3001, 4001], names='abcd')
|
|
1688
|
+
sage: a,b,c,d = A.gens()
|
|
1689
|
+
sage: B = A.subgroup([a^3,b,c,d])
|
|
1690
|
+
sage: B.gens_orders()
|
|
1691
|
+
(1009, 2003, 3001, 4001)
|
|
1692
|
+
sage: A.order()
|
|
1693
|
+
24266473210027
|
|
1694
|
+
sage: B.order()
|
|
1695
|
+
24266473210027
|
|
1696
|
+
sage: A = AbelianGroup(4, [1008, 2003, 3001, 4001], names='abcd')
|
|
1697
|
+
sage: a,b,c,d = A.gens()
|
|
1698
|
+
sage: B = A.subgroup([a^3,b,c,d]); B
|
|
1699
|
+
Multiplicative Abelian subgroup isomorphic
|
|
1700
|
+
to C3 x C7 x C16 x C2003 x C3001 x C4001 generated by {a^3, b, c, d}
|
|
1701
|
+
|
|
1702
|
+
Infinite groups can also be handled::
|
|
1703
|
+
|
|
1704
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1705
|
+
sage: G = AbelianGroup([3,4,0], names='abc')
|
|
1706
|
+
sage: a,b,c = G.gens()
|
|
1707
|
+
sage: F = G.subgroup([a, b^2, c]); F
|
|
1708
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 x Z
|
|
1709
|
+
generated by {a, b^2, c}
|
|
1710
|
+
sage: F.gens_orders()
|
|
1711
|
+
(2, 3, 0)
|
|
1712
|
+
sage: F.gens()
|
|
1713
|
+
(a, b^2, c)
|
|
1714
|
+
sage: F.order()
|
|
1715
|
+
+Infinity
|
|
1716
|
+
|
|
1717
|
+
Testing issue :issue:`18863`::
|
|
1718
|
+
|
|
1719
|
+
sage: G = AbelianGroup(5,[2])
|
|
1720
|
+
sage: G.subgroup([prod(g^k for g,k in zip(G.gens(),[1,-2,3,-4,5]))]) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1721
|
+
Multiplicative Abelian subgroup isomorphic to Z
|
|
1722
|
+
generated by {f0*f1^-2*f2^3*f3^-4*f4}
|
|
1723
|
+
"""
|
|
1724
|
+
from sage.libs.gap.libgap import libgap
|
|
1725
|
+
if not isinstance(ambient, AbelianGroup_class):
|
|
1726
|
+
raise TypeError("ambient (=%s) must be an abelian group" % ambient)
|
|
1727
|
+
if not isinstance(gens, tuple):
|
|
1728
|
+
raise TypeError("gens (=%s) must be a tuple" % gens)
|
|
1729
|
+
|
|
1730
|
+
self._ambient_group = ambient
|
|
1731
|
+
H_gens = tuple(x for x in gens if x != ambient.one()) # clean entry
|
|
1732
|
+
self._gens = H_gens
|
|
1733
|
+
|
|
1734
|
+
H = libgap(ambient).Subgroup(H_gens)
|
|
1735
|
+
|
|
1736
|
+
invs = H.TorsionSubgroup().AbelianInvariants().sage()
|
|
1737
|
+
rank = len([1 for g in H.GeneratorsOfGroup()
|
|
1738
|
+
if g.Order().sage() is infinity])
|
|
1739
|
+
invs += [0] * rank
|
|
1740
|
+
|
|
1741
|
+
self._abinvs = invs
|
|
1742
|
+
invs = tuple(ZZ(i) for i in invs)
|
|
1743
|
+
|
|
1744
|
+
if category is None:
|
|
1745
|
+
category = Groups().Commutative().Subobjects()
|
|
1746
|
+
AbelianGroup_class.__init__(self, invs, names, category=category)
|
|
1747
|
+
|
|
1748
|
+
def __contains__(self, x):
|
|
1749
|
+
"""
|
|
1750
|
+
Test whether ``x`` is an element of this subgroup.
|
|
1751
|
+
|
|
1752
|
+
EXAMPLES::
|
|
1753
|
+
|
|
1754
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1755
|
+
sage: G.<a,b> = AbelianGroup(2)
|
|
1756
|
+
sage: A = G.subgroup([a])
|
|
1757
|
+
sage: a in G
|
|
1758
|
+
True
|
|
1759
|
+
sage: a in A
|
|
1760
|
+
True
|
|
1761
|
+
|
|
1762
|
+
TESTS:
|
|
1763
|
+
|
|
1764
|
+
Check that :issue:`32910` is fixed::
|
|
1765
|
+
|
|
1766
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1767
|
+
sage: G.<a,b> = AbelianGroup(2, [4, 576])
|
|
1768
|
+
sage: Hgens = [a^2, a*b^2]
|
|
1769
|
+
sage: H = G.subgroup(Hgens)
|
|
1770
|
+
sage: [g in H for g in (a^3, b^2, b^3, a^3*b^2, "junk")]
|
|
1771
|
+
[False, False, False, True, False]
|
|
1772
|
+
|
|
1773
|
+
Check that :issue:`31507` is fixed::
|
|
1774
|
+
|
|
1775
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1776
|
+
sage: G = AbelianGroup(2, gens_orders=[16, 16])
|
|
1777
|
+
sage: f0, f1 = G.gens()
|
|
1778
|
+
sage: H = G.subgroup([f0*f1^3])
|
|
1779
|
+
sage: [g in H for g in (f0, f0*f1^2, f0*f1^3, f0*f1^4)]
|
|
1780
|
+
[False, False, True, False]
|
|
1781
|
+
|
|
1782
|
+
sage: G.<a,b> = AbelianGroup(2)
|
|
1783
|
+
sage: Hgens = [a*b, a*b^-1]
|
|
1784
|
+
sage: H = G.subgroup(Hgens) # optional - gap_package_polycyclic
|
|
1785
|
+
sage: b^2 in H # optional - gap_package_polycyclic
|
|
1786
|
+
True
|
|
1787
|
+
"""
|
|
1788
|
+
if not isinstance(x, AbelianGroupElement):
|
|
1789
|
+
return False
|
|
1790
|
+
if x.parent() is self:
|
|
1791
|
+
return True
|
|
1792
|
+
if x in self.ambient_group():
|
|
1793
|
+
amb_inv = self.ambient_group().gens_orders()
|
|
1794
|
+
inv_basis = diagonal_matrix(ZZ, amb_inv)
|
|
1795
|
+
gens_basis = matrix(
|
|
1796
|
+
ZZ, len(self._gens), len(amb_inv),
|
|
1797
|
+
[g.list() for g in self._gens]
|
|
1798
|
+
)
|
|
1799
|
+
return (vector(ZZ, x.list())
|
|
1800
|
+
in inv_basis.stack(gens_basis).row_module())
|
|
1801
|
+
return False
|
|
1802
|
+
|
|
1803
|
+
def ambient_group(self):
|
|
1804
|
+
"""
|
|
1805
|
+
Return the ambient group related to ``self``.
|
|
1806
|
+
|
|
1807
|
+
OUTPUT: a multiplicative Abelian group
|
|
1808
|
+
|
|
1809
|
+
EXAMPLES::
|
|
1810
|
+
|
|
1811
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1812
|
+
sage: G.<a,b,c> = AbelianGroup([2,3,4])
|
|
1813
|
+
sage: H = G.subgroup([a, b^2])
|
|
1814
|
+
sage: H.ambient_group() is G
|
|
1815
|
+
True
|
|
1816
|
+
"""
|
|
1817
|
+
return self._ambient_group
|
|
1818
|
+
|
|
1819
|
+
def equals(left, right):
|
|
1820
|
+
"""
|
|
1821
|
+
Check whether ``left`` and ``right`` are the same (sub)group.
|
|
1822
|
+
|
|
1823
|
+
INPUT:
|
|
1824
|
+
|
|
1825
|
+
- ``right`` -- anything
|
|
1826
|
+
|
|
1827
|
+
OUTPUT:
|
|
1828
|
+
|
|
1829
|
+
boolean; if ``right`` is a subgroup, test whether ``left`` and
|
|
1830
|
+
``right`` are the same subset of the ambient group. If
|
|
1831
|
+
``right`` is not a subgroup, test whether they are isomorphic
|
|
1832
|
+
groups, see :meth:`~AbelianGroup_class.is_isomorphic`.
|
|
1833
|
+
|
|
1834
|
+
EXAMPLES::
|
|
1835
|
+
|
|
1836
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1837
|
+
sage: G = AbelianGroup(3, [2,3,4], names='abc'); G
|
|
1838
|
+
Multiplicative Abelian group isomorphic to C2 x C3 x C4
|
|
1839
|
+
sage: a,b,c = G.gens()
|
|
1840
|
+
sage: F = G.subgroup([a,b^2]); F
|
|
1841
|
+
Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
|
|
1842
|
+
sage: F<G
|
|
1843
|
+
True
|
|
1844
|
+
sage: A = AbelianGroup(1, [6])
|
|
1845
|
+
sage: A.subgroup(list(A.gens())) == A
|
|
1846
|
+
True
|
|
1847
|
+
sage: G.<a,b> = AbelianGroup(2)
|
|
1848
|
+
sage: A = G.subgroup([a])
|
|
1849
|
+
sage: B = G.subgroup([b])
|
|
1850
|
+
sage: A.equals(B)
|
|
1851
|
+
False
|
|
1852
|
+
sage: A == B # sames as A.equals(B)
|
|
1853
|
+
False
|
|
1854
|
+
sage: A.is_isomorphic(B)
|
|
1855
|
+
True
|
|
1856
|
+
"""
|
|
1857
|
+
left_ambient = left.ambient_group()
|
|
1858
|
+
try:
|
|
1859
|
+
right_ambient = right.ambient_group()
|
|
1860
|
+
except AttributeError:
|
|
1861
|
+
# right is not a subgroup
|
|
1862
|
+
return left.is_isomorphic(right)
|
|
1863
|
+
if left_ambient is not right_ambient:
|
|
1864
|
+
return False
|
|
1865
|
+
return left <= right <= left
|
|
1866
|
+
|
|
1867
|
+
__eq__ = equals
|
|
1868
|
+
|
|
1869
|
+
def _repr_(self):
|
|
1870
|
+
"""
|
|
1871
|
+
Return a string representation.
|
|
1872
|
+
|
|
1873
|
+
EXAMPLES::
|
|
1874
|
+
|
|
1875
|
+
sage: G.<a,b> = AbelianGroup(2)
|
|
1876
|
+
sage: G._repr_()
|
|
1877
|
+
'Multiplicative Abelian group isomorphic to Z x Z'
|
|
1878
|
+
sage: A = G.subgroup([a]) # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1879
|
+
sage: A._repr_() # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1880
|
+
'Multiplicative Abelian subgroup isomorphic to Z generated by {a}'
|
|
1881
|
+
"""
|
|
1882
|
+
eldv = self._abinvs
|
|
1883
|
+
if self.is_trivial():
|
|
1884
|
+
return "Trivial Abelian subgroup"
|
|
1885
|
+
s = 'Multiplicative Abelian subgroup isomorphic to '
|
|
1886
|
+
s += self._group_notation(eldv)
|
|
1887
|
+
s += ' generated by '
|
|
1888
|
+
s += '{' + ', '.join(map(str, self.gens())) + '}'
|
|
1889
|
+
return s
|
|
1890
|
+
|
|
1891
|
+
def gens(self) -> tuple:
|
|
1892
|
+
"""
|
|
1893
|
+
Return the generators for this subgroup.
|
|
1894
|
+
|
|
1895
|
+
OUTPUT: tuple of group elements generating the subgroup
|
|
1896
|
+
|
|
1897
|
+
EXAMPLES::
|
|
1898
|
+
|
|
1899
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1900
|
+
sage: G.<a,b> = AbelianGroup(2)
|
|
1901
|
+
sage: A = G.subgroup([a])
|
|
1902
|
+
sage: G.gens()
|
|
1903
|
+
(a, b)
|
|
1904
|
+
sage: A.gens()
|
|
1905
|
+
(a,)
|
|
1906
|
+
"""
|
|
1907
|
+
return self._gens
|
|
1908
|
+
|
|
1909
|
+
def gen(self, n):
|
|
1910
|
+
"""
|
|
1911
|
+
Return the `n`-th generator of this subgroup.
|
|
1912
|
+
|
|
1913
|
+
EXAMPLES::
|
|
1914
|
+
|
|
1915
|
+
sage: # needs sage.libs.gap # optional - gap_package_polycyclic
|
|
1916
|
+
sage: G.<a,b> = AbelianGroup(2)
|
|
1917
|
+
sage: A = G.subgroup([a])
|
|
1918
|
+
sage: A.gen(0)
|
|
1919
|
+
a
|
|
1920
|
+
"""
|
|
1921
|
+
return self._gens[n]
|
|
1922
|
+
|
|
1923
|
+
|
|
1924
|
+
# We allow subclasses to override this, analogous to Element
|
|
1925
|
+
AbelianGroup_class.Subgroup = AbelianGroup_subgroup
|