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,1790 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
r"""
|
|
3
|
+
Integral lattices
|
|
4
|
+
|
|
5
|
+
An integral lattice is a finitely generated free abelian group
|
|
6
|
+
`L \cong \ZZ^r` equipped with a non-degenerate, symmetric bilinear
|
|
7
|
+
form `L \times L \colon \rightarrow \ZZ`.
|
|
8
|
+
|
|
9
|
+
Here, lattices have an ambient quadratic space `\QQ^n` and
|
|
10
|
+
a distinguished basis.
|
|
11
|
+
|
|
12
|
+
EXAMPLES::
|
|
13
|
+
|
|
14
|
+
sage: M = Matrix(ZZ, [[0,1], [1,0]])
|
|
15
|
+
sage: IntegralLattice(M)
|
|
16
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
17
|
+
Standard basis
|
|
18
|
+
Inner product matrix:
|
|
19
|
+
[0 1]
|
|
20
|
+
[1 0]
|
|
21
|
+
|
|
22
|
+
A lattice can be defined by an inner product matrix of the
|
|
23
|
+
ambient space and a basis::
|
|
24
|
+
|
|
25
|
+
sage: G = matrix.identity(3)
|
|
26
|
+
sage: basis = [[1,-1,0], [0,1,-1]]
|
|
27
|
+
sage: L = IntegralLattice(G, basis)
|
|
28
|
+
sage: L
|
|
29
|
+
Lattice of degree 3 and rank 2 over Integer Ring
|
|
30
|
+
Basis matrix:
|
|
31
|
+
[ 1 -1 0]
|
|
32
|
+
[ 0 1 -1]
|
|
33
|
+
Standard scalar product
|
|
34
|
+
|
|
35
|
+
sage: L.gram_matrix()
|
|
36
|
+
[ 2 -1]
|
|
37
|
+
[-1 2]
|
|
38
|
+
|
|
39
|
+
AUTHORS:
|
|
40
|
+
|
|
41
|
+
- Simon Brandhorst (2017-09): First created
|
|
42
|
+
- Paolo Menegatti (2018-03): Added IntegralLatticeDirectSum, IntegralLatticeGluing
|
|
43
|
+
- Lorenz Panny (2024): enumeration routines for short and close vectors
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
# ****************************************************************************
|
|
47
|
+
# Copyright (C) 2017 Simon Brandhorst <sbrandhorst@web.de>
|
|
48
|
+
#
|
|
49
|
+
# This program is free software: you can redistribute it and/or modify
|
|
50
|
+
# it under the terms of the GNU General Public License as published by
|
|
51
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
52
|
+
# (at your option) any later version.
|
|
53
|
+
# https://www.gnu.org/licenses/
|
|
54
|
+
# ****************************************************************************
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
from copy import copy
|
|
57
|
+
|
|
58
|
+
from sage.rings.integer_ring import ZZ
|
|
59
|
+
from sage.rings.integer import Integer
|
|
60
|
+
from sage.rings.rational_field import QQ
|
|
61
|
+
from sage.modules.free_quadratic_module import FreeQuadraticModule_submodule_with_basis_pid, FreeQuadraticModule
|
|
62
|
+
from sage.matrix.constructor import matrix
|
|
63
|
+
from sage.structure.element import Matrix
|
|
64
|
+
from sage.arith.misc import gcd
|
|
65
|
+
from sage.misc.cachefunc import cached_method
|
|
66
|
+
|
|
67
|
+
###############################################################################
|
|
68
|
+
#
|
|
69
|
+
# Constructor functions
|
|
70
|
+
#
|
|
71
|
+
###############################################################################
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def IntegralLattice(data, basis=None):
|
|
75
|
+
r"""
|
|
76
|
+
Return the integral lattice spanned by ``basis`` in the ambient space.
|
|
77
|
+
|
|
78
|
+
A lattice is a finitely generated free abelian group `L \cong \ZZ^r`
|
|
79
|
+
equipped with a non-degenerate, symmetric bilinear form
|
|
80
|
+
`L \times L \colon \rightarrow \ZZ`. Here, lattices have an
|
|
81
|
+
ambient quadratic space `\QQ^n` and a distinguished basis.
|
|
82
|
+
|
|
83
|
+
INPUT:
|
|
84
|
+
|
|
85
|
+
The input is a descriptor of the lattice and a (optional) basis.
|
|
86
|
+
- ``data`` -- can be one of the following:
|
|
87
|
+
|
|
88
|
+
* a symmetric matrix over the rationals -- the inner product matrix
|
|
89
|
+
* an integer -- the dimension for a Euclidean lattice
|
|
90
|
+
* a symmetric Cartan type or anything recognized by
|
|
91
|
+
:class:`CartanMatrix` (see also
|
|
92
|
+
:mod:`Cartan types <sage.combinat.root_system.cartan_type>`)
|
|
93
|
+
-- for a root lattice
|
|
94
|
+
* the string ``'U'`` or ``'H'`` -- for hyperbolic lattices
|
|
95
|
+
|
|
96
|
+
- ``basis`` -- (optional) a matrix whose rows form a basis of the
|
|
97
|
+
lattice, or a list of module elements forming a basis
|
|
98
|
+
|
|
99
|
+
OUTPUT:
|
|
100
|
+
|
|
101
|
+
A lattice in the ambient space defined by the inner_product_matrix.
|
|
102
|
+
Unless specified, the basis of the lattice is the standard basis.
|
|
103
|
+
|
|
104
|
+
EXAMPLES::
|
|
105
|
+
|
|
106
|
+
sage: H5 = Matrix(ZZ, 2, [2,1,1,-2])
|
|
107
|
+
sage: IntegralLattice(H5)
|
|
108
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
109
|
+
Standard basis
|
|
110
|
+
Inner product matrix:
|
|
111
|
+
[ 2 1]
|
|
112
|
+
[ 1 -2]
|
|
113
|
+
|
|
114
|
+
A basis can be specified too::
|
|
115
|
+
|
|
116
|
+
sage: IntegralLattice(H5, Matrix([1,1]))
|
|
117
|
+
Lattice of degree 2 and rank 1 over Integer Ring
|
|
118
|
+
Basis matrix:
|
|
119
|
+
[1 1]
|
|
120
|
+
Inner product matrix:
|
|
121
|
+
[ 2 1]
|
|
122
|
+
[ 1 -2]
|
|
123
|
+
|
|
124
|
+
We can define a Euclidean lattice just by its dimension::
|
|
125
|
+
|
|
126
|
+
sage: IntegralLattice(3)
|
|
127
|
+
Lattice of degree 3 and rank 3 over Integer Ring
|
|
128
|
+
Standard basis
|
|
129
|
+
Standard scalar product
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
Here is an example of the `A_2` root lattice in Euclidean space::
|
|
133
|
+
|
|
134
|
+
sage: basis = Matrix([[1,-1,0], [0,1,-1]])
|
|
135
|
+
sage: A2 = IntegralLattice(3, basis)
|
|
136
|
+
sage: A2
|
|
137
|
+
Lattice of degree 3 and rank 2 over Integer Ring
|
|
138
|
+
Basis matrix:
|
|
139
|
+
[ 1 -1 0]
|
|
140
|
+
[ 0 1 -1]
|
|
141
|
+
Standard scalar product
|
|
142
|
+
sage: A2.gram_matrix()
|
|
143
|
+
[ 2 -1]
|
|
144
|
+
[-1 2]
|
|
145
|
+
|
|
146
|
+
We use ``'U'`` or ``'H'`` for defining a hyperbolic lattice::
|
|
147
|
+
|
|
148
|
+
sage: L1 = IntegralLattice('U')
|
|
149
|
+
sage: L1
|
|
150
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
151
|
+
Standard basis
|
|
152
|
+
Inner product matrix:
|
|
153
|
+
[0 1]
|
|
154
|
+
[1 0]
|
|
155
|
+
sage: L1 == IntegralLattice('H')
|
|
156
|
+
True
|
|
157
|
+
|
|
158
|
+
We can construct root lattices by specifying their type
|
|
159
|
+
(see :mod:`Cartan types <sage.combinat.root_system.cartan_type>`
|
|
160
|
+
and :class:`CartanMatrix`)::
|
|
161
|
+
|
|
162
|
+
sage: # needs sage.graphs
|
|
163
|
+
sage: IntegralLattice(["E", 7])
|
|
164
|
+
Lattice of degree 7 and rank 7 over Integer Ring
|
|
165
|
+
Standard basis
|
|
166
|
+
Inner product matrix:
|
|
167
|
+
[ 2 0 -1 0 0 0 0]
|
|
168
|
+
[ 0 2 0 -1 0 0 0]
|
|
169
|
+
[-1 0 2 -1 0 0 0]
|
|
170
|
+
[ 0 -1 -1 2 -1 0 0]
|
|
171
|
+
[ 0 0 0 -1 2 -1 0]
|
|
172
|
+
[ 0 0 0 0 -1 2 -1]
|
|
173
|
+
[ 0 0 0 0 0 -1 2]
|
|
174
|
+
sage: IntegralLattice(["A", 2])
|
|
175
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
176
|
+
Standard basis
|
|
177
|
+
Inner product matrix:
|
|
178
|
+
[ 2 -1]
|
|
179
|
+
[-1 2]
|
|
180
|
+
sage: IntegralLattice("D3")
|
|
181
|
+
Lattice of degree 3 and rank 3 over Integer Ring
|
|
182
|
+
Standard basis
|
|
183
|
+
Inner product matrix:
|
|
184
|
+
[ 2 -1 -1]
|
|
185
|
+
[-1 2 0]
|
|
186
|
+
[-1 0 2]
|
|
187
|
+
sage: IntegralLattice(["D", 4])
|
|
188
|
+
Lattice of degree 4 and rank 4 over Integer Ring
|
|
189
|
+
Standard basis
|
|
190
|
+
Inner product matrix:
|
|
191
|
+
[ 2 -1 0 0]
|
|
192
|
+
[-1 2 -1 -1]
|
|
193
|
+
[ 0 -1 2 0]
|
|
194
|
+
[ 0 -1 0 2]
|
|
195
|
+
|
|
196
|
+
We can specify a basis as well::
|
|
197
|
+
|
|
198
|
+
sage: G = Matrix(ZZ, 2, [0,1,1,0])
|
|
199
|
+
sage: B = [vector([1,1])]
|
|
200
|
+
sage: IntegralLattice(G, basis=B)
|
|
201
|
+
Lattice of degree 2 and rank 1 over Integer Ring
|
|
202
|
+
Basis matrix:
|
|
203
|
+
[1 1]
|
|
204
|
+
Inner product matrix:
|
|
205
|
+
[0 1]
|
|
206
|
+
[1 0]
|
|
207
|
+
sage: IntegralLattice(["A", 3], [[1,1,1]]) # needs sage.graphs
|
|
208
|
+
Lattice of degree 3 and rank 1 over Integer Ring
|
|
209
|
+
Basis matrix:
|
|
210
|
+
[1 1 1]
|
|
211
|
+
Inner product matrix:
|
|
212
|
+
[ 2 -1 0]
|
|
213
|
+
[-1 2 -1]
|
|
214
|
+
[ 0 -1 2]
|
|
215
|
+
sage: IntegralLattice(4, [[1,1,1,1]])
|
|
216
|
+
Lattice of degree 4 and rank 1 over Integer Ring
|
|
217
|
+
Basis matrix:
|
|
218
|
+
[1 1 1 1]
|
|
219
|
+
Standard scalar product
|
|
220
|
+
sage: IntegralLattice("A2", [[1,1]]) # needs sage.graphs
|
|
221
|
+
Lattice of degree 2 and rank 1 over Integer Ring
|
|
222
|
+
Basis matrix:
|
|
223
|
+
[1 1]
|
|
224
|
+
Inner product matrix:
|
|
225
|
+
[ 2 -1]
|
|
226
|
+
[-1 2]
|
|
227
|
+
|
|
228
|
+
TESTS::
|
|
229
|
+
|
|
230
|
+
sage: IntegralLattice(["A", 1, 1]) # needs sage.graphs
|
|
231
|
+
Traceback (most recent call last):
|
|
232
|
+
...
|
|
233
|
+
ValueError: lattices must be nondegenerate; use FreeQuadraticModule instead
|
|
234
|
+
sage: IntegralLattice(["D", 3, 1]) # needs sage.graphs
|
|
235
|
+
Traceback (most recent call last):
|
|
236
|
+
...
|
|
237
|
+
ValueError: lattices must be nondegenerate; use FreeQuadraticModule instead
|
|
238
|
+
"""
|
|
239
|
+
if isinstance(data, Matrix):
|
|
240
|
+
inner_product_matrix = data
|
|
241
|
+
elif isinstance(data, Integer):
|
|
242
|
+
inner_product_matrix = matrix.identity(ZZ, data)
|
|
243
|
+
elif data == "U" or data == "H":
|
|
244
|
+
inner_product_matrix = matrix([[0, 1], [1, 0]])
|
|
245
|
+
else:
|
|
246
|
+
from sage.combinat.root_system.cartan_matrix import CartanMatrix
|
|
247
|
+
inner_product_matrix = CartanMatrix(data)
|
|
248
|
+
if basis is None:
|
|
249
|
+
basis = matrix.identity(ZZ, inner_product_matrix.ncols())
|
|
250
|
+
if inner_product_matrix != inner_product_matrix.transpose():
|
|
251
|
+
raise ValueError("the inner product matrix must be symmetric\n%s"
|
|
252
|
+
% inner_product_matrix)
|
|
253
|
+
|
|
254
|
+
A = FreeQuadraticModule(ZZ,
|
|
255
|
+
inner_product_matrix.ncols(),
|
|
256
|
+
inner_product_matrix=inner_product_matrix)
|
|
257
|
+
return FreeQuadraticModule_integer_symmetric(ambient=A,
|
|
258
|
+
basis=basis,
|
|
259
|
+
inner_product_matrix=A.inner_product_matrix(),
|
|
260
|
+
already_echelonized=False)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def IntegralLatticeDirectSum(Lattices, return_embeddings=False):
|
|
264
|
+
r"""
|
|
265
|
+
Return the direct sum of the lattices contained in the list ``Lattices``.
|
|
266
|
+
|
|
267
|
+
INPUT:
|
|
268
|
+
|
|
269
|
+
- ``Lattices`` -- list of lattices ``[L_1,...,L_n]``
|
|
270
|
+
- ``return_embeddings`` -- boolean (default: ``False``)
|
|
271
|
+
|
|
272
|
+
OUTPUT:
|
|
273
|
+
|
|
274
|
+
The direct sum of the `L_i` if ``return_embeddings`` is ``False`` or
|
|
275
|
+
the tuple ``[L, phi]`` where `L` is the direct sum of `L_i` and ``phi``
|
|
276
|
+
is the list of embeddings from `L_i` to `L`.
|
|
277
|
+
|
|
278
|
+
EXAMPLES::
|
|
279
|
+
|
|
280
|
+
sage: # needs sage.graphs
|
|
281
|
+
sage: from sage.modules.free_quadratic_module_integer_symmetric import IntegralLatticeDirectSum
|
|
282
|
+
sage: L1 = IntegralLattice("D4")
|
|
283
|
+
sage: L2 = IntegralLattice("A3", [[1, 1, 2]])
|
|
284
|
+
sage: L3 = IntegralLattice("A4", [[0, 1, 1, 2], [1, 2, 3, 1]])
|
|
285
|
+
sage: Lattices = [L1, L2, L3]
|
|
286
|
+
sage: IntegralLatticeDirectSum([L1, L2, L3])
|
|
287
|
+
Lattice of degree 11 and rank 7 over Integer Ring
|
|
288
|
+
Basis matrix:
|
|
289
|
+
[1 0 0 0 0 0 0 0 0 0 0]
|
|
290
|
+
[0 1 0 0 0 0 0 0 0 0 0]
|
|
291
|
+
[0 0 1 0 0 0 0 0 0 0 0]
|
|
292
|
+
[0 0 0 1 0 0 0 0 0 0 0]
|
|
293
|
+
[0 0 0 0 1 1 2 0 0 0 0]
|
|
294
|
+
[0 0 0 0 0 0 0 0 1 1 2]
|
|
295
|
+
[0 0 0 0 0 0 0 1 2 3 1]
|
|
296
|
+
Inner product matrix:
|
|
297
|
+
[ 2 -1 0 0 0 0 0 0 0 0 0]
|
|
298
|
+
[-1 2 -1 -1 0 0 0 0 0 0 0]
|
|
299
|
+
[ 0 -1 2 0 0 0 0 0 0 0 0]
|
|
300
|
+
[ 0 -1 0 2 0 0 0 0 0 0 0]
|
|
301
|
+
[ 0 0 0 0 2 -1 0 0 0 0 0]
|
|
302
|
+
[ 0 0 0 0 -1 2 -1 0 0 0 0]
|
|
303
|
+
[ 0 0 0 0 0 -1 2 0 0 0 0]
|
|
304
|
+
[ 0 0 0 0 0 0 0 2 -1 0 0]
|
|
305
|
+
[ 0 0 0 0 0 0 0 -1 2 -1 0]
|
|
306
|
+
[ 0 0 0 0 0 0 0 0 -1 2 -1]
|
|
307
|
+
[ 0 0 0 0 0 0 0 0 0 -1 2]
|
|
308
|
+
sage: L, phi = IntegralLatticeDirectSum([L1, L2, L3], True)
|
|
309
|
+
sage: LL3 = L.sublattice(phi[2].image().basis_matrix())
|
|
310
|
+
sage: L3.discriminant() == LL3.discriminant()
|
|
311
|
+
True
|
|
312
|
+
sage: x = L3([1, 2, 3, 1])
|
|
313
|
+
sage: phi[2](x).inner_product(phi[2](x)) == x.inner_product(x)
|
|
314
|
+
True
|
|
315
|
+
|
|
316
|
+
TESTS::
|
|
317
|
+
|
|
318
|
+
sage: IntegralLatticeDirectSum([IntegralLattice("D4")]) # needs sage.graphs
|
|
319
|
+
Lattice of degree 4 and rank 4 over Integer Ring
|
|
320
|
+
Standard basis
|
|
321
|
+
Inner product matrix:
|
|
322
|
+
[ 2 -1 0 0]
|
|
323
|
+
[-1 2 -1 -1]
|
|
324
|
+
[ 0 -1 2 0]
|
|
325
|
+
[ 0 -1 0 2]
|
|
326
|
+
|
|
327
|
+
sage: L1 = IntegralLattice(2 * matrix.identity(2), [[1/2, 1/2]])
|
|
328
|
+
sage: L2 = IntegralLattice("A3", [[1, 1, 2]]) # needs sage.graphs
|
|
329
|
+
sage: L, phi = IntegralLatticeDirectSum([L1, L2], True) # needs sage.graphs
|
|
330
|
+
sage: L # needs sage.graphs
|
|
331
|
+
Lattice of degree 5 and rank 2 over Integer Ring
|
|
332
|
+
Basis matrix:
|
|
333
|
+
[1/2 1/2 0 0 0]
|
|
334
|
+
[ 0 0 1 1 2]
|
|
335
|
+
Inner product matrix:
|
|
336
|
+
[ 2 0 0 0 0]
|
|
337
|
+
[ 0 2 0 0 0]
|
|
338
|
+
[ 0 0 2 -1 0]
|
|
339
|
+
[ 0 0 -1 2 -1]
|
|
340
|
+
[ 0 0 0 -1 2]
|
|
341
|
+
"""
|
|
342
|
+
for L in Lattices:
|
|
343
|
+
if not isinstance(L, FreeQuadraticModule_integer_symmetric):
|
|
344
|
+
raise ValueError("Lattices must be a list of lattices")
|
|
345
|
+
N = len(Lattices)
|
|
346
|
+
dims = [L_i.dimension() for L_i in Lattices]
|
|
347
|
+
degrees = [L_i.degree() for L_i in Lattices]
|
|
348
|
+
degree_tot = sum(degrees)
|
|
349
|
+
sum_degree = [sum(degrees[:i]) for i in range(N + 1)]
|
|
350
|
+
inner_product_list = [copy(L_i.inner_product_matrix()) for L_i in Lattices]
|
|
351
|
+
IM = matrix.block_diagonal(inner_product_list)
|
|
352
|
+
ambient = FreeQuadraticModule(ZZ,
|
|
353
|
+
degree_tot,
|
|
354
|
+
inner_product_matrix=IM)
|
|
355
|
+
basis = [matrix.block(1, 3, [matrix.zero(dims[i], sum_degree[i]),
|
|
356
|
+
Lattices[i].basis_matrix(),
|
|
357
|
+
matrix.zero(dims[i], sum_degree[-1] - sum_degree[i+1])
|
|
358
|
+
]) for i in range(N)]
|
|
359
|
+
basis_matrix = matrix.block(N, 1, basis)
|
|
360
|
+
ipm = ambient.inner_product_matrix()
|
|
361
|
+
direct_sum = FreeQuadraticModule_integer_symmetric(ambient=ambient,
|
|
362
|
+
basis=basis_matrix,
|
|
363
|
+
inner_product_matrix=ipm,
|
|
364
|
+
already_echelonized=False)
|
|
365
|
+
if not return_embeddings:
|
|
366
|
+
return direct_sum
|
|
367
|
+
sum_dims = [sum(dims[:i]) for i in range(N+1)]
|
|
368
|
+
phi = [Lattices[i].hom(direct_sum.basis()[sum_dims[i]:sum_dims[i+1]])
|
|
369
|
+
for i in range(N)]
|
|
370
|
+
return [direct_sum, phi]
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def IntegralLatticeGluing(Lattices, glue, return_embeddings=False):
|
|
374
|
+
r"""
|
|
375
|
+
Return an overlattice of the direct sum as defined by ``glue``.
|
|
376
|
+
|
|
377
|
+
INPUT:
|
|
378
|
+
|
|
379
|
+
- ``Lattices`` -- list of lattices `[L_1,...,L_n]`
|
|
380
|
+
- ``glue`` -- list where the elements are lists in the form `[g_1,...,g_n]`;
|
|
381
|
+
here `g_i` is an element of the discriminant group of `L_i`and
|
|
382
|
+
the overlattice is spanned by the additional ``[sum(g) for g in glue]``
|
|
383
|
+
- ``return_embeddings`` -- boolean (default: ``False``)
|
|
384
|
+
|
|
385
|
+
OUTPUT:
|
|
386
|
+
|
|
387
|
+
The glued lattice given by `L_i` and ``glue`` if ``return_embeddings``
|
|
388
|
+
is ``False`` or the tuple ``[L, phi]`` where `L` is the glued lattice and
|
|
389
|
+
``phi`` the list of embeddings from `L_i` to `L`
|
|
390
|
+
|
|
391
|
+
EXAMPLES:
|
|
392
|
+
|
|
393
|
+
A single lattice can be glued. This is the same as taking an overlattice::
|
|
394
|
+
|
|
395
|
+
sage: from sage.modules.free_quadratic_module_integer_symmetric import IntegralLatticeGluing
|
|
396
|
+
|
|
397
|
+
sage: # needs sage.libs.pari
|
|
398
|
+
sage: L1 = IntegralLattice(matrix([[4]]))
|
|
399
|
+
sage: g1 = L1.discriminant_group().gens()[0]
|
|
400
|
+
sage: glue = [[2 * g1]]
|
|
401
|
+
sage: L = IntegralLatticeGluing([L1], glue)
|
|
402
|
+
sage: L
|
|
403
|
+
Lattice of degree 1 and rank 1 over Integer Ring
|
|
404
|
+
Basis matrix:
|
|
405
|
+
[1/2]
|
|
406
|
+
Inner product matrix:
|
|
407
|
+
[4]
|
|
408
|
+
sage: L.gram_matrix()
|
|
409
|
+
[1]
|
|
410
|
+
sage: IntegralLatticeGluing([L1], glue, return_embeddings=True)
|
|
411
|
+
[Lattice of degree 1 and rank 1 over Integer Ring
|
|
412
|
+
Basis matrix:
|
|
413
|
+
[1/2]
|
|
414
|
+
Inner product matrix:
|
|
415
|
+
[4], [Free module morphism defined by the matrix
|
|
416
|
+
[2]
|
|
417
|
+
Domain: Lattice of degree 1 and rank 1 over Integer Ring
|
|
418
|
+
Standard basis
|
|
419
|
+
Inner product matrix:
|
|
420
|
+
[4]
|
|
421
|
+
Codomain: Lattice of degree 1 and rank 1 over Integer Ring
|
|
422
|
+
Basis matrix:
|
|
423
|
+
[1/2]
|
|
424
|
+
Inner product matrix:
|
|
425
|
+
[4]]]
|
|
426
|
+
|
|
427
|
+
sage: # needs sage.graphs
|
|
428
|
+
sage: L1 = IntegralLattice([[2]])
|
|
429
|
+
sage: L2 = IntegralLattice([[2]])
|
|
430
|
+
sage: AL1 = L1.discriminant_group()
|
|
431
|
+
sage: AL2 = L2.discriminant_group()
|
|
432
|
+
sage: AL1
|
|
433
|
+
Finite quadratic module over Integer Ring with invariants (2,)
|
|
434
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
435
|
+
[1/2]
|
|
436
|
+
sage: g1 = L1.discriminant_group().gens()[0]
|
|
437
|
+
sage: g2 = L2.discriminant_group().gens()[0]
|
|
438
|
+
sage: glue = [[g1, g2]]
|
|
439
|
+
sage: IntegralLatticeGluing([L1, L2], glue)
|
|
440
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
441
|
+
Basis matrix:
|
|
442
|
+
[1/2 1/2]
|
|
443
|
+
[ 0 1]
|
|
444
|
+
Inner product matrix:
|
|
445
|
+
[2 0]
|
|
446
|
+
[0 2]
|
|
447
|
+
|
|
448
|
+
sage: # needs sage.graphs
|
|
449
|
+
sage: L1 = IntegralLattice("A4")
|
|
450
|
+
sage: L2 = IntegralLattice("A4")
|
|
451
|
+
sage: g1 = L1.discriminant_group().gens()[0]
|
|
452
|
+
sage: g2 = L2.discriminant_group().gens()[0]
|
|
453
|
+
sage: glue = [[g1, 2 * g2]]
|
|
454
|
+
sage: V, phi = IntegralLatticeGluing([L1, L2], glue, True)
|
|
455
|
+
sage: V
|
|
456
|
+
Lattice of degree 8 and rank 8 over Integer Ring
|
|
457
|
+
Basis matrix:
|
|
458
|
+
[1/5 2/5 3/5 4/5 2/5 4/5 1/5 3/5]
|
|
459
|
+
[ 0 1 0 0 0 0 0 0]
|
|
460
|
+
[ 0 0 1 0 0 0 0 0]
|
|
461
|
+
[ 0 0 0 1 0 0 0 0]
|
|
462
|
+
[ 0 0 0 0 1 0 0 0]
|
|
463
|
+
[ 0 0 0 0 0 1 0 0]
|
|
464
|
+
[ 0 0 0 0 0 0 1 0]
|
|
465
|
+
[ 0 0 0 0 0 0 0 1]
|
|
466
|
+
Inner product matrix:
|
|
467
|
+
[ 2 -1 0 0 0 0 0 0]
|
|
468
|
+
[-1 2 -1 0 0 0 0 0]
|
|
469
|
+
[ 0 -1 2 -1 0 0 0 0]
|
|
470
|
+
[ 0 0 -1 2 0 0 0 0]
|
|
471
|
+
[ 0 0 0 0 2 -1 0 0]
|
|
472
|
+
[ 0 0 0 0 -1 2 -1 0]
|
|
473
|
+
[ 0 0 0 0 0 -1 2 -1]
|
|
474
|
+
[ 0 0 0 0 0 0 -1 2]
|
|
475
|
+
sage: V.sublattice(phi[0].image().basis_matrix())
|
|
476
|
+
Lattice of degree 8 and rank 4 over Integer Ring
|
|
477
|
+
Basis matrix:
|
|
478
|
+
[1 0 0 0 0 0 0 0]
|
|
479
|
+
[0 1 0 0 0 0 0 0]
|
|
480
|
+
[0 0 1 0 0 0 0 0]
|
|
481
|
+
[0 0 0 1 0 0 0 0]
|
|
482
|
+
Inner product matrix:
|
|
483
|
+
[ 2 -1 0 0 0 0 0 0]
|
|
484
|
+
[-1 2 -1 0 0 0 0 0]
|
|
485
|
+
[ 0 -1 2 -1 0 0 0 0]
|
|
486
|
+
[ 0 0 -1 2 0 0 0 0]
|
|
487
|
+
[ 0 0 0 0 2 -1 0 0]
|
|
488
|
+
[ 0 0 0 0 -1 2 -1 0]
|
|
489
|
+
[ 0 0 0 0 0 -1 2 -1]
|
|
490
|
+
[ 0 0 0 0 0 0 -1 2]
|
|
491
|
+
|
|
492
|
+
Different gluings can be composed::
|
|
493
|
+
|
|
494
|
+
sage: # needs sage.graphs
|
|
495
|
+
sage: D4 = IntegralLattice("D4")
|
|
496
|
+
sage: D4.discriminant_group()
|
|
497
|
+
Finite quadratic module over Integer Ring with invariants (2, 2)
|
|
498
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
499
|
+
[ 1 1/2]
|
|
500
|
+
[1/2 1]
|
|
501
|
+
sage: L2 = IntegralLattice(2 * matrix.identity(2))
|
|
502
|
+
sage: L2.discriminant_group()
|
|
503
|
+
Finite quadratic module over Integer Ring with invariants (2, 2)
|
|
504
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
505
|
+
[1/2 0]
|
|
506
|
+
[ 0 1/2]
|
|
507
|
+
sage: g1 = D4.discriminant_group().gens()[0]
|
|
508
|
+
sage: g2 = L2.discriminant_group().gens()[0] + L2.discriminant_group().gens()[1]
|
|
509
|
+
sage: D6, phi = IntegralLatticeGluing([D4, L2], [[g1, g2]], True)
|
|
510
|
+
sage: AD6 = D6.discriminant_group()
|
|
511
|
+
sage: AD6.normal_form()
|
|
512
|
+
Finite quadratic module over Integer Ring with invariants (2, 2)
|
|
513
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
514
|
+
[3/2 0]
|
|
515
|
+
[ 0 3/2]
|
|
516
|
+
sage: f1, g1 = AD6.normal_form().gens()
|
|
517
|
+
sage: f2, g2 = L2.discriminant_group().gens()
|
|
518
|
+
sage: E8, psi = IntegralLatticeGluing([D6, L2], [[f1, f2], [g1, g2]], True)
|
|
519
|
+
sage: D4embed = E8.sublattice(psi[0](phi[0].image()).basis_matrix())
|
|
520
|
+
sage: x = D4([1, 0, 0, 0])
|
|
521
|
+
sage: psi[0](phi[0](x)).inner_product(psi[0](phi[0](x))) == x.inner_product(x)
|
|
522
|
+
True
|
|
523
|
+
sage: D4embed
|
|
524
|
+
Lattice of degree 8 and rank 4 over Integer Ring
|
|
525
|
+
Basis matrix:
|
|
526
|
+
[1 0 0 0 0 0 0 0]
|
|
527
|
+
[0 1 0 0 0 0 0 0]
|
|
528
|
+
[0 0 1 0 0 0 0 0]
|
|
529
|
+
[0 0 0 1 0 0 0 0]
|
|
530
|
+
Inner product matrix:
|
|
531
|
+
[ 2 -1 0 0 0 0 0 0]
|
|
532
|
+
[-1 2 -1 -1 0 0 0 0]
|
|
533
|
+
[ 0 -1 2 0 0 0 0 0]
|
|
534
|
+
[ 0 -1 0 2 0 0 0 0]
|
|
535
|
+
[ 0 0 0 0 2 0 0 0]
|
|
536
|
+
[ 0 0 0 0 0 2 0 0]
|
|
537
|
+
[ 0 0 0 0 0 0 2 0]
|
|
538
|
+
[ 0 0 0 0 0 0 0 2]
|
|
539
|
+
|
|
540
|
+
The input may be a list of three or more lattices::
|
|
541
|
+
|
|
542
|
+
sage: # needs sage.graphs
|
|
543
|
+
sage: A7 = IntegralLattice("A7")
|
|
544
|
+
sage: D5 = IntegralLattice("D5")
|
|
545
|
+
sage: gA7 = A7.discriminant_group().gens()[0]
|
|
546
|
+
sage: gD5 = D5.discriminant_group().gens()[0]
|
|
547
|
+
sage: L, phi = IntegralLatticeGluing([A7, A7, D5, D5],
|
|
548
|
+
....: [[gA7, gA7, gD5, 2 * gD5],
|
|
549
|
+
....: [gA7, 7 * gA7, 2 * gD5, gD5]], True)
|
|
550
|
+
sage: L.determinant()
|
|
551
|
+
1
|
|
552
|
+
sage: B = phi[0].matrix()
|
|
553
|
+
sage: B*L.gram_matrix()*B.transpose() == A7.gram_matrix()
|
|
554
|
+
True
|
|
555
|
+
|
|
556
|
+
The gluing takes place in the direct sum of the respective ambient spaces::
|
|
557
|
+
|
|
558
|
+
sage: # needs sage.graphs
|
|
559
|
+
sage: L1 = IntegralLattice("D4", [[1, 1, 0, 0], [0, 1, 1, 0]])
|
|
560
|
+
sage: L2 = IntegralLattice("E6", [[0, 2, 0, 0, 0, 0], [0, 0, 0, 0, 1, 1]])
|
|
561
|
+
sage: f1, f2 = L1.discriminant_group().gens()
|
|
562
|
+
sage: g1, g2 = L2.discriminant_group().gens()
|
|
563
|
+
sage: L, phi = IntegralLatticeGluing([L1, L2],
|
|
564
|
+
....: [[f1, g1], [f2, 2 * g2]], True)
|
|
565
|
+
sage: phi[0]
|
|
566
|
+
Free module morphism defined by the matrix
|
|
567
|
+
[ 2 2 -2 -1]
|
|
568
|
+
[ 0 2 -1 0]
|
|
569
|
+
Domain: Lattice of degree 4 and rank 2 over Integer Ring
|
|
570
|
+
Basis matrix:
|
|
571
|
+
[1 1 0 0]
|
|
572
|
+
[0 1 1 0]
|
|
573
|
+
Inner product matrix:
|
|
574
|
+
[ 2 -1 0 0]
|
|
575
|
+
[-1 2 -1 -1]
|
|
576
|
+
[ 0 -1 2 0]
|
|
577
|
+
[ 0 -1 0 2]
|
|
578
|
+
Codomain: Lattice of degree 10 and rank 4 over Integer Ring
|
|
579
|
+
Basis matrix:
|
|
580
|
+
[ 1/2 0 -1/2 0 0 1/2 0 0 1/2 1/2]
|
|
581
|
+
[ 0 1/2 1/2 0 0 1/2 0 0 0 0]
|
|
582
|
+
[ 0 0 0 0 0 1 0 0 0 0]
|
|
583
|
+
[ 0 0 0 0 0 0 0 0 1 1]
|
|
584
|
+
Inner product matrix:
|
|
585
|
+
[ 2 -1 0 0 0 0 0 0 0 0]
|
|
586
|
+
[-1 2 -1 -1 0 0 0 0 0 0]
|
|
587
|
+
[ 0 -1 2 0 0 0 0 0 0 0]
|
|
588
|
+
[ 0 -1 0 2 0 0 0 0 0 0]
|
|
589
|
+
[ 0 0 0 0 2 0 -1 0 0 0]
|
|
590
|
+
[ 0 0 0 0 0 2 0 -1 0 0]
|
|
591
|
+
[ 0 0 0 0 -1 0 2 -1 0 0]
|
|
592
|
+
[ 0 0 0 0 0 -1 -1 2 -1 0]
|
|
593
|
+
[ 0 0 0 0 0 0 0 -1 2 -1]
|
|
594
|
+
[ 0 0 0 0 0 0 0 0 -1 2]
|
|
595
|
+
sage: B = phi[0].matrix()
|
|
596
|
+
sage: B * L.gram_matrix() * B.transpose() == L1.gram_matrix()
|
|
597
|
+
True
|
|
598
|
+
"""
|
|
599
|
+
direct_sum, phi = IntegralLatticeDirectSum(Lattices, return_embeddings=True)
|
|
600
|
+
N = len(Lattices)
|
|
601
|
+
for g in glue:
|
|
602
|
+
if not len(g) == N:
|
|
603
|
+
raise ValueError("the lengths of the lists do not match")
|
|
604
|
+
for i in range(N):
|
|
605
|
+
ALi = Lattices[i].discriminant_group()
|
|
606
|
+
for g in glue:
|
|
607
|
+
# Check that the gluing vectors are in the
|
|
608
|
+
# corresponding discriminant groups
|
|
609
|
+
ALi(g[i])
|
|
610
|
+
generators = [sum(phi[i](g[i].lift()*g[i].order())/g[i].order()
|
|
611
|
+
for i in range(N))
|
|
612
|
+
for g in glue]
|
|
613
|
+
glued_lattice = direct_sum.overlattice(generators)
|
|
614
|
+
if not return_embeddings:
|
|
615
|
+
return glued_lattice
|
|
616
|
+
HomSpaces = [Lattices[i].Hom(glued_lattice) for i in range(N)]
|
|
617
|
+
G = glued_lattice.basis_matrix().solve_left(direct_sum.basis_matrix())
|
|
618
|
+
f = [HomSpaces[i](phi[i].matrix() * G) for i in range(N)]
|
|
619
|
+
return [glued_lattice, f]
|
|
620
|
+
|
|
621
|
+
###############################################################################
|
|
622
|
+
#
|
|
623
|
+
# Base class for Lattices
|
|
624
|
+
#
|
|
625
|
+
###############################################################################
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
class FreeQuadraticModule_integer_symmetric(FreeQuadraticModule_submodule_with_basis_pid):
|
|
629
|
+
r"""
|
|
630
|
+
This class represents non-degenerate, integral,
|
|
631
|
+
symmetric free quadratic `\ZZ`-modules.
|
|
632
|
+
|
|
633
|
+
INPUT:
|
|
634
|
+
|
|
635
|
+
- ``ambient`` -- an ambient free quadratic module
|
|
636
|
+
- ``basis`` -- list of elements of ambient or a matrix
|
|
637
|
+
- ``inner_product_matrix`` -- a symmetric matrix over the rationals
|
|
638
|
+
|
|
639
|
+
EXAMPLES::
|
|
640
|
+
|
|
641
|
+
sage: IntegralLattice("U", basis=[vector([1,1])])
|
|
642
|
+
Lattice of degree 2 and rank 1 over Integer Ring
|
|
643
|
+
Basis matrix:
|
|
644
|
+
[1 1]
|
|
645
|
+
Inner product matrix:
|
|
646
|
+
[0 1]
|
|
647
|
+
[1 0]
|
|
648
|
+
"""
|
|
649
|
+
def __init__(self, ambient, basis, inner_product_matrix,
|
|
650
|
+
check=True, already_echelonized=False):
|
|
651
|
+
r"""
|
|
652
|
+
Create the integral lattice spanned by ``basis`` in the ambient space.
|
|
653
|
+
|
|
654
|
+
TESTS::
|
|
655
|
+
|
|
656
|
+
sage: L = IntegralLattice("U")
|
|
657
|
+
sage: TestSuite(L).run()
|
|
658
|
+
"""
|
|
659
|
+
FreeQuadraticModule_submodule_with_basis_pid.__init__(
|
|
660
|
+
self,
|
|
661
|
+
ambient,
|
|
662
|
+
basis,
|
|
663
|
+
inner_product_matrix,
|
|
664
|
+
check=check,
|
|
665
|
+
already_echelonized=already_echelonized)
|
|
666
|
+
if self.determinant() == 0:
|
|
667
|
+
raise ValueError("lattices must be nondegenerate; "
|
|
668
|
+
"use FreeQuadraticModule instead")
|
|
669
|
+
if self.gram_matrix().base_ring() is not ZZ:
|
|
670
|
+
if self.gram_matrix().denominator() != 1:
|
|
671
|
+
raise ValueError("lattices must be integral; "
|
|
672
|
+
"use FreeQuadraticModule instead")
|
|
673
|
+
|
|
674
|
+
def _mul_(self, other, switch_sides=False):
|
|
675
|
+
r"""
|
|
676
|
+
Multiplication of the basis by ``other``.
|
|
677
|
+
|
|
678
|
+
EXAMPLES::
|
|
679
|
+
|
|
680
|
+
sage: M = Matrix(ZZ,2,[1,2,2,-1])
|
|
681
|
+
sage: L = IntegralLattice(M)
|
|
682
|
+
sage: 2 * L
|
|
683
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
684
|
+
Basis matrix:
|
|
685
|
+
[2 0]
|
|
686
|
+
[0 2]
|
|
687
|
+
Inner product matrix:
|
|
688
|
+
[ 1 2]
|
|
689
|
+
[ 2 -1]
|
|
690
|
+
sage: L * matrix(ZZ,2,[1,2,3,4])
|
|
691
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
692
|
+
Basis matrix:
|
|
693
|
+
[1 2]
|
|
694
|
+
[3 4]
|
|
695
|
+
Inner product matrix:
|
|
696
|
+
[ 1 2]
|
|
697
|
+
[ 2 -1]
|
|
698
|
+
"""
|
|
699
|
+
B = self.basis_matrix()
|
|
700
|
+
B = other * B if switch_sides else B * other
|
|
701
|
+
# check whether it is integral
|
|
702
|
+
if other in ZZ or other.denominator() == 1:
|
|
703
|
+
return self.sublattice(B.rows())
|
|
704
|
+
else:
|
|
705
|
+
return self.span(B.rows())
|
|
706
|
+
|
|
707
|
+
def _repr_(self):
|
|
708
|
+
r"""
|
|
709
|
+
The print representation of this lattice.
|
|
710
|
+
|
|
711
|
+
EXAMPLES::
|
|
712
|
+
|
|
713
|
+
sage: A2 = IntegralLattice("A2") # needs sage.graphs
|
|
714
|
+
sage: A2 # needs sage.graphs
|
|
715
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
716
|
+
Standard basis
|
|
717
|
+
Inner product matrix:
|
|
718
|
+
[ 2 -1]
|
|
719
|
+
[-1 2]
|
|
720
|
+
"""
|
|
721
|
+
s = ""
|
|
722
|
+
if self.is_sparse():
|
|
723
|
+
s += "Sparse lattice "
|
|
724
|
+
else:
|
|
725
|
+
s += "Lattice "
|
|
726
|
+
s += "of degree %s and rank %s over %s\n" % (
|
|
727
|
+
self.degree(), self.rank(), self.base_ring())
|
|
728
|
+
if self.basis_matrix().is_one():
|
|
729
|
+
s += "Standard basis \n"
|
|
730
|
+
else:
|
|
731
|
+
s += "Basis matrix:\n%s\n" % self.basis_matrix()
|
|
732
|
+
if self.inner_product_matrix().is_one():
|
|
733
|
+
s += "Standard scalar product"
|
|
734
|
+
else:
|
|
735
|
+
s += "Inner product matrix:\n%s" % self.inner_product_matrix()
|
|
736
|
+
return s
|
|
737
|
+
|
|
738
|
+
@cached_method
|
|
739
|
+
def is_even(self) -> bool:
|
|
740
|
+
r"""
|
|
741
|
+
Return whether the diagonal entries of the Gram matrix are even.
|
|
742
|
+
|
|
743
|
+
EXAMPLES::
|
|
744
|
+
|
|
745
|
+
sage: G = Matrix(ZZ, 2, 2, [-1,1,1,2])
|
|
746
|
+
sage: L = IntegralLattice(G)
|
|
747
|
+
sage: L.is_even()
|
|
748
|
+
False
|
|
749
|
+
sage: L = IntegralLattice("A2") # needs sage.graphs
|
|
750
|
+
sage: L.is_even() # needs sage.graphs
|
|
751
|
+
True
|
|
752
|
+
"""
|
|
753
|
+
return all(d % 2 == 0 for d in self.gram_matrix().diagonal())
|
|
754
|
+
|
|
755
|
+
@cached_method
|
|
756
|
+
def dual_lattice(self):
|
|
757
|
+
r"""
|
|
758
|
+
Return the dual lattice as a :class:`FreeQuadraticModule`.
|
|
759
|
+
|
|
760
|
+
Let `L` be a lattice. Its dual lattice is
|
|
761
|
+
|
|
762
|
+
.. MATH::
|
|
763
|
+
|
|
764
|
+
L^\vee = \{x \in L \otimes \QQ : (x, l) \in \ZZ \; \forall l \in L \}.
|
|
765
|
+
|
|
766
|
+
EXAMPLES::
|
|
767
|
+
|
|
768
|
+
sage: L = IntegralLattice("A2") # needs sage.graphs
|
|
769
|
+
sage: Ldual = L.dual_lattice(); Ldual # needs sage.graphs
|
|
770
|
+
Free module of degree 2 and rank 2 over Integer Ring
|
|
771
|
+
Echelon basis matrix:
|
|
772
|
+
[1/3 2/3]
|
|
773
|
+
[ 0 1]
|
|
774
|
+
|
|
775
|
+
Since our lattices are always integral, a lattice is contained in its dual::
|
|
776
|
+
|
|
777
|
+
sage: L.is_submodule(Ldual) # needs sage.graphs
|
|
778
|
+
True
|
|
779
|
+
"""
|
|
780
|
+
return self.span(self.gram_matrix().inverse()*self.basis_matrix())
|
|
781
|
+
|
|
782
|
+
def discriminant_group(self, s=0):
|
|
783
|
+
r"""
|
|
784
|
+
Return the discriminant group `L^\vee / L` of this lattice.
|
|
785
|
+
|
|
786
|
+
INPUT:
|
|
787
|
+
|
|
788
|
+
- ``s`` -- integer (default: 0)
|
|
789
|
+
|
|
790
|
+
OUTPUT:
|
|
791
|
+
|
|
792
|
+
The `s` primary part of the discriminant group.
|
|
793
|
+
If `s=0`, returns the whole discriminant group.
|
|
794
|
+
|
|
795
|
+
EXAMPLES::
|
|
796
|
+
|
|
797
|
+
sage: # needs sage.libs.pari
|
|
798
|
+
sage: L = IntegralLattice(Matrix(ZZ, 2, 2, [2,1,1,-2]) * 2)
|
|
799
|
+
sage: L.discriminant_group()
|
|
800
|
+
Finite quadratic module over Integer Ring with invariants (2, 10)
|
|
801
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
802
|
+
[ 1 1/2]
|
|
803
|
+
[1/2 1/5]
|
|
804
|
+
sage: L.discriminant_group(2)
|
|
805
|
+
Finite quadratic module over Integer Ring with invariants (2, 2)
|
|
806
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
807
|
+
[ 1 1/2]
|
|
808
|
+
[1/2 1]
|
|
809
|
+
sage: L.discriminant_group(5)
|
|
810
|
+
Finite quadratic module over Integer Ring with invariants (5,)
|
|
811
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
812
|
+
[4/5]
|
|
813
|
+
|
|
814
|
+
TESTS::
|
|
815
|
+
|
|
816
|
+
sage: # needs sage.libs.pari
|
|
817
|
+
sage: L = IntegralLattice("H")
|
|
818
|
+
sage: L.discriminant_group()
|
|
819
|
+
Finite quadratic module over Integer Ring with invariants ()
|
|
820
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
821
|
+
[]
|
|
822
|
+
|
|
823
|
+
Test that the memory leak in :issue:`31625` is fixed::
|
|
824
|
+
|
|
825
|
+
sage: # needs sage.libs.pari
|
|
826
|
+
sage: import gc
|
|
827
|
+
sage: gc.freeze()
|
|
828
|
+
sage: L = IntegralLattice("A2") # needs sage.graphs
|
|
829
|
+
sage: for k in range(1,500): # long time
|
|
830
|
+
....: G = L.twist(k)
|
|
831
|
+
....: D = G.discriminant_group()
|
|
832
|
+
sage: tmp = gc.collect()
|
|
833
|
+
sage: tmp = gc.collect()
|
|
834
|
+
sage: len([a for a in gc.get_objects() if type(a) == type(L)]) <= 300
|
|
835
|
+
True
|
|
836
|
+
sage: gc.unfreeze()
|
|
837
|
+
"""
|
|
838
|
+
from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
839
|
+
D = TorsionQuadraticModule(self.dual_lattice(), self)
|
|
840
|
+
d = D.annihilator().gen()
|
|
841
|
+
a = d.prime_to_m_part(s)
|
|
842
|
+
Dp_gens = [a*g for g in D.gens()]
|
|
843
|
+
return D.submodule(Dp_gens)
|
|
844
|
+
|
|
845
|
+
def signature(self):
|
|
846
|
+
r"""
|
|
847
|
+
Return the signature of this lattice, which is defined as
|
|
848
|
+
the difference between the number of positive eigenvalues and
|
|
849
|
+
the number of negative eigenvalues in the Gram matrix.
|
|
850
|
+
|
|
851
|
+
EXAMPLES::
|
|
852
|
+
|
|
853
|
+
sage: U = IntegralLattice("U")
|
|
854
|
+
sage: U.signature()
|
|
855
|
+
0
|
|
856
|
+
"""
|
|
857
|
+
sig = self.signature_pair()
|
|
858
|
+
return sig[0] - sig[1]
|
|
859
|
+
|
|
860
|
+
@cached_method
|
|
861
|
+
def signature_pair(self):
|
|
862
|
+
r"""
|
|
863
|
+
Return the signature tuple `(n_+,n_-)` of this lattice.
|
|
864
|
+
|
|
865
|
+
Here `n_+` (resp. `n_-`) is the number of positive (resp. negative)
|
|
866
|
+
eigenvalues of the Gram matrix.
|
|
867
|
+
|
|
868
|
+
EXAMPLES::
|
|
869
|
+
|
|
870
|
+
sage: A2 = IntegralLattice("A2") # needs sage.graphs
|
|
871
|
+
sage: A2.signature_pair() # needs sage.graphs
|
|
872
|
+
(2, 0)
|
|
873
|
+
"""
|
|
874
|
+
from sage.quadratic_forms.quadratic_form import QuadraticForm
|
|
875
|
+
return QuadraticForm(QQ, self.gram_matrix()).signature_vector()[:2]
|
|
876
|
+
|
|
877
|
+
def direct_sum(self, M):
|
|
878
|
+
r"""
|
|
879
|
+
Return the direct sum of this lattice with ``M``.
|
|
880
|
+
|
|
881
|
+
INPUT:
|
|
882
|
+
|
|
883
|
+
- ``M`` -- a module over `\ZZ`
|
|
884
|
+
|
|
885
|
+
EXAMPLES::
|
|
886
|
+
|
|
887
|
+
sage: A = IntegralLattice(1)
|
|
888
|
+
sage: A.direct_sum(A)
|
|
889
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
890
|
+
Standard basis
|
|
891
|
+
Standard scalar product
|
|
892
|
+
"""
|
|
893
|
+
IM = matrix.block_diagonal([self.inner_product_matrix(),
|
|
894
|
+
M.inner_product_matrix()])
|
|
895
|
+
ambient = FreeQuadraticModule(ZZ,
|
|
896
|
+
self.degree() + M.degree(), IM)
|
|
897
|
+
smzero = matrix.zero(self.rank(), M.degree())
|
|
898
|
+
mszero = matrix.zero(M.rank(), self.degree())
|
|
899
|
+
basis = self.basis_matrix().augment(smzero).stack(
|
|
900
|
+
mszero.augment(M.basis_matrix()))
|
|
901
|
+
ipm = ambient.inner_product_matrix()
|
|
902
|
+
return FreeQuadraticModule_integer_symmetric(ambient=ambient,
|
|
903
|
+
basis=basis,
|
|
904
|
+
inner_product_matrix=ipm,
|
|
905
|
+
already_echelonized=False)
|
|
906
|
+
|
|
907
|
+
def is_primitive(self, M) -> bool:
|
|
908
|
+
r"""
|
|
909
|
+
Return whether ``M`` is a primitive submodule of this lattice.
|
|
910
|
+
|
|
911
|
+
A `\ZZ`-submodule ``M`` of a `\ZZ`-module ``L`` is called primitive if
|
|
912
|
+
the quotient ``L/M`` is torsion free.
|
|
913
|
+
|
|
914
|
+
INPUT:
|
|
915
|
+
|
|
916
|
+
- ``M`` -- a submodule of this lattice
|
|
917
|
+
|
|
918
|
+
EXAMPLES::
|
|
919
|
+
|
|
920
|
+
sage: # needs sage.libs.pari
|
|
921
|
+
sage: U = IntegralLattice("U")
|
|
922
|
+
sage: L1 = U.span([vector([1,1])])
|
|
923
|
+
sage: L2 = U.span([vector([1,-1])])
|
|
924
|
+
sage: U.is_primitive(L1)
|
|
925
|
+
True
|
|
926
|
+
sage: U.is_primitive(L2)
|
|
927
|
+
True
|
|
928
|
+
sage: U.is_primitive(L1 + L2)
|
|
929
|
+
False
|
|
930
|
+
|
|
931
|
+
We can also compute the index::
|
|
932
|
+
|
|
933
|
+
sage: (L1 + L2).index_in(U) # needs sage.libs.pari
|
|
934
|
+
2
|
|
935
|
+
"""
|
|
936
|
+
return gcd((self/M).invariants()) == 0
|
|
937
|
+
|
|
938
|
+
def orthogonal_complement(self, M):
|
|
939
|
+
r"""
|
|
940
|
+
Return the orthogonal complement of ``M`` in this lattice.
|
|
941
|
+
|
|
942
|
+
INPUT:
|
|
943
|
+
|
|
944
|
+
- ``M`` -- a module in the same ambient space or
|
|
945
|
+
a list of elements of the ambient space
|
|
946
|
+
|
|
947
|
+
EXAMPLES::
|
|
948
|
+
|
|
949
|
+
sage: H5 = Matrix(ZZ, 2, [2,1,1,-2])
|
|
950
|
+
sage: L = IntegralLattice(H5)
|
|
951
|
+
sage: S = L.span([vector([1,1])])
|
|
952
|
+
sage: L.orthogonal_complement(S)
|
|
953
|
+
Lattice of degree 2 and rank 1 over Integer Ring
|
|
954
|
+
Basis matrix:
|
|
955
|
+
[1 3]
|
|
956
|
+
Inner product matrix:
|
|
957
|
+
[ 2 1]
|
|
958
|
+
[ 1 -2]
|
|
959
|
+
|
|
960
|
+
sage: L = IntegralLattice(2)
|
|
961
|
+
sage: L.orthogonal_complement([vector(ZZ, [1,0])])
|
|
962
|
+
Lattice of degree 2 and rank 1 over Integer Ring
|
|
963
|
+
Basis matrix:
|
|
964
|
+
[0 1]
|
|
965
|
+
Standard scalar product
|
|
966
|
+
"""
|
|
967
|
+
from sage.modules.free_module import FreeModule_generic
|
|
968
|
+
if not isinstance(M, FreeModule_generic):
|
|
969
|
+
M = self.span(M)
|
|
970
|
+
elif M.ambient_vector_space() != self.ambient_vector_space():
|
|
971
|
+
raise ValueError("M must have the same "
|
|
972
|
+
"ambient vector space as this lattice")
|
|
973
|
+
|
|
974
|
+
K = (self.inner_product_matrix() * M.basis_matrix().transpose()).kernel()
|
|
975
|
+
K = self.span(K.basis())
|
|
976
|
+
K = K.base_extend(QQ)
|
|
977
|
+
return self.sublattice(self.intersection(K).basis())
|
|
978
|
+
|
|
979
|
+
def sublattice(self, basis):
|
|
980
|
+
r"""
|
|
981
|
+
Return the sublattice spanned by ``basis``.
|
|
982
|
+
|
|
983
|
+
INPUT:
|
|
984
|
+
|
|
985
|
+
- ``basis`` -- list of elements of this lattice
|
|
986
|
+
|
|
987
|
+
EXAMPLES::
|
|
988
|
+
|
|
989
|
+
sage: U = IntegralLattice("U")
|
|
990
|
+
sage: S = U.sublattice([vector([1,1])]); S
|
|
991
|
+
Lattice of degree 2 and rank 1 over Integer Ring
|
|
992
|
+
Basis matrix:
|
|
993
|
+
[1 1]
|
|
994
|
+
Inner product matrix:
|
|
995
|
+
[0 1]
|
|
996
|
+
[1 0]
|
|
997
|
+
sage: U.sublattice([vector([1,-1])/2])
|
|
998
|
+
Traceback (most recent call last):
|
|
999
|
+
...
|
|
1000
|
+
ValueError: lattices must be integral; use FreeQuadraticModule instead
|
|
1001
|
+
sage: S.sublattice([vector([1,-1])])
|
|
1002
|
+
Traceback (most recent call last):
|
|
1003
|
+
...
|
|
1004
|
+
ValueError: the basis (= [(1, -1)]) does not span a submodule
|
|
1005
|
+
"""
|
|
1006
|
+
M = FreeQuadraticModule_integer_symmetric(
|
|
1007
|
+
ambient=self.ambient_module(), basis=basis,
|
|
1008
|
+
inner_product_matrix=self.inner_product_matrix(),
|
|
1009
|
+
already_echelonized=False)
|
|
1010
|
+
if not M.is_submodule(self):
|
|
1011
|
+
raise ValueError("the basis (= %s) does not span "
|
|
1012
|
+
"a submodule" % basis)
|
|
1013
|
+
return M
|
|
1014
|
+
|
|
1015
|
+
def overlattice(self, gens):
|
|
1016
|
+
r"""
|
|
1017
|
+
Return the lattice spanned by this lattice and ``gens``.
|
|
1018
|
+
|
|
1019
|
+
INPUT:
|
|
1020
|
+
|
|
1021
|
+
- ``gens`` -- list of elements or a rational matrix
|
|
1022
|
+
|
|
1023
|
+
EXAMPLES::
|
|
1024
|
+
|
|
1025
|
+
sage: L = IntegralLattice(Matrix(ZZ, 2, 2, [2,0,0,2]))
|
|
1026
|
+
sage: M = L.overlattice([vector([1,1])/2])
|
|
1027
|
+
sage: M.gram_matrix()
|
|
1028
|
+
[1 1]
|
|
1029
|
+
[1 2]
|
|
1030
|
+
"""
|
|
1031
|
+
basis = (self + self.span(gens)).basis()
|
|
1032
|
+
return FreeQuadraticModule_integer_symmetric(
|
|
1033
|
+
ambient=self.ambient_module(), basis=basis,
|
|
1034
|
+
inner_product_matrix=self.inner_product_matrix(),
|
|
1035
|
+
already_echelonized=False)
|
|
1036
|
+
|
|
1037
|
+
def maximal_overlattice(self, p=None):
|
|
1038
|
+
r"""
|
|
1039
|
+
Return a maximal even integral overlattice of this lattice.
|
|
1040
|
+
|
|
1041
|
+
INPUT:
|
|
1042
|
+
|
|
1043
|
+
- ``p`` -- (default: ``None``) if given return an overlattice
|
|
1044
|
+
`M` of this lattice `L` that is maximal at `p` and the
|
|
1045
|
+
completions `M_q = L_q` are equal for all primes `q \neq p`
|
|
1046
|
+
|
|
1047
|
+
If `p` is `2` or ``None``, then the lattice must be even.
|
|
1048
|
+
|
|
1049
|
+
EXAMPLES::
|
|
1050
|
+
|
|
1051
|
+
sage: # needs sage.graphs sage.libs.pari
|
|
1052
|
+
sage: L = IntegralLattice("A4").twist(25*89)
|
|
1053
|
+
sage: L.maximal_overlattice().determinant()
|
|
1054
|
+
5
|
|
1055
|
+
sage: L.maximal_overlattice(89).determinant().factor()
|
|
1056
|
+
5^9
|
|
1057
|
+
sage: L.maximal_overlattice(5).determinant().factor()
|
|
1058
|
+
5 * 89^4
|
|
1059
|
+
|
|
1060
|
+
TESTS::
|
|
1061
|
+
|
|
1062
|
+
sage: # needs sage.libs.flint (otherwise timeout) sage.libs.pari
|
|
1063
|
+
sage: L = IntegralLattice(matrix.diagonal([2,4,4,8]))
|
|
1064
|
+
sage: L.maximal_overlattice().is_even()
|
|
1065
|
+
True
|
|
1066
|
+
"""
|
|
1067
|
+
# this code is somewhat slow but it works
|
|
1068
|
+
# it might speed up things to use the algorithms given in
|
|
1069
|
+
# https://arxiv.org/abs/1208.2481
|
|
1070
|
+
# and trac:11940
|
|
1071
|
+
if not self.is_even() and (p is None or p == 2):
|
|
1072
|
+
raise ValueError("this lattice must be even to admit an even overlattice")
|
|
1073
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
1074
|
+
L = self
|
|
1075
|
+
if p is None:
|
|
1076
|
+
P = ZZ(self.determinant()).prime_factors()
|
|
1077
|
+
else:
|
|
1078
|
+
P = ZZ(p).prime_factors()
|
|
1079
|
+
# even case
|
|
1080
|
+
if 2 in P:
|
|
1081
|
+
# create an isotropic subspace by rescaling
|
|
1082
|
+
# the generators
|
|
1083
|
+
D = L.discriminant_group(2)
|
|
1084
|
+
isotropic = []
|
|
1085
|
+
for b in D.gens():
|
|
1086
|
+
e = b.additive_order()
|
|
1087
|
+
v = e.valuation(2)
|
|
1088
|
+
q = b.q().lift()
|
|
1089
|
+
delta = (q*e) % 2
|
|
1090
|
+
b = 2**(((e.valuation(2)+1)//2) + delta) * b.lift()
|
|
1091
|
+
isotropic.append(b)
|
|
1092
|
+
L = L.overlattice(isotropic)
|
|
1093
|
+
D = L.discriminant_group()
|
|
1094
|
+
# now L is of exponent at most 4.
|
|
1095
|
+
if D.cardinality() > 512:
|
|
1096
|
+
D = D.normal_form(partial=True)
|
|
1097
|
+
isotropic = []
|
|
1098
|
+
# extract an isotropic space spanned by
|
|
1099
|
+
# a subset of the generators of D
|
|
1100
|
+
i = 0
|
|
1101
|
+
while i < len(D.gens()):
|
|
1102
|
+
t = D.gens()[i]
|
|
1103
|
+
if t.q() == 0 and all(t.b(g) == 0 for g in isotropic):
|
|
1104
|
+
isotropic.append(t)
|
|
1105
|
+
i += 1
|
|
1106
|
+
isotropic = [g.lift() for g in isotropic]
|
|
1107
|
+
L = L.overlattice(isotropic)
|
|
1108
|
+
D = L.discriminant_group(2)
|
|
1109
|
+
# clean up whatever is left by brute force
|
|
1110
|
+
while D.cardinality().valuation(2) > 1:
|
|
1111
|
+
for t in D:
|
|
1112
|
+
if t != 0 and t.q() == 0:
|
|
1113
|
+
break
|
|
1114
|
+
if t.q() != 0:
|
|
1115
|
+
# no isotropic vector left
|
|
1116
|
+
break
|
|
1117
|
+
L = L.overlattice([t.lift()])
|
|
1118
|
+
D = L.discriminant_group(2)
|
|
1119
|
+
# odd case
|
|
1120
|
+
for p in P:
|
|
1121
|
+
if p == 2:
|
|
1122
|
+
continue
|
|
1123
|
+
# go squarefree
|
|
1124
|
+
D = L.discriminant_group(p).normal_form()
|
|
1125
|
+
isotropic = [p**((-b.q().lift().valuation(p)+1)//2) * b.lift() for b in D.gens()]
|
|
1126
|
+
L = L.overlattice(isotropic)
|
|
1127
|
+
# now the p-discriminant_group is a vector space
|
|
1128
|
+
while True:
|
|
1129
|
+
d = L.discriminant_group(p).gram_matrix_bilinear().det()
|
|
1130
|
+
v = -d.valuation(p)
|
|
1131
|
+
u = d.numerator()
|
|
1132
|
+
if v <= 1 or (v == 2 and ZZ(-1).kronecker(p) != u.kronecker(p)):
|
|
1133
|
+
# the lattice is already maximal at p
|
|
1134
|
+
break
|
|
1135
|
+
# diagonalize the gram matrix
|
|
1136
|
+
D = L.discriminant_group(p).normal_form(partial=True)
|
|
1137
|
+
gen = D.gens()
|
|
1138
|
+
G = D.gram_matrix_quadratic().diagonal()
|
|
1139
|
+
k = GF(p)
|
|
1140
|
+
a = k(G[0].numerator())
|
|
1141
|
+
b = k(G[1].numerator())
|
|
1142
|
+
if (-b/a).is_square():
|
|
1143
|
+
# solve: a*x^2 + b *y^2 = 0
|
|
1144
|
+
x = (-b/a).sqrt()
|
|
1145
|
+
y = 1
|
|
1146
|
+
t = ZZ(x)*gen[0] + ZZ(y)*gen[1]
|
|
1147
|
+
else:
|
|
1148
|
+
# or solve a*x^2 + b*y^2 + c = 0
|
|
1149
|
+
# we know the rank is at least 3
|
|
1150
|
+
c = k(G[2].numerator())
|
|
1151
|
+
# brute force to find a suitable y
|
|
1152
|
+
# very fast
|
|
1153
|
+
for y in GF(p):
|
|
1154
|
+
x = (-c - b*y**2)/a
|
|
1155
|
+
if x.is_square():
|
|
1156
|
+
x = x.sqrt()
|
|
1157
|
+
break
|
|
1158
|
+
t = ZZ(x)*gen[0] + ZZ(y)*gen[1] + ZZ(1)*gen[2]
|
|
1159
|
+
L = L.overlattice([t.lift()])
|
|
1160
|
+
return L
|
|
1161
|
+
|
|
1162
|
+
def orthogonal_group(self, gens=None, is_finite=None):
|
|
1163
|
+
"""
|
|
1164
|
+
Return the orthogonal group of this lattice as a matrix group.
|
|
1165
|
+
|
|
1166
|
+
The elements are isometries of the ambient vector space
|
|
1167
|
+
which preserve this lattice. They are represented by
|
|
1168
|
+
matrices with respect to the standard basis.
|
|
1169
|
+
|
|
1170
|
+
INPUT:
|
|
1171
|
+
|
|
1172
|
+
- ``gens`` -- list of matrices (default: ``None``)
|
|
1173
|
+
- ``is_finite`` -- boolean (default: ``None``); if set to ``True``,
|
|
1174
|
+
then the group is placed in the category of finite groups. Sage does
|
|
1175
|
+
not check this.
|
|
1176
|
+
|
|
1177
|
+
OUTPUT:
|
|
1178
|
+
|
|
1179
|
+
The matrix group generated by ``gens``.
|
|
1180
|
+
If ``gens`` is not specified, then generators of the full
|
|
1181
|
+
orthogonal group of this lattice are computed. They are
|
|
1182
|
+
continued as the identity on the orthogonal complement of
|
|
1183
|
+
the lattice in its ambient space. Currently, we can only
|
|
1184
|
+
compute the orthogonal group for positive definite lattices.
|
|
1185
|
+
|
|
1186
|
+
EXAMPLES::
|
|
1187
|
+
|
|
1188
|
+
sage: A4 = IntegralLattice("A4") # needs sage.graphs
|
|
1189
|
+
sage: Aut = A4.orthogonal_group(); Aut # needs sage.graphs sage.libs.gap
|
|
1190
|
+
Group of isometries with 4 generators (
|
|
1191
|
+
[0 0 0 1] [-1 -1 -1 0] [ 1 0 0 0] [ 1 0 0 0]
|
|
1192
|
+
[0 0 1 0] [ 0 0 0 -1] [-1 -1 -1 -1] [ 0 1 0 0]
|
|
1193
|
+
[0 1 0 0] [ 0 0 1 1] [ 0 0 0 1] [ 0 0 1 1]
|
|
1194
|
+
[1 0 0 0], [ 0 1 0 0], [ 0 0 1 0], [ 0 0 0 -1]
|
|
1195
|
+
)
|
|
1196
|
+
|
|
1197
|
+
The group acts from the right on the lattice and its discriminant group::
|
|
1198
|
+
|
|
1199
|
+
sage: # needs sage.graphs sage.libs.gap
|
|
1200
|
+
sage: x = A4.an_element()
|
|
1201
|
+
sage: g = Aut.an_element(); g
|
|
1202
|
+
[-1 -1 -1 0]
|
|
1203
|
+
[ 0 0 1 0]
|
|
1204
|
+
[ 0 0 -1 -1]
|
|
1205
|
+
[ 0 1 1 1]
|
|
1206
|
+
sage: x*g
|
|
1207
|
+
(-1, -1, -1, 0)
|
|
1208
|
+
sage: (x*g).parent() == A4
|
|
1209
|
+
True
|
|
1210
|
+
sage: (g*x).parent()
|
|
1211
|
+
Vector space of dimension 4 over Rational Field
|
|
1212
|
+
sage: y = A4.discriminant_group().an_element()
|
|
1213
|
+
sage: y*g
|
|
1214
|
+
(4)
|
|
1215
|
+
|
|
1216
|
+
If the group is finite we can compute the usual things::
|
|
1217
|
+
|
|
1218
|
+
sage: # needs sage.graphs sage.libs.gap
|
|
1219
|
+
sage: Aut.order()
|
|
1220
|
+
240
|
|
1221
|
+
sage: conj = Aut.conjugacy_classes_representatives()
|
|
1222
|
+
sage: len(conj)
|
|
1223
|
+
14
|
|
1224
|
+
sage: Aut.structure_description()
|
|
1225
|
+
'C2 x S5'
|
|
1226
|
+
|
|
1227
|
+
The lattice can live in a larger ambient space::
|
|
1228
|
+
|
|
1229
|
+
sage: A2 = IntegralLattice(matrix.identity(3),
|
|
1230
|
+
....: Matrix(ZZ, 2, 3, [1,-1,0,0,1,-1]))
|
|
1231
|
+
sage: A2.orthogonal_group() # needs sage.libs.gap sage.libs.pari
|
|
1232
|
+
Group of isometries with 2 generators (
|
|
1233
|
+
[ 2/3 2/3 -1/3] [1 0 0]
|
|
1234
|
+
[ 2/3 -1/3 2/3] [0 0 1]
|
|
1235
|
+
[-1/3 2/3 2/3], [0 1 0]
|
|
1236
|
+
)
|
|
1237
|
+
|
|
1238
|
+
It can be negative definite as well::
|
|
1239
|
+
|
|
1240
|
+
sage: A2m = IntegralLattice(-Matrix(ZZ, 2, [2,1,1,2]))
|
|
1241
|
+
sage: G = A2m.orthogonal_group() # needs sage.libs.gap sage.libs.pari
|
|
1242
|
+
sage: G.order() # needs sage.libs.gap sage.libs.pari
|
|
1243
|
+
12
|
|
1244
|
+
|
|
1245
|
+
If the lattice is indefinite, sage does not know how to compute generators.
|
|
1246
|
+
Can you teach it?::
|
|
1247
|
+
|
|
1248
|
+
sage: U = IntegralLattice(Matrix(ZZ, 2, [0,1,1,0]))
|
|
1249
|
+
sage: U.orthogonal_group() # needs sage.libs.gap
|
|
1250
|
+
Traceback (most recent call last):
|
|
1251
|
+
...
|
|
1252
|
+
NotImplementedError: currently, we can only compute generators
|
|
1253
|
+
for orthogonal groups over definite lattices.
|
|
1254
|
+
|
|
1255
|
+
But we can define subgroups::
|
|
1256
|
+
|
|
1257
|
+
sage: S = IntegralLattice(Matrix(ZZ, 2, [2, 3, 3, 2]))
|
|
1258
|
+
sage: f = Matrix(ZZ, 2, [0,1,-1,3])
|
|
1259
|
+
sage: S.orthogonal_group([f]) # needs sage.libs.gap
|
|
1260
|
+
Group of isometries with 1 generator (
|
|
1261
|
+
[ 0 1]
|
|
1262
|
+
[-1 3]
|
|
1263
|
+
)
|
|
1264
|
+
|
|
1265
|
+
TESTS:
|
|
1266
|
+
|
|
1267
|
+
We can handle the trivial group::
|
|
1268
|
+
|
|
1269
|
+
sage: S = IntegralLattice(Matrix(ZZ, 2, [2, 3, 3, 2]))
|
|
1270
|
+
sage: S.orthogonal_group([]) # needs sage.libs.gap
|
|
1271
|
+
Group of isometries with 1 generator (
|
|
1272
|
+
[1 0]
|
|
1273
|
+
[0 1]
|
|
1274
|
+
)
|
|
1275
|
+
"""
|
|
1276
|
+
from sage.categories.groups import Groups
|
|
1277
|
+
from sage.groups.matrix_gps.isometries import GroupOfIsometries
|
|
1278
|
+
sig = self.signature_pair()
|
|
1279
|
+
if gens is None:
|
|
1280
|
+
gens = []
|
|
1281
|
+
if sig[1] == 0 or sig[0] == 0: # definite
|
|
1282
|
+
from sage.quadratic_forms.quadratic_form import QuadraticForm
|
|
1283
|
+
is_finite = True
|
|
1284
|
+
# Compute transformation matrix to the ambient module.
|
|
1285
|
+
L = self.overlattice(self.ambient_module().gens())
|
|
1286
|
+
Orthogonal = L.orthogonal_complement(self)
|
|
1287
|
+
B = self.basis_matrix().stack(Orthogonal.basis_matrix())
|
|
1288
|
+
if sig[0] == 0: # negative definite
|
|
1289
|
+
q = QuadraticForm(ZZ, -2*self.gram_matrix())
|
|
1290
|
+
else: # positive definite
|
|
1291
|
+
q = QuadraticForm(ZZ, 2*self.gram_matrix())
|
|
1292
|
+
identity = matrix.identity(Orthogonal.rank())
|
|
1293
|
+
for g in q.automorphism_group().gens():
|
|
1294
|
+
g = g.matrix().T
|
|
1295
|
+
# We continue g as identity on the orthogonal complement.
|
|
1296
|
+
g = matrix.block_diagonal([g, identity])
|
|
1297
|
+
g = B.inverse()*g*B
|
|
1298
|
+
gens.append(g)
|
|
1299
|
+
else: # indefinite
|
|
1300
|
+
raise NotImplementedError(
|
|
1301
|
+
"currently, we can only compute generators "
|
|
1302
|
+
"for orthogonal groups over definite lattices.")
|
|
1303
|
+
deg = self.degree()
|
|
1304
|
+
base = self.ambient_vector_space().base_ring()
|
|
1305
|
+
inv_bil = self.inner_product_matrix()
|
|
1306
|
+
if is_finite:
|
|
1307
|
+
cat = Groups().Finite()
|
|
1308
|
+
else:
|
|
1309
|
+
cat = Groups()
|
|
1310
|
+
D = self.discriminant_group()
|
|
1311
|
+
G = GroupOfIsometries(deg,
|
|
1312
|
+
base,
|
|
1313
|
+
gens,
|
|
1314
|
+
inv_bil,
|
|
1315
|
+
category=cat,
|
|
1316
|
+
invariant_submodule=self,
|
|
1317
|
+
invariant_quotient_module=D)
|
|
1318
|
+
return G
|
|
1319
|
+
|
|
1320
|
+
automorphisms = orthogonal_group
|
|
1321
|
+
|
|
1322
|
+
def genus(self):
|
|
1323
|
+
r"""
|
|
1324
|
+
Return the genus of this lattice.
|
|
1325
|
+
|
|
1326
|
+
EXAMPLES::
|
|
1327
|
+
|
|
1328
|
+
sage: L = IntegralLattice("U")
|
|
1329
|
+
sage: L.genus() # needs sage.padics
|
|
1330
|
+
Genus of
|
|
1331
|
+
[0 1]
|
|
1332
|
+
[1 0]
|
|
1333
|
+
Signature: (1, 1)
|
|
1334
|
+
Genus symbol at 2: 1^2
|
|
1335
|
+
"""
|
|
1336
|
+
from sage.quadratic_forms.genera.genus import Genus
|
|
1337
|
+
return Genus(self.gram_matrix())
|
|
1338
|
+
|
|
1339
|
+
def tensor_product(self, other, discard_basis=False):
|
|
1340
|
+
r"""
|
|
1341
|
+
Return the tensor product of ``self`` and ``other``.
|
|
1342
|
+
|
|
1343
|
+
INPUT:
|
|
1344
|
+
|
|
1345
|
+
- ``other`` -- an integral lattice
|
|
1346
|
+
- ``discard_basis`` -- boolean (default: ``False``); if ``True``, then
|
|
1347
|
+
the lattice returned is equipped with the standard basis
|
|
1348
|
+
|
|
1349
|
+
EXAMPLES::
|
|
1350
|
+
|
|
1351
|
+
sage: # needs sage.graphs
|
|
1352
|
+
sage: L = IntegralLattice("D3", [[1,-1,0], [0,1,-1]])
|
|
1353
|
+
sage: L1 = L.tensor_product(L); L1
|
|
1354
|
+
Lattice of degree 9 and rank 4 over Integer Ring
|
|
1355
|
+
Basis matrix:
|
|
1356
|
+
[ 1 -1 0 -1 1 0 0 0 0]
|
|
1357
|
+
[ 0 1 -1 0 -1 1 0 0 0]
|
|
1358
|
+
[ 0 0 0 1 -1 0 -1 1 0]
|
|
1359
|
+
[ 0 0 0 0 1 -1 0 -1 1]
|
|
1360
|
+
Inner product matrix:
|
|
1361
|
+
[ 4 -2 -2 -2 1 1 -2 1 1]
|
|
1362
|
+
[-2 4 0 1 -2 0 1 -2 0]
|
|
1363
|
+
[-2 0 4 1 0 -2 1 0 -2]
|
|
1364
|
+
[-2 1 1 4 -2 -2 0 0 0]
|
|
1365
|
+
[ 1 -2 0 -2 4 0 0 0 0]
|
|
1366
|
+
[ 1 0 -2 -2 0 4 0 0 0]
|
|
1367
|
+
[-2 1 1 0 0 0 4 -2 -2]
|
|
1368
|
+
[ 1 -2 0 0 0 0 -2 4 0]
|
|
1369
|
+
[ 1 0 -2 0 0 0 -2 0 4]
|
|
1370
|
+
sage: L1.gram_matrix()
|
|
1371
|
+
[ 36 -12 -12 4]
|
|
1372
|
+
[-12 24 4 -8]
|
|
1373
|
+
[-12 4 24 -8]
|
|
1374
|
+
[ 4 -8 -8 16]
|
|
1375
|
+
sage: L2 = L.tensor_product(L, True); L2
|
|
1376
|
+
Lattice of degree 4 and rank 4 over Integer Ring
|
|
1377
|
+
Standard basis
|
|
1378
|
+
Inner product matrix:
|
|
1379
|
+
[ 36 -12 -12 4]
|
|
1380
|
+
[-12 24 4 -8]
|
|
1381
|
+
[-12 4 24 -8]
|
|
1382
|
+
[ 4 -8 -8 16]
|
|
1383
|
+
"""
|
|
1384
|
+
if not isinstance(other, FreeQuadraticModule_integer_symmetric):
|
|
1385
|
+
raise ValueError("other (=%s) must be an integral lattice" % other)
|
|
1386
|
+
if discard_basis:
|
|
1387
|
+
gram_matrix = self.gram_matrix().tensor_product(other.gram_matrix())
|
|
1388
|
+
return IntegralLattice(gram_matrix)
|
|
1389
|
+
else:
|
|
1390
|
+
inner_product_matrix = self.inner_product_matrix().tensor_product(other.inner_product_matrix())
|
|
1391
|
+
basis_matrix = self.basis_matrix().tensor_product(other.basis_matrix())
|
|
1392
|
+
n = self.degree()
|
|
1393
|
+
m = other.degree()
|
|
1394
|
+
ambient = FreeQuadraticModule(self.base_ring(), m * n, inner_product_matrix)
|
|
1395
|
+
return FreeQuadraticModule_integer_symmetric(ambient=ambient,
|
|
1396
|
+
basis=basis_matrix,
|
|
1397
|
+
inner_product_matrix=ambient.inner_product_matrix())
|
|
1398
|
+
|
|
1399
|
+
@cached_method
|
|
1400
|
+
def quadratic_form(self):
|
|
1401
|
+
r"""
|
|
1402
|
+
Return the quadratic form given by `q(x)=(x,x)`.
|
|
1403
|
+
|
|
1404
|
+
EXAMPLES::
|
|
1405
|
+
|
|
1406
|
+
sage: L = IntegralLattice("A2") # needs sage.graphs
|
|
1407
|
+
sage: q = L.quadratic_form(); q # needs sage.graphs
|
|
1408
|
+
Quadratic form in 2 variables over Integer Ring with coefficients:
|
|
1409
|
+
[ 2 -2 ]
|
|
1410
|
+
[ * 2 ]
|
|
1411
|
+
"""
|
|
1412
|
+
from sage.quadratic_forms.quadratic_form import QuadraticForm
|
|
1413
|
+
return QuadraticForm(2 * self.gram_matrix())
|
|
1414
|
+
|
|
1415
|
+
@cached_method
|
|
1416
|
+
def minimum(self):
|
|
1417
|
+
r"""
|
|
1418
|
+
Return the minimum of this lattice.
|
|
1419
|
+
|
|
1420
|
+
.. MATH::
|
|
1421
|
+
|
|
1422
|
+
\min\{x^2 | x \in L\setminus \{0\}\}
|
|
1423
|
+
|
|
1424
|
+
EXAMPLES::
|
|
1425
|
+
|
|
1426
|
+
sage: L = IntegralLattice('A2') # needs sage.graphs
|
|
1427
|
+
sage: L.minimum() # needs sage.graphs
|
|
1428
|
+
2
|
|
1429
|
+
sage: L.twist(-1).minimum() # needs sage.graphs
|
|
1430
|
+
-Infinity
|
|
1431
|
+
"""
|
|
1432
|
+
p, n = self.signature_pair()
|
|
1433
|
+
if self.rank() == 0:
|
|
1434
|
+
raise ValueError("the empty set does not have a minimum")
|
|
1435
|
+
if n != 0:
|
|
1436
|
+
from sage.rings.infinity import MinusInfinity
|
|
1437
|
+
return MinusInfinity()
|
|
1438
|
+
mpari = self.gram_matrix().__pari__().qfminim(None, 0)[1]
|
|
1439
|
+
return mpari
|
|
1440
|
+
|
|
1441
|
+
@cached_method
|
|
1442
|
+
def maximum(self):
|
|
1443
|
+
r"""
|
|
1444
|
+
Return the maximum of this lattice.
|
|
1445
|
+
|
|
1446
|
+
.. MATH::
|
|
1447
|
+
|
|
1448
|
+
\max\{x^2 | x \in L\setminus \{0\}\}
|
|
1449
|
+
|
|
1450
|
+
EXAMPLES::
|
|
1451
|
+
|
|
1452
|
+
sage: L = IntegralLattice('A2') # needs sage.graphs
|
|
1453
|
+
sage: L.maximum() # needs sage.graphs
|
|
1454
|
+
+Infinity
|
|
1455
|
+
sage: L.twist(-1).maximum() # needs sage.graphs sage.libs.pari
|
|
1456
|
+
-2
|
|
1457
|
+
"""
|
|
1458
|
+
if self.rank() == 0:
|
|
1459
|
+
raise ValueError("the empty set does not have a maximum")
|
|
1460
|
+
p, n = self.signature_pair()
|
|
1461
|
+
if p != 0:
|
|
1462
|
+
from sage.rings.infinity import PlusInfinity
|
|
1463
|
+
return PlusInfinity()
|
|
1464
|
+
mpari = (-self.gram_matrix()).__pari__().qfminim(None, 0)[1]
|
|
1465
|
+
return -mpari
|
|
1466
|
+
|
|
1467
|
+
min = minimum
|
|
1468
|
+
max = maximum
|
|
1469
|
+
|
|
1470
|
+
def LLL(self):
|
|
1471
|
+
r"""
|
|
1472
|
+
Return this lattice with an LLL reduced basis.
|
|
1473
|
+
|
|
1474
|
+
EXAMPLES::
|
|
1475
|
+
|
|
1476
|
+
sage: L = IntegralLattice('A2') # needs sage.graphs
|
|
1477
|
+
sage: L.lll() == L # needs sage.graphs sage.libs.pari
|
|
1478
|
+
True
|
|
1479
|
+
|
|
1480
|
+
sage: G = matrix(ZZ, 3, [0,1,0, 1,0,0, 0,0,7])
|
|
1481
|
+
sage: V = matrix(ZZ, 3, [-14,-15,-15, -4,1,16, -5,-5,-4])
|
|
1482
|
+
sage: L = IntegralLattice(V * G * V.T)
|
|
1483
|
+
sage: L.lll().gram_matrix() # needs sage.libs.gap sage.libs.pari
|
|
1484
|
+
[0 0 1]
|
|
1485
|
+
[0 7 0]
|
|
1486
|
+
[1 0 0]
|
|
1487
|
+
"""
|
|
1488
|
+
p, n = self.signature_pair()
|
|
1489
|
+
if p * n != 0:
|
|
1490
|
+
from sage.env import SAGE_EXTCODE
|
|
1491
|
+
from sage.libs.pari import pari
|
|
1492
|
+
m = self.gram_matrix()
|
|
1493
|
+
pari.read(Path(SAGE_EXTCODE) / "pari" / "simon" / "qfsolve.gp")
|
|
1494
|
+
m = pari('qflllgram_indefgoon')(m)
|
|
1495
|
+
# convert the output to sage
|
|
1496
|
+
G, U = m.sage()
|
|
1497
|
+
U = U.T
|
|
1498
|
+
else:
|
|
1499
|
+
e = 1
|
|
1500
|
+
if n != 0:
|
|
1501
|
+
e = -1
|
|
1502
|
+
U = (e * self.gram_matrix().change_ring(ZZ)).LLL_gram().T
|
|
1503
|
+
return self.sublattice(U * self.basis_matrix())
|
|
1504
|
+
|
|
1505
|
+
lll = LLL
|
|
1506
|
+
|
|
1507
|
+
def short_vectors(self, n, **kwargs):
|
|
1508
|
+
r"""
|
|
1509
|
+
Return the short vectors of length `< n`.
|
|
1510
|
+
|
|
1511
|
+
INPUT:
|
|
1512
|
+
|
|
1513
|
+
- ``n`` -- integer
|
|
1514
|
+
- further keyword arguments are passed on to
|
|
1515
|
+
:meth:`sage.quadratic_forms.short_vector_list_up_to_length`
|
|
1516
|
+
|
|
1517
|
+
OUTPUT: list `L` where ``L[k]`` is the list of vectors of lengths `k`
|
|
1518
|
+
|
|
1519
|
+
EXAMPLES::
|
|
1520
|
+
|
|
1521
|
+
sage: A2 = IntegralLattice('A2') # needs sage.graphs
|
|
1522
|
+
sage: A2.short_vectors(3) # needs sage.graphs sage.libs.pari
|
|
1523
|
+
[[(0, 0)], [], [(1, 1), (-1, -1), (0, 1), (0, -1), (1, 0), (-1, 0)]]
|
|
1524
|
+
sage: A2.short_vectors(3, up_to_sign_flag=True) # needs sage.graphs sage.libs.pari
|
|
1525
|
+
[[(0, 0)], [], [(1, 1), (0, 1), (1, 0)]]
|
|
1526
|
+
|
|
1527
|
+
TESTS:
|
|
1528
|
+
|
|
1529
|
+
Check that keyword arguments are passed to :meth:`sage.quadratic_forms.short_vector_list_up_to_length`
|
|
1530
|
+
(:issue:`39848`)::
|
|
1531
|
+
|
|
1532
|
+
sage: A2 = IntegralLattice('A2') # needs sage.graphs
|
|
1533
|
+
sage: A2.short_vectors(3, up_to_sign_flag=False) # needs sage.graphs sage.libs.pari
|
|
1534
|
+
[[(0, 0)], [], [(1, 1), (-1, -1), (0, 1), (0, -1), (1, 0), (-1, 0)]]
|
|
1535
|
+
"""
|
|
1536
|
+
p, m = self.signature_pair()
|
|
1537
|
+
if p * m != 0:
|
|
1538
|
+
raise NotImplementedError("the lattice has to be positive definite")
|
|
1539
|
+
e = 2
|
|
1540
|
+
if m != 0:
|
|
1541
|
+
e = -2
|
|
1542
|
+
from sage.quadratic_forms.quadratic_form import QuadraticForm
|
|
1543
|
+
q = QuadraticForm(e * self.gram_matrix())
|
|
1544
|
+
short = q.short_vector_list_up_to_length(n, **kwargs)
|
|
1545
|
+
# (matrix(L)* B ).rows() is faster than [v * B for v in L]
|
|
1546
|
+
return [[self(r, check=False) for r in matrix(L) * self.basis_matrix()] if L else [] for L in short]
|
|
1547
|
+
|
|
1548
|
+
def _fplll_enumerate(self, target=None):
|
|
1549
|
+
r"""
|
|
1550
|
+
Internal helper method to invoke the fplll enumeration routines.
|
|
1551
|
+
|
|
1552
|
+
EXAMPLES::
|
|
1553
|
+
|
|
1554
|
+
sage: # needs fpylll sage.graphs
|
|
1555
|
+
sage: L = IntegralLattice('A4')
|
|
1556
|
+
sage: t = vector([1.2, -3/11, 5.5, -9.1])
|
|
1557
|
+
sage: short = L.enumerate_short_vectors() # implicit doctest
|
|
1558
|
+
sage: vecs = [next(short) for _ in range(10)]
|
|
1559
|
+
sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v))
|
|
1560
|
+
[(0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 1, 0),
|
|
1561
|
+
(0, 1, 1, 1), (1, 0, 0, 0), (1, 1, 0, 0), (1, 1, 1, 0), (1, 1, 1, 1)]
|
|
1562
|
+
sage: close = L.enumerate_close_vectors(t) # implicit doctest
|
|
1563
|
+
sage: vecs = [next(close) for _ in range(10)]
|
|
1564
|
+
sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v))
|
|
1565
|
+
[(1, 0, 6, -8), (1, 0, 5, -9), (2, 0, 5, -9), (1, -1, 5, -9), (2, 1, 6, -9),
|
|
1566
|
+
(1, 0, 6, -9), (2, 0, 6, -9), (1, 0, 5, -10), (1, -1, 6, -9), (1, -1, 5, -10)]
|
|
1567
|
+
"""
|
|
1568
|
+
L = self.LLL()
|
|
1569
|
+
dim = L.dimension()
|
|
1570
|
+
gram = L.gram_matrix()
|
|
1571
|
+
basis = L.basis_matrix()
|
|
1572
|
+
|
|
1573
|
+
import fpylll
|
|
1574
|
+
gmat = fpylll.IntegerMatrix(dim, dim)
|
|
1575
|
+
for i in range(dim):
|
|
1576
|
+
for j in range(dim):
|
|
1577
|
+
gmat[i, j] = gram[i, j]
|
|
1578
|
+
gso = fpylll.GSO.Mat(gmat, gram=True)
|
|
1579
|
+
ok = gso.update_gso()
|
|
1580
|
+
assert ok
|
|
1581
|
+
|
|
1582
|
+
coord = None
|
|
1583
|
+
if target is not None:
|
|
1584
|
+
coord = basis.solve_left(target)
|
|
1585
|
+
Mu = 1 + matrix([gso.get_mu(i, j) for j in range(dim)]
|
|
1586
|
+
for i in range(dim))
|
|
1587
|
+
coord *= Mu
|
|
1588
|
+
|
|
1589
|
+
count = 8
|
|
1590
|
+
bound = gso.get_r(dim - 1, dim - 1)
|
|
1591
|
+
seen = set()
|
|
1592
|
+
while True:
|
|
1593
|
+
enum = fpylll.Enumeration(gso, count, fpylll.EvaluatorStrategy.BEST_N_SOLUTIONS)
|
|
1594
|
+
try:
|
|
1595
|
+
combs = enum.enumerate(0, dim, bound, 0, coord)
|
|
1596
|
+
except fpylll.EnumerationError:
|
|
1597
|
+
combs = []
|
|
1598
|
+
if len(combs) < count:
|
|
1599
|
+
bound *= 2
|
|
1600
|
+
continue
|
|
1601
|
+
for length, comb in combs:
|
|
1602
|
+
vec = sum(ZZ(c) * b for c, b in zip(comb, basis))
|
|
1603
|
+
if tuple(vec) not in seen:
|
|
1604
|
+
yield vec
|
|
1605
|
+
seen.add(tuple(vec))
|
|
1606
|
+
count *= 2
|
|
1607
|
+
|
|
1608
|
+
def enumerate_short_vectors(self):
|
|
1609
|
+
r"""
|
|
1610
|
+
Return an iterator over all the vectors in this lattice (modulo sign),
|
|
1611
|
+
starting from shorter vectors.
|
|
1612
|
+
|
|
1613
|
+
.. WARNING::
|
|
1614
|
+
|
|
1615
|
+
The returned vectors are not necessarily ordered strictly
|
|
1616
|
+
by length.
|
|
1617
|
+
|
|
1618
|
+
EXAMPLES::
|
|
1619
|
+
|
|
1620
|
+
sage: # needs fpylll sage.libs.pari
|
|
1621
|
+
sage: L = IntegralLattice(4, [[1,2,3,4], [7,7,8,8], [1,-1,1,0]])
|
|
1622
|
+
sage: short = L.enumerate_short_vectors()
|
|
1623
|
+
sage: vecs = [next(short) for _ in range(20)]
|
|
1624
|
+
sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v))
|
|
1625
|
+
[(1, -1, 1, 0), (2, -2, 2, 0), (3, -3, 3, 0), (0, 3, 2, 4), (1, 2, 3, 4),
|
|
1626
|
+
(3, 2, -2, -4), (4, 4, 1, 0), (-1, 4, 1, 4), (3, 5, 0, 0), (4, 1, -1, -4),
|
|
1627
|
+
(2, 1, 4, 4), (2, 3, -3, -4), (5, 3, 2, 0), (2, 6, -1, 0), (5, 0, 0, -4),
|
|
1628
|
+
(-2, 5, 0, 4), (4, -4, 4, 0), (1, 4, -4, -4), (6, 2, 3, 0), (3, 0, 5, 4)]
|
|
1629
|
+
|
|
1630
|
+
This example demonstrates that the lattice inner product is used for the norm::
|
|
1631
|
+
|
|
1632
|
+
sage: # needs fpylll sage.libs.pari
|
|
1633
|
+
sage: Q = Matrix(QQ, [[1000, 0], [0, 1]])
|
|
1634
|
+
sage: B = [[1, 1], [1, -1]]
|
|
1635
|
+
sage: L = IntegralLattice(Q, basis=B)
|
|
1636
|
+
sage: short = L.enumerate_short_vectors()
|
|
1637
|
+
sage: vecs = [next(short) for _ in range(20)]
|
|
1638
|
+
sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v))
|
|
1639
|
+
[(0, -2), (0, -4), (0, -6), (0, -8), (0, -10), (0, -12), (0, -14), (0, -16),
|
|
1640
|
+
(0, -18), (0, -20), (0, -22), (0, -24), (0, -26), (0, -28), (0, -30), (-1, -1),
|
|
1641
|
+
(-1, 1), (-1, -3), (-1, 3), (0, -32)]
|
|
1642
|
+
"""
|
|
1643
|
+
yield from self._fplll_enumerate()
|
|
1644
|
+
|
|
1645
|
+
def enumerate_close_vectors(self, target):
|
|
1646
|
+
r"""
|
|
1647
|
+
Return an iterator over all the vectors in this lattice, starting
|
|
1648
|
+
from vectors relatively close to the given ``target`` vector.
|
|
1649
|
+
|
|
1650
|
+
.. WARNING::
|
|
1651
|
+
|
|
1652
|
+
The returned vectors are not necessarily ordered strictly
|
|
1653
|
+
by their distance to the target.
|
|
1654
|
+
|
|
1655
|
+
EXAMPLES::
|
|
1656
|
+
|
|
1657
|
+
sage: # needs fpylll sage.libs.pari
|
|
1658
|
+
sage: L = IntegralLattice(4, [[1,2,3,4], [7,7,8,8], [1,-1,1,0]])
|
|
1659
|
+
sage: t = vector([1/2, -133/7, 123.44, -11])
|
|
1660
|
+
sage: close = L.enumerate_close_vectors(t)
|
|
1661
|
+
sage: vecs = [next(close) for _ in range(10)]
|
|
1662
|
+
sage: sorted(vecs, key=lambda v: (L(v).inner_product(L(v)), v))
|
|
1663
|
+
[(-1, -16, 121, 148), (0, -17, 122, 148), (-3, -22, 122, 148), (1, -18, 123, 148), (-2, -23, 123, 148),
|
|
1664
|
+
(2, -19, 124, 148), (3, -20, 125, 148), (4, -21, 126, 148), (-3, -19, 124, 152), (-2, -20, 125, 152)]
|
|
1665
|
+
"""
|
|
1666
|
+
yield from self._fplll_enumerate(target)
|
|
1667
|
+
|
|
1668
|
+
def twist(self, s, discard_basis=False):
|
|
1669
|
+
r"""
|
|
1670
|
+
Return the lattice with inner product matrix scaled by ``s``.
|
|
1671
|
+
|
|
1672
|
+
INPUT:
|
|
1673
|
+
|
|
1674
|
+
- ``s`` -- nonzero integer
|
|
1675
|
+
- ``discard_basis`` -- boolean (default: ``False``); if ``True``, then
|
|
1676
|
+
the lattice returned is equipped with the standard basis
|
|
1677
|
+
|
|
1678
|
+
EXAMPLES::
|
|
1679
|
+
|
|
1680
|
+
sage: L = IntegralLattice("A4") # needs sage.graphs
|
|
1681
|
+
sage: L.twist(3) # needs sage.graphs
|
|
1682
|
+
Lattice of degree 4 and rank 4 over Integer Ring
|
|
1683
|
+
Standard basis
|
|
1684
|
+
Inner product matrix:
|
|
1685
|
+
[ 6 -3 0 0]
|
|
1686
|
+
[-3 6 -3 0]
|
|
1687
|
+
[ 0 -3 6 -3]
|
|
1688
|
+
[ 0 0 -3 6]
|
|
1689
|
+
sage: L = IntegralLattice(3, [[2,1,0], [0,1,1]]); L
|
|
1690
|
+
Lattice of degree 3 and rank 2 over Integer Ring
|
|
1691
|
+
Basis matrix:
|
|
1692
|
+
[2 1 0]
|
|
1693
|
+
[0 1 1]
|
|
1694
|
+
Standard scalar product
|
|
1695
|
+
sage: L.twist(1)
|
|
1696
|
+
Lattice of degree 3 and rank 2 over Integer Ring
|
|
1697
|
+
Basis matrix:
|
|
1698
|
+
[2 1 0]
|
|
1699
|
+
[0 1 1]
|
|
1700
|
+
Standard scalar product
|
|
1701
|
+
sage: L.twist(1, True)
|
|
1702
|
+
Lattice of degree 2 and rank 2 over Integer Ring
|
|
1703
|
+
Standard basis
|
|
1704
|
+
Inner product matrix:
|
|
1705
|
+
[5 1]
|
|
1706
|
+
[1 2]
|
|
1707
|
+
"""
|
|
1708
|
+
try:
|
|
1709
|
+
s = self.base_ring()(s)
|
|
1710
|
+
except TypeError:
|
|
1711
|
+
raise ValueError("the scaling factor must be an element of the base ring.")
|
|
1712
|
+
if s == 0:
|
|
1713
|
+
raise ValueError("the scaling factor must be nonzero")
|
|
1714
|
+
if discard_basis:
|
|
1715
|
+
return IntegralLattice(s * self.gram_matrix())
|
|
1716
|
+
else:
|
|
1717
|
+
n = self.degree()
|
|
1718
|
+
inner_product_matrix = s * self.inner_product_matrix()
|
|
1719
|
+
ambient = FreeQuadraticModule(self.base_ring(), n, inner_product_matrix)
|
|
1720
|
+
return FreeQuadraticModule_integer_symmetric(ambient=ambient, basis=self.basis(), inner_product_matrix=inner_product_matrix)
|
|
1721
|
+
|
|
1722
|
+
|
|
1723
|
+
def local_modification(M, G, p, check=True):
|
|
1724
|
+
r"""
|
|
1725
|
+
Return a local modification of `M` that matches `G` at `p`.
|
|
1726
|
+
|
|
1727
|
+
INPUT:
|
|
1728
|
+
|
|
1729
|
+
- ``M`` -- a `\ZZ_p`-maximal lattice
|
|
1730
|
+
|
|
1731
|
+
- ``G`` -- the gram matrix of a lattice isomorphic to `M` over `\QQ_p`
|
|
1732
|
+
|
|
1733
|
+
- ``p`` -- a prime number
|
|
1734
|
+
|
|
1735
|
+
OUTPUT:
|
|
1736
|
+
|
|
1737
|
+
an integral lattice `M'` in the ambient space of `M` such that `M` and `M'` are locally equal at all
|
|
1738
|
+
completions except at `p` where `M'` is locally equivalent to the lattice with gram matrix `G`
|
|
1739
|
+
|
|
1740
|
+
EXAMPLES::
|
|
1741
|
+
|
|
1742
|
+
sage: # needs sage.graphs sage.libs.pari
|
|
1743
|
+
sage: from sage.modules.free_quadratic_module_integer_symmetric import local_modification
|
|
1744
|
+
sage: L = IntegralLattice("A3").twist(15)
|
|
1745
|
+
sage: M = L.maximal_overlattice()
|
|
1746
|
+
sage: for p in prime_divisors(L.determinant()):
|
|
1747
|
+
....: M = local_modification(M, L.gram_matrix(), p)
|
|
1748
|
+
sage: M.genus() == L.genus()
|
|
1749
|
+
True
|
|
1750
|
+
sage: L = IntegralLattice("D4").twist(3*4)
|
|
1751
|
+
sage: M = L.maximal_overlattice()
|
|
1752
|
+
sage: local_modification(M, L.gram_matrix(), 2)
|
|
1753
|
+
Lattice of degree 4 and rank 4 over Integer Ring
|
|
1754
|
+
Basis matrix:
|
|
1755
|
+
[1/3 0 2/3 2/3]
|
|
1756
|
+
[ 0 1/3 0 2/3]
|
|
1757
|
+
[ 0 0 1 0]
|
|
1758
|
+
[ 0 0 0 1]
|
|
1759
|
+
Inner product matrix:
|
|
1760
|
+
[ 24 -12 0 0]
|
|
1761
|
+
[-12 24 -12 -12]
|
|
1762
|
+
[ 0 -12 24 0]
|
|
1763
|
+
[ 0 -12 0 24]
|
|
1764
|
+
"""
|
|
1765
|
+
from sage.quadratic_forms.genera.normal_form import p_adic_normal_form
|
|
1766
|
+
from sage.quadratic_forms.genera.genus import Genus_Symbol_p_adic_ring, p_adic_symbol
|
|
1767
|
+
|
|
1768
|
+
# notation
|
|
1769
|
+
d = G.inverse().denominator()
|
|
1770
|
+
scale = d.valuation(p)
|
|
1771
|
+
d = p**scale
|
|
1772
|
+
|
|
1773
|
+
L = IntegralLattice(G)
|
|
1774
|
+
L_max = L.maximal_overlattice(p=p)
|
|
1775
|
+
|
|
1776
|
+
# invert the gerstein operations
|
|
1777
|
+
_, U = p_adic_normal_form(L_max.gram_matrix(), p, precision=scale+3)
|
|
1778
|
+
B = (~L_max.basis_matrix()).change_ring(ZZ)*~U.change_ring(ZZ)
|
|
1779
|
+
|
|
1780
|
+
_, UM = p_adic_normal_form(M.gram_matrix(), p, precision=scale+3)
|
|
1781
|
+
B = B * UM.change_ring(ZZ) * M.basis_matrix()
|
|
1782
|
+
|
|
1783
|
+
# the local modification
|
|
1784
|
+
S = M.sublattice(((M.span(B) & M) + d * M).gens())
|
|
1785
|
+
# confirm result
|
|
1786
|
+
if check:
|
|
1787
|
+
s1 = Genus_Symbol_p_adic_ring(p, p_adic_symbol(S.gram_matrix(), p, scale))
|
|
1788
|
+
s2 = Genus_Symbol_p_adic_ring(p, p_adic_symbol(G, p, scale))
|
|
1789
|
+
assert s1 == s2, "oops"
|
|
1790
|
+
return S
|