passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-modules might be problematic. Click here for more details.
- passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
- passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-503f0c35.3.29.so +0 -0
- sage/algebras/all__sagemath_modules.py +20 -0
- sage/algebras/catalog.py +148 -0
- sage/algebras/clifford_algebra.py +3107 -0
- sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/clifford_algebra_element.pxd +16 -0
- sage/algebras/clifford_algebra_element.pyx +997 -0
- sage/algebras/commutative_dga.py +4252 -0
- sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/exterior_algebra_groebner.pxd +55 -0
- sage/algebras/exterior_algebra_groebner.pyx +727 -0
- sage/algebras/finite_dimensional_algebras/all.py +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
- sage/algebras/finite_gca.py +528 -0
- sage/algebras/group_algebra.py +232 -0
- sage/algebras/lie_algebras/abelian.py +197 -0
- sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
- sage/algebras/lie_algebras/all.py +25 -0
- sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
- sage/algebras/lie_algebras/bch.py +177 -0
- sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
- sage/algebras/lie_algebras/bgg_resolution.py +232 -0
- sage/algebras/lie_algebras/center_uea.py +767 -0
- sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
- sage/algebras/lie_algebras/examples.py +683 -0
- sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
- sage/algebras/lie_algebras/heisenberg.py +820 -0
- sage/algebras/lie_algebras/lie_algebra.py +1562 -0
- sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
- sage/algebras/lie_algebras/morphism.py +661 -0
- sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
- sage/algebras/lie_algebras/onsager.py +1324 -0
- sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
- sage/algebras/lie_algebras/quotient.py +462 -0
- sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
- sage/algebras/lie_algebras/representation.py +1040 -0
- sage/algebras/lie_algebras/structure_coefficients.py +459 -0
- sage/algebras/lie_algebras/subalgebra.py +967 -0
- sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
- sage/algebras/lie_algebras/verma_module.py +1630 -0
- sage/algebras/lie_algebras/virasoro.py +1186 -0
- sage/algebras/octonion_algebra.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/octonion_algebra.pxd +20 -0
- sage/algebras/octonion_algebra.pyx +987 -0
- sage/algebras/orlik_solomon.py +907 -0
- sage/algebras/orlik_terao.py +779 -0
- sage/algebras/steenrod/all.py +7 -0
- sage/algebras/steenrod/steenrod_algebra.py +4258 -0
- sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
- sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
- sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
- sage/algebras/weyl_algebra.py +1126 -0
- sage/all__sagemath_modules.py +62 -0
- sage/calculus/all__sagemath_modules.py +19 -0
- sage/calculus/expr.py +205 -0
- sage/calculus/integration.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/riemann.pyx +1521 -0
- sage/calculus/test_sympy.py +201 -0
- sage/calculus/transforms/all.py +7 -0
- sage/calculus/transforms/dft.py +844 -0
- sage/calculus/transforms/dwt.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/dwt.pxd +7 -0
- sage/calculus/transforms/dwt.pyx +160 -0
- sage/calculus/transforms/fft.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/fft.pxd +12 -0
- sage/calculus/transforms/fft.pyx +487 -0
- sage/calculus/wester.py +662 -0
- sage/coding/abstract_code.py +1108 -0
- sage/coding/ag_code.py +868 -0
- sage/coding/ag_code_decoders.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/ag_code_decoders.pyx +2639 -0
- sage/coding/all.py +15 -0
- sage/coding/bch_code.py +494 -0
- sage/coding/binary_code.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/binary_code.pxd +124 -0
- sage/coding/binary_code.pyx +4139 -0
- sage/coding/bounds_catalog.py +43 -0
- sage/coding/channel.py +819 -0
- sage/coding/channels_catalog.py +29 -0
- sage/coding/code_bounds.py +755 -0
- sage/coding/code_constructions.py +804 -0
- sage/coding/codes_catalog.py +111 -0
- sage/coding/cyclic_code.py +1329 -0
- sage/coding/databases.py +316 -0
- sage/coding/decoder.py +373 -0
- sage/coding/decoders_catalog.py +88 -0
- sage/coding/delsarte_bounds.py +709 -0
- sage/coding/encoder.py +390 -0
- sage/coding/encoders_catalog.py +64 -0
- sage/coding/extended_code.py +468 -0
- sage/coding/gabidulin_code.py +1058 -0
- sage/coding/golay_code.py +404 -0
- sage/coding/goppa_code.py +441 -0
- sage/coding/grs_code.py +2371 -0
- sage/coding/guava.py +107 -0
- sage/coding/guruswami_sudan/all.py +1 -0
- sage/coding/guruswami_sudan/gs_decoder.py +897 -0
- sage/coding/guruswami_sudan/interpolation.py +409 -0
- sage/coding/guruswami_sudan/utils.py +176 -0
- sage/coding/hamming_code.py +176 -0
- sage/coding/information_set_decoder.py +1032 -0
- sage/coding/kasami_codes.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/kasami_codes.pyx +351 -0
- sage/coding/linear_code.py +3067 -0
- sage/coding/linear_code_no_metric.py +1354 -0
- sage/coding/linear_rank_metric.py +961 -0
- sage/coding/parity_check_code.py +353 -0
- sage/coding/punctured_code.py +719 -0
- sage/coding/reed_muller_code.py +999 -0
- sage/coding/self_dual_codes.py +942 -0
- sage/coding/source_coding/all.py +2 -0
- sage/coding/source_coding/huffman.py +553 -0
- sage/coding/subfield_subcode.py +423 -0
- sage/coding/two_weight_db.py +399 -0
- sage/combinat/all__sagemath_modules.py +7 -0
- sage/combinat/cartesian_product.py +347 -0
- sage/combinat/family.py +11 -0
- sage/combinat/free_module.py +1977 -0
- sage/combinat/root_system/all.py +147 -0
- sage/combinat/root_system/ambient_space.py +527 -0
- sage/combinat/root_system/associahedron.py +471 -0
- sage/combinat/root_system/braid_move_calculator.py +143 -0
- sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-musl.so +0 -0
- sage/combinat/root_system/braid_orbit.pyx +144 -0
- sage/combinat/root_system/branching_rules.py +2301 -0
- sage/combinat/root_system/cartan_matrix.py +1245 -0
- sage/combinat/root_system/cartan_type.py +3069 -0
- sage/combinat/root_system/coxeter_group.py +162 -0
- sage/combinat/root_system/coxeter_matrix.py +1261 -0
- sage/combinat/root_system/coxeter_type.py +681 -0
- sage/combinat/root_system/dynkin_diagram.py +900 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
- sage/combinat/root_system/fundamental_group.py +795 -0
- sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
- sage/combinat/root_system/integrable_representations.py +1227 -0
- sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
- sage/combinat/root_system/pieri_factors.py +1147 -0
- sage/combinat/root_system/plot.py +1615 -0
- sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
- sage/combinat/root_system/root_lattice_realizations.py +4628 -0
- sage/combinat/root_system/root_space.py +487 -0
- sage/combinat/root_system/root_system.py +882 -0
- sage/combinat/root_system/type_A.py +348 -0
- sage/combinat/root_system/type_A_affine.py +227 -0
- sage/combinat/root_system/type_A_infinity.py +241 -0
- sage/combinat/root_system/type_B.py +347 -0
- sage/combinat/root_system/type_BC_affine.py +287 -0
- sage/combinat/root_system/type_B_affine.py +216 -0
- sage/combinat/root_system/type_C.py +317 -0
- sage/combinat/root_system/type_C_affine.py +188 -0
- sage/combinat/root_system/type_D.py +357 -0
- sage/combinat/root_system/type_D_affine.py +208 -0
- sage/combinat/root_system/type_E.py +641 -0
- sage/combinat/root_system/type_E_affine.py +231 -0
- sage/combinat/root_system/type_F.py +387 -0
- sage/combinat/root_system/type_F_affine.py +137 -0
- sage/combinat/root_system/type_G.py +293 -0
- sage/combinat/root_system/type_G_affine.py +132 -0
- sage/combinat/root_system/type_H.py +105 -0
- sage/combinat/root_system/type_I.py +110 -0
- sage/combinat/root_system/type_Q.py +150 -0
- sage/combinat/root_system/type_affine.py +509 -0
- sage/combinat/root_system/type_dual.py +704 -0
- sage/combinat/root_system/type_folded.py +301 -0
- sage/combinat/root_system/type_marked.py +748 -0
- sage/combinat/root_system/type_reducible.py +601 -0
- sage/combinat/root_system/type_relabel.py +730 -0
- sage/combinat/root_system/type_super_A.py +837 -0
- sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
- sage/combinat/root_system/weight_space.py +639 -0
- sage/combinat/root_system/weyl_characters.py +2238 -0
- sage/crypto/__init__.py +4 -0
- sage/crypto/all.py +28 -0
- sage/crypto/block_cipher/all.py +7 -0
- sage/crypto/block_cipher/des.py +1065 -0
- sage/crypto/block_cipher/miniaes.py +2171 -0
- sage/crypto/block_cipher/present.py +909 -0
- sage/crypto/block_cipher/sdes.py +1527 -0
- sage/crypto/boolean_function.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/boolean_function.pxd +10 -0
- sage/crypto/boolean_function.pyx +1487 -0
- sage/crypto/cipher.py +78 -0
- sage/crypto/classical.py +3668 -0
- sage/crypto/classical_cipher.py +569 -0
- sage/crypto/cryptosystem.py +387 -0
- sage/crypto/key_exchange/all.py +7 -0
- sage/crypto/key_exchange/catalog.py +24 -0
- sage/crypto/key_exchange/diffie_hellman.py +323 -0
- sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
- sage/crypto/lattice.py +312 -0
- sage/crypto/lfsr.py +295 -0
- sage/crypto/lwe.py +840 -0
- sage/crypto/mq/__init__.py +4 -0
- sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
- sage/crypto/mq/rijndael_gf.py +2345 -0
- sage/crypto/mq/sbox.py +7 -0
- sage/crypto/mq/sr.py +3344 -0
- sage/crypto/public_key/all.py +5 -0
- sage/crypto/public_key/blum_goldwasser.py +776 -0
- sage/crypto/sbox.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/sbox.pyx +2090 -0
- sage/crypto/sboxes.py +2090 -0
- sage/crypto/stream.py +390 -0
- sage/crypto/stream_cipher.py +297 -0
- sage/crypto/util.py +519 -0
- sage/ext/all__sagemath_modules.py +1 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_modules.py +2 -0
- sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +30 -0
- sage/ext/interpreters/wrapper_cc.pyx +252 -0
- sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +26 -0
- sage/ext/interpreters/wrapper_cdf.pyx +245 -0
- sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +23 -0
- sage/ext/interpreters/wrapper_rdf.pyx +221 -0
- sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +28 -0
- sage/ext/interpreters/wrapper_rr.pyx +335 -0
- sage/geometry/all__sagemath_modules.py +5 -0
- sage/geometry/toric_lattice.py +1745 -0
- sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/geometry/toric_lattice_element.pyx +432 -0
- sage/groups/abelian_gps/abelian_group.py +1925 -0
- sage/groups/abelian_gps/abelian_group_element.py +164 -0
- sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
- sage/groups/abelian_gps/dual_abelian_group.py +421 -0
- sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
- sage/groups/abelian_gps/element_base.py +341 -0
- sage/groups/abelian_gps/values.py +488 -0
- sage/groups/additive_abelian/additive_abelian_group.py +476 -0
- sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
- sage/groups/additive_abelian/all.py +4 -0
- sage/groups/additive_abelian/qmodnz.py +231 -0
- sage/groups/additive_abelian/qmodnz_element.py +349 -0
- sage/groups/affine_gps/affine_group.py +535 -0
- sage/groups/affine_gps/all.py +1 -0
- sage/groups/affine_gps/catalog.py +17 -0
- sage/groups/affine_gps/euclidean_group.py +246 -0
- sage/groups/affine_gps/group_element.py +562 -0
- sage/groups/all__sagemath_modules.py +12 -0
- sage/groups/galois_group.py +479 -0
- sage/groups/matrix_gps/all.py +4 -0
- sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
- sage/groups/matrix_gps/catalog.py +26 -0
- sage/groups/matrix_gps/coxeter_group.py +927 -0
- sage/groups/matrix_gps/finitely_generated.py +487 -0
- sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/matrix_gps/group_element.pxd +11 -0
- sage/groups/matrix_gps/group_element.pyx +431 -0
- sage/groups/matrix_gps/linear.py +440 -0
- sage/groups/matrix_gps/matrix_group.py +617 -0
- sage/groups/matrix_gps/named_group.py +296 -0
- sage/groups/matrix_gps/orthogonal.py +544 -0
- sage/groups/matrix_gps/symplectic.py +251 -0
- sage/groups/matrix_gps/unitary.py +436 -0
- sage/groups/misc_gps/all__sagemath_modules.py +1 -0
- sage/groups/misc_gps/argument_groups.py +1905 -0
- sage/groups/misc_gps/imaginary_groups.py +479 -0
- sage/groups/perm_gps/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
- sage/homology/algebraic_topological_model.py +595 -0
- sage/homology/all.py +2 -0
- sage/homology/all__sagemath_modules.py +8 -0
- sage/homology/chain_complex.py +2148 -0
- sage/homology/chain_complex_homspace.py +165 -0
- sage/homology/chain_complex_morphism.py +629 -0
- sage/homology/chain_homotopy.py +604 -0
- sage/homology/chains.py +653 -0
- sage/homology/free_resolution.py +923 -0
- sage/homology/graded_resolution.py +567 -0
- sage/homology/hochschild_complex.py +756 -0
- sage/homology/homology_group.py +188 -0
- sage/homology/homology_morphism.py +422 -0
- sage/homology/homology_vector_space_with_basis.py +1454 -0
- sage/homology/koszul_complex.py +169 -0
- sage/homology/matrix_utils.py +205 -0
- sage/libs/all__sagemath_modules.py +1 -0
- sage/libs/gsl/__init__.py +1 -0
- sage/libs/gsl/airy.pxd +56 -0
- sage/libs/gsl/all.pxd +66 -0
- sage/libs/gsl/array.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/gsl/array.pxd +5 -0
- sage/libs/gsl/array.pyx +102 -0
- sage/libs/gsl/bessel.pxd +208 -0
- sage/libs/gsl/blas.pxd +116 -0
- sage/libs/gsl/blas_types.pxd +34 -0
- sage/libs/gsl/block.pxd +52 -0
- sage/libs/gsl/chebyshev.pxd +37 -0
- sage/libs/gsl/clausen.pxd +12 -0
- sage/libs/gsl/combination.pxd +47 -0
- sage/libs/gsl/complex.pxd +151 -0
- sage/libs/gsl/coulomb.pxd +30 -0
- sage/libs/gsl/coupling.pxd +21 -0
- sage/libs/gsl/dawson.pxd +12 -0
- sage/libs/gsl/debye.pxd +24 -0
- sage/libs/gsl/dilog.pxd +14 -0
- sage/libs/gsl/eigen.pxd +46 -0
- sage/libs/gsl/elementary.pxd +12 -0
- sage/libs/gsl/ellint.pxd +48 -0
- sage/libs/gsl/elljac.pxd +8 -0
- sage/libs/gsl/erf.pxd +32 -0
- sage/libs/gsl/errno.pxd +26 -0
- sage/libs/gsl/exp.pxd +44 -0
- sage/libs/gsl/expint.pxd +44 -0
- sage/libs/gsl/fermi_dirac.pxd +44 -0
- sage/libs/gsl/fft.pxd +121 -0
- sage/libs/gsl/fit.pxd +50 -0
- sage/libs/gsl/gamma.pxd +94 -0
- sage/libs/gsl/gegenbauer.pxd +26 -0
- sage/libs/gsl/histogram.pxd +176 -0
- sage/libs/gsl/hyperg.pxd +52 -0
- sage/libs/gsl/integration.pxd +69 -0
- sage/libs/gsl/interp.pxd +109 -0
- sage/libs/gsl/laguerre.pxd +24 -0
- sage/libs/gsl/lambert.pxd +16 -0
- sage/libs/gsl/legendre.pxd +90 -0
- sage/libs/gsl/linalg.pxd +185 -0
- sage/libs/gsl/log.pxd +26 -0
- sage/libs/gsl/math.pxd +43 -0
- sage/libs/gsl/matrix.pxd +143 -0
- sage/libs/gsl/matrix_complex.pxd +130 -0
- sage/libs/gsl/min.pxd +67 -0
- sage/libs/gsl/monte.pxd +56 -0
- sage/libs/gsl/ntuple.pxd +32 -0
- sage/libs/gsl/odeiv.pxd +70 -0
- sage/libs/gsl/permutation.pxd +78 -0
- sage/libs/gsl/poly.pxd +40 -0
- sage/libs/gsl/pow_int.pxd +12 -0
- sage/libs/gsl/psi.pxd +28 -0
- sage/libs/gsl/qrng.pxd +29 -0
- sage/libs/gsl/random.pxd +257 -0
- sage/libs/gsl/rng.pxd +100 -0
- sage/libs/gsl/roots.pxd +72 -0
- sage/libs/gsl/sort.pxd +36 -0
- sage/libs/gsl/statistics.pxd +59 -0
- sage/libs/gsl/sum.pxd +55 -0
- sage/libs/gsl/synchrotron.pxd +16 -0
- sage/libs/gsl/transport.pxd +24 -0
- sage/libs/gsl/trig.pxd +58 -0
- sage/libs/gsl/types.pxd +137 -0
- sage/libs/gsl/vector.pxd +101 -0
- sage/libs/gsl/vector_complex.pxd +83 -0
- sage/libs/gsl/wavelet.pxd +49 -0
- sage/libs/gsl/zeta.pxd +28 -0
- sage/libs/mpc/__init__.pxd +114 -0
- sage/libs/mpc/types.pxd +28 -0
- sage/libs/mpfr/__init__.pxd +299 -0
- sage/libs/mpfr/types.pxd +26 -0
- sage/libs/mpmath/__init__.py +1 -0
- sage/libs/mpmath/all.py +27 -0
- sage/libs/mpmath/all__sagemath_modules.py +1 -0
- sage/libs/mpmath/utils.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/action.pxd +26 -0
- sage/matrix/action.pyx +596 -0
- sage/matrix/all.py +9 -0
- sage/matrix/args.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/args.pxd +144 -0
- sage/matrix/args.pyx +1668 -0
- sage/matrix/benchmark.py +1258 -0
- sage/matrix/berlekamp_massey.py +95 -0
- sage/matrix/compute_J_ideal.py +926 -0
- sage/matrix/constructor.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_cdv.pxd +4 -0
- sage/matrix/matrix_cdv.pyx +93 -0
- sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_complex_double_dense.pxd +5 -0
- sage/matrix/matrix_complex_double_dense.pyx +98 -0
- sage/matrix/matrix_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_dense.pxd +5 -0
- sage/matrix/matrix_dense.pyx +343 -0
- sage/matrix/matrix_domain_dense.pxd +5 -0
- sage/matrix/matrix_domain_sparse.pxd +5 -0
- sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_dense.pxd +7 -0
- sage/matrix/matrix_double_dense.pyx +3906 -0
- sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_sparse.pxd +6 -0
- sage/matrix/matrix_double_sparse.pyx +248 -0
- sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_dense.pxd +7 -0
- sage/matrix/matrix_generic_dense.pyx +354 -0
- sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_sparse.pxd +7 -0
- sage/matrix/matrix_generic_sparse.pyx +461 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
- sage/matrix/matrix_misc.py +313 -0
- sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_dense.pxd +14 -0
- sage/matrix/matrix_numpy_dense.pyx +450 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
- sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
- sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_polynomial_dense.pxd +5 -0
- sage/matrix/matrix_polynomial_dense.pyx +5341 -0
- sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_real_double_dense.pxd +7 -0
- sage/matrix/matrix_real_double_dense.pyx +122 -0
- sage/matrix/matrix_space.py +2848 -0
- sage/matrix/matrix_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_sparse.pxd +5 -0
- sage/matrix/matrix_sparse.pyx +1222 -0
- sage/matrix/matrix_window.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_window.pxd +37 -0
- sage/matrix/matrix_window.pyx +242 -0
- sage/matrix/misc_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/misc_mpfr.pyx +80 -0
- sage/matrix/operation_table.py +1182 -0
- sage/matrix/special.py +3666 -0
- sage/matrix/strassen.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/strassen.pyx +851 -0
- sage/matrix/symplectic_basis.py +541 -0
- sage/matrix/template.pxd +6 -0
- sage/matrix/tests.py +71 -0
- sage/matroids/advanced.py +77 -0
- sage/matroids/all.py +13 -0
- sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_exchange_matroid.pxd +96 -0
- sage/matroids/basis_exchange_matroid.pyx +2344 -0
- sage/matroids/basis_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_matroid.pxd +45 -0
- sage/matroids/basis_matroid.pyx +1217 -0
- sage/matroids/catalog.py +44 -0
- sage/matroids/chow_ring.py +473 -0
- sage/matroids/chow_ring_ideal.py +849 -0
- sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuit_closures_matroid.pxd +16 -0
- sage/matroids/circuit_closures_matroid.pyx +559 -0
- sage/matroids/circuits_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuits_matroid.pxd +38 -0
- sage/matroids/circuits_matroid.pyx +947 -0
- sage/matroids/constructor.py +1086 -0
- sage/matroids/database_collections.py +365 -0
- sage/matroids/database_matroids.py +5338 -0
- sage/matroids/dual_matroid.py +583 -0
- sage/matroids/extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/flats_matroid.pxd +28 -0
- sage/matroids/flats_matroid.pyx +715 -0
- sage/matroids/gammoid.py +600 -0
- sage/matroids/graphic_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/graphic_matroid.pxd +39 -0
- sage/matroids/graphic_matroid.pyx +2024 -0
- sage/matroids/lean_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/lean_matrix.pxd +126 -0
- sage/matroids/lean_matrix.pyx +3667 -0
- sage/matroids/linear_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/matroid.pxd +243 -0
- sage/matroids/matroid.pyx +8759 -0
- sage/matroids/matroids_catalog.py +190 -0
- sage/matroids/matroids_plot_helpers.py +890 -0
- sage/matroids/minor_matroid.py +480 -0
- sage/matroids/minorfix.h +9 -0
- sage/matroids/named_matroids.py +5 -0
- sage/matroids/rank_matroid.py +268 -0
- sage/matroids/set_system.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/set_system.pxd +38 -0
- sage/matroids/set_system.pyx +800 -0
- sage/matroids/transversal_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/transversal_matroid.pxd +14 -0
- sage/matroids/transversal_matroid.pyx +893 -0
- sage/matroids/union_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/unpickling.pyx +843 -0
- sage/matroids/utilities.py +809 -0
- sage/misc/all__sagemath_modules.py +20 -0
- sage/misc/c3.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/c3.pyx +238 -0
- sage/misc/compat.py +87 -0
- sage/misc/element_with_label.py +173 -0
- sage/misc/func_persist.py +79 -0
- sage/misc/pickle_old.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/pickle_old.pyx +19 -0
- sage/misc/proof.py +7 -0
- sage/misc/replace_dot_all.py +472 -0
- sage/misc/sagedoc_conf.py +168 -0
- sage/misc/sphinxify.py +167 -0
- sage/misc/test_class_pickling.py +85 -0
- sage/modules/all.py +42 -0
- sage/modules/complex_double_vector.py +25 -0
- sage/modules/diamond_cutting.py +380 -0
- sage/modules/fg_pid/all.py +1 -0
- sage/modules/fg_pid/fgp_element.py +456 -0
- sage/modules/fg_pid/fgp_module.py +2091 -0
- sage/modules/fg_pid/fgp_morphism.py +550 -0
- sage/modules/filtered_vector_space.py +1271 -0
- sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/finite_submodule_iter.pxd +27 -0
- sage/modules/finite_submodule_iter.pyx +452 -0
- sage/modules/fp_graded/all.py +1 -0
- sage/modules/fp_graded/element.py +346 -0
- sage/modules/fp_graded/free_element.py +298 -0
- sage/modules/fp_graded/free_homspace.py +53 -0
- sage/modules/fp_graded/free_module.py +1060 -0
- sage/modules/fp_graded/free_morphism.py +217 -0
- sage/modules/fp_graded/homspace.py +563 -0
- sage/modules/fp_graded/module.py +1340 -0
- sage/modules/fp_graded/morphism.py +1990 -0
- sage/modules/fp_graded/steenrod/all.py +1 -0
- sage/modules/fp_graded/steenrod/homspace.py +65 -0
- sage/modules/fp_graded/steenrod/module.py +477 -0
- sage/modules/fp_graded/steenrod/morphism.py +404 -0
- sage/modules/fp_graded/steenrod/profile.py +241 -0
- sage/modules/free_module.py +8447 -0
- sage/modules/free_module_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/free_module_element.pxd +22 -0
- sage/modules/free_module_element.pyx +5445 -0
- sage/modules/free_module_homspace.py +369 -0
- sage/modules/free_module_integer.py +896 -0
- sage/modules/free_module_morphism.py +823 -0
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module.py +1706 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
- sage/modules/matrix_morphism.py +1745 -0
- sage/modules/misc.py +103 -0
- sage/modules/module_functors.py +192 -0
- sage/modules/multi_filtered_vector_space.py +719 -0
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +699 -0
- sage/modules/real_double_vector.py +22 -0
- sage/modules/submodule.py +255 -0
- sage/modules/tensor_operations.py +567 -0
- sage/modules/torsion_quadratic_module.py +1352 -0
- sage/modules/tutorial_free_modules.py +248 -0
- sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_complex_double_dense.pxd +6 -0
- sage/modules/vector_complex_double_dense.pyx +117 -0
- sage/modules/vector_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_double_dense.pxd +6 -0
- sage/modules/vector_double_dense.pyx +604 -0
- sage/modules/vector_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_dense.pxd +15 -0
- sage/modules/vector_integer_dense.pyx +361 -0
- sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_sparse.pxd +29 -0
- sage/modules/vector_integer_sparse.pyx +406 -0
- sage/modules/vector_modn_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_dense.pxd +12 -0
- sage/modules/vector_modn_dense.pyx +394 -0
- sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_sparse.pxd +21 -0
- sage/modules/vector_modn_sparse.pyx +298 -0
- sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_dense.pxd +15 -0
- sage/modules/vector_numpy_dense.pyx +304 -0
- sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_integer_dense.pxd +7 -0
- sage/modules/vector_numpy_integer_dense.pyx +54 -0
- sage/modules/vector_rational_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_dense.pxd +15 -0
- sage/modules/vector_rational_dense.pyx +387 -0
- sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_sparse.pxd +30 -0
- sage/modules/vector_rational_sparse.pyx +413 -0
- sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_real_double_dense.pxd +6 -0
- sage/modules/vector_real_double_dense.pyx +126 -0
- sage/modules/vector_space_homspace.py +430 -0
- sage/modules/vector_space_morphism.py +989 -0
- sage/modules/with_basis/all.py +15 -0
- sage/modules/with_basis/cell_module.py +494 -0
- sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/with_basis/indexed_element.pxd +13 -0
- sage/modules/with_basis/indexed_element.pyx +1058 -0
- sage/modules/with_basis/invariant.py +1075 -0
- sage/modules/with_basis/morphism.py +1636 -0
- sage/modules/with_basis/representation.py +2939 -0
- sage/modules/with_basis/subquotient.py +685 -0
- sage/numerical/all__sagemath_modules.py +6 -0
- sage/numerical/gauss_legendre.cpython-314-aarch64-linux-musl.so +0 -0
- sage/numerical/gauss_legendre.pyx +381 -0
- sage/numerical/optimize.py +910 -0
- sage/probability/all.py +10 -0
- sage/probability/probability_distribution.cpython-314-aarch64-linux-musl.so +0 -0
- sage/probability/probability_distribution.pyx +1242 -0
- sage/probability/random_variable.py +411 -0
- sage/quadratic_forms/all.py +4 -0
- sage/quadratic_forms/all__sagemath_modules.py +15 -0
- sage/quadratic_forms/binary_qf.py +2042 -0
- sage/quadratic_forms/bqf_class_group.py +748 -0
- sage/quadratic_forms/constructions.py +93 -0
- sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/count_local_2.pyx +365 -0
- sage/quadratic_forms/extras.py +195 -0
- sage/quadratic_forms/quadratic_form.py +1753 -0
- sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
- sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
- sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
- sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
- sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
- sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
- sage/quadratic_forms/quadratic_form__theta.py +352 -0
- sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
- sage/quadratic_forms/random_quadraticform.py +209 -0
- sage/quadratic_forms/ternary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/ternary.pyx +1154 -0
- sage/quadratic_forms/ternary_qf.py +2027 -0
- sage/rings/all__sagemath_modules.py +28 -0
- sage/rings/asymptotic/all__sagemath_modules.py +1 -0
- sage/rings/asymptotic/misc.py +1252 -0
- sage/rings/cc.py +4 -0
- sage/rings/cfinite_sequence.py +1306 -0
- sage/rings/complex_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_conversion.pxd +8 -0
- sage/rings/complex_conversion.pyx +23 -0
- sage/rings/complex_double.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_double.pxd +21 -0
- sage/rings/complex_double.pyx +2654 -0
- sage/rings/complex_mpc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpc.pxd +21 -0
- sage/rings/complex_mpc.pyx +2576 -0
- sage/rings/complex_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpfr.pxd +18 -0
- sage/rings/complex_mpfr.pyx +3602 -0
- sage/rings/derivation.py +2334 -0
- sage/rings/finite_rings/all__sagemath_modules.py +1 -0
- sage/rings/finite_rings/maps_finite_field.py +191 -0
- sage/rings/function_field/all__sagemath_modules.py +8 -0
- sage/rings/function_field/derivations.py +102 -0
- sage/rings/function_field/derivations_rational.py +132 -0
- sage/rings/function_field/differential.py +853 -0
- sage/rings/function_field/divisor.py +1107 -0
- sage/rings/function_field/drinfeld_modules/action.py +199 -0
- sage/rings/function_field/drinfeld_modules/all.py +1 -0
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
- sage/rings/function_field/drinfeld_modules/homset.py +420 -0
- sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
- sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +935 -0
- sage/rings/invariants/all.py +4 -0
- sage/rings/invariants/invariant_theory.py +4597 -0
- sage/rings/invariants/reconstruction.py +395 -0
- sage/rings/polynomial/all__sagemath_modules.py +17 -0
- sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
- sage/rings/polynomial/ore_function_element.py +952 -0
- sage/rings/polynomial/ore_function_field.py +1028 -0
- sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
- sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
- sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
- sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
- sage/rings/polynomial/skew_polynomial_ring.py +908 -0
- sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_double_element_gsl.pxd +8 -0
- sage/rings/real_double_element_gsl.pyx +794 -0
- sage/rings/real_field.py +58 -0
- sage/rings/real_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_mpfr.pxd +29 -0
- sage/rings/real_mpfr.pyx +6122 -0
- sage/rings/ring_extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension.pxd +42 -0
- sage/rings/ring_extension.pyx +2779 -0
- sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_conversion.pxd +16 -0
- sage/rings/ring_extension_conversion.pyx +462 -0
- sage/rings/ring_extension_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_element.pxd +21 -0
- sage/rings/ring_extension_element.pyx +1635 -0
- sage/rings/ring_extension_homset.py +64 -0
- sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_morphism.pxd +35 -0
- sage/rings/ring_extension_morphism.pyx +920 -0
- sage/schemes/all__sagemath_modules.py +1 -0
- sage/schemes/projective/all__sagemath_modules.py +1 -0
- sage/schemes/projective/coherent_sheaf.py +300 -0
- sage/schemes/projective/cohomology.py +510 -0
- sage/stats/all.py +15 -0
- sage/stats/basic_stats.py +489 -0
- sage/stats/distributions/all.py +7 -0
- sage/stats/distributions/catalog.py +34 -0
- sage/stats/distributions/dgs.h +50 -0
- sage/stats/distributions/dgs.pxd +111 -0
- sage/stats/distributions/dgs_bern.h +400 -0
- sage/stats/distributions/dgs_gauss.h +614 -0
- sage/stats/distributions/dgs_misc.h +104 -0
- sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
- sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
- sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
- sage/stats/hmm/all.py +15 -0
- sage/stats/hmm/chmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/distributions.pxd +29 -0
- sage/stats/hmm/distributions.pyx +531 -0
- sage/stats/hmm/hmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/hmm.pxd +17 -0
- sage/stats/hmm/hmm.pyx +1388 -0
- sage/stats/hmm/util.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/intlist.pxd +14 -0
- sage/stats/intlist.pyx +588 -0
- sage/stats/r.py +49 -0
- sage/stats/time_series.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/time_series.pxd +6 -0
- sage/stats/time_series.pyx +2546 -0
- sage/tensor/all.py +2 -0
- sage/tensor/modules/all.py +8 -0
- sage/tensor/modules/alternating_contr_tensor.py +761 -0
- sage/tensor/modules/comp.py +5598 -0
- sage/tensor/modules/ext_pow_free_module.py +824 -0
- sage/tensor/modules/finite_rank_free_module.py +3589 -0
- sage/tensor/modules/format_utilities.py +333 -0
- sage/tensor/modules/free_module_alt_form.py +858 -0
- sage/tensor/modules/free_module_automorphism.py +1207 -0
- sage/tensor/modules/free_module_basis.py +1074 -0
- sage/tensor/modules/free_module_element.py +284 -0
- sage/tensor/modules/free_module_homset.py +652 -0
- sage/tensor/modules/free_module_linear_group.py +564 -0
- sage/tensor/modules/free_module_morphism.py +1581 -0
- sage/tensor/modules/free_module_tensor.py +3289 -0
- sage/tensor/modules/reflexive_module.py +386 -0
- sage/tensor/modules/tensor_free_module.py +780 -0
- sage/tensor/modules/tensor_free_submodule.py +538 -0
- sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
- sage/tensor/modules/tensor_with_indices.py +1043 -0
|
@@ -0,0 +1,4252 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.libs.singular sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Commutative Differential Graded Algebras
|
|
5
|
+
|
|
6
|
+
An algebra is said to be *graded commutative* if it is endowed with a
|
|
7
|
+
grading and its multiplication satisfies the Koszul sign convention:
|
|
8
|
+
`yx = (-1)^{ij} xy` if `x` and `y` are homogeneous of degrees `i` and
|
|
9
|
+
`j`, respectively. Thus the multiplication is anticommutative for odd
|
|
10
|
+
degree elements, commutative otherwise. *Commutative differential
|
|
11
|
+
graded algebras* are graded commutative algebras endowed with a graded
|
|
12
|
+
differential of degree 1. These algebras can be graded over the
|
|
13
|
+
integers or they can be multi-graded (i.e., graded over a finite rank
|
|
14
|
+
free abelian group `\ZZ^n`); if multi-graded, the total degree is used
|
|
15
|
+
in the Koszul sign convention, and the differential must have total
|
|
16
|
+
degree 1.
|
|
17
|
+
|
|
18
|
+
EXAMPLES:
|
|
19
|
+
|
|
20
|
+
All of these algebras may be constructed with the function
|
|
21
|
+
:func:`GradedCommutativeAlgebra`. For most users, that will be the
|
|
22
|
+
main function of interest. See its documentation for many more
|
|
23
|
+
examples.
|
|
24
|
+
|
|
25
|
+
We start by constructing some graded commutative algebras. Generators
|
|
26
|
+
have degree 1 by default::
|
|
27
|
+
|
|
28
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ)
|
|
29
|
+
sage: x.degree()
|
|
30
|
+
1
|
|
31
|
+
sage: x^2
|
|
32
|
+
0
|
|
33
|
+
sage: y*x
|
|
34
|
+
-x*y
|
|
35
|
+
sage: B.<a,b> = GradedCommutativeAlgebra(QQ, degrees = (2,3))
|
|
36
|
+
sage: a.degree()
|
|
37
|
+
2
|
|
38
|
+
sage: b.degree()
|
|
39
|
+
3
|
|
40
|
+
|
|
41
|
+
Once we have defined a graded commutative algebra, it is easy to
|
|
42
|
+
define a differential on it using the :meth:`GCAlgebra.cdg_algebra` method::
|
|
43
|
+
|
|
44
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
45
|
+
sage: B = A.cdg_algebra({x: x*y, y: -x*y})
|
|
46
|
+
sage: B
|
|
47
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z')
|
|
48
|
+
in degrees (1, 1, 2) over Rational Field with differential:
|
|
49
|
+
x --> x*y
|
|
50
|
+
y --> -x*y
|
|
51
|
+
z --> 0
|
|
52
|
+
sage: B.cohomology(3)
|
|
53
|
+
Free module generated by {[x*z + y*z]} over Rational Field
|
|
54
|
+
sage: B.cohomology(4)
|
|
55
|
+
Free module generated by {[z^2]} over Rational Field
|
|
56
|
+
|
|
57
|
+
We can also compute algebra generators for the cohomology in a range
|
|
58
|
+
of degrees, and in this case we compute up to degree 10::
|
|
59
|
+
|
|
60
|
+
sage: B.cohomology_generators(10)
|
|
61
|
+
{1: [x + y], 2: [z]}
|
|
62
|
+
|
|
63
|
+
AUTHORS:
|
|
64
|
+
|
|
65
|
+
- Miguel Marco, John Palmieri (2014-07): initial version
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
# ****************************************************************************
|
|
69
|
+
# Copyright (C) 2014 Miguel Marco <mmarco@unizar.es>
|
|
70
|
+
#
|
|
71
|
+
# This program is free software: you can redistribute it and/or modify
|
|
72
|
+
# it under the terms of the GNU General Public License as published by
|
|
73
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
74
|
+
# (at your option) any later version.
|
|
75
|
+
# https://www.gnu.org/licenses/
|
|
76
|
+
# ****************************************************************************
|
|
77
|
+
|
|
78
|
+
from sage.structure.unique_representation import UniqueRepresentation, CachedRepresentation
|
|
79
|
+
from sage.structure.sage_object import SageObject
|
|
80
|
+
from sage.misc.cachefunc import cached_method
|
|
81
|
+
from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
|
|
82
|
+
from sage.misc.functional import is_odd, is_even
|
|
83
|
+
from sage.misc.lazy_import import lazy_import
|
|
84
|
+
from sage.misc.misc_c import prod
|
|
85
|
+
from sage.categories.chain_complexes import ChainComplexes
|
|
86
|
+
from sage.categories.algebras import Algebras
|
|
87
|
+
from sage.categories.morphism import Morphism
|
|
88
|
+
from sage.categories.modules import Modules
|
|
89
|
+
from sage.categories.homset import Hom
|
|
90
|
+
|
|
91
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
92
|
+
from sage.combinat.free_module import CombinatorialFreeModule
|
|
93
|
+
from sage.combinat.integer_vector_weighted import WeightedIntegerVectors
|
|
94
|
+
from sage.groups.additive_abelian.additive_abelian_group import AdditiveAbelianGroup
|
|
95
|
+
from sage.matrix.constructor import matrix
|
|
96
|
+
from sage.modules.free_module import VectorSpace
|
|
97
|
+
from sage.modules.free_module_element import vector
|
|
98
|
+
from sage.rings.integer_ring import ZZ
|
|
99
|
+
from sage.rings.homset import RingHomset_generic
|
|
100
|
+
from sage.rings.morphism import RingHomomorphism_im_gens
|
|
101
|
+
from sage.rings.polynomial.term_order import TermOrder
|
|
102
|
+
from sage.rings.quotient_ring import QuotientRing_nc
|
|
103
|
+
from sage.rings.quotient_ring_element import QuotientRingElement
|
|
104
|
+
from sage.misc.cachefunc import cached_function
|
|
105
|
+
|
|
106
|
+
import sage.interfaces.abc
|
|
107
|
+
|
|
108
|
+
lazy_import('sage.algebras.free_algebra', 'FreeAlgebra')
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def sorting_keys(element):
|
|
112
|
+
r"""
|
|
113
|
+
Auxiliary function to sort the elements of a basis of a Cohomology group.
|
|
114
|
+
|
|
115
|
+
It is needed to ensure that elements of a cohomology group are represented
|
|
116
|
+
in a consistent way.
|
|
117
|
+
|
|
118
|
+
INPUT:
|
|
119
|
+
|
|
120
|
+
- ``element`` -- a CohomologyClass
|
|
121
|
+
|
|
122
|
+
OUTPUT: its coordinates in the corresponding ``cohomology_raw`` quotient vector space
|
|
123
|
+
|
|
124
|
+
EXAMPLES::
|
|
125
|
+
|
|
126
|
+
sage: from sage.algebras.commutative_dga import sorting_keys
|
|
127
|
+
sage: A.<e1,e2,e3,e4,e5> = GradedCommutativeAlgebra(QQ)
|
|
128
|
+
sage: B = A.cdg_algebra({e5:e1*e2+e3*e4})
|
|
129
|
+
sage: B.inject_variables()
|
|
130
|
+
Defining e1, e2, e3, e4, e5
|
|
131
|
+
sage: C = B.cohomology(3)
|
|
132
|
+
sage: [sorting_keys(el) for el in C.basis().keys()]
|
|
133
|
+
[[1, 0, 0, 0, 0],
|
|
134
|
+
[0, 1, 0, 0, 0],
|
|
135
|
+
[0, 0, 1, 0, 0],
|
|
136
|
+
[0, 0, 0, 1, 0],
|
|
137
|
+
[0, 0, 0, 0, 1]]
|
|
138
|
+
"""
|
|
139
|
+
x = element._x
|
|
140
|
+
P = x.parent()
|
|
141
|
+
CR = P.cohomology_raw(x.degree())
|
|
142
|
+
V = CR.V()
|
|
143
|
+
return list(CR(V(x.basis_coefficients())))
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class Differential(UniqueRepresentation, Morphism,
|
|
147
|
+
metaclass=InheritComparisonClasscallMetaclass):
|
|
148
|
+
r"""
|
|
149
|
+
Differential of a commutative graded algebra.
|
|
150
|
+
|
|
151
|
+
INPUT:
|
|
152
|
+
|
|
153
|
+
- ``A`` -- algebra where the differential is defined
|
|
154
|
+
- ``im_gens`` -- tuple containing the image of each generator
|
|
155
|
+
|
|
156
|
+
EXAMPLES::
|
|
157
|
+
|
|
158
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2, 3))
|
|
159
|
+
sage: B = A.cdg_algebra({x: x*y, y: -x*y , z: t})
|
|
160
|
+
sage: B
|
|
161
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't')
|
|
162
|
+
in degrees (1, 1, 2, 3) over Rational Field with differential:
|
|
163
|
+
x --> x*y
|
|
164
|
+
y --> -x*y
|
|
165
|
+
z --> t
|
|
166
|
+
t --> 0
|
|
167
|
+
sage: B.differential()(x)
|
|
168
|
+
x*y
|
|
169
|
+
"""
|
|
170
|
+
@staticmethod
|
|
171
|
+
def __classcall__(cls, A, im_gens):
|
|
172
|
+
r"""
|
|
173
|
+
Normalize input to ensure a unique representation.
|
|
174
|
+
|
|
175
|
+
TESTS::
|
|
176
|
+
|
|
177
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2, 3))
|
|
178
|
+
sage: d1 = A.cdg_algebra({x: x*y, y: -x*y, z: t}).differential()
|
|
179
|
+
sage: d2 = A.cdg_algebra({x: x*y, z: t, y: -x*y, t: 0}).differential()
|
|
180
|
+
sage: d1 is d2
|
|
181
|
+
True
|
|
182
|
+
|
|
183
|
+
Check that :issue:`34818` is solved::
|
|
184
|
+
|
|
185
|
+
sage: A.<a,b,x,u> = GradedCommutativeAlgebra(QQ,degrees=(2,2,3,3))
|
|
186
|
+
sage: A = A.quotient(A.ideal([a*u,b*u,x*u]))
|
|
187
|
+
sage: A.cdg_algebra({x:a*b,a:u})
|
|
188
|
+
Commutative Differential Graded Algebra with generators ('a', 'b', 'x', 'u')
|
|
189
|
+
in degrees (2, 2, 3, 3) with relations [a*u, b*u, x*u] over Rational Field
|
|
190
|
+
with differential:
|
|
191
|
+
a --> u
|
|
192
|
+
b --> 0
|
|
193
|
+
x --> a*b
|
|
194
|
+
u --> 0
|
|
195
|
+
sage: A.cdg_algebra({x:a*b,a:u,u:a^2})
|
|
196
|
+
Traceback (most recent call last):
|
|
197
|
+
...
|
|
198
|
+
ValueError: the differential does not preserve the ideal
|
|
199
|
+
"""
|
|
200
|
+
if isinstance(im_gens, (list, tuple)):
|
|
201
|
+
im_gens = {A.gen(i): A(x) for i, x in enumerate(im_gens)}
|
|
202
|
+
else:
|
|
203
|
+
im_gens = {A(a): A(im_gens[a]) for a in im_gens}
|
|
204
|
+
|
|
205
|
+
I = A.defining_ideal()
|
|
206
|
+
|
|
207
|
+
def image_monomial(exponent):
|
|
208
|
+
i = 0
|
|
209
|
+
cexp = list(exponent)
|
|
210
|
+
ell = len(cexp)
|
|
211
|
+
while i < ell:
|
|
212
|
+
if not cexp[i]:
|
|
213
|
+
i += 1
|
|
214
|
+
continue
|
|
215
|
+
a = A.gen(i)
|
|
216
|
+
try:
|
|
217
|
+
da = im_gens[a]
|
|
218
|
+
except KeyError:
|
|
219
|
+
da = A.zero()
|
|
220
|
+
cexp[i] -= 1
|
|
221
|
+
b = A.prod(A.gen(j) ** cexp[j] for j in range(len(cexp)))
|
|
222
|
+
db = image_monomial(cexp)
|
|
223
|
+
im = da * b + (-1)**A._degrees[i] * a * db
|
|
224
|
+
return A(im)
|
|
225
|
+
return A.zero()
|
|
226
|
+
|
|
227
|
+
for g in I.gens():
|
|
228
|
+
d = g.monomial_coefficients()
|
|
229
|
+
res = A.sum(d[ex] * image_monomial(ex) for ex in d)
|
|
230
|
+
if not res.is_zero():
|
|
231
|
+
raise ValueError("the differential does not preserve the ideal")
|
|
232
|
+
|
|
233
|
+
for i in im_gens:
|
|
234
|
+
x = im_gens[i]
|
|
235
|
+
if (not x.is_zero()
|
|
236
|
+
and (not x.is_homogeneous()
|
|
237
|
+
or total_degree(x.degree())
|
|
238
|
+
!= total_degree(i.degree()) + 1)):
|
|
239
|
+
raise ValueError("the given dictionary does not determine a degree 1 map")
|
|
240
|
+
|
|
241
|
+
im_gens = tuple(im_gens.get(x, A.zero()) for x in A.gens())
|
|
242
|
+
return super().__classcall__(cls, A, im_gens)
|
|
243
|
+
|
|
244
|
+
def __init__(self, A, im_gens):
|
|
245
|
+
r"""
|
|
246
|
+
Initialize ``self``.
|
|
247
|
+
|
|
248
|
+
INPUT:
|
|
249
|
+
|
|
250
|
+
- ``A`` -- algebra where the differential is defined
|
|
251
|
+
|
|
252
|
+
- ``im_gens`` -- tuple containing the image of each generator
|
|
253
|
+
|
|
254
|
+
EXAMPLES::
|
|
255
|
+
|
|
256
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ)
|
|
257
|
+
sage: B = A.cdg_algebra({x: x*y, y: x*y, z: z*t, t: t*z})
|
|
258
|
+
sage: [B.cohomology(i).dimension() for i in range(6)]
|
|
259
|
+
[1, 2, 1, 0, 0, 0]
|
|
260
|
+
sage: d = B.differential()
|
|
261
|
+
|
|
262
|
+
We skip the category test because homsets/morphisms aren't
|
|
263
|
+
proper parents/elements yet::
|
|
264
|
+
|
|
265
|
+
sage: TestSuite(d).run(skip='_test_category')
|
|
266
|
+
|
|
267
|
+
An error is raised if the differential `d` does not have
|
|
268
|
+
degree 1 or if `d \circ d` is not zero::
|
|
269
|
+
|
|
270
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,2,3))
|
|
271
|
+
sage: A.cdg_algebra({a:b, b:c})
|
|
272
|
+
Traceback (most recent call last):
|
|
273
|
+
...
|
|
274
|
+
ValueError: the given dictionary does not determine a valid differential
|
|
275
|
+
"""
|
|
276
|
+
self._dic_ = {A.gen(i): x for i, x in enumerate(im_gens)}
|
|
277
|
+
Morphism.__init__(self, Hom(A, A, category=Modules(A.base_ring())))
|
|
278
|
+
|
|
279
|
+
for i in A.gens():
|
|
280
|
+
if not self(self(i)).is_zero():
|
|
281
|
+
raise ValueError("the given dictionary does not determine a valid differential")
|
|
282
|
+
|
|
283
|
+
def _call_(self, x):
|
|
284
|
+
r"""
|
|
285
|
+
Apply the differential to ``x``.
|
|
286
|
+
|
|
287
|
+
INPUT:
|
|
288
|
+
|
|
289
|
+
- ``x`` -- an element of the domain of this differential
|
|
290
|
+
|
|
291
|
+
EXAMPLES::
|
|
292
|
+
|
|
293
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ)
|
|
294
|
+
sage: B = A.cdg_algebra({x: x*y, y: x*y, z: z*t, t: t*z})
|
|
295
|
+
sage: D = B.differential()
|
|
296
|
+
sage: D(x*t+1/2*t*x*y) # indirect doctest
|
|
297
|
+
-1/2*x*y*z*t + x*y*t + x*z*t
|
|
298
|
+
|
|
299
|
+
Test positive characteristic::
|
|
300
|
+
|
|
301
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(GF(17), degrees=(2, 3))
|
|
302
|
+
sage: B = A.cdg_algebra(differential={x:y})
|
|
303
|
+
sage: B.differential()(x^17)
|
|
304
|
+
0
|
|
305
|
+
"""
|
|
306
|
+
if x.is_zero():
|
|
307
|
+
return self.codomain().zero()
|
|
308
|
+
res = self.codomain().zero()
|
|
309
|
+
dic = x.monomial_coefficients()
|
|
310
|
+
for key in dic:
|
|
311
|
+
keyl = list(key)
|
|
312
|
+
coef = dic[key]
|
|
313
|
+
idx = 0
|
|
314
|
+
while keyl:
|
|
315
|
+
exp = keyl.pop(0)
|
|
316
|
+
if exp > 0:
|
|
317
|
+
v1 = (exp * self._dic_[x.parent().gen(idx)]
|
|
318
|
+
* x.parent().gen(idx)**(exp - 1))
|
|
319
|
+
v2 = prod(x.parent().gen(i + idx + 1)**keyl[i] for i in
|
|
320
|
+
range(len(keyl)))
|
|
321
|
+
res += coef * v1 * v2
|
|
322
|
+
coef *= ((-1) ** total_degree(x.parent()._degrees[idx])
|
|
323
|
+
* x.parent().gen(idx)**exp)
|
|
324
|
+
idx += 1
|
|
325
|
+
return res
|
|
326
|
+
|
|
327
|
+
def _repr_defn(self):
|
|
328
|
+
r"""
|
|
329
|
+
Return a string showing where ``self`` sends each generator.
|
|
330
|
+
|
|
331
|
+
EXAMPLES::
|
|
332
|
+
|
|
333
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ)
|
|
334
|
+
sage: B = A.cdg_algebra({x: x*y, y: x*y, z: z*t, t: t*z})
|
|
335
|
+
sage: D = B.differential()
|
|
336
|
+
sage: print(D._repr_defn())
|
|
337
|
+
x --> x*y
|
|
338
|
+
y --> x*y
|
|
339
|
+
z --> z*t
|
|
340
|
+
t --> -z*t
|
|
341
|
+
"""
|
|
342
|
+
return '\n'.join(f"{i} --> {self(i)}" for i in self.domain().gens())
|
|
343
|
+
|
|
344
|
+
def _repr_(self):
|
|
345
|
+
r"""
|
|
346
|
+
Return a string representation of ``self``.
|
|
347
|
+
|
|
348
|
+
EXAMPLES::
|
|
349
|
+
|
|
350
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ)
|
|
351
|
+
sage: D = A.differential({x: x*y, y: x*y, z: z*t, t: t*z})
|
|
352
|
+
sage: D
|
|
353
|
+
Differential of Graded Commutative Algebra with generators ('x', 'y', 'z', 't') in degrees (1, 1, 1, 1) over Rational Field
|
|
354
|
+
Defn: x --> x*y
|
|
355
|
+
y --> x*y
|
|
356
|
+
z --> z*t
|
|
357
|
+
t --> -z*t
|
|
358
|
+
"""
|
|
359
|
+
if self.domain() is None:
|
|
360
|
+
return "Defunct morphism"
|
|
361
|
+
|
|
362
|
+
s = "Differential of {}".format(self.domain()._base_repr())
|
|
363
|
+
s += "\n Defn: " + '\n '.join(self._repr_defn().split('\n'))
|
|
364
|
+
return s
|
|
365
|
+
|
|
366
|
+
@cached_method
|
|
367
|
+
def differential_matrix(self, n):
|
|
368
|
+
r"""
|
|
369
|
+
The matrix that gives the differential in degree ``n``.
|
|
370
|
+
|
|
371
|
+
INPUT:
|
|
372
|
+
|
|
373
|
+
- ``n`` -- degree
|
|
374
|
+
|
|
375
|
+
EXAMPLES::
|
|
376
|
+
|
|
377
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(GF(5), degrees=(2, 2, 3, 4))
|
|
378
|
+
sage: d = A.differential({t: x*z, x: z, y: z})
|
|
379
|
+
sage: d.differential_matrix(4)
|
|
380
|
+
[2 0]
|
|
381
|
+
[1 1]
|
|
382
|
+
[0 2]
|
|
383
|
+
[1 0]
|
|
384
|
+
sage: A.inject_variables()
|
|
385
|
+
Defining x, y, z, t
|
|
386
|
+
sage: d(t)
|
|
387
|
+
x*z
|
|
388
|
+
sage: d(y^2)
|
|
389
|
+
2*y*z
|
|
390
|
+
sage: d(x*y)
|
|
391
|
+
x*z + y*z
|
|
392
|
+
sage: d(x^2)
|
|
393
|
+
2*x*z
|
|
394
|
+
"""
|
|
395
|
+
A = self.domain()
|
|
396
|
+
dom = A.basis(n)
|
|
397
|
+
cod = A.basis(n + 1)
|
|
398
|
+
cokeys = [next(iter(a.lift().monomial_coefficients().keys())) for a in cod]
|
|
399
|
+
m = matrix(A.base_ring(), len(dom), len(cod))
|
|
400
|
+
for i, domi in enumerate(dom):
|
|
401
|
+
im = self(domi)
|
|
402
|
+
dic = im.lift().monomial_coefficients()
|
|
403
|
+
for j in dic.keys():
|
|
404
|
+
k = cokeys.index(j)
|
|
405
|
+
m[i, k] = dic[j]
|
|
406
|
+
m.set_immutable()
|
|
407
|
+
return m
|
|
408
|
+
|
|
409
|
+
def coboundaries(self, n):
|
|
410
|
+
r"""
|
|
411
|
+
The ``n``-th coboundary group of the algebra.
|
|
412
|
+
|
|
413
|
+
This is a vector space over the base field `F`, and it is
|
|
414
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
415
|
+
``n``-th homogeneous component has dimension `d`.
|
|
416
|
+
|
|
417
|
+
INPUT:
|
|
418
|
+
|
|
419
|
+
- ``n`` -- degree
|
|
420
|
+
|
|
421
|
+
EXAMPLES::
|
|
422
|
+
|
|
423
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2))
|
|
424
|
+
sage: d = A.differential({z: x*z})
|
|
425
|
+
sage: d.coboundaries(2)
|
|
426
|
+
Vector space of degree 2 and dimension 0 over Rational Field
|
|
427
|
+
Basis matrix:
|
|
428
|
+
[]
|
|
429
|
+
sage: d.coboundaries(3)
|
|
430
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
431
|
+
Basis matrix:
|
|
432
|
+
[1 0]
|
|
433
|
+
sage: d.coboundaries(1)
|
|
434
|
+
Vector space of degree 2 and dimension 0 over Rational Field
|
|
435
|
+
Basis matrix:
|
|
436
|
+
[]
|
|
437
|
+
"""
|
|
438
|
+
A = self.domain()
|
|
439
|
+
F = A.base_ring()
|
|
440
|
+
if n == 0:
|
|
441
|
+
return VectorSpace(F, 0)
|
|
442
|
+
if n == 1:
|
|
443
|
+
V0 = VectorSpace(F, len(A.basis(1)))
|
|
444
|
+
return V0.subspace([])
|
|
445
|
+
M = self.differential_matrix(n - 1)
|
|
446
|
+
V0 = VectorSpace(F, M.nrows())
|
|
447
|
+
V1 = VectorSpace(F, M.ncols())
|
|
448
|
+
mor = V0.Hom(V1)(M)
|
|
449
|
+
return mor.image()
|
|
450
|
+
|
|
451
|
+
def cocycles(self, n):
|
|
452
|
+
r"""
|
|
453
|
+
The ``n``-th cocycle group of the algebra.
|
|
454
|
+
|
|
455
|
+
This is a vector space over the base field `F`, and it is
|
|
456
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
457
|
+
``n``-th homogeneous component has dimension `d`.
|
|
458
|
+
|
|
459
|
+
INPUT:
|
|
460
|
+
|
|
461
|
+
- ``n`` -- degree
|
|
462
|
+
|
|
463
|
+
EXAMPLES::
|
|
464
|
+
|
|
465
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2))
|
|
466
|
+
sage: d = A.differential({z: x*z})
|
|
467
|
+
sage: d.cocycles(2)
|
|
468
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
469
|
+
Basis matrix:
|
|
470
|
+
[1 0]
|
|
471
|
+
"""
|
|
472
|
+
A = self.domain()
|
|
473
|
+
F = A.base_ring()
|
|
474
|
+
if n == 0:
|
|
475
|
+
return VectorSpace(F, 1)
|
|
476
|
+
M = self.differential_matrix(n)
|
|
477
|
+
V0 = VectorSpace(F, M.nrows())
|
|
478
|
+
V1 = VectorSpace(F, M.ncols())
|
|
479
|
+
mor = V0.Hom(V1)(M)
|
|
480
|
+
return mor.kernel()
|
|
481
|
+
|
|
482
|
+
def cohomology_raw(self, n):
|
|
483
|
+
r"""
|
|
484
|
+
The ``n``-th cohomology group of ``self``.
|
|
485
|
+
|
|
486
|
+
This is a vector space over the base ring, and it is returned
|
|
487
|
+
as the quotient cocycles/coboundaries.
|
|
488
|
+
|
|
489
|
+
INPUT:
|
|
490
|
+
|
|
491
|
+
- ``n`` -- degree
|
|
492
|
+
|
|
493
|
+
.. SEEALSO::
|
|
494
|
+
|
|
495
|
+
:meth:`cohomology`
|
|
496
|
+
|
|
497
|
+
EXAMPLES::
|
|
498
|
+
|
|
499
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 4))
|
|
500
|
+
sage: d = A.differential({t: x*z, x: z, y: z})
|
|
501
|
+
sage: d.cohomology_raw(4)
|
|
502
|
+
Vector space quotient V/W of dimension 2 over Rational Field where
|
|
503
|
+
V: Vector space of degree 4 and dimension 2 over Rational Field
|
|
504
|
+
Basis matrix:
|
|
505
|
+
[ 1 0 0 -2]
|
|
506
|
+
[ 0 1 -1/2 -1]
|
|
507
|
+
W: Vector space of degree 4 and dimension 0 over Rational Field
|
|
508
|
+
Basis matrix:
|
|
509
|
+
[]
|
|
510
|
+
|
|
511
|
+
Compare to :meth:`cohomology`::
|
|
512
|
+
|
|
513
|
+
sage: d.cohomology(4)
|
|
514
|
+
Free module generated by {[x^2 - 2*t], [x*y - 1/2*y^2 - t]} over Rational Field
|
|
515
|
+
"""
|
|
516
|
+
return self.cocycles(n).quotient(self.coboundaries(n))
|
|
517
|
+
|
|
518
|
+
def cohomology(self, n):
|
|
519
|
+
r"""
|
|
520
|
+
The ``n``-th cohomology group of ``self``.
|
|
521
|
+
|
|
522
|
+
This is a vector space over the base ring, defined as the
|
|
523
|
+
quotient cocycles/coboundaries. The elements of the quotient
|
|
524
|
+
are lifted to the vector space of cocycles, and this is
|
|
525
|
+
described in terms of those lifts.
|
|
526
|
+
|
|
527
|
+
INPUT:
|
|
528
|
+
|
|
529
|
+
- ``n`` -- degree
|
|
530
|
+
|
|
531
|
+
.. SEEALSO::
|
|
532
|
+
|
|
533
|
+
:meth:`cohomology_raw`
|
|
534
|
+
|
|
535
|
+
EXAMPLES::
|
|
536
|
+
|
|
537
|
+
sage: A.<a,b,c,d,e> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 1, 1, 1))
|
|
538
|
+
sage: d = A.differential({d: a*b, e: b*c})
|
|
539
|
+
sage: d.cohomology(2)
|
|
540
|
+
Free module generated by {[a*c], [a*d], [b*d], [c*d - a*e], [b*e], [c*e]} over Rational Field
|
|
541
|
+
|
|
542
|
+
Compare to :meth:`cohomology_raw`::
|
|
543
|
+
|
|
544
|
+
sage: d.cohomology_raw(2)
|
|
545
|
+
Vector space quotient V/W of dimension 6 over Rational Field where
|
|
546
|
+
V: Vector space of degree 10 and dimension 8 over Rational Field
|
|
547
|
+
Basis matrix:
|
|
548
|
+
[ 1 0 0 0 0 0 0 0 0 0]
|
|
549
|
+
[ 0 1 0 0 0 0 0 0 0 0]
|
|
550
|
+
[ 0 0 1 0 0 0 0 0 0 0]
|
|
551
|
+
[ 0 0 0 1 0 0 0 0 0 0]
|
|
552
|
+
[ 0 0 0 0 1 0 0 0 0 0]
|
|
553
|
+
[ 0 0 0 0 0 1 -1 0 0 0]
|
|
554
|
+
[ 0 0 0 0 0 0 0 1 0 0]
|
|
555
|
+
[ 0 0 0 0 0 0 0 0 1 0]
|
|
556
|
+
W: Vector space of degree 10 and dimension 2 over Rational Field
|
|
557
|
+
Basis matrix:
|
|
558
|
+
[1 0 0 0 0 0 0 0 0 0]
|
|
559
|
+
[0 0 1 0 0 0 0 0 0 0]
|
|
560
|
+
"""
|
|
561
|
+
H = self.cohomology_raw(n)
|
|
562
|
+
H_basis_raw = (H.lift(H.basis()[i]) for i in range(H.dimension()))
|
|
563
|
+
A = self.domain()
|
|
564
|
+
B = A.basis(n)
|
|
565
|
+
H_basis = (sum(c * b for (c, b) in zip(coeffs, B))
|
|
566
|
+
for coeffs in H_basis_raw)
|
|
567
|
+
# Put brackets around classes.
|
|
568
|
+
H_basis_brackets = [CohomologyClass(b, A) for b in H_basis]
|
|
569
|
+
return CombinatorialFreeModule(A.base_ring(),
|
|
570
|
+
H_basis_brackets,
|
|
571
|
+
sorting_key=sorting_keys,
|
|
572
|
+
monomial_reverse=True)
|
|
573
|
+
|
|
574
|
+
homology = cohomology
|
|
575
|
+
|
|
576
|
+
def _is_nonzero(self):
|
|
577
|
+
"""
|
|
578
|
+
Return ``True`` iff this morphism is nonzero.
|
|
579
|
+
|
|
580
|
+
This is used by the :meth:`Morphism.__bool__` method, which
|
|
581
|
+
in turn is used by the :func:`TestSuite` test
|
|
582
|
+
``_test_nonzero_equal``.
|
|
583
|
+
|
|
584
|
+
EXAMPLES::
|
|
585
|
+
|
|
586
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2, 3))
|
|
587
|
+
sage: B = A.cdg_algebra({x: x*y, y: -x*y , z: t})
|
|
588
|
+
sage: B.differential()._is_nonzero()
|
|
589
|
+
True
|
|
590
|
+
sage: bool(B.differential())
|
|
591
|
+
True
|
|
592
|
+
sage: C = A.cdg_algebra({x: 0, y: 0, z: 0})
|
|
593
|
+
sage: C.differential()._is_nonzero()
|
|
594
|
+
False
|
|
595
|
+
sage: bool(C.differential())
|
|
596
|
+
False
|
|
597
|
+
"""
|
|
598
|
+
return any(self._dic_.values())
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
class Differential_multigraded(Differential):
|
|
602
|
+
"""
|
|
603
|
+
Differential of a commutative multi-graded algebra.
|
|
604
|
+
"""
|
|
605
|
+
def __init__(self, A, im_gens):
|
|
606
|
+
"""
|
|
607
|
+
Initialize ``self``.
|
|
608
|
+
|
|
609
|
+
EXAMPLES::
|
|
610
|
+
|
|
611
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1, 0), (0, 1), (0, 2)))
|
|
612
|
+
sage: d = A.differential({a: c})
|
|
613
|
+
|
|
614
|
+
We skip the category test because homsets/morphisms aren't
|
|
615
|
+
proper parents/elements yet::
|
|
616
|
+
|
|
617
|
+
sage: TestSuite(d).run(skip='_test_category')
|
|
618
|
+
"""
|
|
619
|
+
Differential.__init__(self, A, im_gens)
|
|
620
|
+
|
|
621
|
+
# Check that the differential has a well-defined degree.
|
|
622
|
+
# diff_deg = [self(x).degree() - x.degree() for x in A.gens()]
|
|
623
|
+
diff_deg = []
|
|
624
|
+
for x in A.gens():
|
|
625
|
+
y = self(x)
|
|
626
|
+
if y != 0:
|
|
627
|
+
diff_deg.append(y.degree() - x.degree())
|
|
628
|
+
if len(set(diff_deg)) > 1:
|
|
629
|
+
raise ValueError("the differential does not have a well-defined degree")
|
|
630
|
+
self._degree_of_differential = diff_deg[0]
|
|
631
|
+
|
|
632
|
+
@cached_method
|
|
633
|
+
def differential_matrix_multigraded(self, n, total=False):
|
|
634
|
+
"""
|
|
635
|
+
The matrix that gives the differential in degree ``n``.
|
|
636
|
+
|
|
637
|
+
.. TODO::
|
|
638
|
+
|
|
639
|
+
Rename this to ``differential_matrix`` once inheritance,
|
|
640
|
+
overriding, and cached methods work together better. See
|
|
641
|
+
:issue:`17201`.
|
|
642
|
+
|
|
643
|
+
INPUT:
|
|
644
|
+
|
|
645
|
+
- ``n`` -- degree
|
|
646
|
+
- ``total`` -- boolean (default: ``False``); if ``True``,
|
|
647
|
+
return the matrix corresponding to total degree `n`
|
|
648
|
+
|
|
649
|
+
If `n` is an integer rather than a multi-index, then the
|
|
650
|
+
total degree is used in that case as well.
|
|
651
|
+
|
|
652
|
+
EXAMPLES::
|
|
653
|
+
|
|
654
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1, 0), (0, 1), (0, 2)))
|
|
655
|
+
sage: d = A.differential({a: c})
|
|
656
|
+
sage: d.differential_matrix_multigraded((1, 0))
|
|
657
|
+
[1]
|
|
658
|
+
sage: d.differential_matrix_multigraded(1, total=True)
|
|
659
|
+
[0 1]
|
|
660
|
+
[0 0]
|
|
661
|
+
sage: d.differential_matrix_multigraded((1, 0), total=True)
|
|
662
|
+
[0 1]
|
|
663
|
+
[0 0]
|
|
664
|
+
sage: d.differential_matrix_multigraded(1)
|
|
665
|
+
[0 1]
|
|
666
|
+
[0 0]
|
|
667
|
+
"""
|
|
668
|
+
if total or n in ZZ:
|
|
669
|
+
return Differential.differential_matrix(self, total_degree(n))
|
|
670
|
+
|
|
671
|
+
A = self.domain()
|
|
672
|
+
G = AdditiveAbelianGroup([0] * A._grading_rank)
|
|
673
|
+
n = G(vector(n))
|
|
674
|
+
dom = A.basis(n)
|
|
675
|
+
cod = A.basis(n + self._degree_of_differential)
|
|
676
|
+
cokeys = [next(iter(a.lift().monomial_coefficients().keys())) for a in cod]
|
|
677
|
+
m = matrix(self.base_ring(), len(dom), len(cod))
|
|
678
|
+
for i, domi in enumerate(dom):
|
|
679
|
+
im = self(domi)
|
|
680
|
+
dic = im.lift().monomial_coefficients()
|
|
681
|
+
for j in dic.keys():
|
|
682
|
+
k = cokeys.index(j)
|
|
683
|
+
m[i, k] = dic[j]
|
|
684
|
+
m.set_immutable()
|
|
685
|
+
return m
|
|
686
|
+
|
|
687
|
+
def coboundaries(self, n, total=False):
|
|
688
|
+
"""
|
|
689
|
+
The `n`-th coboundary group of the algebra.
|
|
690
|
+
|
|
691
|
+
This is a vector space over the base field `F`, and it is
|
|
692
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
693
|
+
`n`-th homogeneous component has dimension `d`.
|
|
694
|
+
|
|
695
|
+
INPUT:
|
|
696
|
+
|
|
697
|
+
- ``n`` -- degree
|
|
698
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
699
|
+
coboundaries in total degree `n`
|
|
700
|
+
|
|
701
|
+
If `n` is an integer rather than a multi-index, then the
|
|
702
|
+
total degree is used in that case as well.
|
|
703
|
+
|
|
704
|
+
EXAMPLES::
|
|
705
|
+
|
|
706
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1, 0), (0, 1), (0, 2)))
|
|
707
|
+
sage: d = A.differential({a: c})
|
|
708
|
+
sage: d.coboundaries((0, 2))
|
|
709
|
+
Vector space of degree 1 and dimension 1 over Rational Field
|
|
710
|
+
Basis matrix:
|
|
711
|
+
[1]
|
|
712
|
+
sage: d.coboundaries(2)
|
|
713
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
714
|
+
Basis matrix:
|
|
715
|
+
[0 1]
|
|
716
|
+
"""
|
|
717
|
+
if total or n in ZZ:
|
|
718
|
+
return Differential.coboundaries(self, total_degree(n))
|
|
719
|
+
|
|
720
|
+
A = self.domain()
|
|
721
|
+
G = AdditiveAbelianGroup([0] * A._grading_rank)
|
|
722
|
+
n = G(vector(n))
|
|
723
|
+
F = A.base_ring()
|
|
724
|
+
if total_degree(n) == 0:
|
|
725
|
+
return VectorSpace(F, 0)
|
|
726
|
+
if total_degree(n) == 1:
|
|
727
|
+
return VectorSpace(F, 0)
|
|
728
|
+
M = self.differential_matrix_multigraded(n - self._degree_of_differential)
|
|
729
|
+
V0 = VectorSpace(F, M.nrows())
|
|
730
|
+
V1 = VectorSpace(F, M.ncols())
|
|
731
|
+
mor = V0.Hom(V1)(M)
|
|
732
|
+
return mor.image()
|
|
733
|
+
|
|
734
|
+
def cocycles(self, n, total=False):
|
|
735
|
+
r"""
|
|
736
|
+
The `n`-th cocycle group of the algebra.
|
|
737
|
+
|
|
738
|
+
This is a vector space over the base field `F`, and it is
|
|
739
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
740
|
+
`n`-th homogeneous component has dimension `d`.
|
|
741
|
+
|
|
742
|
+
INPUT:
|
|
743
|
+
|
|
744
|
+
- ``n`` -- degree
|
|
745
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
746
|
+
cocycles in total degree `n`
|
|
747
|
+
|
|
748
|
+
If `n` is an integer rather than a multi-index, then the
|
|
749
|
+
total degree is used in that case as well.
|
|
750
|
+
|
|
751
|
+
EXAMPLES::
|
|
752
|
+
|
|
753
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1, 0), (0, 1), (0, 2)))
|
|
754
|
+
sage: d = A.differential({a: c})
|
|
755
|
+
sage: d.cocycles((0, 1))
|
|
756
|
+
Vector space of degree 1 and dimension 1 over Rational Field
|
|
757
|
+
Basis matrix:
|
|
758
|
+
[1]
|
|
759
|
+
sage: d.cocycles((0, 1), total=True)
|
|
760
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
761
|
+
Basis matrix:
|
|
762
|
+
[0 1]
|
|
763
|
+
"""
|
|
764
|
+
if total or n in ZZ:
|
|
765
|
+
return Differential.cocycles(self, total_degree(n))
|
|
766
|
+
|
|
767
|
+
A = self.domain()
|
|
768
|
+
G = AdditiveAbelianGroup([0] * A._grading_rank)
|
|
769
|
+
n = G(vector(n))
|
|
770
|
+
F = A.base_ring()
|
|
771
|
+
if total_degree(n) == 0:
|
|
772
|
+
return VectorSpace(F, 1)
|
|
773
|
+
M = self.differential_matrix_multigraded(n)
|
|
774
|
+
V0 = VectorSpace(F, M.nrows())
|
|
775
|
+
V1 = VectorSpace(F, M.ncols())
|
|
776
|
+
mor = V0.Hom(V1)(M)
|
|
777
|
+
return mor.kernel()
|
|
778
|
+
|
|
779
|
+
def cohomology_raw(self, n, total=False):
|
|
780
|
+
r"""
|
|
781
|
+
The `n`-th cohomology group of the algebra.
|
|
782
|
+
|
|
783
|
+
This is a vector space over the base ring, and it is returned
|
|
784
|
+
as the quotient cocycles/coboundaries.
|
|
785
|
+
|
|
786
|
+
INPUT:
|
|
787
|
+
|
|
788
|
+
- ``n`` -- degree
|
|
789
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
790
|
+
cohomology in total degree `n`
|
|
791
|
+
|
|
792
|
+
If `n` is an integer rather than a multi-index, then the
|
|
793
|
+
total degree is used in that case as well.
|
|
794
|
+
|
|
795
|
+
.. SEEALSO::
|
|
796
|
+
|
|
797
|
+
:meth:`cohomology`
|
|
798
|
+
|
|
799
|
+
EXAMPLES::
|
|
800
|
+
|
|
801
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1, 0), (0, 1), (0, 2)))
|
|
802
|
+
sage: d = A.differential({a: c})
|
|
803
|
+
sage: d.cohomology_raw((0, 2))
|
|
804
|
+
Vector space quotient V/W of dimension 0 over Rational Field where
|
|
805
|
+
V: Vector space of degree 1 and dimension 1 over Rational Field
|
|
806
|
+
Basis matrix:
|
|
807
|
+
[1]
|
|
808
|
+
W: Vector space of degree 1 and dimension 1 over Rational Field
|
|
809
|
+
Basis matrix:
|
|
810
|
+
[1]
|
|
811
|
+
|
|
812
|
+
sage: d.cohomology_raw(1)
|
|
813
|
+
Vector space quotient V/W of dimension 1 over Rational Field where
|
|
814
|
+
V: Vector space of degree 2 and dimension 1 over Rational Field
|
|
815
|
+
Basis matrix:
|
|
816
|
+
[0 1]
|
|
817
|
+
W: Vector space of degree 2 and dimension 0 over Rational Field
|
|
818
|
+
Basis matrix:
|
|
819
|
+
[]
|
|
820
|
+
"""
|
|
821
|
+
return self.cocycles(n, total).quotient(self.coboundaries(n, total))
|
|
822
|
+
|
|
823
|
+
def cohomology(self, n, total=False):
|
|
824
|
+
r"""
|
|
825
|
+
The `n`-th cohomology group of the algebra.
|
|
826
|
+
|
|
827
|
+
This is a vector space over the base ring, defined as the
|
|
828
|
+
quotient cocycles/coboundaries. The elements of the quotient
|
|
829
|
+
are lifted to the vector space of cocycles, and this is
|
|
830
|
+
described in terms of those lifts.
|
|
831
|
+
|
|
832
|
+
INPUT:
|
|
833
|
+
|
|
834
|
+
- ``n`` -- degree
|
|
835
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
836
|
+
cohomology in total degree `n`
|
|
837
|
+
|
|
838
|
+
If `n` is an integer rather than a multi-index, then the
|
|
839
|
+
total degree is used in that case as well.
|
|
840
|
+
|
|
841
|
+
.. SEEALSO::
|
|
842
|
+
|
|
843
|
+
:meth:`cohomology_raw`
|
|
844
|
+
|
|
845
|
+
EXAMPLES::
|
|
846
|
+
|
|
847
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1, 0), (0, 1), (0, 2)))
|
|
848
|
+
sage: d = A.differential({a: c})
|
|
849
|
+
sage: d.cohomology((0, 2))
|
|
850
|
+
Free module generated by {} over Rational Field
|
|
851
|
+
|
|
852
|
+
sage: d.cohomology(1)
|
|
853
|
+
Free module generated by {[b]} over Rational Field
|
|
854
|
+
"""
|
|
855
|
+
H = self.cohomology_raw(n, total)
|
|
856
|
+
H_basis_raw = (H.lift(H.basis()[i]) for i in range(H.dimension()))
|
|
857
|
+
A = self.domain()
|
|
858
|
+
B = A.basis(n, total)
|
|
859
|
+
H_basis = (sum(c * b for (c, b) in zip(coeffs, B))
|
|
860
|
+
for coeffs in H_basis_raw)
|
|
861
|
+
# Put brackets around classes.
|
|
862
|
+
H_basis_brackets = [CohomologyClass(b, A) for b in H_basis]
|
|
863
|
+
return CombinatorialFreeModule(A.base_ring(),
|
|
864
|
+
H_basis_brackets,
|
|
865
|
+
sorting_key=sorting_keys,
|
|
866
|
+
monomial_reverse=True)
|
|
867
|
+
|
|
868
|
+
homology = cohomology
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
###########################################################
|
|
872
|
+
# Commutative graded algebras
|
|
873
|
+
|
|
874
|
+
class GCAlgebra(UniqueRepresentation, QuotientRing_nc):
|
|
875
|
+
r"""
|
|
876
|
+
A graded commutative algebra.
|
|
877
|
+
|
|
878
|
+
INPUT:
|
|
879
|
+
|
|
880
|
+
- ``base`` -- the base field
|
|
881
|
+
|
|
882
|
+
- ``names`` -- (optional) names of the generators: a list of
|
|
883
|
+
strings or a single string with the names separated by
|
|
884
|
+
commas. If not specified, the generators are named "x0", "x1",
|
|
885
|
+
...
|
|
886
|
+
|
|
887
|
+
- ``degrees`` -- (optional) a tuple or list specifying the degrees
|
|
888
|
+
of the generators; if omitted, each generator is given degree
|
|
889
|
+
1, and if both ``names`` and ``degrees`` are omitted, an error is
|
|
890
|
+
raised.
|
|
891
|
+
|
|
892
|
+
- ``R`` -- (default: ``None``) the ring over which the
|
|
893
|
+
algebra is defined: if this is specified, the algebra is defined
|
|
894
|
+
to be ``R/I``.
|
|
895
|
+
|
|
896
|
+
- ``I`` -- (default: ``None``) an ideal in `R`. It is
|
|
897
|
+
should include, among other relations, the squares of the
|
|
898
|
+
generators of odd degree
|
|
899
|
+
|
|
900
|
+
As described in the module-level documentation, these are graded
|
|
901
|
+
algebras for which oddly graded elements anticommute and evenly
|
|
902
|
+
graded elements commute.
|
|
903
|
+
|
|
904
|
+
The arguments ``R`` and ``I`` are primarily for use by the
|
|
905
|
+
:meth:`quotient` method.
|
|
906
|
+
|
|
907
|
+
These algebras should be graded over the integers; multi-graded
|
|
908
|
+
algebras should be constructed using
|
|
909
|
+
:class:`GCAlgebra_multigraded` instead.
|
|
910
|
+
|
|
911
|
+
EXAMPLES::
|
|
912
|
+
|
|
913
|
+
sage: A.<a,b> = GradedCommutativeAlgebra(QQ, degrees = (2, 3))
|
|
914
|
+
sage: a.degree()
|
|
915
|
+
2
|
|
916
|
+
sage: B = A.quotient(A.ideal(a**2*b))
|
|
917
|
+
sage: B
|
|
918
|
+
Graded Commutative Algebra with generators ('a', 'b') in degrees (2, 3)
|
|
919
|
+
with relations [a^2*b] over Rational Field
|
|
920
|
+
sage: A.basis(7)
|
|
921
|
+
[a^2*b]
|
|
922
|
+
sage: B.basis(7)
|
|
923
|
+
[]
|
|
924
|
+
|
|
925
|
+
Note that the function :func:`GradedCommutativeAlgebra` can also be used to
|
|
926
|
+
construct these algebras.
|
|
927
|
+
"""
|
|
928
|
+
# TODO: This should be a __classcall_private__?
|
|
929
|
+
@staticmethod
|
|
930
|
+
def __classcall__(cls, base, names=None, degrees=None, R=None, I=None, category=None):
|
|
931
|
+
r"""
|
|
932
|
+
Normalize the input for the :meth:`__init__` method and the
|
|
933
|
+
unique representation.
|
|
934
|
+
|
|
935
|
+
INPUT:
|
|
936
|
+
|
|
937
|
+
- ``base`` -- the base ring of the algebra
|
|
938
|
+
|
|
939
|
+
- ``names`` -- the names of the variables; by default, set to ``x1``,
|
|
940
|
+
``x2``, etc.
|
|
941
|
+
|
|
942
|
+
- ``degrees`` -- the degrees of the generators; by default, set to 1
|
|
943
|
+
|
|
944
|
+
- ``R`` -- an underlying `g`-algebra; only meant to be used by the
|
|
945
|
+
quotient method
|
|
946
|
+
|
|
947
|
+
- ``I`` -- a two-sided ideal in ``R``, with the desired relations;
|
|
948
|
+
Only meant to be used by the quotient method
|
|
949
|
+
|
|
950
|
+
TESTS::
|
|
951
|
+
|
|
952
|
+
sage: A1 = GradedCommutativeAlgebra(GF(2), 'x,y', (3, 6))
|
|
953
|
+
sage: A2 = GradedCommutativeAlgebra(GF(2), ['x', 'y'], [3, 6])
|
|
954
|
+
sage: A1 is A2
|
|
955
|
+
True
|
|
956
|
+
|
|
957
|
+
Testing the single generator case (:issue:`25276`)::
|
|
958
|
+
|
|
959
|
+
sage: A3.<z> = GradedCommutativeAlgebra(QQ)
|
|
960
|
+
sage: z**2 == 0
|
|
961
|
+
True
|
|
962
|
+
sage: A4.<z> = GradedCommutativeAlgebra(QQ, degrees=[4])
|
|
963
|
+
sage: z**2 == 0
|
|
964
|
+
False
|
|
965
|
+
sage: A5.<z> = GradedCommutativeAlgebra(GF(2))
|
|
966
|
+
sage: z**2 == 0
|
|
967
|
+
False
|
|
968
|
+
"""
|
|
969
|
+
if names is None:
|
|
970
|
+
if degrees is None:
|
|
971
|
+
raise ValueError("you must specify names or degrees")
|
|
972
|
+
n = len(degrees)
|
|
973
|
+
names = tuple(f'x{i}' for i in range(n))
|
|
974
|
+
elif isinstance(names, str):
|
|
975
|
+
names = tuple(names.split(','))
|
|
976
|
+
n = len(names)
|
|
977
|
+
else:
|
|
978
|
+
n = len(names)
|
|
979
|
+
names = tuple(names)
|
|
980
|
+
|
|
981
|
+
if degrees is None:
|
|
982
|
+
degrees = tuple([1] * n)
|
|
983
|
+
else:
|
|
984
|
+
# Deal with multigrading: convert lists and tuples to elements
|
|
985
|
+
# of an additive abelian group.
|
|
986
|
+
if degrees:
|
|
987
|
+
try:
|
|
988
|
+
rank = len(list(degrees[0]))
|
|
989
|
+
G = AdditiveAbelianGroup([0] * rank)
|
|
990
|
+
degrees = [G(vector(d)) for d in degrees]
|
|
991
|
+
except TypeError:
|
|
992
|
+
# The entries of degrees are not iterables, so
|
|
993
|
+
# treat as singly-graded.
|
|
994
|
+
pass
|
|
995
|
+
|
|
996
|
+
degrees = tuple(degrees)
|
|
997
|
+
if not R or not I:
|
|
998
|
+
if n > 1:
|
|
999
|
+
F = FreeAlgebra(base, n, names)
|
|
1000
|
+
else: # n = 1
|
|
1001
|
+
F = PolynomialRing(base, n, names)
|
|
1002
|
+
gens = F.gens()
|
|
1003
|
+
rels = {}
|
|
1004
|
+
tot_degs = [total_degree(d) for d in degrees]
|
|
1005
|
+
for i in range(len(gens) - 1):
|
|
1006
|
+
for j in range(i + 1, len(gens)):
|
|
1007
|
+
rels[gens[j] * gens[i]] = ((-1)**(tot_degs[i] * tot_degs[j])
|
|
1008
|
+
* gens[i] * gens[j])
|
|
1009
|
+
if n > 1:
|
|
1010
|
+
R = F.g_algebra(rels, order=TermOrder('wdegrevlex', tot_degs))
|
|
1011
|
+
else: # n = 1
|
|
1012
|
+
R = F.quotient(rels)
|
|
1013
|
+
if base.characteristic() == 2:
|
|
1014
|
+
I = R.ideal(0, side='twosided')
|
|
1015
|
+
else:
|
|
1016
|
+
I = R.ideal([R.gen(i)**2
|
|
1017
|
+
for i in range(n) if is_odd(tot_degs[i])],
|
|
1018
|
+
side='twosided')
|
|
1019
|
+
|
|
1020
|
+
return super().__classcall__(cls, base=base, names=names,
|
|
1021
|
+
degrees=degrees, R=R, I=I,
|
|
1022
|
+
category=category)
|
|
1023
|
+
|
|
1024
|
+
def __init__(self, base, R=None, I=None, names=None, degrees=None, category=None):
|
|
1025
|
+
"""
|
|
1026
|
+
Initialize ``self``.
|
|
1027
|
+
|
|
1028
|
+
INPUT:
|
|
1029
|
+
|
|
1030
|
+
- ``base`` -- the base field
|
|
1031
|
+
|
|
1032
|
+
- ``R`` -- (optional) the ring over which the algebra is defined
|
|
1033
|
+
|
|
1034
|
+
- ``I`` -- (optional) an ideal over the corresponding `g`-algebra;
|
|
1035
|
+
it is meant to include, among other relations, the squares of the
|
|
1036
|
+
generators of odd degree
|
|
1037
|
+
|
|
1038
|
+
- ``names`` -- (optional) the names of the generators; if omitted,
|
|
1039
|
+
this uses the names ``x0``, ``x1``, ...
|
|
1040
|
+
|
|
1041
|
+
- ``degrees`` -- (optional) the degrees of the generators; if
|
|
1042
|
+
omitted, they are given degree 1
|
|
1043
|
+
|
|
1044
|
+
EXAMPLES::
|
|
1045
|
+
|
|
1046
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ)
|
|
1047
|
+
sage: TestSuite(A).run()
|
|
1048
|
+
sage: A = GradedCommutativeAlgebra(QQ, ('x','y','z'), [2,3,4])
|
|
1049
|
+
sage: TestSuite(A).run()
|
|
1050
|
+
sage: A = GradedCommutativeAlgebra(QQ, ('x','y','z','t'), [1,2,3,4])
|
|
1051
|
+
sage: TestSuite(A).run()
|
|
1052
|
+
"""
|
|
1053
|
+
self._degrees = tuple(degrees)
|
|
1054
|
+
category = Algebras(R.base_ring()).Graded().or_subcategory(category)
|
|
1055
|
+
QuotientRing_nc.__init__(self, R, I, names, category=category)
|
|
1056
|
+
|
|
1057
|
+
def _repr_(self):
|
|
1058
|
+
"""
|
|
1059
|
+
Print representation.
|
|
1060
|
+
|
|
1061
|
+
EXAMPLES::
|
|
1062
|
+
|
|
1063
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=[1, 2, 3, 4])
|
|
1064
|
+
sage: A
|
|
1065
|
+
Graded Commutative Algebra with generators ('x', 'y', 'z', 't') in degrees (1, 2, 3, 4) over Rational Field
|
|
1066
|
+
sage: A.quotient(A.ideal(3*x*t - 2*y*z))
|
|
1067
|
+
Graded Commutative Algebra with generators ('x', 'y', 'z', 't') in degrees (1, 2, 3, 4) with relations [-2*y*z + 3*x*t] over Rational Field
|
|
1068
|
+
"""
|
|
1069
|
+
s = "Graded Commutative Algebra with generators {} in degrees {}".format(self._names, self._degrees)
|
|
1070
|
+
# Find any nontrivial relations.
|
|
1071
|
+
I = self.defining_ideal()
|
|
1072
|
+
R = self.cover_ring()
|
|
1073
|
+
degrees = self._degrees
|
|
1074
|
+
if self.base().characteristic() != 2:
|
|
1075
|
+
squares = [R.gen(i)**2
|
|
1076
|
+
for i in range(len(degrees)) if is_odd(degrees[i])]
|
|
1077
|
+
else:
|
|
1078
|
+
squares = [R.zero()]
|
|
1079
|
+
relns = [g for g in I.gens() if g not in squares]
|
|
1080
|
+
if relns:
|
|
1081
|
+
s += " with relations {}".format(relns)
|
|
1082
|
+
return s + " over {}".format(self.base_ring())
|
|
1083
|
+
|
|
1084
|
+
_base_repr = _repr_
|
|
1085
|
+
|
|
1086
|
+
@cached_method
|
|
1087
|
+
def _basis_for_free_alg(self, n):
|
|
1088
|
+
r"""
|
|
1089
|
+
Basis of the associated free commutative DGA in degree `n`.
|
|
1090
|
+
|
|
1091
|
+
That is, ignore the relations when computing the basis:
|
|
1092
|
+
compute the basis of the free commutative DGA with generators
|
|
1093
|
+
in degrees given by ``self._degrees``.
|
|
1094
|
+
|
|
1095
|
+
INPUT:
|
|
1096
|
+
|
|
1097
|
+
- ``n`` -- integer
|
|
1098
|
+
|
|
1099
|
+
OUTPUT: tuple of basis elements in degree `n`, as tuples of exponents
|
|
1100
|
+
|
|
1101
|
+
EXAMPLES::
|
|
1102
|
+
|
|
1103
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,2,3))
|
|
1104
|
+
sage: A._basis_for_free_alg(3)
|
|
1105
|
+
[(0, 0, 1), (1, 1, 0)]
|
|
1106
|
+
sage: B = A.quotient(A.ideal(a*b, b**2+a*c))
|
|
1107
|
+
sage: B._basis_for_free_alg(3)
|
|
1108
|
+
[(0, 0, 1), (1, 1, 0)]
|
|
1109
|
+
|
|
1110
|
+
sage: GradedCommutativeAlgebra(QQ, degrees=(1,1))._basis_for_free_alg(3)
|
|
1111
|
+
[]
|
|
1112
|
+
sage: GradedCommutativeAlgebra(GF(2), degrees=(1,1))._basis_for_free_alg(3)
|
|
1113
|
+
[(0, 3), (1, 2), (2, 1), (3, 0)]
|
|
1114
|
+
|
|
1115
|
+
sage: A = GradedCommutativeAlgebra(GF(2), degrees=(4,8,12))
|
|
1116
|
+
sage: A._basis_for_free_alg(399)
|
|
1117
|
+
[]
|
|
1118
|
+
"""
|
|
1119
|
+
if n == 0:
|
|
1120
|
+
return ((0,) * len(self._degrees),)
|
|
1121
|
+
if self.base_ring().characteristic() == 2:
|
|
1122
|
+
return [tuple(_) for _ in WeightedIntegerVectors(n, self._degrees)]
|
|
1123
|
+
|
|
1124
|
+
even_degrees = []
|
|
1125
|
+
odd_degrees = []
|
|
1126
|
+
for a in self._degrees:
|
|
1127
|
+
if is_even(a):
|
|
1128
|
+
even_degrees.append(a)
|
|
1129
|
+
else:
|
|
1130
|
+
odd_degrees.append(a)
|
|
1131
|
+
|
|
1132
|
+
if not even_degrees: # No even generators.
|
|
1133
|
+
return [tuple(_)
|
|
1134
|
+
for _ in exterior_algebra_basis(n, tuple(odd_degrees))]
|
|
1135
|
+
if not odd_degrees: # No odd generators.
|
|
1136
|
+
return [tuple(_)
|
|
1137
|
+
for _ in WeightedIntegerVectors(n, tuple(even_degrees))]
|
|
1138
|
+
|
|
1139
|
+
# General case: both even and odd generators.
|
|
1140
|
+
result = []
|
|
1141
|
+
for dim in range(n + 1):
|
|
1142
|
+
# First find the even part of the basis.
|
|
1143
|
+
if dim == 0:
|
|
1144
|
+
even_result = [[0] * len(even_degrees)]
|
|
1145
|
+
else:
|
|
1146
|
+
even_result = WeightedIntegerVectors(dim, tuple(even_degrees))
|
|
1147
|
+
# Now find the odd part of the basis.
|
|
1148
|
+
for even_mono in even_result:
|
|
1149
|
+
deg = n - dim
|
|
1150
|
+
odd_result = exterior_algebra_basis(deg, tuple(odd_degrees))
|
|
1151
|
+
for odd_mono in odd_result:
|
|
1152
|
+
temp_even = list(even_mono)
|
|
1153
|
+
temp_odd = list(odd_mono)
|
|
1154
|
+
mono = []
|
|
1155
|
+
for a in self._degrees:
|
|
1156
|
+
if is_even(a):
|
|
1157
|
+
mono.append(temp_even.pop(0))
|
|
1158
|
+
else:
|
|
1159
|
+
mono.append(temp_odd.pop(0))
|
|
1160
|
+
result.append(tuple(mono))
|
|
1161
|
+
return result
|
|
1162
|
+
|
|
1163
|
+
def basis(self, n):
|
|
1164
|
+
"""
|
|
1165
|
+
Return a basis of the `n`-th homogeneous component of ``self``.
|
|
1166
|
+
|
|
1167
|
+
EXAMPLES::
|
|
1168
|
+
|
|
1169
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
|
|
1170
|
+
sage: A.basis(2)
|
|
1171
|
+
[y, z]
|
|
1172
|
+
sage: A.basis(3)
|
|
1173
|
+
[x*y, x*z, t]
|
|
1174
|
+
sage: A.basis(4)
|
|
1175
|
+
[y^2, y*z, z^2, x*t]
|
|
1176
|
+
sage: A.basis(5)
|
|
1177
|
+
[x*y^2, x*y*z, x*z^2, y*t, z*t]
|
|
1178
|
+
sage: A.basis(6)
|
|
1179
|
+
[y^3, y^2*z, y*z^2, z^3, x*y*t, x*z*t]
|
|
1180
|
+
"""
|
|
1181
|
+
free_basis = self._basis_for_free_alg(n)
|
|
1182
|
+
fb_reversed_entries = [list(reversed(e)) for e in free_basis]
|
|
1183
|
+
fb_reversed_entries.sort()
|
|
1184
|
+
free_basis = (tuple(reversed(e)) for e in fb_reversed_entries)
|
|
1185
|
+
basis = []
|
|
1186
|
+
for v in free_basis:
|
|
1187
|
+
el = prod([self.gen(i)**v[i] for i in range(len(v))])
|
|
1188
|
+
di = el.monomial_coefficients()
|
|
1189
|
+
if len(di) == 1:
|
|
1190
|
+
k, = di.keys()
|
|
1191
|
+
if tuple(k) == v:
|
|
1192
|
+
basis.append(el)
|
|
1193
|
+
return basis
|
|
1194
|
+
|
|
1195
|
+
def quotient(self, I, check=True):
|
|
1196
|
+
"""
|
|
1197
|
+
Create the quotient of this algebra by a two-sided ideal ``I``.
|
|
1198
|
+
|
|
1199
|
+
INPUT:
|
|
1200
|
+
|
|
1201
|
+
- ``I`` -- a two-sided homogeneous ideal of this algebra
|
|
1202
|
+
|
|
1203
|
+
- ``check`` -- boolean (default: ``True``); if ``True``, check whether
|
|
1204
|
+
``I`` is generated by homogeneous elements
|
|
1205
|
+
|
|
1206
|
+
EXAMPLES::
|
|
1207
|
+
|
|
1208
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(GF(5), degrees=(2, 2, 3, 4))
|
|
1209
|
+
sage: I = A.ideal([x*t+z^2, x*y - t])
|
|
1210
|
+
sage: B = A.quotient(I); B
|
|
1211
|
+
Graded Commutative Algebra with generators ('x', 'y', 'z', 't')
|
|
1212
|
+
in degrees (2, 2, 3, 4) with relations [x*t, x*y - t]
|
|
1213
|
+
over Finite Field of size 5
|
|
1214
|
+
sage: B(x*t)
|
|
1215
|
+
0
|
|
1216
|
+
sage: B(x*y)
|
|
1217
|
+
t
|
|
1218
|
+
sage: A.basis(7)
|
|
1219
|
+
[x^2*z, x*y*z, y^2*z, z*t]
|
|
1220
|
+
sage: B.basis(7)
|
|
1221
|
+
[x^2*z, y^2*z, z*t]
|
|
1222
|
+
"""
|
|
1223
|
+
if check and any(not i.is_homogeneous() for i in I.gens()):
|
|
1224
|
+
raise ValueError("the ideal must be homogeneous")
|
|
1225
|
+
NCR = self.cover_ring()
|
|
1226
|
+
gens1 = list(self.defining_ideal().gens())
|
|
1227
|
+
gens2 = [i.lift() for i in I.gens()]
|
|
1228
|
+
gens = [g for g in gens1 + gens2 if g != NCR.zero()]
|
|
1229
|
+
J = NCR.ideal(gens, side='twosided')
|
|
1230
|
+
return GCAlgebra(self.base_ring(), self._names, self._degrees, NCR, J)
|
|
1231
|
+
|
|
1232
|
+
def _coerce_map_from_(self, other):
|
|
1233
|
+
r"""
|
|
1234
|
+
Return ``True`` if there is a coercion map from ``R`` to ``self``.
|
|
1235
|
+
|
|
1236
|
+
EXAMPLES::
|
|
1237
|
+
|
|
1238
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
1239
|
+
sage: B = A.cdg_algebra({y:x*y, x: x*y})
|
|
1240
|
+
sage: A._coerce_map_from_(B)
|
|
1241
|
+
True
|
|
1242
|
+
sage: B._coerce_map_from_(A)
|
|
1243
|
+
True
|
|
1244
|
+
sage: B._coerce_map_from_(QQ)
|
|
1245
|
+
True
|
|
1246
|
+
sage: B._coerce_map_from_(GF(3))
|
|
1247
|
+
False
|
|
1248
|
+
"""
|
|
1249
|
+
if isinstance(other, GCAlgebra):
|
|
1250
|
+
if self._names != other._names or self._degrees != other._degrees:
|
|
1251
|
+
return False
|
|
1252
|
+
if set(self.defining_ideal().gens()) != set(other
|
|
1253
|
+
.defining_ideal()
|
|
1254
|
+
.gens()):
|
|
1255
|
+
return False
|
|
1256
|
+
return self.cover_ring().has_coerce_map_from(other.cover_ring())
|
|
1257
|
+
return super()._coerce_map_from_(other)
|
|
1258
|
+
|
|
1259
|
+
def _element_constructor_(self, x, coerce=True):
|
|
1260
|
+
r"""
|
|
1261
|
+
EXAMPLES::
|
|
1262
|
+
|
|
1263
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 4))
|
|
1264
|
+
sage: A({(1,3,0,1): 2, (2,2,1,2): 3})
|
|
1265
|
+
3*x^2*y^2*z*t^2 + 2*x*y^3*t
|
|
1266
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(GF(5))
|
|
1267
|
+
sage: A({(1,3,0,1): 2, (2,2,1,2): 3})
|
|
1268
|
+
0
|
|
1269
|
+
|
|
1270
|
+
TESTS::
|
|
1271
|
+
|
|
1272
|
+
sage: B = A.cdg_algebra({})
|
|
1273
|
+
sage: B(x, coerce=False)
|
|
1274
|
+
x
|
|
1275
|
+
"""
|
|
1276
|
+
if isinstance(x, QuotientRingElement):
|
|
1277
|
+
if x.parent() is self:
|
|
1278
|
+
return x
|
|
1279
|
+
x = x.lift()
|
|
1280
|
+
if isinstance(x, dict):
|
|
1281
|
+
res = self.zero()
|
|
1282
|
+
for i in x.keys():
|
|
1283
|
+
mon = prod(self.gen(j)**i[j] for j in range(len(i)))
|
|
1284
|
+
res += x[i] * mon
|
|
1285
|
+
return res
|
|
1286
|
+
if coerce:
|
|
1287
|
+
R = self.cover_ring()
|
|
1288
|
+
x = R(x)
|
|
1289
|
+
|
|
1290
|
+
if isinstance(x, sage.interfaces.abc.SingularElement):
|
|
1291
|
+
# self._singular_().set_ring()
|
|
1292
|
+
x = self.element_class(self, x.sage_poly(self.cover_ring()))
|
|
1293
|
+
return x
|
|
1294
|
+
|
|
1295
|
+
return self.element_class(self, x)
|
|
1296
|
+
|
|
1297
|
+
def _Hom_(self, B, category):
|
|
1298
|
+
"""
|
|
1299
|
+
Return the homset from ``self`` to ``B`` in the category ``category``.
|
|
1300
|
+
|
|
1301
|
+
INPUT:
|
|
1302
|
+
|
|
1303
|
+
- ``B`` -- a graded commutative algebra
|
|
1304
|
+
- ``category`` -- a subcategory of graded algebras or ``None``
|
|
1305
|
+
|
|
1306
|
+
EXAMPLES::
|
|
1307
|
+
|
|
1308
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ)
|
|
1309
|
+
sage: B.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,2,3))
|
|
1310
|
+
sage: C.<d> = GradedCommutativeAlgebra(GF(17))
|
|
1311
|
+
sage: Hom(A,A)
|
|
1312
|
+
Set of Homomorphisms
|
|
1313
|
+
from Graded Commutative Algebra with generators ('x', 'y')
|
|
1314
|
+
in degrees (1, 1) over Rational Field
|
|
1315
|
+
to Graded Commutative Algebra with generators ('x', 'y')
|
|
1316
|
+
in degrees (1, 1) over Rational Field
|
|
1317
|
+
sage: Hom(A,B)
|
|
1318
|
+
Set of Homomorphisms
|
|
1319
|
+
from Graded Commutative Algebra with generators ('x', 'y')
|
|
1320
|
+
in degrees (1, 1) over Rational Field
|
|
1321
|
+
to Graded Commutative Algebra with generators ('a', 'b', 'c')
|
|
1322
|
+
in degrees (1, 2, 3) over Rational Field
|
|
1323
|
+
sage: Hom(A,C)
|
|
1324
|
+
Traceback (most recent call last):
|
|
1325
|
+
...
|
|
1326
|
+
NotImplementedError: homomorphisms of graded commutative algebras
|
|
1327
|
+
have only been implemented when the base rings are the same
|
|
1328
|
+
"""
|
|
1329
|
+
R = self.base_ring()
|
|
1330
|
+
# The base rings need to be checked before the categories, or
|
|
1331
|
+
# else the function sage.categories.homset.Hom catches the
|
|
1332
|
+
# TypeError and uses the wrong category (the meet of the
|
|
1333
|
+
# categories for self and B, which might be the category of
|
|
1334
|
+
# rings).
|
|
1335
|
+
if R != B.base_ring():
|
|
1336
|
+
raise NotImplementedError('homomorphisms of graded commutative '
|
|
1337
|
+
'algebras have only been implemented '
|
|
1338
|
+
'when the base rings are the same')
|
|
1339
|
+
cat = Algebras(R).Graded()
|
|
1340
|
+
if category is not None and not category.is_subcategory(cat):
|
|
1341
|
+
raise TypeError("{} is not a subcategory of graded algebras"
|
|
1342
|
+
.format(category))
|
|
1343
|
+
return GCAlgebraHomset(self, B, category=category)
|
|
1344
|
+
|
|
1345
|
+
def differential(self, diff):
|
|
1346
|
+
"""
|
|
1347
|
+
Construct a differential on ``self``.
|
|
1348
|
+
|
|
1349
|
+
INPUT:
|
|
1350
|
+
|
|
1351
|
+
- ``diff`` -- dictionary defining a differential
|
|
1352
|
+
|
|
1353
|
+
The keys of the dictionary are generators of the algebra, and
|
|
1354
|
+
the associated values are their targets under the
|
|
1355
|
+
differential. Any generators which are not specified are
|
|
1356
|
+
assumed to have zero differential.
|
|
1357
|
+
|
|
1358
|
+
EXAMPLES::
|
|
1359
|
+
|
|
1360
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2))
|
|
1361
|
+
sage: A.differential({y:x*y, x: x*y})
|
|
1362
|
+
Differential of Graded Commutative Algebra with generators ('x', 'y', 'z')
|
|
1363
|
+
in degrees (1, 1, 2) over Rational Field
|
|
1364
|
+
Defn: x --> x*y
|
|
1365
|
+
y --> x*y
|
|
1366
|
+
z --> 0
|
|
1367
|
+
sage: B.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2))
|
|
1368
|
+
sage: d = B.differential({b:a*c, c:a*c})
|
|
1369
|
+
sage: d(b*c)
|
|
1370
|
+
a*b*c + a*c^2
|
|
1371
|
+
"""
|
|
1372
|
+
return Differential(self, diff)
|
|
1373
|
+
|
|
1374
|
+
def cdg_algebra(self, differential):
|
|
1375
|
+
r"""
|
|
1376
|
+
Construct a differential graded commutative algebra from ``self``
|
|
1377
|
+
by specifying a differential.
|
|
1378
|
+
|
|
1379
|
+
INPUT:
|
|
1380
|
+
|
|
1381
|
+
- ``differential`` -- dictionary defining a differential or
|
|
1382
|
+
a map defining a valid differential
|
|
1383
|
+
|
|
1384
|
+
The keys of the dictionary are generators of the algebra, and
|
|
1385
|
+
the associated values are their targets under the
|
|
1386
|
+
differential. Any generators which are not specified are
|
|
1387
|
+
assumed to have zero differential. Alternatively, the
|
|
1388
|
+
differential can be defined using the :meth:`differential`
|
|
1389
|
+
method; see below for an example.
|
|
1390
|
+
|
|
1391
|
+
.. SEEALSO::
|
|
1392
|
+
|
|
1393
|
+
:meth:`differential`
|
|
1394
|
+
|
|
1395
|
+
EXAMPLES::
|
|
1396
|
+
|
|
1397
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 1))
|
|
1398
|
+
sage: B = A.cdg_algebra({a: b*c, b: a*c})
|
|
1399
|
+
sage: B
|
|
1400
|
+
Commutative Differential Graded Algebra with generators ('a', 'b', 'c')
|
|
1401
|
+
in degrees (1, 1, 1) over Rational Field with differential:
|
|
1402
|
+
a --> b*c
|
|
1403
|
+
b --> a*c
|
|
1404
|
+
c --> 0
|
|
1405
|
+
|
|
1406
|
+
Note that ``differential`` can also be a map::
|
|
1407
|
+
|
|
1408
|
+
sage: d = A.differential({a: b*c, b: a*c})
|
|
1409
|
+
sage: d
|
|
1410
|
+
Differential of Graded Commutative Algebra with generators ('a', 'b', 'c')
|
|
1411
|
+
in degrees (1, 1, 1) over Rational Field
|
|
1412
|
+
Defn: a --> b*c
|
|
1413
|
+
b --> a*c
|
|
1414
|
+
c --> 0
|
|
1415
|
+
sage: A.cdg_algebra(d) is B
|
|
1416
|
+
True
|
|
1417
|
+
"""
|
|
1418
|
+
return DifferentialGCAlgebra(self, differential)
|
|
1419
|
+
|
|
1420
|
+
# TODO: Do we want a fully spelled out alias?
|
|
1421
|
+
# commutative_differential_graded_algebra = cdg_algebra
|
|
1422
|
+
|
|
1423
|
+
class Element(QuotientRingElement):
|
|
1424
|
+
r"""
|
|
1425
|
+
An element of a graded commutative algebra.
|
|
1426
|
+
"""
|
|
1427
|
+
def __init__(self, A, rep):
|
|
1428
|
+
r"""
|
|
1429
|
+
Initialize ``self``.
|
|
1430
|
+
|
|
1431
|
+
INPUT:
|
|
1432
|
+
|
|
1433
|
+
- ``parent`` -- the graded commutative algebra in which
|
|
1434
|
+
this element lies, viewed as a quotient `R / I`
|
|
1435
|
+
|
|
1436
|
+
- ``rep`` -- a representative of the element in `R`; this is used
|
|
1437
|
+
as the internal representation of the element
|
|
1438
|
+
|
|
1439
|
+
EXAMPLES::
|
|
1440
|
+
|
|
1441
|
+
sage: B.<x,y> = GradedCommutativeAlgebra(QQ, degrees=(2, 2))
|
|
1442
|
+
sage: a = B({(1,1): -3, (2,5): 1/2})
|
|
1443
|
+
sage: a
|
|
1444
|
+
1/2*x^2*y^5 - 3*x*y
|
|
1445
|
+
sage: TestSuite(a).run()
|
|
1446
|
+
|
|
1447
|
+
sage: b = x^2*y^3+2
|
|
1448
|
+
sage: b
|
|
1449
|
+
x^2*y^3 + 2
|
|
1450
|
+
"""
|
|
1451
|
+
QuotientRingElement.__init__(self, A, rep)
|
|
1452
|
+
|
|
1453
|
+
def degree(self, total=False):
|
|
1454
|
+
r"""
|
|
1455
|
+
The degree of this element.
|
|
1456
|
+
|
|
1457
|
+
If the element is not homogeneous, this returns the
|
|
1458
|
+
maximum of the degrees of its monomials.
|
|
1459
|
+
|
|
1460
|
+
INPUT:
|
|
1461
|
+
|
|
1462
|
+
- ``total`` -- ignored, present for compatibility with the
|
|
1463
|
+
multi-graded case
|
|
1464
|
+
|
|
1465
|
+
EXAMPLES::
|
|
1466
|
+
|
|
1467
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 3, 3))
|
|
1468
|
+
sage: el = z*t+2*x*y-y^2*z
|
|
1469
|
+
sage: el.degree()
|
|
1470
|
+
7
|
|
1471
|
+
sage: el.monomials()
|
|
1472
|
+
[y^2*z, z*t, x*y]
|
|
1473
|
+
sage: [i.degree() for i in el.monomials()]
|
|
1474
|
+
[7, 6, 3]
|
|
1475
|
+
|
|
1476
|
+
sage: A(0).degree()
|
|
1477
|
+
Traceback (most recent call last):
|
|
1478
|
+
...
|
|
1479
|
+
ValueError: the zero element does not have a well-defined degree
|
|
1480
|
+
"""
|
|
1481
|
+
if self.is_zero():
|
|
1482
|
+
raise ValueError("the zero element does not have a well-defined degree")
|
|
1483
|
+
exps = self.monomial_coefficients().keys()
|
|
1484
|
+
degrees = self.parent()._degrees
|
|
1485
|
+
n = self.parent().ngens()
|
|
1486
|
+
l = [sum(e[i] * degrees[i] for i in range(n)) for e in exps]
|
|
1487
|
+
return max(l)
|
|
1488
|
+
|
|
1489
|
+
def is_homogeneous(self, total=False):
|
|
1490
|
+
r"""
|
|
1491
|
+
Return ``True`` if ``self`` is homogeneous and ``False`` otherwise.
|
|
1492
|
+
|
|
1493
|
+
INPUT:
|
|
1494
|
+
|
|
1495
|
+
- ``total`` -- boolean (default: ``False``); only used in the
|
|
1496
|
+
multi-graded case, in which case if ``True``, check to see
|
|
1497
|
+
if ``self`` is homogeneous with respect to total degree
|
|
1498
|
+
|
|
1499
|
+
EXAMPLES::
|
|
1500
|
+
|
|
1501
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 3, 3))
|
|
1502
|
+
sage: el = z*t + 2*x*y - y^2*z
|
|
1503
|
+
sage: el.degree()
|
|
1504
|
+
7
|
|
1505
|
+
sage: el.monomials()
|
|
1506
|
+
[y^2*z, z*t, x*y]
|
|
1507
|
+
sage: [i.degree() for i in el.monomials()]
|
|
1508
|
+
[7, 6, 3]
|
|
1509
|
+
sage: el.is_homogeneous()
|
|
1510
|
+
False
|
|
1511
|
+
sage: em = y^3 - 5*z*t + 3/2*x*y*t
|
|
1512
|
+
sage: em.is_homogeneous()
|
|
1513
|
+
True
|
|
1514
|
+
sage: em.monomials()
|
|
1515
|
+
[y^3, x*y*t, z*t]
|
|
1516
|
+
sage: [i.degree() for i in em.monomials()]
|
|
1517
|
+
[6, 6, 6]
|
|
1518
|
+
|
|
1519
|
+
The element 0 is homogeneous, even though it doesn't have
|
|
1520
|
+
a well-defined degree::
|
|
1521
|
+
|
|
1522
|
+
sage: A(0).is_homogeneous()
|
|
1523
|
+
True
|
|
1524
|
+
|
|
1525
|
+
A multi-graded example::
|
|
1526
|
+
|
|
1527
|
+
sage: B.<c,d> = GradedCommutativeAlgebra(QQ, degrees=((2, 0), (0, 4)))
|
|
1528
|
+
sage: (c^2 - 1/2 * d).is_homogeneous()
|
|
1529
|
+
False
|
|
1530
|
+
sage: (c^2 - 1/2 * d).is_homogeneous(total=True)
|
|
1531
|
+
True
|
|
1532
|
+
"""
|
|
1533
|
+
degree = None
|
|
1534
|
+
for m in self.monomials():
|
|
1535
|
+
if degree is None:
|
|
1536
|
+
degree = m.degree(total)
|
|
1537
|
+
else:
|
|
1538
|
+
if degree != m.degree(total):
|
|
1539
|
+
return False
|
|
1540
|
+
return True
|
|
1541
|
+
|
|
1542
|
+
def homogeneous_parts(self):
|
|
1543
|
+
r"""
|
|
1544
|
+
Return the homogeneous parts of the element. The result is given as
|
|
1545
|
+
a dictionary indexed by degree.
|
|
1546
|
+
|
|
1547
|
+
EXAMPLES::
|
|
1548
|
+
|
|
1549
|
+
sage: A.<e1,e2,e3,e4,e5> = GradedCommutativeAlgebra(QQ)
|
|
1550
|
+
sage: a = e1*e3*e5-3*e2*e3*e5 + e1*e2 -2*e3 + e5
|
|
1551
|
+
sage: a.homogeneous_parts()
|
|
1552
|
+
{1: -2*e3 + e5, 2: e1*e2, 3: e1*e3*e5 - 3*e2*e3*e5}
|
|
1553
|
+
"""
|
|
1554
|
+
dic = self.monomial_coefficients()
|
|
1555
|
+
terms = [self.parent()({t: dic[t]}) for t in dic.keys()]
|
|
1556
|
+
res = {}
|
|
1557
|
+
for term in terms:
|
|
1558
|
+
deg = term.degree()
|
|
1559
|
+
if deg in res:
|
|
1560
|
+
res[deg] += term
|
|
1561
|
+
else:
|
|
1562
|
+
res[deg] = term
|
|
1563
|
+
return {i: res[i] for i in sorted(res.keys())}
|
|
1564
|
+
|
|
1565
|
+
def monomial_coefficients(self, copy=True):
|
|
1566
|
+
r"""
|
|
1567
|
+
A dictionary that determines the element.
|
|
1568
|
+
|
|
1569
|
+
The keys of this dictionary are the tuples of exponents of each
|
|
1570
|
+
monomial, and the values are the corresponding coefficients.
|
|
1571
|
+
|
|
1572
|
+
EXAMPLES::
|
|
1573
|
+
|
|
1574
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
|
|
1575
|
+
sage: elt = x*y - 5*y*z + 7*x*y^2*z^3*t
|
|
1576
|
+
sage: sorted(elt.monomial_coefficients().items())
|
|
1577
|
+
[((0, 1, 1, 0), -5), ((1, 1, 0, 0), 1), ((1, 2, 3, 1), 7)]
|
|
1578
|
+
|
|
1579
|
+
``dict`` is an alias::
|
|
1580
|
+
|
|
1581
|
+
sage: sorted(elt.dict().items())
|
|
1582
|
+
[((0, 1, 1, 0), -5), ((1, 1, 0, 0), 1), ((1, 2, 3, 1), 7)]
|
|
1583
|
+
"""
|
|
1584
|
+
return self.lift().monomial_coefficients(copy=copy)
|
|
1585
|
+
|
|
1586
|
+
dict = monomial_coefficients
|
|
1587
|
+
|
|
1588
|
+
def __call__(self, *values, **kwargs):
|
|
1589
|
+
r"""
|
|
1590
|
+
Evaluate the reduced expression of this element at ``x``, where ``x``
|
|
1591
|
+
is either the tuple of values to evaluate in, a dictionary indicating
|
|
1592
|
+
to which value is each generator evaluated, or keywords giving
|
|
1593
|
+
the value to which generators should be evaluated.
|
|
1594
|
+
|
|
1595
|
+
INPUT:
|
|
1596
|
+
|
|
1597
|
+
- ``values`` -- (optional) either the values in which the variables
|
|
1598
|
+
will be evaluated or a dictionary
|
|
1599
|
+
|
|
1600
|
+
OUTPUT: this element evaluated at the given values
|
|
1601
|
+
|
|
1602
|
+
EXAMPLES::
|
|
1603
|
+
|
|
1604
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
|
|
1605
|
+
sage: f = x*y - 5*y*z + 7*x*y^2*z^3*t
|
|
1606
|
+
sage: f(3, y, x^2, x*z)
|
|
1607
|
+
3*y
|
|
1608
|
+
sage: f(x=3)
|
|
1609
|
+
21*y^2*z^3*t - 5*y*z + 3*y
|
|
1610
|
+
sage: f({x:3, z:x^2})
|
|
1611
|
+
3*y
|
|
1612
|
+
|
|
1613
|
+
If the wrong number of values is provided, it results in an error::
|
|
1614
|
+
|
|
1615
|
+
sage: f(3, 5, y)
|
|
1616
|
+
Traceback (most recent call last):
|
|
1617
|
+
...
|
|
1618
|
+
ValueError: number of arguments does not match number of variables in parent
|
|
1619
|
+
|
|
1620
|
+
It is also possible to use keywords like this::
|
|
1621
|
+
|
|
1622
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
|
|
1623
|
+
sage: f = x*y - 5*y*z + 7*x*y^2*z^3*t
|
|
1624
|
+
sage: f(x=3)
|
|
1625
|
+
21*y^2*z^3*t - 5*y*z + 3*y
|
|
1626
|
+
sage: f(t=x,y=z)
|
|
1627
|
+
-5*z^2 + x*z
|
|
1628
|
+
|
|
1629
|
+
If both a dictionary and keywords are used, only the dictionary is
|
|
1630
|
+
considered::
|
|
1631
|
+
|
|
1632
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
|
|
1633
|
+
sage: f = x*y - 5*y*z + 7*x*y^2*z^3*t
|
|
1634
|
+
sage: f({x:1}, t=x,y=z)
|
|
1635
|
+
7*y^2*z^3*t - 5*y*z + y
|
|
1636
|
+
"""
|
|
1637
|
+
gens = self.parent().gens()
|
|
1638
|
+
images = list(gens)
|
|
1639
|
+
if values and not isinstance(values[0], dict):
|
|
1640
|
+
for (i, p) in enumerate(values):
|
|
1641
|
+
images[i] = p
|
|
1642
|
+
if len(values) == 1 and isinstance(values[0], dict):
|
|
1643
|
+
images = list(gens)
|
|
1644
|
+
for (i, g) in enumerate(gens):
|
|
1645
|
+
if g in values[0]:
|
|
1646
|
+
images[i] = values[0][g]
|
|
1647
|
+
elif len(values) == len(gens):
|
|
1648
|
+
images = list(values)
|
|
1649
|
+
elif values:
|
|
1650
|
+
raise ValueError("number of arguments does not match number of variables in parent")
|
|
1651
|
+
else:
|
|
1652
|
+
images = list(gens)
|
|
1653
|
+
for (i, g) in enumerate(gens):
|
|
1654
|
+
gstr = str(g)
|
|
1655
|
+
if gstr in kwargs:
|
|
1656
|
+
images[i] = kwargs[gstr]
|
|
1657
|
+
res = 0
|
|
1658
|
+
for m, c in self.monomial_coefficients().items():
|
|
1659
|
+
term = prod((gen ** y for y, gen in zip(m, images)), c)
|
|
1660
|
+
res += term
|
|
1661
|
+
return res
|
|
1662
|
+
|
|
1663
|
+
def basis_coefficients(self, total=False):
|
|
1664
|
+
"""
|
|
1665
|
+
Return the coefficients of this homogeneous element with
|
|
1666
|
+
respect to the basis in its degree.
|
|
1667
|
+
|
|
1668
|
+
For example, if this is the sum of the `0`-th and `2`-nd basis
|
|
1669
|
+
elements, return the list ``[1, 0, 1]``.
|
|
1670
|
+
|
|
1671
|
+
Raise an error if the element is not homogeneous.
|
|
1672
|
+
|
|
1673
|
+
INPUT:
|
|
1674
|
+
|
|
1675
|
+
- ``total`` -- boolean (default: ``False``); this
|
|
1676
|
+
is only used in the multi-graded case, in which case if
|
|
1677
|
+
``True``, it returns the coefficients with respect to
|
|
1678
|
+
the basis for the total degree of this element
|
|
1679
|
+
|
|
1680
|
+
OUTPUT: list of elements of the base field
|
|
1681
|
+
|
|
1682
|
+
EXAMPLES::
|
|
1683
|
+
|
|
1684
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
|
|
1685
|
+
sage: A.basis(3)
|
|
1686
|
+
[x*y, x*z, t]
|
|
1687
|
+
sage: (t + 3*x*y).basis_coefficients()
|
|
1688
|
+
[3, 0, 1]
|
|
1689
|
+
sage: (t + x).basis_coefficients()
|
|
1690
|
+
Traceback (most recent call last):
|
|
1691
|
+
...
|
|
1692
|
+
ValueError: this element is not homogeneous
|
|
1693
|
+
|
|
1694
|
+
sage: B.<c,d> = GradedCommutativeAlgebra(QQ, degrees=((2,0), (0,4)))
|
|
1695
|
+
sage: B.basis(4)
|
|
1696
|
+
[c^2, d]
|
|
1697
|
+
sage: (c^2 - 1/2 * d).basis_coefficients(total=True)
|
|
1698
|
+
[1, -1/2]
|
|
1699
|
+
sage: (c^2 - 1/2 * d).basis_coefficients()
|
|
1700
|
+
Traceback (most recent call last):
|
|
1701
|
+
...
|
|
1702
|
+
ValueError: this element is not homogeneous
|
|
1703
|
+
"""
|
|
1704
|
+
if not self.is_homogeneous(total):
|
|
1705
|
+
raise ValueError('this element is not homogeneous')
|
|
1706
|
+
|
|
1707
|
+
basis = self.parent().basis(self.degree(total))
|
|
1708
|
+
lift = self.lift()
|
|
1709
|
+
return [lift.monomial_coefficient(x.lift()) for x in basis]
|
|
1710
|
+
|
|
1711
|
+
|
|
1712
|
+
class GCAlgebra_multigraded(GCAlgebra):
|
|
1713
|
+
"""
|
|
1714
|
+
A multi-graded commutative algebra.
|
|
1715
|
+
|
|
1716
|
+
INPUT:
|
|
1717
|
+
|
|
1718
|
+
- ``base`` -- the base field
|
|
1719
|
+
|
|
1720
|
+
- ``degrees`` -- tuple or list specifying the degrees of the
|
|
1721
|
+
generators
|
|
1722
|
+
|
|
1723
|
+
- ``names`` -- (optional) names of the generators: a list of
|
|
1724
|
+
strings or a single string with the names separated by
|
|
1725
|
+
commas; if not specified, the generators are named ``x0``,
|
|
1726
|
+
``x1``, ...
|
|
1727
|
+
|
|
1728
|
+
- ``R`` -- (optional) the ring over which the algebra is defined
|
|
1729
|
+
|
|
1730
|
+
- ``I`` -- (optional) an ideal in ``R``; it should include, among
|
|
1731
|
+
other relations, the squares of the generators of odd degree
|
|
1732
|
+
|
|
1733
|
+
When defining such an algebra, each entry of ``degrees`` should be
|
|
1734
|
+
a list, tuple, or element of an additive (free) abelian
|
|
1735
|
+
group. Regardless of how the user specifies the degrees, Sage
|
|
1736
|
+
converts them to group elements.
|
|
1737
|
+
|
|
1738
|
+
The arguments ``R`` and ``I`` are primarily for use by the
|
|
1739
|
+
:meth:`GCAlgebra.quotient` method.
|
|
1740
|
+
|
|
1741
|
+
EXAMPLES::
|
|
1742
|
+
|
|
1743
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0,1), (1,1)))
|
|
1744
|
+
sage: A
|
|
1745
|
+
Graded Commutative Algebra with generators ('a', 'b', 'c')
|
|
1746
|
+
in degrees ((1, 0), (0, 1), (1, 1)) over Rational Field
|
|
1747
|
+
sage: a**2
|
|
1748
|
+
0
|
|
1749
|
+
sage: c.degree(total=True)
|
|
1750
|
+
2
|
|
1751
|
+
sage: c**2
|
|
1752
|
+
c^2
|
|
1753
|
+
sage: c.degree()
|
|
1754
|
+
(1, 1)
|
|
1755
|
+
|
|
1756
|
+
Although the degree of ``c`` was defined using a Python tuple, it
|
|
1757
|
+
is returned as an element of an additive abelian group, and so it
|
|
1758
|
+
can be manipulated via arithmetic operations::
|
|
1759
|
+
|
|
1760
|
+
sage: type(c.degree())
|
|
1761
|
+
<class 'sage.groups.additive_abelian.additive_abelian_group.AdditiveAbelianGroup_fixed_gens_with_category.element_class'>
|
|
1762
|
+
sage: 2 * c.degree()
|
|
1763
|
+
(2, 2)
|
|
1764
|
+
sage: (a*b).degree() == a.degree() + b.degree()
|
|
1765
|
+
True
|
|
1766
|
+
|
|
1767
|
+
The :meth:`basis` method and the :meth:`Element.degree` method both accept
|
|
1768
|
+
the boolean keyword ``total``. If ``True``, use the total degree::
|
|
1769
|
+
|
|
1770
|
+
sage: A.basis(2, total=True)
|
|
1771
|
+
[a*b, c]
|
|
1772
|
+
sage: c.degree(total=True)
|
|
1773
|
+
2
|
|
1774
|
+
"""
|
|
1775
|
+
def __init__(self, base, degrees, names=None, R=None, I=None, category=None):
|
|
1776
|
+
"""
|
|
1777
|
+
Initialize ``self``.
|
|
1778
|
+
|
|
1779
|
+
EXAMPLES::
|
|
1780
|
+
|
|
1781
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0,1), (1,1)))
|
|
1782
|
+
sage: TestSuite(A).run()
|
|
1783
|
+
sage: B.<w> = GradedCommutativeAlgebra(GF(2), degrees=((3,2),))
|
|
1784
|
+
sage: TestSuite(B).run(skip=['_test_construction'])
|
|
1785
|
+
sage: C = GradedCommutativeAlgebra(GF(7), degrees=((3,2),))
|
|
1786
|
+
sage: TestSuite(C).run()
|
|
1787
|
+
"""
|
|
1788
|
+
total_degs = [total_degree(d) for d in degrees]
|
|
1789
|
+
GCAlgebra.__init__(self, base, R=R, I=I, names=names,
|
|
1790
|
+
degrees=total_degs, category=category)
|
|
1791
|
+
self._degrees_multi = degrees
|
|
1792
|
+
self._grading_rank = len(list(degrees[0]))
|
|
1793
|
+
|
|
1794
|
+
def _repr_(self):
|
|
1795
|
+
"""
|
|
1796
|
+
Print representation.
|
|
1797
|
+
|
|
1798
|
+
EXAMPLES::
|
|
1799
|
+
|
|
1800
|
+
sage: GradedCommutativeAlgebra(QQ, degrees=((1,0,0), (0,0,1), (1,1,1)))
|
|
1801
|
+
Graded Commutative Algebra with generators ('x0', 'x1', 'x2') in degrees ((1, 0, 0), (0, 0, 1), (1, 1, 1)) over Rational Field
|
|
1802
|
+
"""
|
|
1803
|
+
s = GCAlgebra._repr_(self)
|
|
1804
|
+
old = '{}'.format(self._degrees)
|
|
1805
|
+
new = '{}'.format(self._degrees_multi)
|
|
1806
|
+
return s.replace(old, new)
|
|
1807
|
+
|
|
1808
|
+
_base_repr = _repr_
|
|
1809
|
+
|
|
1810
|
+
def quotient(self, I, check=True):
|
|
1811
|
+
"""
|
|
1812
|
+
Create the quotient of this algebra by a two-sided ideal ``I``.
|
|
1813
|
+
|
|
1814
|
+
INPUT:
|
|
1815
|
+
|
|
1816
|
+
- ``I`` -- a two-sided homogeneous ideal of this algebra
|
|
1817
|
+
|
|
1818
|
+
- ``check`` -- boolean (default: ``True``); if ``True``, check whether
|
|
1819
|
+
``I`` is generated by homogeneous elements
|
|
1820
|
+
|
|
1821
|
+
EXAMPLES::
|
|
1822
|
+
|
|
1823
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(GF(5), degrees=(2, 2, 3, 4))
|
|
1824
|
+
sage: I = A.ideal([x*t+z^2, x*y - t])
|
|
1825
|
+
sage: B = A.quotient(I)
|
|
1826
|
+
sage: B
|
|
1827
|
+
Graded Commutative Algebra with generators ('x', 'y', 'z', 't')
|
|
1828
|
+
in degrees (2, 2, 3, 4) with relations [x*t, x*y - t]
|
|
1829
|
+
over Finite Field of size 5
|
|
1830
|
+
sage: B(x*t)
|
|
1831
|
+
0
|
|
1832
|
+
sage: B(x*y)
|
|
1833
|
+
t
|
|
1834
|
+
sage: A.basis(7)
|
|
1835
|
+
[x^2*z, x*y*z, y^2*z, z*t]
|
|
1836
|
+
sage: B.basis(7)
|
|
1837
|
+
[x^2*z, y^2*z, z*t]
|
|
1838
|
+
"""
|
|
1839
|
+
if check and any(not i.is_homogeneous() for i in I.gens()):
|
|
1840
|
+
raise ValueError("the ideal must be homogeneous")
|
|
1841
|
+
NCR = self.cover_ring()
|
|
1842
|
+
gens1 = list(self.defining_ideal().gens())
|
|
1843
|
+
gens2 = [i.lift() for i in I.gens()]
|
|
1844
|
+
gens = [g for g in gens1 + gens2 if g != NCR.zero()]
|
|
1845
|
+
J = NCR.ideal(gens, side='twosided')
|
|
1846
|
+
return GCAlgebra_multigraded(self.base_ring(), self._names,
|
|
1847
|
+
self._degrees_multi, NCR, J)
|
|
1848
|
+
|
|
1849
|
+
def _coerce_map_from_(self, other):
|
|
1850
|
+
r"""
|
|
1851
|
+
Return ``True`` if there is a coercion map from ``R`` to ``self``.
|
|
1852
|
+
|
|
1853
|
+
EXAMPLES::
|
|
1854
|
+
|
|
1855
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
1856
|
+
sage: B = A.cdg_algebra({a: c})
|
|
1857
|
+
sage: B._coerce_map_from_(A)
|
|
1858
|
+
True
|
|
1859
|
+
sage: B._coerce_map_from_(QQ)
|
|
1860
|
+
True
|
|
1861
|
+
sage: B._coerce_map_from_(GF(3))
|
|
1862
|
+
False
|
|
1863
|
+
"""
|
|
1864
|
+
if isinstance(other, GCAlgebra_multigraded):
|
|
1865
|
+
if self._degrees_multi != other._degrees_multi:
|
|
1866
|
+
return False
|
|
1867
|
+
elif isinstance(other, GCAlgebra): # Not multigraded
|
|
1868
|
+
return False
|
|
1869
|
+
return super()._coerce_map_from_(other)
|
|
1870
|
+
|
|
1871
|
+
def basis(self, n, total=False):
|
|
1872
|
+
"""
|
|
1873
|
+
Basis in degree `n`.
|
|
1874
|
+
|
|
1875
|
+
- ``n`` -- degree or integer
|
|
1876
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
1877
|
+
basis in total degree `n`
|
|
1878
|
+
|
|
1879
|
+
If `n` is an integer rather than a multi-index, then the
|
|
1880
|
+
total degree is used in that case as well.
|
|
1881
|
+
|
|
1882
|
+
EXAMPLES::
|
|
1883
|
+
|
|
1884
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(GF(2), degrees=((1,0), (0,1), (1,1)))
|
|
1885
|
+
sage: A.basis((1,1))
|
|
1886
|
+
[a*b, c]
|
|
1887
|
+
sage: A.basis(2, total=True)
|
|
1888
|
+
[a^2, a*b, b^2, c]
|
|
1889
|
+
|
|
1890
|
+
Since 2 is a not a multi-index, we don't need to specify that ``total``
|
|
1891
|
+
is ``True``::
|
|
1892
|
+
|
|
1893
|
+
sage: A.basis(2)
|
|
1894
|
+
[a^2, a*b, b^2, c]
|
|
1895
|
+
|
|
1896
|
+
If ``total`` is ``True``, then `n` can still be a tuple, list,
|
|
1897
|
+
etc., and its total degree is used instead::
|
|
1898
|
+
|
|
1899
|
+
sage: A.basis((1,1), total=True)
|
|
1900
|
+
[a^2, a*b, b^2, c]
|
|
1901
|
+
"""
|
|
1902
|
+
tot_basis = GCAlgebra.basis(self, total_degree(n))
|
|
1903
|
+
if total or n in ZZ:
|
|
1904
|
+
return tot_basis
|
|
1905
|
+
G = AdditiveAbelianGroup([0] * self._grading_rank)
|
|
1906
|
+
n = G(vector(n))
|
|
1907
|
+
return [b for b in tot_basis if b.degree() == n]
|
|
1908
|
+
|
|
1909
|
+
def differential(self, diff):
|
|
1910
|
+
"""
|
|
1911
|
+
Construct a differential on ``self``.
|
|
1912
|
+
|
|
1913
|
+
INPUT:
|
|
1914
|
+
|
|
1915
|
+
- ``diff`` -- dictionary defining a differential
|
|
1916
|
+
|
|
1917
|
+
The keys of the dictionary are generators of the algebra, and
|
|
1918
|
+
the associated values are their targets under the
|
|
1919
|
+
differential. Any generators which are not specified are
|
|
1920
|
+
assumed to have zero differential.
|
|
1921
|
+
|
|
1922
|
+
EXAMPLES::
|
|
1923
|
+
|
|
1924
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
1925
|
+
sage: A.differential({a: c})
|
|
1926
|
+
Differential of Graded Commutative Algebra with generators ('a', 'b', 'c')
|
|
1927
|
+
in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field
|
|
1928
|
+
Defn: a --> c
|
|
1929
|
+
b --> 0
|
|
1930
|
+
c --> 0
|
|
1931
|
+
"""
|
|
1932
|
+
return Differential_multigraded(self, diff)
|
|
1933
|
+
|
|
1934
|
+
def cdg_algebra(self, differential):
|
|
1935
|
+
r"""
|
|
1936
|
+
Construct a differential graded commutative algebra from ``self``
|
|
1937
|
+
by specifying a differential.
|
|
1938
|
+
|
|
1939
|
+
INPUT:
|
|
1940
|
+
|
|
1941
|
+
- ``differential`` -- dictionary defining a differential or
|
|
1942
|
+
a map defining a valid differential
|
|
1943
|
+
|
|
1944
|
+
The keys of the dictionary are generators of the algebra, and
|
|
1945
|
+
the associated values are their targets under the
|
|
1946
|
+
differential. Any generators which are not specified are
|
|
1947
|
+
assumed to have zero differential. Alternatively, the
|
|
1948
|
+
differential can be defined using the :meth:`differential`
|
|
1949
|
+
method; see below for an example.
|
|
1950
|
+
|
|
1951
|
+
.. SEEALSO::
|
|
1952
|
+
|
|
1953
|
+
:meth:`differential`
|
|
1954
|
+
|
|
1955
|
+
EXAMPLES::
|
|
1956
|
+
|
|
1957
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
1958
|
+
sage: A.cdg_algebra({a: c})
|
|
1959
|
+
Commutative Differential Graded Algebra with generators ('a', 'b', 'c')
|
|
1960
|
+
in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field with differential:
|
|
1961
|
+
a --> c
|
|
1962
|
+
b --> 0
|
|
1963
|
+
c --> 0
|
|
1964
|
+
sage: d = A.differential({a: c})
|
|
1965
|
+
sage: A.cdg_algebra(d)
|
|
1966
|
+
Commutative Differential Graded Algebra with generators ('a', 'b', 'c')
|
|
1967
|
+
in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field with differential:
|
|
1968
|
+
a --> c
|
|
1969
|
+
b --> 0
|
|
1970
|
+
c --> 0
|
|
1971
|
+
"""
|
|
1972
|
+
return DifferentialGCAlgebra_multigraded(self, differential)
|
|
1973
|
+
|
|
1974
|
+
class Element(GCAlgebra.Element):
|
|
1975
|
+
def degree(self, total=False):
|
|
1976
|
+
"""
|
|
1977
|
+
Return the degree of this element.
|
|
1978
|
+
|
|
1979
|
+
INPUT:
|
|
1980
|
+
|
|
1981
|
+
- ``total`` -- if ``True``, return the total degree, an
|
|
1982
|
+
integer; otherwise, return the degree as an element of
|
|
1983
|
+
an additive free abelian group
|
|
1984
|
+
|
|
1985
|
+
If not requesting the total degree, raise an error if the
|
|
1986
|
+
element is not homogeneous.
|
|
1987
|
+
|
|
1988
|
+
EXAMPLES::
|
|
1989
|
+
|
|
1990
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(GF(2),
|
|
1991
|
+
....: degrees=((1,0), (0,1), (1,1)))
|
|
1992
|
+
sage: (a**2*b).degree()
|
|
1993
|
+
(2, 1)
|
|
1994
|
+
sage: (a**2*b).degree(total=True)
|
|
1995
|
+
3
|
|
1996
|
+
sage: (a**2*b + c).degree()
|
|
1997
|
+
Traceback (most recent call last):
|
|
1998
|
+
...
|
|
1999
|
+
ValueError: this element is not homogeneous
|
|
2000
|
+
sage: (a**2*b + c).degree(total=True)
|
|
2001
|
+
3
|
|
2002
|
+
sage: A(0).degree()
|
|
2003
|
+
Traceback (most recent call last):
|
|
2004
|
+
...
|
|
2005
|
+
ValueError: the zero element does not have a well-defined degree
|
|
2006
|
+
"""
|
|
2007
|
+
if total:
|
|
2008
|
+
return GCAlgebra.Element.degree(self)
|
|
2009
|
+
if self.is_zero():
|
|
2010
|
+
raise ValueError("the zero element does not have a well-defined degree")
|
|
2011
|
+
degrees = self.parent()._degrees_multi
|
|
2012
|
+
n = self.parent().ngens()
|
|
2013
|
+
exps = self.monomial_coefficients().keys()
|
|
2014
|
+
l = [sum(exp[i] * degrees[i] for i in range(n)) for exp in exps]
|
|
2015
|
+
if len(set(l)) == 1:
|
|
2016
|
+
return l[0]
|
|
2017
|
+
raise ValueError('this element is not homogeneous')
|
|
2018
|
+
|
|
2019
|
+
|
|
2020
|
+
###########################################################
|
|
2021
|
+
# Differential algebras
|
|
2022
|
+
|
|
2023
|
+
class DifferentialGCAlgebra(GCAlgebra):
|
|
2024
|
+
"""
|
|
2025
|
+
A commutative differential graded algebra.
|
|
2026
|
+
|
|
2027
|
+
INPUT:
|
|
2028
|
+
|
|
2029
|
+
- ``A`` -- a graded commutative algebra; that is, an instance
|
|
2030
|
+
of :class:`GCAlgebra`
|
|
2031
|
+
|
|
2032
|
+
- ``differential`` -- a differential
|
|
2033
|
+
|
|
2034
|
+
As described in the module-level documentation, these are graded
|
|
2035
|
+
algebras for which oddly graded elements anticommute and evenly
|
|
2036
|
+
graded elements commute, and on which there is a graded
|
|
2037
|
+
differential of degree 1.
|
|
2038
|
+
|
|
2039
|
+
These algebras should be graded over the integers; multi-graded
|
|
2040
|
+
algebras should be constructed using
|
|
2041
|
+
:class:`DifferentialGCAlgebra_multigraded` instead.
|
|
2042
|
+
|
|
2043
|
+
Note that a natural way to construct these is to use the
|
|
2044
|
+
:func:`GradedCommutativeAlgebra` function and the
|
|
2045
|
+
:meth:`GCAlgebra.cdg_algebra` method.
|
|
2046
|
+
|
|
2047
|
+
EXAMPLES::
|
|
2048
|
+
|
|
2049
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 3))
|
|
2050
|
+
sage: A.cdg_algebra({z: x*y})
|
|
2051
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't')
|
|
2052
|
+
in degrees (2, 2, 3, 3) over Rational Field with differential:
|
|
2053
|
+
x --> 0
|
|
2054
|
+
y --> 0
|
|
2055
|
+
z --> x*y
|
|
2056
|
+
t --> 0
|
|
2057
|
+
|
|
2058
|
+
Alternatively, starting with :func:`GradedCommutativeAlgebra`::
|
|
2059
|
+
|
|
2060
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 3))
|
|
2061
|
+
sage: A.cdg_algebra(differential={z: x*y})
|
|
2062
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't')
|
|
2063
|
+
in degrees (2, 2, 3, 3) over Rational Field with differential:
|
|
2064
|
+
x --> 0
|
|
2065
|
+
y --> 0
|
|
2066
|
+
z --> x*y
|
|
2067
|
+
t --> 0
|
|
2068
|
+
|
|
2069
|
+
See the function :func:`GradedCommutativeAlgebra` for more examples.
|
|
2070
|
+
"""
|
|
2071
|
+
@staticmethod
|
|
2072
|
+
def __classcall__(cls, A, differential):
|
|
2073
|
+
"""
|
|
2074
|
+
Normalize input to ensure a unique representation.
|
|
2075
|
+
|
|
2076
|
+
EXAMPLES::
|
|
2077
|
+
|
|
2078
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1))
|
|
2079
|
+
sage: D1 = A.cdg_algebra({a: b*c, b: a*c})
|
|
2080
|
+
sage: D2 = A.cdg_algebra(D1.differential())
|
|
2081
|
+
sage: D1 is D2
|
|
2082
|
+
True
|
|
2083
|
+
sage: from sage.algebras.commutative_dga import DifferentialGCAlgebra
|
|
2084
|
+
sage: D1 is DifferentialGCAlgebra(A, {a: b*c, b: a*c, c: 0})
|
|
2085
|
+
True
|
|
2086
|
+
"""
|
|
2087
|
+
if not isinstance(differential, Differential):
|
|
2088
|
+
differential = A.differential(differential)
|
|
2089
|
+
elif differential.parent() != A:
|
|
2090
|
+
differential = Differential(A, differential._dic_)
|
|
2091
|
+
return super(GCAlgebra, cls).__classcall__(cls, A, differential)
|
|
2092
|
+
|
|
2093
|
+
def __init__(self, A, differential):
|
|
2094
|
+
"""
|
|
2095
|
+
Initialize ``self``.
|
|
2096
|
+
|
|
2097
|
+
INPUT:
|
|
2098
|
+
|
|
2099
|
+
- ``A`` -- a graded commutative algebra
|
|
2100
|
+
|
|
2101
|
+
- ``differential`` -- a differential
|
|
2102
|
+
|
|
2103
|
+
EXAMPLES::
|
|
2104
|
+
|
|
2105
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 3))
|
|
2106
|
+
sage: D = A.cdg_algebra({z: x*y})
|
|
2107
|
+
sage: TestSuite(D).run()
|
|
2108
|
+
|
|
2109
|
+
The degree of the differential must be 1::
|
|
2110
|
+
|
|
2111
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1))
|
|
2112
|
+
sage: A.cdg_algebra({a: a*b*c})
|
|
2113
|
+
Traceback (most recent call last):
|
|
2114
|
+
...
|
|
2115
|
+
ValueError: the given dictionary does not determine a degree 1 map
|
|
2116
|
+
|
|
2117
|
+
The differential composed with itself must be zero::
|
|
2118
|
+
|
|
2119
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,2,3))
|
|
2120
|
+
sage: A.cdg_algebra({a:b, b:c})
|
|
2121
|
+
Traceback (most recent call last):
|
|
2122
|
+
...
|
|
2123
|
+
ValueError: the given dictionary does not determine a valid differential
|
|
2124
|
+
"""
|
|
2125
|
+
cat = Algebras(A.base()).Graded() & ChainComplexes(A.base())
|
|
2126
|
+
GCAlgebra.__init__(self, A.base(), names=A._names,
|
|
2127
|
+
degrees=A._degrees, R=A.cover_ring(),
|
|
2128
|
+
I=A.defining_ideal(), category=cat)
|
|
2129
|
+
self._differential = Differential(self, differential._dic_)
|
|
2130
|
+
self._minimalmodels = {}
|
|
2131
|
+
self._numerical_invariants = {}
|
|
2132
|
+
|
|
2133
|
+
def cdg_algebra(self, differential):
|
|
2134
|
+
r"""
|
|
2135
|
+
Construct a differential graded commutative algebra from the underlying
|
|
2136
|
+
graded commutative algebra by specifying a differential. This may be used
|
|
2137
|
+
to get a new differential over the same algebra structure.
|
|
2138
|
+
|
|
2139
|
+
INPUT:
|
|
2140
|
+
|
|
2141
|
+
- ``differential`` -- dictionary defining a differential or
|
|
2142
|
+
a map defining a valid differential
|
|
2143
|
+
|
|
2144
|
+
The keys of the dictionary are generators of the algebra, and
|
|
2145
|
+
the associated values are their targets under the
|
|
2146
|
+
differential. Any generators which are not specified are
|
|
2147
|
+
assumed to have zero differential. Alternatively, the
|
|
2148
|
+
differential can be defined using the :meth:`differential`
|
|
2149
|
+
method; see below for an example.
|
|
2150
|
+
|
|
2151
|
+
.. SEEALSO::
|
|
2152
|
+
|
|
2153
|
+
:meth:`differential`
|
|
2154
|
+
|
|
2155
|
+
EXAMPLES::
|
|
2156
|
+
|
|
2157
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(GF(5), degrees=(2, 3, 2, 4))
|
|
2158
|
+
sage: B = A.quotient(A.ideal(x^3-z*t))
|
|
2159
|
+
sage: C = B.cdg_algebra({y:t})
|
|
2160
|
+
sage: C
|
|
2161
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't')
|
|
2162
|
+
in degrees (2, 3, 2, 4) with relations [x^3 - z*t]
|
|
2163
|
+
over Finite Field of size 5 with differential:
|
|
2164
|
+
x --> 0
|
|
2165
|
+
y --> t
|
|
2166
|
+
z --> 0
|
|
2167
|
+
t --> 0
|
|
2168
|
+
sage: C.cdg_algebra({})
|
|
2169
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't')
|
|
2170
|
+
in degrees (2, 3, 2, 4) with relations [x^3 - z*t]
|
|
2171
|
+
over Finite Field of size 5 with differential:
|
|
2172
|
+
x --> 0
|
|
2173
|
+
y --> 0
|
|
2174
|
+
z --> 0
|
|
2175
|
+
t --> 0
|
|
2176
|
+
"""
|
|
2177
|
+
return self.graded_commutative_algebra().cdg_algebra(differential)
|
|
2178
|
+
|
|
2179
|
+
def graded_commutative_algebra(self):
|
|
2180
|
+
"""
|
|
2181
|
+
Return the base graded commutative algebra of ``self``.
|
|
2182
|
+
|
|
2183
|
+
EXAMPLES::
|
|
2184
|
+
|
|
2185
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 3))
|
|
2186
|
+
sage: D = A.cdg_algebra({z: x*y})
|
|
2187
|
+
sage: D.graded_commutative_algebra() == A
|
|
2188
|
+
True
|
|
2189
|
+
"""
|
|
2190
|
+
return GCAlgebra(self.base(), names=self._names, degrees=self._degrees,
|
|
2191
|
+
R=self.cover_ring(), I=self.defining_ideal())
|
|
2192
|
+
|
|
2193
|
+
def _base_repr(self):
|
|
2194
|
+
"""
|
|
2195
|
+
Return the base string representation of ``self``.
|
|
2196
|
+
|
|
2197
|
+
EXAMPLES::
|
|
2198
|
+
|
|
2199
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=[1, 2, 3, 4])
|
|
2200
|
+
sage: A.cdg_algebra({x:y, z:t})._base_repr()
|
|
2201
|
+
"Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (1, 2, 3, 4) over Rational Field"
|
|
2202
|
+
"""
|
|
2203
|
+
return GCAlgebra._repr_(self).replace('Graded Commutative', 'Commutative Differential Graded')
|
|
2204
|
+
|
|
2205
|
+
def _repr_(self):
|
|
2206
|
+
"""
|
|
2207
|
+
EXAMPLES::
|
|
2208
|
+
|
|
2209
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=[1, 2, 3, 4])
|
|
2210
|
+
sage: A.cdg_algebra({x:y, z:t})
|
|
2211
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (1, 2, 3, 4) over Rational Field with differential:
|
|
2212
|
+
x --> y
|
|
2213
|
+
y --> 0
|
|
2214
|
+
z --> t
|
|
2215
|
+
t --> 0
|
|
2216
|
+
"""
|
|
2217
|
+
d = self._differential._repr_defn().replace('\n', '\n ')
|
|
2218
|
+
return self._base_repr() + f" with differential:\n {d}"
|
|
2219
|
+
|
|
2220
|
+
def quotient(self, I, check=True):
|
|
2221
|
+
"""
|
|
2222
|
+
Create the quotient of this algebra by a two-sided ideal ``I``.
|
|
2223
|
+
|
|
2224
|
+
INPUT:
|
|
2225
|
+
|
|
2226
|
+
- ``I`` -- a two-sided homogeneous ideal of this algebra
|
|
2227
|
+
|
|
2228
|
+
- ``check`` -- boolean (default: ``True``); if ``True``, check whether
|
|
2229
|
+
``I`` is generated by homogeneous elements
|
|
2230
|
+
|
|
2231
|
+
EXAMPLES::
|
|
2232
|
+
|
|
2233
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
2234
|
+
sage: B = A.cdg_algebra({y:x*y, z:x*z})
|
|
2235
|
+
sage: B.inject_variables()
|
|
2236
|
+
Defining x, y, z
|
|
2237
|
+
sage: I = B.ideal([y*z])
|
|
2238
|
+
sage: C = B.quotient(I)
|
|
2239
|
+
sage: (y*z).differential()
|
|
2240
|
+
2*x*y*z
|
|
2241
|
+
sage: C((y*z).differential())
|
|
2242
|
+
0
|
|
2243
|
+
sage: C(y*z)
|
|
2244
|
+
0
|
|
2245
|
+
|
|
2246
|
+
It is checked that the differential maps the ideal into itself, to make
|
|
2247
|
+
sure that the quotient inherits a differential structure::
|
|
2248
|
+
|
|
2249
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,2,2))
|
|
2250
|
+
sage: B = A.cdg_algebra({x:y})
|
|
2251
|
+
sage: B.quotient(B.ideal(y*x))
|
|
2252
|
+
Traceback (most recent call last):
|
|
2253
|
+
...
|
|
2254
|
+
ValueError: the differential does not preserve the ideal
|
|
2255
|
+
sage: B.quotient(B.ideal(x))
|
|
2256
|
+
Traceback (most recent call last):
|
|
2257
|
+
...
|
|
2258
|
+
ValueError: the differential does not preserve the ideal
|
|
2259
|
+
"""
|
|
2260
|
+
J = self.ideal(I)
|
|
2261
|
+
AQ = GCAlgebra.quotient(self, J, check)
|
|
2262
|
+
for g in I.gens():
|
|
2263
|
+
if not AQ(g.differential()).is_zero():
|
|
2264
|
+
raise ValueError("the differential does not preserve the ideal")
|
|
2265
|
+
dic = {AQ(a): AQ(a.differential()) for a in self.gens()}
|
|
2266
|
+
return AQ.cdg_algebra(dic)
|
|
2267
|
+
|
|
2268
|
+
def differential(self, x=None):
|
|
2269
|
+
r"""
|
|
2270
|
+
The differential of ``self``.
|
|
2271
|
+
|
|
2272
|
+
This returns a map, and so it may be evaluated on elements of
|
|
2273
|
+
this algebra.
|
|
2274
|
+
|
|
2275
|
+
EXAMPLES::
|
|
2276
|
+
|
|
2277
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
2278
|
+
sage: B = A.cdg_algebra({y:x*y, x: y*x})
|
|
2279
|
+
sage: d = B.differential(); d
|
|
2280
|
+
Differential of Commutative Differential Graded Algebra
|
|
2281
|
+
with generators ('x', 'y', 'z') in degrees (1, 1, 2) over Rational Field
|
|
2282
|
+
Defn: x --> -x*y
|
|
2283
|
+
y --> x*y
|
|
2284
|
+
z --> 0
|
|
2285
|
+
sage: d(y)
|
|
2286
|
+
x*y
|
|
2287
|
+
"""
|
|
2288
|
+
return self._differential
|
|
2289
|
+
|
|
2290
|
+
def coboundaries(self, n):
|
|
2291
|
+
"""
|
|
2292
|
+
The `n`-th coboundary group of the algebra.
|
|
2293
|
+
|
|
2294
|
+
This is a vector space over the base field `F`, and it is
|
|
2295
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
2296
|
+
`n`-th homogeneous component has dimension `d`.
|
|
2297
|
+
|
|
2298
|
+
INPUT:
|
|
2299
|
+
|
|
2300
|
+
- ``n`` -- degree
|
|
2301
|
+
|
|
2302
|
+
EXAMPLES::
|
|
2303
|
+
|
|
2304
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
2305
|
+
sage: B = A.cdg_algebra(differential={z: x*z})
|
|
2306
|
+
sage: B.coboundaries(2)
|
|
2307
|
+
Vector space of degree 2 and dimension 0 over Rational Field
|
|
2308
|
+
Basis matrix:
|
|
2309
|
+
[]
|
|
2310
|
+
sage: B.coboundaries(3)
|
|
2311
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
2312
|
+
Basis matrix:
|
|
2313
|
+
[1 0]
|
|
2314
|
+
sage: B.basis(3)
|
|
2315
|
+
[x*z, y*z]
|
|
2316
|
+
"""
|
|
2317
|
+
return self._differential.coboundaries(n)
|
|
2318
|
+
|
|
2319
|
+
def cocycles(self, n):
|
|
2320
|
+
"""
|
|
2321
|
+
The `n`-th cocycle group of the algebra.
|
|
2322
|
+
|
|
2323
|
+
This is a vector space over the base field `F`, and it is
|
|
2324
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
2325
|
+
`n`-th homogeneous component has dimension `d`.
|
|
2326
|
+
|
|
2327
|
+
INPUT:
|
|
2328
|
+
|
|
2329
|
+
- ``n`` -- degree
|
|
2330
|
+
|
|
2331
|
+
EXAMPLES::
|
|
2332
|
+
|
|
2333
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
2334
|
+
sage: B = A.cdg_algebra(differential={z: x*z})
|
|
2335
|
+
sage: B.cocycles(2)
|
|
2336
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
2337
|
+
Basis matrix:
|
|
2338
|
+
[1 0]
|
|
2339
|
+
sage: B.basis(2)
|
|
2340
|
+
[x*y, z]
|
|
2341
|
+
"""
|
|
2342
|
+
return self._differential.cocycles(n)
|
|
2343
|
+
|
|
2344
|
+
def cohomology_raw(self, n):
|
|
2345
|
+
"""
|
|
2346
|
+
The `n`-th cohomology group of ``self``.
|
|
2347
|
+
|
|
2348
|
+
This is a vector space over the base ring, and it is returned
|
|
2349
|
+
as the quotient cocycles/coboundaries.
|
|
2350
|
+
|
|
2351
|
+
INPUT:
|
|
2352
|
+
|
|
2353
|
+
- ``n`` -- degree
|
|
2354
|
+
|
|
2355
|
+
EXAMPLES::
|
|
2356
|
+
|
|
2357
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees = (2,2,3,4))
|
|
2358
|
+
sage: B = A.cdg_algebra({t: x*z, x: z, y: z})
|
|
2359
|
+
sage: B.cohomology_raw(4)
|
|
2360
|
+
Vector space quotient V/W of dimension 2 over Rational Field where
|
|
2361
|
+
V: Vector space of degree 4 and dimension 2 over Rational Field
|
|
2362
|
+
Basis matrix:
|
|
2363
|
+
[ 1 0 0 -2]
|
|
2364
|
+
[ 0 1 -1/2 -1]
|
|
2365
|
+
W: Vector space of degree 4 and dimension 0 over Rational Field
|
|
2366
|
+
Basis matrix:
|
|
2367
|
+
[]
|
|
2368
|
+
|
|
2369
|
+
Compare to :meth:`cohomology`::
|
|
2370
|
+
|
|
2371
|
+
sage: B.cohomology(4)
|
|
2372
|
+
Free module generated by {[x^2 - 2*t], [x*y - 1/2*y^2 - t]} over Rational Field
|
|
2373
|
+
"""
|
|
2374
|
+
return self._differential.cohomology_raw(n)
|
|
2375
|
+
|
|
2376
|
+
def cohomology(self, n):
|
|
2377
|
+
"""
|
|
2378
|
+
The `n`-th cohomology group of ``self``.
|
|
2379
|
+
|
|
2380
|
+
This is a vector space over the base ring, defined as the
|
|
2381
|
+
quotient cocycles/coboundaries. The elements of the quotient
|
|
2382
|
+
are lifted to the vector space of cocycles, and this is
|
|
2383
|
+
described in terms of those lifts.
|
|
2384
|
+
|
|
2385
|
+
INPUT:
|
|
2386
|
+
|
|
2387
|
+
- ``n`` -- degree
|
|
2388
|
+
|
|
2389
|
+
EXAMPLES::
|
|
2390
|
+
|
|
2391
|
+
sage: A.<a,b,c,d,e> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1,1,1))
|
|
2392
|
+
sage: B = A.cdg_algebra({d: a*b, e: b*c})
|
|
2393
|
+
sage: B.cohomology(2)
|
|
2394
|
+
Free module generated by {[a*c], [a*d], [b*d], [c*d - a*e], [b*e], [c*e]}
|
|
2395
|
+
over Rational Field
|
|
2396
|
+
|
|
2397
|
+
Compare to :meth:`cohomology_raw`::
|
|
2398
|
+
|
|
2399
|
+
sage: B.cohomology_raw(2)
|
|
2400
|
+
Vector space quotient V/W of dimension 6 over Rational Field where
|
|
2401
|
+
V: Vector space of degree 10 and dimension 8 over Rational Field
|
|
2402
|
+
Basis matrix:
|
|
2403
|
+
[ 1 0 0 0 0 0 0 0 0 0]
|
|
2404
|
+
[ 0 1 0 0 0 0 0 0 0 0]
|
|
2405
|
+
[ 0 0 1 0 0 0 0 0 0 0]
|
|
2406
|
+
[ 0 0 0 1 0 0 0 0 0 0]
|
|
2407
|
+
[ 0 0 0 0 1 0 0 0 0 0]
|
|
2408
|
+
[ 0 0 0 0 0 1 -1 0 0 0]
|
|
2409
|
+
[ 0 0 0 0 0 0 0 1 0 0]
|
|
2410
|
+
[ 0 0 0 0 0 0 0 0 1 0]
|
|
2411
|
+
W: Vector space of degree 10 and dimension 2 over Rational Field
|
|
2412
|
+
Basis matrix:
|
|
2413
|
+
[1 0 0 0 0 0 0 0 0 0]
|
|
2414
|
+
[0 0 1 0 0 0 0 0 0 0]
|
|
2415
|
+
|
|
2416
|
+
TESTS:
|
|
2417
|
+
|
|
2418
|
+
Check that the issue discovered in :issue:`28155` is solved::
|
|
2419
|
+
|
|
2420
|
+
sage: A.<e1,e2,e3,e4,e5> = GradedCommutativeAlgebra(QQ)
|
|
2421
|
+
sage: B = A.cdg_algebra({e5:e1*e2+e3*e4})
|
|
2422
|
+
sage: B.cohomology(3) is B.cohomology(3)
|
|
2423
|
+
True
|
|
2424
|
+
"""
|
|
2425
|
+
return self._differential.cohomology(n)
|
|
2426
|
+
|
|
2427
|
+
homology = cohomology
|
|
2428
|
+
|
|
2429
|
+
def cohomology_generators(self, max_degree):
|
|
2430
|
+
"""
|
|
2431
|
+
Return lifts of algebra generators for cohomology in degrees at
|
|
2432
|
+
most ``max_degree``.
|
|
2433
|
+
|
|
2434
|
+
INPUT:
|
|
2435
|
+
|
|
2436
|
+
- ``max_degree`` -- integer
|
|
2437
|
+
|
|
2438
|
+
OUTPUT:
|
|
2439
|
+
|
|
2440
|
+
A dictionary keyed by degree, where the corresponding
|
|
2441
|
+
value is a list of cohomology generators in that degree.
|
|
2442
|
+
Actually, the elements are lifts of cohomology generators,
|
|
2443
|
+
which means that they lie in this differential graded
|
|
2444
|
+
algebra. It also means that they are only well-defined up to
|
|
2445
|
+
cohomology, not on the nose.
|
|
2446
|
+
|
|
2447
|
+
ALGORITHM:
|
|
2448
|
+
|
|
2449
|
+
Reduce a basis of the `n`-th cohomology modulo all the degree `n`
|
|
2450
|
+
products of the lower degree cohomologies.
|
|
2451
|
+
|
|
2452
|
+
EXAMPLES::
|
|
2453
|
+
|
|
2454
|
+
sage: A.<a,x,y> = GradedCommutativeAlgebra(QQ, degrees=(1,2,2))
|
|
2455
|
+
sage: B = A.cdg_algebra(differential={y: a*x})
|
|
2456
|
+
sage: B.cohomology_generators(3)
|
|
2457
|
+
{1: [a], 2: [x], 3: [a*y]}
|
|
2458
|
+
|
|
2459
|
+
The previous example has infinitely generated cohomology:
|
|
2460
|
+
`a y^n` is a cohomology generator for each `n`::
|
|
2461
|
+
|
|
2462
|
+
sage: B.cohomology_generators(10)
|
|
2463
|
+
{1: [a], 2: [x], 3: [a*y], 5: [a*y^2], 7: [a*y^3], 9: [a*y^4]}
|
|
2464
|
+
|
|
2465
|
+
In contrast, the corresponding algebra in characteristic `p`
|
|
2466
|
+
has finitely generated cohomology::
|
|
2467
|
+
|
|
2468
|
+
sage: A3.<a,x,y> = GradedCommutativeAlgebra(GF(3), degrees=(1,2,2))
|
|
2469
|
+
sage: B3 = A3.cdg_algebra(differential={y: a*x})
|
|
2470
|
+
sage: B3.cohomology_generators(16)
|
|
2471
|
+
{1: [a], 2: [x], 3: [a*y], 5: [a*y^2], 6: [y^3]}
|
|
2472
|
+
|
|
2473
|
+
This method works with both singly graded and multi-graded algebras::
|
|
2474
|
+
|
|
2475
|
+
sage: Cs.<a,b,c,d> = GradedCommutativeAlgebra(GF(2), degrees=(1,2,2,3))
|
|
2476
|
+
sage: Ds = Cs.cdg_algebra({a:c, b:d})
|
|
2477
|
+
sage: Ds.cohomology_generators(10)
|
|
2478
|
+
{2: [a^2], 4: [b^2]}
|
|
2479
|
+
|
|
2480
|
+
sage: Cm.<a,b,c,d> = GradedCommutativeAlgebra(GF(2),
|
|
2481
|
+
....: degrees=((1,0), (1,1),
|
|
2482
|
+
....: (0,2), (0,3)))
|
|
2483
|
+
sage: Dm = Cm.cdg_algebra({a:c, b:d})
|
|
2484
|
+
sage: Dm.cohomology_generators(10)
|
|
2485
|
+
{2: [a^2], 4: [b^2]}
|
|
2486
|
+
|
|
2487
|
+
TESTS:
|
|
2488
|
+
|
|
2489
|
+
Test that coboundaries do not appear as cohomology generators::
|
|
2490
|
+
|
|
2491
|
+
sage: X.<x,y> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
2492
|
+
sage: acyclic = X.cdg_algebra({x: y})
|
|
2493
|
+
sage: acyclic.cohomology_generators(3)
|
|
2494
|
+
{}
|
|
2495
|
+
|
|
2496
|
+
Test that redundant generators are eliminated::
|
|
2497
|
+
|
|
2498
|
+
sage: A.<e1,e2,e3,e4> = GradedCommutativeAlgebra(QQ)
|
|
2499
|
+
sage: d = A.differential({e1:e4*e3,e2:e4*e3})
|
|
2500
|
+
sage: B = A.cdg_algebra(d)
|
|
2501
|
+
sage: B.cohomology_generators(3)
|
|
2502
|
+
{1: [e1 - e2, e3, e4], 2: [e1*e3, e1*e4]}
|
|
2503
|
+
"""
|
|
2504
|
+
if not (max_degree in ZZ and max_degree > 0):
|
|
2505
|
+
raise ValueError('the given maximal degree must be a '
|
|
2506
|
+
'positive integer')
|
|
2507
|
+
|
|
2508
|
+
def vector_to_element(v, deg):
|
|
2509
|
+
"""
|
|
2510
|
+
If an element of this algebra in degree ``deg`` is represented
|
|
2511
|
+
by a raw vector ``v``, convert it back to an element of the
|
|
2512
|
+
algebra again.
|
|
2513
|
+
"""
|
|
2514
|
+
return sum(c * b for (c, b) in zip(v, self.basis(deg)))
|
|
2515
|
+
if max_degree == 1:
|
|
2516
|
+
cohom1 = self.cohomology(1).basis().keys()
|
|
2517
|
+
if not cohom1:
|
|
2518
|
+
return {}
|
|
2519
|
+
return {1: [g.representative() for g in cohom1]}
|
|
2520
|
+
smaller_degree = {i: [g.representative() for g in
|
|
2521
|
+
self.cohomology(i).basis().keys()] for i in
|
|
2522
|
+
range(1, max_degree)}
|
|
2523
|
+
already_generated = []
|
|
2524
|
+
for i in range(1, max_degree):
|
|
2525
|
+
already_generated += [a * b for a in smaller_degree[i] for b in
|
|
2526
|
+
smaller_degree[max_degree - i]]
|
|
2527
|
+
CR = self.cohomology_raw(max_degree)
|
|
2528
|
+
V = CR.V()
|
|
2529
|
+
S = CR.submodule([CR(V(g.basis_coefficients(total=True))) for g in
|
|
2530
|
+
already_generated if not g.is_zero()])
|
|
2531
|
+
Q = CR.quotient(S)
|
|
2532
|
+
res = self.cohomology_generators(max_degree - 1)
|
|
2533
|
+
if Q.basis():
|
|
2534
|
+
res[max_degree] = [vector_to_element(CR.lift(Q.lift(g)),
|
|
2535
|
+
max_degree)
|
|
2536
|
+
for g in Q.basis()]
|
|
2537
|
+
return res
|
|
2538
|
+
|
|
2539
|
+
def minimal_model(self, i=3, max_iterations=3, partial_result=False):
|
|
2540
|
+
r"""
|
|
2541
|
+
Try to compute a map from a `i`-minimal gcda that is a
|
|
2542
|
+
`i`-quasi-isomorphism to ``self``.
|
|
2543
|
+
|
|
2544
|
+
INPUT:
|
|
2545
|
+
|
|
2546
|
+
- ``i`` -- integer (default: `3`); degree to which the result is
|
|
2547
|
+
required to induce an isomorphism in cohomology, and the domain is
|
|
2548
|
+
required to be minimal
|
|
2549
|
+
|
|
2550
|
+
- ``max_iterations`` -- integer (default: `3`); the number of
|
|
2551
|
+
iterations of the method at each degree. If the algorithm does not
|
|
2552
|
+
finish in this many iterations at each degree, an error is raised,
|
|
2553
|
+
or the partial result computed up to that point is returned, deppending
|
|
2554
|
+
on the ``partial_result`` flag.
|
|
2555
|
+
|
|
2556
|
+
- ``partial_result`` -- boolean (default: ``False``); whether to return
|
|
2557
|
+
the partial result if the ``max_iterations`` limit is reached
|
|
2558
|
+
|
|
2559
|
+
OUTPUT:
|
|
2560
|
+
|
|
2561
|
+
A morphism from a minimal Sullivan (up to degree ``i``) CDGA's to self,
|
|
2562
|
+
that induces an isomorphism in cohomology up to degree ``i``, and a
|
|
2563
|
+
monomorphism in degree ``i+1``.
|
|
2564
|
+
|
|
2565
|
+
EXAMPLES::
|
|
2566
|
+
|
|
2567
|
+
sage: S.<x, y, z> = GradedCommutativeAlgebra(QQ, degrees = (1, 1, 2))
|
|
2568
|
+
sage: d = S.differential({x:x*y, y:x*y})
|
|
2569
|
+
sage: R = S.cdg_algebra(d)
|
|
2570
|
+
sage: p = R.minimal_model()
|
|
2571
|
+
sage: T = p.domain()
|
|
2572
|
+
sage: p
|
|
2573
|
+
Commutative Differential Graded Algebra morphism:
|
|
2574
|
+
From: Commutative Differential Graded Algebra
|
|
2575
|
+
with generators ('x1_0', 'x2_0') in degrees (1, 2)
|
|
2576
|
+
over Rational Field with differential:
|
|
2577
|
+
x1_0 --> 0
|
|
2578
|
+
x2_0 --> 0
|
|
2579
|
+
To: Commutative Differential Graded Algebra
|
|
2580
|
+
with generators ('x', 'y', 'z') in degrees (1, 1, 2)
|
|
2581
|
+
over Rational Field with differential:
|
|
2582
|
+
x --> x*y
|
|
2583
|
+
y --> x*y
|
|
2584
|
+
z --> 0
|
|
2585
|
+
Defn: (x1_0, x2_0) --> (x - y, z)
|
|
2586
|
+
sage: R.cohomology(1)
|
|
2587
|
+
Free module generated by {[x - y]} over Rational Field
|
|
2588
|
+
sage: T.cohomology(1)
|
|
2589
|
+
Free module generated by {[x1_0]} over Rational Field
|
|
2590
|
+
sage: [p(g.representative()) for g in T.cohomology(1).basis().keys()]
|
|
2591
|
+
[x - y]
|
|
2592
|
+
sage: R.cohomology(2)
|
|
2593
|
+
Free module generated by {[z]} over Rational Field
|
|
2594
|
+
sage: T.cohomology(2)
|
|
2595
|
+
Free module generated by {[x2_0]} over Rational Field
|
|
2596
|
+
sage: [p(g.representative()) for g in T.cohomology(2).basis().keys()]
|
|
2597
|
+
[z]
|
|
2598
|
+
|
|
2599
|
+
|
|
2600
|
+
sage: A.<e1, e2, e3, e4, e5, e6, e7> = GradedCommutativeAlgebra(QQ)
|
|
2601
|
+
sage: d = A.differential({e1:e1*e7, e2:e2*e7, e3:-e3*e7, e4:-e4*e7})
|
|
2602
|
+
sage: B = A.cdg_algebra(d)
|
|
2603
|
+
sage: phi = B.minimal_model(i=3)
|
|
2604
|
+
sage: M = phi.domain()
|
|
2605
|
+
sage: M
|
|
2606
|
+
Commutative Differential Graded Algebra with generators
|
|
2607
|
+
('x1_0', 'x1_1', 'x1_2', 'x2_0', 'x2_1', 'x2_2', 'x2_3',
|
|
2608
|
+
'y3_0', 'y3_1', 'y3_2', 'y3_3', 'y3_4', 'y3_5', 'y3_6', 'y3_7', 'y3_8')
|
|
2609
|
+
in degrees (1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3)
|
|
2610
|
+
over Rational Field with differential:
|
|
2611
|
+
x1_0 --> 0
|
|
2612
|
+
x1_1 --> 0
|
|
2613
|
+
x1_2 --> 0
|
|
2614
|
+
x2_0 --> 0
|
|
2615
|
+
x2_1 --> 0
|
|
2616
|
+
x2_2 --> 0
|
|
2617
|
+
x2_3 --> 0
|
|
2618
|
+
y3_0 --> x2_0^2
|
|
2619
|
+
y3_1 --> x2_0*x2_1
|
|
2620
|
+
y3_2 --> x2_1^2
|
|
2621
|
+
y3_3 --> x2_0*x2_2
|
|
2622
|
+
y3_4 --> x2_1*x2_2 + x2_0*x2_3
|
|
2623
|
+
y3_5 --> x2_2^2
|
|
2624
|
+
y3_6 --> x2_1*x2_3
|
|
2625
|
+
y3_7 --> x2_2*x2_3
|
|
2626
|
+
y3_8 --> x2_3^2
|
|
2627
|
+
|
|
2628
|
+
sage: phi
|
|
2629
|
+
Commutative Differential Graded Algebra morphism:
|
|
2630
|
+
From: Commutative Differential Graded Algebra with generators
|
|
2631
|
+
('x1_0', 'x1_1', 'x1_2', 'x2_0', 'x2_1', 'x2_2', 'x2_3',
|
|
2632
|
+
'y3_0', 'y3_1', 'y3_2', 'y3_3', 'y3_4', 'y3_5', 'y3_6', 'y3_7', 'y3_8')
|
|
2633
|
+
in degrees (1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3)
|
|
2634
|
+
over Rational Field with differential:
|
|
2635
|
+
x1_0 --> 0
|
|
2636
|
+
x1_1 --> 0
|
|
2637
|
+
x1_2 --> 0
|
|
2638
|
+
x2_0 --> 0
|
|
2639
|
+
x2_1 --> 0
|
|
2640
|
+
x2_2 --> 0
|
|
2641
|
+
x2_3 --> 0
|
|
2642
|
+
y3_0 --> x2_0^2
|
|
2643
|
+
y3_1 --> x2_0*x2_1
|
|
2644
|
+
y3_2 --> x2_1^2
|
|
2645
|
+
y3_3 --> x2_0*x2_2
|
|
2646
|
+
y3_4 --> x2_1*x2_2 + x2_0*x2_3
|
|
2647
|
+
y3_5 --> x2_2^2
|
|
2648
|
+
y3_6 --> x2_1*x2_3
|
|
2649
|
+
y3_7 --> x2_2*x2_3
|
|
2650
|
+
y3_8 --> x2_3^2
|
|
2651
|
+
To: Commutative Differential Graded Algebra with generators
|
|
2652
|
+
('e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7')
|
|
2653
|
+
in degrees (1, 1, 1, 1, 1, 1, 1) over Rational Field with differential:
|
|
2654
|
+
e1 --> e1*e7
|
|
2655
|
+
e2 --> e2*e7
|
|
2656
|
+
e3 --> -e3*e7
|
|
2657
|
+
e4 --> -e4*e7
|
|
2658
|
+
e5 --> 0
|
|
2659
|
+
e6 --> 0
|
|
2660
|
+
e7 --> 0
|
|
2661
|
+
Defn: (x1_0, x1_1, x1_2, x2_0, x2_1, x2_2, x2_3,
|
|
2662
|
+
y3_0, y3_1, y3_2, y3_3, y3_4, y3_5, y3_6, y3_7, y3_8)
|
|
2663
|
+
--> (e5, e6, e7, e1*e3, e2*e3, e1*e4, e2*e4, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
2664
|
+
sage: [B.cohomology(i).dimension() for i in [1..3]]
|
|
2665
|
+
[3, 7, 13]
|
|
2666
|
+
sage: [M.cohomology(i).dimension() for i in [1..3]]
|
|
2667
|
+
[3, 7, 13]
|
|
2668
|
+
|
|
2669
|
+
ALGORITHM:
|
|
2670
|
+
|
|
2671
|
+
We follow the algorithm described in [Man2019]_. It consists in
|
|
2672
|
+
constructing the minimal Sullivan algebra ``S`` by iteratively adding
|
|
2673
|
+
generators to it. Start with one closed generator of degree 1 for each
|
|
2674
|
+
element in the basis of the first cohomology of the algebra. Then
|
|
2675
|
+
proceed degree by degree. At each degree `d`, we keep adding generators
|
|
2676
|
+
of degree `d-1` whose differential kills the elements in the kernel of
|
|
2677
|
+
the map `H^d(S)\to H^d(self)`. Once this map is made injective, we add
|
|
2678
|
+
the needed closed generators in degree `d` to make it surjective.
|
|
2679
|
+
|
|
2680
|
+
.. WARNING::
|
|
2681
|
+
|
|
2682
|
+
The method is not granted to finish (it can't, since the minimal
|
|
2683
|
+
model could be infinitely generated in some degrees).
|
|
2684
|
+
The parameter ``max_iterations`` controls how many iterations of
|
|
2685
|
+
the method are attempted at each degree. In case they are not
|
|
2686
|
+
enough, an exception is raised. If you think that the result will
|
|
2687
|
+
be finitely generated, you can try to run it again with a higher
|
|
2688
|
+
value for ``max_iterations``.
|
|
2689
|
+
|
|
2690
|
+
.. SEEALSO::
|
|
2691
|
+
|
|
2692
|
+
:wikipedia:`Rational_homotopy_theory#Sullivan_algebras`
|
|
2693
|
+
|
|
2694
|
+
TESTS::
|
|
2695
|
+
|
|
2696
|
+
sage: A.<x, y, z, t> = GradedCommutativeAlgebra(QQ,degrees = (1, 2, 3, 3))
|
|
2697
|
+
sage: d = A.differential({x:y})
|
|
2698
|
+
sage: B = A.cdg_algebra(d)
|
|
2699
|
+
sage: B.minimal_model(i=3)
|
|
2700
|
+
Commutative Differential Graded Algebra morphism:
|
|
2701
|
+
From: Commutative Differential Graded Algebra with generators ('x3_0', 'x3_1') in degrees (3, 3) over Rational Field with differential:
|
|
2702
|
+
x3_0 --> 0
|
|
2703
|
+
x3_1 --> 0
|
|
2704
|
+
To: Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (1, 2, 3, 3) over Rational Field with differential:
|
|
2705
|
+
x --> y
|
|
2706
|
+
y --> 0
|
|
2707
|
+
z --> 0
|
|
2708
|
+
t --> 0
|
|
2709
|
+
Defn: (x3_0, x3_1) --> (z, t)
|
|
2710
|
+
|
|
2711
|
+
::
|
|
2712
|
+
|
|
2713
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ)
|
|
2714
|
+
sage: I = A.ideal([a*b-a*c+b*c])
|
|
2715
|
+
sage: B = A.quotient(I)
|
|
2716
|
+
sage: S = B.cdg_algebra({})
|
|
2717
|
+
sage: S.minimal_model()
|
|
2718
|
+
Traceback (most recent call last):
|
|
2719
|
+
...
|
|
2720
|
+
ValueError: could not cover all relations in max iterations in degree 2
|
|
2721
|
+
sage: S.minimal_model(partial_result=True)
|
|
2722
|
+
Commutative Differential Graded Algebra morphism:
|
|
2723
|
+
From: Commutative Differential Graded Algebra with generators
|
|
2724
|
+
('x1_0', 'x1_1', 'x1_2', 'y1_0', 'y1_1', 'y1_2') in degrees (1, 1, 1, 1, 1, 1)
|
|
2725
|
+
over Rational Field with differential:
|
|
2726
|
+
x1_0 --> 0
|
|
2727
|
+
x1_1 --> 0
|
|
2728
|
+
x1_2 --> 0
|
|
2729
|
+
y1_0 --> x1_0*x1_1 - x1_0*x1_2 + x1_1*x1_2
|
|
2730
|
+
y1_1 --> x1_0*y1_0 - x1_2*y1_0
|
|
2731
|
+
y1_2 --> x1_1*y1_0 - x1_2*y1_0
|
|
2732
|
+
To: Commutative Differential Graded Algebra with generators ('a', 'b', 'c')
|
|
2733
|
+
in degrees (1, 1, 1) with relations [a*b - a*c + b*c] over Rational Field with differential:
|
|
2734
|
+
a --> 0
|
|
2735
|
+
b --> 0
|
|
2736
|
+
c --> 0
|
|
2737
|
+
Defn: (x1_0, x1_1, x1_2, y1_0, y1_1, y1_2) --> (a, b, c, 0, 0, 0)
|
|
2738
|
+
|
|
2739
|
+
REFERENCES:
|
|
2740
|
+
|
|
2741
|
+
- [Fel2001]_
|
|
2742
|
+
|
|
2743
|
+
- [Man2019]_
|
|
2744
|
+
"""
|
|
2745
|
+
max_degree = int(i)
|
|
2746
|
+
if max_degree < 1:
|
|
2747
|
+
raise ValueError("the degree must be a positive integer")
|
|
2748
|
+
if max_iterations not in ZZ or max_iterations < 1:
|
|
2749
|
+
raise ValueError("max_iterations must be a positive integer")
|
|
2750
|
+
if max_degree in self._minimalmodels:
|
|
2751
|
+
return self._minimalmodels[max_degree]
|
|
2752
|
+
from copy import copy
|
|
2753
|
+
|
|
2754
|
+
def extend(phi, ndegrees, ndifs, nimags, nnames):
|
|
2755
|
+
"""
|
|
2756
|
+
Extend phi to a new algebra with new generators, labeled by nnames
|
|
2757
|
+
"""
|
|
2758
|
+
B = phi.domain()
|
|
2759
|
+
names = [str(g) for g in B.gens()]
|
|
2760
|
+
degrees = [g.degree() for g in B.gens()]
|
|
2761
|
+
A = GradedCommutativeAlgebra(B.base_ring(), names=names + nnames,
|
|
2762
|
+
degrees=degrees + ndegrees)
|
|
2763
|
+
h = B.hom(A.gens()[:B.ngens()], check=False)
|
|
2764
|
+
d = B.differential()
|
|
2765
|
+
diff = {h(g): h(d(g)) for g in B.gens()}
|
|
2766
|
+
cndifs = copy(ndifs)
|
|
2767
|
+
for g in A.gens()[B.ngens():]:
|
|
2768
|
+
diff[g] = h(cndifs.pop(0))
|
|
2769
|
+
NB = A.cdg_algebra(diff)
|
|
2770
|
+
return NB.hom([phi(g) for g in B.gens()] + nimags, check=False)
|
|
2771
|
+
|
|
2772
|
+
def extendx(phi, degree):
|
|
2773
|
+
B = phi.domain()
|
|
2774
|
+
imagesbcohom = [phi(g.representative())
|
|
2775
|
+
for g in B.cohomology(degree).basis().keys()]
|
|
2776
|
+
CS = self.cohomology_raw(degree)
|
|
2777
|
+
VS = CS.V()
|
|
2778
|
+
CB = B.cohomology_raw(degree)
|
|
2779
|
+
imagesphico = []
|
|
2780
|
+
for g in imagesbcohom:
|
|
2781
|
+
if g.is_zero():
|
|
2782
|
+
imagesphico.append(CS.zero())
|
|
2783
|
+
else:
|
|
2784
|
+
imagesphico.append(CS(VS(g.basis_coefficients())))
|
|
2785
|
+
phico = CB.hom(imagesphico, codomain=CS)
|
|
2786
|
+
QI = CS.quotient(phico.image())
|
|
2787
|
+
self._numerical_invariants[degree] = [QI.dimension()]
|
|
2788
|
+
if QI.dimension() > 0:
|
|
2789
|
+
nnames = [f'x{degree}_{j}' for j in range(QI.dimension())]
|
|
2790
|
+
nbasis = []
|
|
2791
|
+
bbasis = self.basis(degree)
|
|
2792
|
+
for v in QI.basis():
|
|
2793
|
+
vl = CS.lift(QI.lift(v))
|
|
2794
|
+
g = sum(bbasis[j] * vl[j] for j in range(len(bbasis)))
|
|
2795
|
+
nbasis.append(g)
|
|
2796
|
+
nimags = nbasis
|
|
2797
|
+
ndegrees = [degree for _ in nbasis]
|
|
2798
|
+
return extend(phi, ndegrees, [B.zero() for _ in nimags],
|
|
2799
|
+
nimags, nnames)
|
|
2800
|
+
return phi
|
|
2801
|
+
|
|
2802
|
+
def extendy(phi, degree):
|
|
2803
|
+
nnamesy = 0
|
|
2804
|
+
for iteration in range(max_iterations):
|
|
2805
|
+
B = phi.domain()
|
|
2806
|
+
imagesbcohom = [phi(g.representative())
|
|
2807
|
+
for g in B.cohomology(degree).basis().keys()]
|
|
2808
|
+
CS = self.cohomology_raw(degree)
|
|
2809
|
+
VS = CS.V()
|
|
2810
|
+
CB = B.cohomology_raw(degree)
|
|
2811
|
+
imagesphico = []
|
|
2812
|
+
for g in imagesbcohom:
|
|
2813
|
+
if g.is_zero():
|
|
2814
|
+
imagesphico.append(CS.zero())
|
|
2815
|
+
else:
|
|
2816
|
+
imagesphico.append(CS(VS(g.basis_coefficients())))
|
|
2817
|
+
phico = CB.hom(imagesphico, codomain=CS)
|
|
2818
|
+
K = phico.kernel()
|
|
2819
|
+
self._numerical_invariants[degree - 1].append(K.dimension())
|
|
2820
|
+
if K.dimension() == 0:
|
|
2821
|
+
return phi
|
|
2822
|
+
if iteration == max_iterations - 1:
|
|
2823
|
+
return (phi,)
|
|
2824
|
+
ndifs = [CB.lift(g) for g in K.basis()]
|
|
2825
|
+
basisdegree = B.basis(degree)
|
|
2826
|
+
ndifs = [sum(basisdegree[j] * g[j] for j in
|
|
2827
|
+
range(len(basisdegree))) for g in ndifs]
|
|
2828
|
+
MS = self.differential().differential_matrix(degree - 1)
|
|
2829
|
+
nimags = []
|
|
2830
|
+
for g in ndifs:
|
|
2831
|
+
if phi(g).is_zero():
|
|
2832
|
+
nimags.append(vector(MS.nrows() * [0]))
|
|
2833
|
+
else:
|
|
2834
|
+
nimags.append(MS.solve_left(vector(phi(g).basis_coefficients())))
|
|
2835
|
+
nimags = [sum(self.basis(degree - 1)[j] * g[j]
|
|
2836
|
+
for j in range(len(self.basis(degree - 1)))
|
|
2837
|
+
) for g in nimags]
|
|
2838
|
+
ndegrees = [degree - 1 for g in nimags]
|
|
2839
|
+
nnames = ['y{}_{}'.format(degree - 1, j + nnamesy)
|
|
2840
|
+
for j in range(len(nimags))]
|
|
2841
|
+
nnamesy += len(nimags)
|
|
2842
|
+
phi = extend(phi, ndegrees, ndifs, nimags, nnames)
|
|
2843
|
+
|
|
2844
|
+
if not self._minimalmodels:
|
|
2845
|
+
degnzero = 1
|
|
2846
|
+
while self.cohomology(degnzero).dimension() == 0:
|
|
2847
|
+
self._numerical_invariants[degnzero] = [0]
|
|
2848
|
+
degnzero += 1
|
|
2849
|
+
if degnzero > max_degree:
|
|
2850
|
+
raise ValueError("cohomology is trivial up to max_degree")
|
|
2851
|
+
gens = [g.representative()
|
|
2852
|
+
for g in self.cohomology(degnzero).basis().keys()]
|
|
2853
|
+
self._numerical_invariants[degnzero] = [len(gens)]
|
|
2854
|
+
names = ['x{}_{}'.format(degnzero, j) for j in range(len(gens))]
|
|
2855
|
+
A = GradedCommutativeAlgebra(self.base_ring(),
|
|
2856
|
+
names,
|
|
2857
|
+
degrees=[degnzero for _ in names])
|
|
2858
|
+
B = A.cdg_algebra(A.differential({}))
|
|
2859
|
+
# Solve case that fails with one generator return B,gens
|
|
2860
|
+
phi = B.hom(gens)
|
|
2861
|
+
phiext = extendy(phi, degnzero + 1)
|
|
2862
|
+
if isinstance(phiext, tuple):
|
|
2863
|
+
if not partial_result:
|
|
2864
|
+
raise ValueError("could not cover all relations in max iterations in degree {}".format(degnzero + 1))
|
|
2865
|
+
return phiext[0]
|
|
2866
|
+
phi = phiext
|
|
2867
|
+
self._minimalmodels[degnzero] = phi
|
|
2868
|
+
else:
|
|
2869
|
+
degnzero = max(self._minimalmodels)
|
|
2870
|
+
phi = self._minimalmodels[degnzero]
|
|
2871
|
+
|
|
2872
|
+
for degree in range(degnzero + 1, max_degree + 1):
|
|
2873
|
+
phi = extendx(phi, degree)
|
|
2874
|
+
phiext = extendy(phi, degree + 1)
|
|
2875
|
+
if isinstance(phiext, tuple):
|
|
2876
|
+
if partial_result:
|
|
2877
|
+
return phiext[0]
|
|
2878
|
+
else:
|
|
2879
|
+
raise ValueError("could not cover all relations in max iterations in degree {}".format(degree + 1))
|
|
2880
|
+
phi = phiext
|
|
2881
|
+
self._minimalmodels[degree] = phi
|
|
2882
|
+
return phi
|
|
2883
|
+
|
|
2884
|
+
def cohomology_algebra(self, max_degree=3):
|
|
2885
|
+
"""
|
|
2886
|
+
Compute a CDGA with trivial differential, that is isomorphic to the cohomology of
|
|
2887
|
+
``self`` up to``max_degree``
|
|
2888
|
+
|
|
2889
|
+
INPUT:
|
|
2890
|
+
|
|
2891
|
+
- ``max_degree`` -- integer (default: `3`); degree to which the result is required to
|
|
2892
|
+
be isomorphic to ``self``'s cohomology
|
|
2893
|
+
|
|
2894
|
+
EXAMPLES::
|
|
2895
|
+
|
|
2896
|
+
sage: A.<e1, e2, e3, e4, e5, e6, e7> = GradedCommutativeAlgebra(QQ)
|
|
2897
|
+
sage: d = A.differential({e1:-e1*e6, e2:-e2*e6, e3:-e3*e6, e4:-e5*e6, e5:e4*e6})
|
|
2898
|
+
sage: B = A.cdg_algebra(d)
|
|
2899
|
+
sage: M = B.cohomology_algebra()
|
|
2900
|
+
sage: M
|
|
2901
|
+
Commutative Differential Graded Algebra with generators ('x0', 'x1', 'x2')
|
|
2902
|
+
in degrees (1, 1, 2) over Rational Field with differential:
|
|
2903
|
+
x0 --> 0
|
|
2904
|
+
x1 --> 0
|
|
2905
|
+
x2 --> 0
|
|
2906
|
+
sage: M.cohomology(1)
|
|
2907
|
+
Free module generated by {[x0], [x1]} over Rational Field
|
|
2908
|
+
sage: B.cohomology(1)
|
|
2909
|
+
Free module generated by {[e6], [e7]} over Rational Field
|
|
2910
|
+
sage: M.cohomology(2)
|
|
2911
|
+
Free module generated by {[x0*x1], [x2]} over Rational Field
|
|
2912
|
+
sage: B.cohomology(2)
|
|
2913
|
+
Free module generated by {[e4*e5], [e6*e7]} over Rational Field
|
|
2914
|
+
sage: M.cohomology(3)
|
|
2915
|
+
Free module generated by {[x0*x2], [x1*x2]} over Rational Field
|
|
2916
|
+
sage: B.cohomology(3)
|
|
2917
|
+
Free module generated by {[e4*e5*e6], [e4*e5*e7]} over Rational Field
|
|
2918
|
+
"""
|
|
2919
|
+
cohomgens = self.cohomology_generators(max_degree)
|
|
2920
|
+
if not cohomgens:
|
|
2921
|
+
raise ValueError("cohomology ring has no generators")
|
|
2922
|
+
chgens = []
|
|
2923
|
+
degrees = []
|
|
2924
|
+
for d in cohomgens:
|
|
2925
|
+
for g in cohomgens[d]:
|
|
2926
|
+
degrees.append(d)
|
|
2927
|
+
chgens.append(g)
|
|
2928
|
+
A = GradedCommutativeAlgebra(self.base_ring(),
|
|
2929
|
+
[f'x{i}' for i in range(len(chgens))],
|
|
2930
|
+
degrees)
|
|
2931
|
+
rels = []
|
|
2932
|
+
for d in range(1, max_degree + 1):
|
|
2933
|
+
B1 = A.basis(d)
|
|
2934
|
+
V2 = self.cohomology_raw(d)
|
|
2935
|
+
images = []
|
|
2936
|
+
for g in B1:
|
|
2937
|
+
ig = g._im_gens_(self, chgens)
|
|
2938
|
+
if ig.is_zero():
|
|
2939
|
+
images.append(V2.zero())
|
|
2940
|
+
else:
|
|
2941
|
+
images.append(V2(V2.V()(ig.basis_coefficients())))
|
|
2942
|
+
V1 = self.base_ring()**len(B1)
|
|
2943
|
+
h = V1.hom(images, codomain=V2)
|
|
2944
|
+
K = h.kernel()
|
|
2945
|
+
for g in K.basis():
|
|
2946
|
+
newrel = sum(g[i] * B1[i] for i in range(len(B1)))
|
|
2947
|
+
rels.append(newrel)
|
|
2948
|
+
return A.quotient(A.ideal(rels)).cdg_algebra({})
|
|
2949
|
+
|
|
2950
|
+
def numerical_invariants(self, max_degree=3, max_iterations=3):
|
|
2951
|
+
r"""
|
|
2952
|
+
Return the numerical invariants of the algebra, up to degree ``d``. The
|
|
2953
|
+
numerical invariants reflect the number of generators added at each step
|
|
2954
|
+
of the construction of the minimal model.
|
|
2955
|
+
|
|
2956
|
+
The numerical invariants are the dimensions of the subsequent Hirsch
|
|
2957
|
+
extensions used at each degree to compute the minimal model.
|
|
2958
|
+
|
|
2959
|
+
INPUT:
|
|
2960
|
+
|
|
2961
|
+
- ``max_degree`` -- integer (default: `3`); the degree up to which the
|
|
2962
|
+
numerical invariants are computed
|
|
2963
|
+
|
|
2964
|
+
- ``max_iterations`` -- integer (default: `3`); the maximum number of iterations
|
|
2965
|
+
used to compute the minimal model, if it is not already cached
|
|
2966
|
+
|
|
2967
|
+
EXAMPLES::
|
|
2968
|
+
|
|
2969
|
+
sage: A.<e1, e2, e3> = GradedCommutativeAlgebra(QQ)
|
|
2970
|
+
sage: B = A.cdg_algebra({e3 : e1*e2})
|
|
2971
|
+
sage: B.minimal_model(4)
|
|
2972
|
+
Commutative Differential Graded Algebra morphism:
|
|
2973
|
+
From: Commutative Differential Graded Algebra with
|
|
2974
|
+
generators ('x1_0', 'x1_1', 'y1_0') in degrees (1, 1, 1)
|
|
2975
|
+
over Rational Field with differential:
|
|
2976
|
+
x1_0 --> 0
|
|
2977
|
+
x1_1 --> 0
|
|
2978
|
+
y1_0 --> x1_0*x1_1
|
|
2979
|
+
To: Commutative Differential Graded Algebra with
|
|
2980
|
+
generators ('e1', 'e2', 'e3') in degrees (1, 1, 1)
|
|
2981
|
+
over Rational Field with differential:
|
|
2982
|
+
e1 --> 0
|
|
2983
|
+
e2 --> 0
|
|
2984
|
+
e3 --> e1*e2
|
|
2985
|
+
Defn: (x1_0, x1_1, y1_0) --> (e1, e2, e3)
|
|
2986
|
+
sage: B.numerical_invariants(2)
|
|
2987
|
+
{1: [2, 1, 0], 2: [0, 0]}
|
|
2988
|
+
|
|
2989
|
+
ALGORITHM:
|
|
2990
|
+
|
|
2991
|
+
The numerical invariants are stored as the minimal model is constructed.
|
|
2992
|
+
|
|
2993
|
+
.. WARNING::
|
|
2994
|
+
|
|
2995
|
+
The method is not granted to finish (it can't, since the minimal
|
|
2996
|
+
model could be infinitely generated in some degrees).
|
|
2997
|
+
The parameter ``max_iterations`` controls how many iterations of
|
|
2998
|
+
the method are attempted at each degree. In case they are not
|
|
2999
|
+
enough, an exception is raised. If you think that the result will
|
|
3000
|
+
be finitely generated, you can try to run it again with a higher
|
|
3001
|
+
value for ``max_iterations``.
|
|
3002
|
+
|
|
3003
|
+
REFERENCES:
|
|
3004
|
+
|
|
3005
|
+
For a precise definition and properties, see [Man2019]_ .
|
|
3006
|
+
"""
|
|
3007
|
+
self.minimal_model(max_degree, max_iterations)
|
|
3008
|
+
return {i: self._numerical_invariants[i]
|
|
3009
|
+
for i in range(1, max_degree + 1)}
|
|
3010
|
+
|
|
3011
|
+
def is_formal(self, i, max_iterations=3):
|
|
3012
|
+
r"""
|
|
3013
|
+
Check if the algebra is ``i``-formal. That is, if it is ``i``-quasi-isomorphic
|
|
3014
|
+
to its cohomology algebra.
|
|
3015
|
+
|
|
3016
|
+
INPUT:
|
|
3017
|
+
|
|
3018
|
+
- ``i`` -- integer; the degree up to which the formality is checked
|
|
3019
|
+
|
|
3020
|
+
- ``max_iterations`` -- integer (default: `3`); the maximum number of
|
|
3021
|
+
iterations used in the computation of the minimal model
|
|
3022
|
+
|
|
3023
|
+
.. WARNING::
|
|
3024
|
+
|
|
3025
|
+
The method is not granted to finish (it can't, since the minimal
|
|
3026
|
+
model could be infinitely generated in some degrees).
|
|
3027
|
+
The parameter ``max_iterations`` controls how many iterations of
|
|
3028
|
+
the method are attempted at each degree. In case they are not
|
|
3029
|
+
enough, an exception is raised. If you think that the result will
|
|
3030
|
+
be finitely generated, you can try to run it again with a higher
|
|
3031
|
+
value for ``max_iterations``.
|
|
3032
|
+
|
|
3033
|
+
Moreover, the method uses criteria that are often enough to conclude
|
|
3034
|
+
that the algebra is either formal or non-formal. However, it could
|
|
3035
|
+
happen that the used criteria can not determine the formality. In
|
|
3036
|
+
that case, an error is raised.
|
|
3037
|
+
|
|
3038
|
+
EXAMPLES::
|
|
3039
|
+
|
|
3040
|
+
sage: A.<e1, e2, e3, e4, e5> = GradedCommutativeAlgebra(QQ)
|
|
3041
|
+
sage: B = A.cdg_algebra({e5: e1*e2 + e3*e4})
|
|
3042
|
+
sage: B.is_formal(1)
|
|
3043
|
+
True
|
|
3044
|
+
sage: B.is_formal(2)
|
|
3045
|
+
False
|
|
3046
|
+
|
|
3047
|
+
ALGORITHM:
|
|
3048
|
+
|
|
3049
|
+
Apply the criteria in [Man2019]_ . Both the `i`-minimal model of the
|
|
3050
|
+
algebra and its cohomology algebra are computed. If the numerical
|
|
3051
|
+
invariants are different, the algebra is not `i`-formal.
|
|
3052
|
+
|
|
3053
|
+
If the numerical invariants match, the `\psi` condition is checked.
|
|
3054
|
+
"""
|
|
3055
|
+
phi = self.minimal_model(i, max_iterations)
|
|
3056
|
+
M = phi.domain()
|
|
3057
|
+
H = M.cohomology_algebra(i + 1)
|
|
3058
|
+
try:
|
|
3059
|
+
H.minimal_model(i, max_iterations)
|
|
3060
|
+
except ValueError: # If we could compute the minimal model in max_iterations
|
|
3061
|
+
return False # but not for the cohomology, the invariants are distinct
|
|
3062
|
+
N1 = self.numerical_invariants(i, max_iterations)
|
|
3063
|
+
N2 = H.numerical_invariants(i, max_iterations)
|
|
3064
|
+
if any(N1[n] != N2[n] for n in range(1, i + 1)):
|
|
3065
|
+
return False # numerical invariants don't match
|
|
3066
|
+
subsdict = {y.lift(): 0 for y in M.gens() if not y.differential().is_zero()}
|
|
3067
|
+
tocheck = [M(g.differential().lift().subs(subsdict)) for g in M.gens()]
|
|
3068
|
+
if all(c.is_coboundary() for c in tocheck):
|
|
3069
|
+
return True # the morphism xi->[xi], yi->0 is i-quasi-iso
|
|
3070
|
+
raise NotImplementedError("the implemented criteria cannot determine formality")
|
|
3071
|
+
|
|
3072
|
+
class Element(GCAlgebra.Element):
|
|
3073
|
+
def differential(self):
|
|
3074
|
+
"""
|
|
3075
|
+
The differential on this element.
|
|
3076
|
+
|
|
3077
|
+
EXAMPLES::
|
|
3078
|
+
|
|
3079
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 4))
|
|
3080
|
+
sage: B = A.cdg_algebra({t: x*z, x: z, y: z})
|
|
3081
|
+
sage: B.inject_variables()
|
|
3082
|
+
Defining x, y, z, t
|
|
3083
|
+
sage: x.differential()
|
|
3084
|
+
z
|
|
3085
|
+
sage: (-1/2 * x^2 + t).differential()
|
|
3086
|
+
0
|
|
3087
|
+
"""
|
|
3088
|
+
return self.parent().differential()(self)
|
|
3089
|
+
|
|
3090
|
+
def is_coboundary(self):
|
|
3091
|
+
"""
|
|
3092
|
+
Return ``True`` if ``self`` is a coboundary and ``False``
|
|
3093
|
+
otherwise.
|
|
3094
|
+
|
|
3095
|
+
This raises an error if the element is not homogeneous.
|
|
3096
|
+
|
|
3097
|
+
EXAMPLES::
|
|
3098
|
+
|
|
3099
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,2,2))
|
|
3100
|
+
sage: B = A.cdg_algebra(differential={b: a*c})
|
|
3101
|
+
sage: x,y,z = B.gens()
|
|
3102
|
+
sage: x.is_coboundary()
|
|
3103
|
+
False
|
|
3104
|
+
sage: (x*z).is_coboundary()
|
|
3105
|
+
True
|
|
3106
|
+
sage: (x*z + x*y).is_coboundary()
|
|
3107
|
+
False
|
|
3108
|
+
sage: (x*z + y**2).is_coboundary()
|
|
3109
|
+
Traceback (most recent call last):
|
|
3110
|
+
...
|
|
3111
|
+
ValueError: this element is not homogeneous
|
|
3112
|
+
"""
|
|
3113
|
+
if not self.is_homogeneous():
|
|
3114
|
+
raise ValueError('this element is not homogeneous')
|
|
3115
|
+
# To avoid taking the degree of 0, we special-case it.
|
|
3116
|
+
if self.is_zero():
|
|
3117
|
+
return True
|
|
3118
|
+
v = vector(self.basis_coefficients())
|
|
3119
|
+
return v in self.parent().coboundaries(self.degree())
|
|
3120
|
+
|
|
3121
|
+
def is_cohomologous_to(self, other):
|
|
3122
|
+
"""
|
|
3123
|
+
Return ``True`` if ``self`` is cohomologous to ``other``
|
|
3124
|
+
and ``False`` otherwise.
|
|
3125
|
+
|
|
3126
|
+
INPUT:
|
|
3127
|
+
|
|
3128
|
+
- ``other`` -- another element of this algebra
|
|
3129
|
+
|
|
3130
|
+
EXAMPLES::
|
|
3131
|
+
|
|
3132
|
+
sage: A.<a,b,c,d> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1,1))
|
|
3133
|
+
sage: B = A.cdg_algebra(differential={a: b*c-c*d})
|
|
3134
|
+
sage: w, x, y, z = B.gens()
|
|
3135
|
+
sage: (x*y).is_cohomologous_to(y*z)
|
|
3136
|
+
True
|
|
3137
|
+
sage: (x*y).is_cohomologous_to(x*z)
|
|
3138
|
+
False
|
|
3139
|
+
sage: (x*y).is_cohomologous_to(x*y)
|
|
3140
|
+
True
|
|
3141
|
+
|
|
3142
|
+
Two elements whose difference is not homogeneous are
|
|
3143
|
+
cohomologous if and only if they are both coboundaries::
|
|
3144
|
+
|
|
3145
|
+
sage: w.is_cohomologous_to(y*z)
|
|
3146
|
+
False
|
|
3147
|
+
sage: (x*y-y*z).is_cohomologous_to(x*y*z)
|
|
3148
|
+
True
|
|
3149
|
+
sage: (x*y*z).is_cohomologous_to(0) # make sure 0 works
|
|
3150
|
+
True
|
|
3151
|
+
"""
|
|
3152
|
+
if other.is_zero():
|
|
3153
|
+
return self.is_coboundary()
|
|
3154
|
+
if (not isinstance(other, DifferentialGCAlgebra.Element)
|
|
3155
|
+
or self.parent() is not other.parent()):
|
|
3156
|
+
raise ValueError(f'the element {other} does not lie in this DGA')
|
|
3157
|
+
if (self - other).is_homogeneous():
|
|
3158
|
+
return (self - other).is_coboundary()
|
|
3159
|
+
return self.is_coboundary() and other.is_coboundary()
|
|
3160
|
+
|
|
3161
|
+
def cohomology_class(self):
|
|
3162
|
+
r"""
|
|
3163
|
+
Return the cohomology class of a homogeneous cycle, as an element
|
|
3164
|
+
of the corresponding cohomology group.
|
|
3165
|
+
|
|
3166
|
+
EXAMPLES::
|
|
3167
|
+
|
|
3168
|
+
sage: A.<e1,e2,e3,e4,e5> = GradedCommutativeAlgebra(QQ)
|
|
3169
|
+
sage: B = A.cdg_algebra({e5: e1*e2+e3*e4})
|
|
3170
|
+
sage: B.inject_variables()
|
|
3171
|
+
Defining e1, e2, e3, e4, e5
|
|
3172
|
+
sage: a = e1*e3*e5 - 3*e2*e3*e5
|
|
3173
|
+
sage: a.cohomology_class()
|
|
3174
|
+
B[[e1*e3*e5]] - 3*B[[e2*e3*e5]]
|
|
3175
|
+
|
|
3176
|
+
TESTS::
|
|
3177
|
+
|
|
3178
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 3))
|
|
3179
|
+
sage: B = A.cdg_algebra({a: b})
|
|
3180
|
+
sage: B.inject_variables()
|
|
3181
|
+
Defining a, b, c
|
|
3182
|
+
sage: b.cohomology_class()
|
|
3183
|
+
0
|
|
3184
|
+
sage: b.cohomology_class().parent()
|
|
3185
|
+
Free module generated by {} over Rational Field
|
|
3186
|
+
|
|
3187
|
+
Check that the issue detected in :issue:`28155` is solved::
|
|
3188
|
+
|
|
3189
|
+
sage: A.<e1,e2,e3,e4,e5> = GradedCommutativeAlgebra(QQ)
|
|
3190
|
+
sage: B = A.cdg_algebra({e5: e1*e2+e3*e4})
|
|
3191
|
+
sage: B.inject_variables()
|
|
3192
|
+
Defining e1, e2, e3, e4, e5
|
|
3193
|
+
sage: a = e1*e3*e5 - 3*e2*e3*e5
|
|
3194
|
+
sage: ca = a.cohomology_class()
|
|
3195
|
+
sage: C = B.cohomology(3)
|
|
3196
|
+
sage: ca in C
|
|
3197
|
+
True
|
|
3198
|
+
"""
|
|
3199
|
+
if not self.is_homogeneous():
|
|
3200
|
+
raise ValueError("the element is not homogeneous")
|
|
3201
|
+
if not self.differential().is_zero():
|
|
3202
|
+
raise ValueError("the element is not closed")
|
|
3203
|
+
d = self.degree()
|
|
3204
|
+
C = self.parent().cohomology(d)
|
|
3205
|
+
CR = self.parent().cohomology_raw(d)
|
|
3206
|
+
V = CR.V()
|
|
3207
|
+
cohomcoefs = CR(V(self.basis_coefficients()))
|
|
3208
|
+
return C.sum(a * b for (a, b) in zip(cohomcoefs, C.basis().values()))
|
|
3209
|
+
|
|
3210
|
+
def _cohomology_class_dict(self):
|
|
3211
|
+
r"""
|
|
3212
|
+
Return the dictionary that represents the cohomology class of
|
|
3213
|
+
the cycle expressed in terms of the cohomology generators.
|
|
3214
|
+
|
|
3215
|
+
This can be used to map the cycle to the cohomology algebra.
|
|
3216
|
+
|
|
3217
|
+
EXAMPLES::
|
|
3218
|
+
|
|
3219
|
+
sage: A.<e1,e2,e3,e4,e5> = GradedCommutativeAlgebra(QQ)
|
|
3220
|
+
sage: B = A.cdg_algebra({e5: e1*e2+e3*e4})
|
|
3221
|
+
sage: a = B(e1*e3*e5-3*e2*e3*e5)
|
|
3222
|
+
sage: a._cohomology_class_dict()
|
|
3223
|
+
{(0, 0, 0, 0, 0, 0, 1, 0, 0): -3, (0, 0, 0, 0, 0, 1, 0, 0, 0): 1}
|
|
3224
|
+
sage: H = B.cohomology_algebra(3)
|
|
3225
|
+
sage: H(a._cohomology_class_dict())
|
|
3226
|
+
x5 - 3*x6
|
|
3227
|
+
sage: B.cohomology_generators(3)
|
|
3228
|
+
{1: [e1, e2, e3, e4],
|
|
3229
|
+
3: [e1*e2*e5 - e3*e4*e5, e1*e3*e5, e2*e3*e5, e1*e4*e5, e2*e4*e5]}
|
|
3230
|
+
sage: [H(g._cohomology_class_dict()) for g in flatten(B.cohomology_generators(3).values())]
|
|
3231
|
+
[x0, x1, x2, x3, x4, x5, x6, x7, x8]
|
|
3232
|
+
"""
|
|
3233
|
+
from sage.misc.flatten import flatten
|
|
3234
|
+
if not self.differential().is_zero():
|
|
3235
|
+
raise ValueError("the element is not closed")
|
|
3236
|
+
if not self.is_homogeneous():
|
|
3237
|
+
res = {}
|
|
3238
|
+
for d in self.homogeneous_parts().values():
|
|
3239
|
+
res.update(d._cohomology_class_dict())
|
|
3240
|
+
return res
|
|
3241
|
+
d = self.degree()
|
|
3242
|
+
gens = flatten(self.parent().cohomology_generators(d).values())
|
|
3243
|
+
ebasis = exterior_algebra_basis(d, tuple(g.degree() for g in gens))
|
|
3244
|
+
gensd = [prod([gens[i]**b[i]
|
|
3245
|
+
for i in range(len(b))]) for b in ebasis]
|
|
3246
|
+
m = matrix([g.cohomology_class()._vector_() for g in gensd])
|
|
3247
|
+
coeffs = m.solve_left(self.cohomology_class()._vector_())
|
|
3248
|
+
return {tuple(ebasis[i]): coeffs[i]
|
|
3249
|
+
for i in range(len(ebasis)) if coeffs[i]}
|
|
3250
|
+
|
|
3251
|
+
|
|
3252
|
+
class DifferentialGCAlgebra_multigraded(DifferentialGCAlgebra,
|
|
3253
|
+
GCAlgebra_multigraded):
|
|
3254
|
+
"""
|
|
3255
|
+
A commutative differential multi-graded algebras.
|
|
3256
|
+
|
|
3257
|
+
INPUT:
|
|
3258
|
+
|
|
3259
|
+
- ``A`` -- a commutative multi-graded algebra
|
|
3260
|
+
|
|
3261
|
+
- ``differential`` -- a differential
|
|
3262
|
+
|
|
3263
|
+
EXAMPLES::
|
|
3264
|
+
|
|
3265
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
3266
|
+
sage: B = A.cdg_algebra(differential={a: c})
|
|
3267
|
+
sage: B.basis((1,0))
|
|
3268
|
+
[a]
|
|
3269
|
+
sage: B.basis(1, total=True)
|
|
3270
|
+
[a, b]
|
|
3271
|
+
sage: B.cohomology((1, 0))
|
|
3272
|
+
Free module generated by {} over Rational Field
|
|
3273
|
+
sage: B.cohomology(1, total=True)
|
|
3274
|
+
Free module generated by {[b]} over Rational Field
|
|
3275
|
+
"""
|
|
3276
|
+
def __init__(self, A, differential):
|
|
3277
|
+
"""
|
|
3278
|
+
Initialize ``self``.
|
|
3279
|
+
|
|
3280
|
+
INPUT:
|
|
3281
|
+
|
|
3282
|
+
- ``A`` -- a multi-graded commutative algebra
|
|
3283
|
+
- ``differential`` -- a differential
|
|
3284
|
+
|
|
3285
|
+
EXAMPLES::
|
|
3286
|
+
|
|
3287
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
3288
|
+
sage: B = A.cdg_algebra(differential={a: c})
|
|
3289
|
+
|
|
3290
|
+
Trying to define a differential which is not multi-graded::
|
|
3291
|
+
|
|
3292
|
+
sage: A.<t,x,y,z> = GradedCommutativeAlgebra(QQ, degrees=((1,0),(1,0),(2,0),(0,2)))
|
|
3293
|
+
sage: B = A.cdg_algebra(differential={x:y}) # good
|
|
3294
|
+
sage: B = A.cdg_algebra(differential={t:z}) # good
|
|
3295
|
+
sage: B = A.cdg_algebra(differential={x:y, t:z}) # bad
|
|
3296
|
+
Traceback (most recent call last):
|
|
3297
|
+
...
|
|
3298
|
+
ValueError: the differential does not have a well-defined degree
|
|
3299
|
+
"""
|
|
3300
|
+
cat = Algebras(A.base()).Graded() & ChainComplexes(A.base())
|
|
3301
|
+
GCAlgebra_multigraded.__init__(self, A.base(), names=A._names,
|
|
3302
|
+
degrees=A._degrees_multi,
|
|
3303
|
+
R=A.cover_ring(), I=A.defining_ideal(),
|
|
3304
|
+
category=cat)
|
|
3305
|
+
self._differential = Differential_multigraded(self, differential._dic_)
|
|
3306
|
+
|
|
3307
|
+
def _base_repr(self):
|
|
3308
|
+
"""
|
|
3309
|
+
Return the base string representation of ``self``.
|
|
3310
|
+
|
|
3311
|
+
EXAMPLES::
|
|
3312
|
+
|
|
3313
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
3314
|
+
sage: A.cdg_algebra(differential={a: c})._base_repr()
|
|
3315
|
+
"Commutative Differential Graded Algebra with generators ('a', 'b', 'c') in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field"
|
|
3316
|
+
"""
|
|
3317
|
+
s = DifferentialGCAlgebra._base_repr(self)
|
|
3318
|
+
old = '{}'.format(self._degrees)
|
|
3319
|
+
new = '{}'.format(self._degrees_multi)
|
|
3320
|
+
return s.replace(old, new)
|
|
3321
|
+
|
|
3322
|
+
def coboundaries(self, n, total=False):
|
|
3323
|
+
"""
|
|
3324
|
+
The `n`-th coboundary group of the algebra.
|
|
3325
|
+
|
|
3326
|
+
This is a vector space over the base field `F`, and it is
|
|
3327
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
3328
|
+
`n`-th homogeneous component has dimension `d`.
|
|
3329
|
+
|
|
3330
|
+
INPUT:
|
|
3331
|
+
|
|
3332
|
+
- ``n`` -- degree
|
|
3333
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
3334
|
+
coboundaries in total degree `n`
|
|
3335
|
+
|
|
3336
|
+
If `n` is an integer rather than a multi-index, then the
|
|
3337
|
+
total degree is used in that case as well.
|
|
3338
|
+
|
|
3339
|
+
EXAMPLES::
|
|
3340
|
+
|
|
3341
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
3342
|
+
sage: B = A.cdg_algebra(differential={a: c})
|
|
3343
|
+
sage: B.coboundaries((0,2))
|
|
3344
|
+
Vector space of degree 1 and dimension 1 over Rational Field
|
|
3345
|
+
Basis matrix:
|
|
3346
|
+
[1]
|
|
3347
|
+
sage: B.coboundaries(2)
|
|
3348
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
3349
|
+
Basis matrix:
|
|
3350
|
+
[0 1]
|
|
3351
|
+
"""
|
|
3352
|
+
return self._differential.coboundaries(n, total)
|
|
3353
|
+
|
|
3354
|
+
def cocycles(self, n, total=False):
|
|
3355
|
+
r"""
|
|
3356
|
+
The `n`-th cocycle group of the algebra.
|
|
3357
|
+
|
|
3358
|
+
This is a vector space over the base field `F`, and it is
|
|
3359
|
+
returned as a subspace of the vector space `F^d`, where the
|
|
3360
|
+
`n`-th homogeneous component has dimension `d`.
|
|
3361
|
+
|
|
3362
|
+
INPUT:
|
|
3363
|
+
|
|
3364
|
+
- ``n`` -- degree
|
|
3365
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
3366
|
+
cocycles in total degree `n`
|
|
3367
|
+
|
|
3368
|
+
If `n` is an integer rather than a multi-index, then the
|
|
3369
|
+
total degree is used in that case as well.
|
|
3370
|
+
|
|
3371
|
+
EXAMPLES::
|
|
3372
|
+
|
|
3373
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
3374
|
+
sage: B = A.cdg_algebra(differential={a: c})
|
|
3375
|
+
sage: B.cocycles((0,1))
|
|
3376
|
+
Vector space of degree 1 and dimension 1 over Rational Field
|
|
3377
|
+
Basis matrix:
|
|
3378
|
+
[1]
|
|
3379
|
+
sage: B.cocycles((0,1), total=True)
|
|
3380
|
+
Vector space of degree 2 and dimension 1 over Rational Field
|
|
3381
|
+
Basis matrix:
|
|
3382
|
+
[0 1]
|
|
3383
|
+
"""
|
|
3384
|
+
return self._differential.cocycles(n, total)
|
|
3385
|
+
|
|
3386
|
+
def cohomology_raw(self, n, total=False):
|
|
3387
|
+
"""
|
|
3388
|
+
The `n`-th cohomology group of the algebra.
|
|
3389
|
+
|
|
3390
|
+
This is a vector space over the base ring, and it is returned
|
|
3391
|
+
as the quotient cocycles/coboundaries.
|
|
3392
|
+
|
|
3393
|
+
Compare to :meth:`cohomology`.
|
|
3394
|
+
|
|
3395
|
+
INPUT:
|
|
3396
|
+
|
|
3397
|
+
- ``n`` -- degree
|
|
3398
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
3399
|
+
cohomology in total degree `n`
|
|
3400
|
+
|
|
3401
|
+
If `n` is an integer rather than a multi-index, then the
|
|
3402
|
+
total degree is used in that case as well.
|
|
3403
|
+
|
|
3404
|
+
EXAMPLES::
|
|
3405
|
+
|
|
3406
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
3407
|
+
sage: B = A.cdg_algebra(differential={a: c})
|
|
3408
|
+
sage: B.cohomology_raw((0,2))
|
|
3409
|
+
Vector space quotient V/W of dimension 0 over Rational Field where
|
|
3410
|
+
V: Vector space of degree 1 and dimension 1 over Rational Field
|
|
3411
|
+
Basis matrix:
|
|
3412
|
+
[1]
|
|
3413
|
+
W: Vector space of degree 1 and dimension 1 over Rational Field
|
|
3414
|
+
Basis matrix:
|
|
3415
|
+
[1]
|
|
3416
|
+
|
|
3417
|
+
sage: B.cohomology_raw(1)
|
|
3418
|
+
Vector space quotient V/W of dimension 1 over Rational Field where
|
|
3419
|
+
V: Vector space of degree 2 and dimension 1 over Rational Field
|
|
3420
|
+
Basis matrix:
|
|
3421
|
+
[0 1]
|
|
3422
|
+
W: Vector space of degree 2 and dimension 0 over Rational Field
|
|
3423
|
+
Basis matrix:
|
|
3424
|
+
[]
|
|
3425
|
+
"""
|
|
3426
|
+
return self._differential.cohomology_raw(n, total)
|
|
3427
|
+
|
|
3428
|
+
def cohomology(self, n, total=False):
|
|
3429
|
+
"""
|
|
3430
|
+
The `n`-th cohomology group of the algebra.
|
|
3431
|
+
|
|
3432
|
+
This is a vector space over the base ring, defined as the
|
|
3433
|
+
quotient cocycles/coboundaries. The elements of the quotient
|
|
3434
|
+
are lifted to the vector space of cocycles, and this is
|
|
3435
|
+
described in terms of those lifts.
|
|
3436
|
+
|
|
3437
|
+
Compare to :meth:`cohomology_raw`.
|
|
3438
|
+
|
|
3439
|
+
INPUT:
|
|
3440
|
+
|
|
3441
|
+
- ``n`` -- degree
|
|
3442
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, return the
|
|
3443
|
+
cohomology in total degree `n`
|
|
3444
|
+
|
|
3445
|
+
If `n` is an integer rather than a multi-index, then the
|
|
3446
|
+
total degree is used in that case as well.
|
|
3447
|
+
|
|
3448
|
+
EXAMPLES::
|
|
3449
|
+
|
|
3450
|
+
sage: A.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2)))
|
|
3451
|
+
sage: B = A.cdg_algebra(differential={a: c})
|
|
3452
|
+
sage: B.cohomology((0,2))
|
|
3453
|
+
Free module generated by {} over Rational Field
|
|
3454
|
+
|
|
3455
|
+
sage: B.cohomology(1)
|
|
3456
|
+
Free module generated by {[b]} over Rational Field
|
|
3457
|
+
"""
|
|
3458
|
+
return self._differential.cohomology(n, total)
|
|
3459
|
+
|
|
3460
|
+
homology = cohomology
|
|
3461
|
+
|
|
3462
|
+
class Element(GCAlgebra_multigraded.Element, DifferentialGCAlgebra.Element):
|
|
3463
|
+
"""
|
|
3464
|
+
Element class of a commutative differential multi-graded algebra.
|
|
3465
|
+
"""
|
|
3466
|
+
|
|
3467
|
+
################################################
|
|
3468
|
+
# Main entry point
|
|
3469
|
+
|
|
3470
|
+
|
|
3471
|
+
def GradedCommutativeAlgebra(ring, names=None, degrees=None, max_degree=None,
|
|
3472
|
+
**kwargs):
|
|
3473
|
+
r"""
|
|
3474
|
+
A graded commutative algebra.
|
|
3475
|
+
|
|
3476
|
+
INPUT:
|
|
3477
|
+
|
|
3478
|
+
There are two ways to call this. The first way defines a free
|
|
3479
|
+
graded commutative algebra:
|
|
3480
|
+
|
|
3481
|
+
- ``ring`` -- the base field over which to work
|
|
3482
|
+
|
|
3483
|
+
- ``names`` -- names of the generators. You may also use Sage's
|
|
3484
|
+
``A.<x,y,...> = ...`` syntax to define the names. If no names
|
|
3485
|
+
are specified, the generators are named ``x0``, ``x1``, ...
|
|
3486
|
+
|
|
3487
|
+
- ``degrees`` -- degrees of the generators; if this is omitted,
|
|
3488
|
+
the degree of each generator is 1, and if both ``names`` and
|
|
3489
|
+
``degrees`` are omitted, an error is raised
|
|
3490
|
+
|
|
3491
|
+
- ``max_degree`` -- the maximal degree of the graded algebra. If omitted,
|
|
3492
|
+
no maximal degree is assumed and an instance of :class:`GCAlgebra` is
|
|
3493
|
+
returned. Otherwise, an instance of
|
|
3494
|
+
:class:`sage.algebras.commutative_graded_algebra.GradedCommutativeAlgebraWithMaxDeg`
|
|
3495
|
+
is created.
|
|
3496
|
+
|
|
3497
|
+
Once such an algebra has been defined, one can use its associated
|
|
3498
|
+
methods to take a quotient, impose a differential, etc. See the
|
|
3499
|
+
examples below.
|
|
3500
|
+
|
|
3501
|
+
The second way takes a graded commutative algebra and imposes
|
|
3502
|
+
relations:
|
|
3503
|
+
|
|
3504
|
+
- ``ring`` -- a graded commutative algebra
|
|
3505
|
+
|
|
3506
|
+
- ``relations`` -- list or tuple of elements of ``ring``
|
|
3507
|
+
|
|
3508
|
+
EXAMPLES:
|
|
3509
|
+
|
|
3510
|
+
Defining a graded commutative algebra::
|
|
3511
|
+
|
|
3512
|
+
sage: GradedCommutativeAlgebra(QQ, 'x, y, z')
|
|
3513
|
+
Graded Commutative Algebra with generators ('x', 'y', 'z')
|
|
3514
|
+
in degrees (1, 1, 1) over Rational Field
|
|
3515
|
+
sage: GradedCommutativeAlgebra(QQ, degrees=(2, 3, 4))
|
|
3516
|
+
Graded Commutative Algebra with generators ('x0', 'x1', 'x2')
|
|
3517
|
+
in degrees (2, 3, 4) over Rational Field
|
|
3518
|
+
|
|
3519
|
+
As usual in Sage, the ``A.<...>`` notation defines both the
|
|
3520
|
+
algebra and the generator names::
|
|
3521
|
+
|
|
3522
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2))
|
|
3523
|
+
sage: x^2
|
|
3524
|
+
0
|
|
3525
|
+
sage: y*x # Odd classes anticommute.
|
|
3526
|
+
-x*y
|
|
3527
|
+
sage: z*y # z is central since it is in degree 2.
|
|
3528
|
+
y*z
|
|
3529
|
+
sage: (x*y*z**3).degree()
|
|
3530
|
+
8
|
|
3531
|
+
sage: A.basis(3) # basis of homogeneous degree 3 elements
|
|
3532
|
+
[x*z, y*z]
|
|
3533
|
+
|
|
3534
|
+
Defining a quotient::
|
|
3535
|
+
|
|
3536
|
+
sage: I = A.ideal(x*z)
|
|
3537
|
+
sage: AQ = A.quotient(I); AQ
|
|
3538
|
+
Graded Commutative Algebra with generators ('x', 'y', 'z')
|
|
3539
|
+
in degrees (1, 1, 2) with relations [x*z] over Rational Field
|
|
3540
|
+
sage: AQ.basis(3)
|
|
3541
|
+
[y*z]
|
|
3542
|
+
|
|
3543
|
+
Note that ``AQ`` has no specified differential. This is reflected in
|
|
3544
|
+
its print representation: ``AQ`` is described as a "graded commutative
|
|
3545
|
+
algebra" -- the word "differential" is missing. Also, it has no
|
|
3546
|
+
default ``differential``::
|
|
3547
|
+
|
|
3548
|
+
sage: AQ.differential()
|
|
3549
|
+
Traceback (most recent call last):
|
|
3550
|
+
...
|
|
3551
|
+
TypeError: ...differential() missing 1 required positional argument:
|
|
3552
|
+
'diff'
|
|
3553
|
+
|
|
3554
|
+
Now we add a differential to ``AQ``::
|
|
3555
|
+
|
|
3556
|
+
sage: B = AQ.cdg_algebra({z: y*z}); B
|
|
3557
|
+
Commutative Differential Graded Algebra with generators ('x', 'y', 'z')
|
|
3558
|
+
in degrees (1, 1, 2) with relations [x*z] over Rational Field with differential:
|
|
3559
|
+
x --> 0
|
|
3560
|
+
y --> 0
|
|
3561
|
+
z --> y*z
|
|
3562
|
+
sage: B.differential()
|
|
3563
|
+
Differential of Commutative Differential Graded Algebra with generators
|
|
3564
|
+
('x', 'y', 'z') in degrees (1, 1, 2) with relations [x*z] over Rational Field
|
|
3565
|
+
Defn: x --> 0
|
|
3566
|
+
y --> 0
|
|
3567
|
+
z --> y*z
|
|
3568
|
+
sage: B.cohomology(1)
|
|
3569
|
+
Free module generated by {[x], [y]} over Rational Field
|
|
3570
|
+
sage: B.cohomology(2)
|
|
3571
|
+
Free module generated by {[x*y]} over Rational Field
|
|
3572
|
+
|
|
3573
|
+
We compute algebra generators for cohomology in a range of
|
|
3574
|
+
degrees. This cohomology algebra appears to be finitely
|
|
3575
|
+
generated::
|
|
3576
|
+
|
|
3577
|
+
sage: B.cohomology_generators(15)
|
|
3578
|
+
{1: [x, y]}
|
|
3579
|
+
|
|
3580
|
+
We can construct multi-graded rings as well. We work in characteristic 2
|
|
3581
|
+
for a change, so the algebras here are honestly commutative::
|
|
3582
|
+
|
|
3583
|
+
sage: C.<a,b,c,d> = GradedCommutativeAlgebra(GF(2),
|
|
3584
|
+
....: degrees=((1,0), (1,1), (0,2), (0,3)))
|
|
3585
|
+
sage: D = C.cdg_algebra(differential={a: c, b: d}); D
|
|
3586
|
+
Commutative Differential Graded Algebra with generators ('a', 'b', 'c', 'd')
|
|
3587
|
+
in degrees ((1, 0), (1, 1), (0, 2), (0, 3)) over Finite Field of size 2
|
|
3588
|
+
with differential:
|
|
3589
|
+
a --> c
|
|
3590
|
+
b --> d
|
|
3591
|
+
c --> 0
|
|
3592
|
+
d --> 0
|
|
3593
|
+
|
|
3594
|
+
We can examine ``D`` using both total degrees and multidegrees.
|
|
3595
|
+
Use tuples, lists, vectors, or elements of additive
|
|
3596
|
+
abelian groups to specify degrees::
|
|
3597
|
+
|
|
3598
|
+
sage: D.basis(3) # basis in total degree 3
|
|
3599
|
+
[a^3, a*b, a*c, d]
|
|
3600
|
+
sage: D.basis((1,2)) # basis in degree (1,2)
|
|
3601
|
+
[a*c]
|
|
3602
|
+
sage: D.basis([1,2])
|
|
3603
|
+
[a*c]
|
|
3604
|
+
sage: D.basis(vector([1,2]))
|
|
3605
|
+
[a*c]
|
|
3606
|
+
sage: G = AdditiveAbelianGroup([0,0]); G
|
|
3607
|
+
Additive abelian group isomorphic to Z + Z
|
|
3608
|
+
sage: D.basis(G(vector([1,2])))
|
|
3609
|
+
[a*c]
|
|
3610
|
+
|
|
3611
|
+
At this point, ``a``, for example, is an element of ``C``. We can
|
|
3612
|
+
redefine it so that it is instead an element of ``D`` in several
|
|
3613
|
+
ways, for instance using :meth:`gens` method::
|
|
3614
|
+
|
|
3615
|
+
sage: a, b, c, d = D.gens()
|
|
3616
|
+
sage: a.differential()
|
|
3617
|
+
c
|
|
3618
|
+
|
|
3619
|
+
Or the :meth:`inject_variables` method::
|
|
3620
|
+
|
|
3621
|
+
sage: D.inject_variables()
|
|
3622
|
+
Defining a, b, c, d
|
|
3623
|
+
sage: (a*b).differential()
|
|
3624
|
+
b*c + a*d
|
|
3625
|
+
sage: (a*b*c**2).degree()
|
|
3626
|
+
(2, 5)
|
|
3627
|
+
|
|
3628
|
+
Degrees are returned as elements of additive abelian groups::
|
|
3629
|
+
|
|
3630
|
+
sage: (a*b*c**2).degree() in G
|
|
3631
|
+
True
|
|
3632
|
+
|
|
3633
|
+
sage: (a*b*c**2).degree(total=True) # total degree
|
|
3634
|
+
7
|
|
3635
|
+
sage: D.cohomology(4)
|
|
3636
|
+
Free module generated by {[a^4], [b^2]} over Finite Field of size 2
|
|
3637
|
+
sage: D.cohomology((2,2))
|
|
3638
|
+
Free module generated by {[b^2]} over Finite Field of size 2
|
|
3639
|
+
|
|
3640
|
+
Graded algebra with maximal degree::
|
|
3641
|
+
|
|
3642
|
+
sage: A.<p,e> = GradedCommutativeAlgebra(QQ, degrees=(4,2), max_degree=6); A
|
|
3643
|
+
Graded commutative algebra with generators ('p', 'e') in degrees (4, 2)
|
|
3644
|
+
with maximal degree 6
|
|
3645
|
+
sage: p^2
|
|
3646
|
+
0
|
|
3647
|
+
|
|
3648
|
+
TESTS:
|
|
3649
|
+
|
|
3650
|
+
We need to specify either name or degrees::
|
|
3651
|
+
|
|
3652
|
+
sage: GradedCommutativeAlgebra(QQ)
|
|
3653
|
+
Traceback (most recent call last):
|
|
3654
|
+
...
|
|
3655
|
+
ValueError: you must specify names or degrees
|
|
3656
|
+
"""
|
|
3657
|
+
if max_degree:
|
|
3658
|
+
from .finite_gca import FiniteGCAlgebra
|
|
3659
|
+
return FiniteGCAlgebra(ring, names=names, degrees=degrees,
|
|
3660
|
+
max_degree=max_degree, **kwargs)
|
|
3661
|
+
multi = False
|
|
3662
|
+
if degrees:
|
|
3663
|
+
try:
|
|
3664
|
+
for d in degrees:
|
|
3665
|
+
list(d)
|
|
3666
|
+
# If the previous line doesn't raise an error, looks multi-graded.
|
|
3667
|
+
multi = True
|
|
3668
|
+
except TypeError:
|
|
3669
|
+
pass
|
|
3670
|
+
if multi:
|
|
3671
|
+
return GCAlgebra_multigraded(ring, names=names, degrees=degrees)
|
|
3672
|
+
return GCAlgebra(ring, names=names, degrees=degrees)
|
|
3673
|
+
|
|
3674
|
+
|
|
3675
|
+
################################################
|
|
3676
|
+
# Morphisms
|
|
3677
|
+
|
|
3678
|
+
class GCAlgebraMorphism(RingHomomorphism_im_gens):
|
|
3679
|
+
"""
|
|
3680
|
+
Create a morphism between two :class:`graded commutative algebras <GCAlgebra>`.
|
|
3681
|
+
|
|
3682
|
+
INPUT:
|
|
3683
|
+
|
|
3684
|
+
- ``parent`` -- the parent homset
|
|
3685
|
+
|
|
3686
|
+
- ``im_gens`` -- the images, in the codomain, of the generators of
|
|
3687
|
+
the domain
|
|
3688
|
+
|
|
3689
|
+
- ``check`` -- boolean (default: ``True``); check whether the
|
|
3690
|
+
proposed map is actually an algebra map; if the domain and
|
|
3691
|
+
codomain have differentials, also check that the map respects
|
|
3692
|
+
those.
|
|
3693
|
+
|
|
3694
|
+
EXAMPLES::
|
|
3695
|
+
|
|
3696
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ)
|
|
3697
|
+
sage: H = Hom(A,A)
|
|
3698
|
+
sage: f = H([y,x])
|
|
3699
|
+
sage: f
|
|
3700
|
+
Graded Commutative Algebra endomorphism of Graded Commutative Algebra
|
|
3701
|
+
with generators ('x', 'y') in degrees (1, 1) over Rational Field
|
|
3702
|
+
Defn: (x, y) --> (y, x)
|
|
3703
|
+
sage: f(x*y)
|
|
3704
|
+
-x*y
|
|
3705
|
+
"""
|
|
3706
|
+
def __init__(self, parent, im_gens, check=True):
|
|
3707
|
+
r"""
|
|
3708
|
+
TESTS:
|
|
3709
|
+
|
|
3710
|
+
The entries in ``im_gens`` must lie in the codomain::
|
|
3711
|
+
|
|
3712
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
3713
|
+
sage: B.<a,b> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
3714
|
+
sage: H = Hom(A,A)
|
|
3715
|
+
sage: H([x,b])
|
|
3716
|
+
Traceback (most recent call last):
|
|
3717
|
+
...
|
|
3718
|
+
ValueError: not all elements of im_gens are in the codomain
|
|
3719
|
+
|
|
3720
|
+
Note that morphisms do not need to respect the grading;
|
|
3721
|
+
whether they do can be tested with the method
|
|
3722
|
+
:meth:`is_graded`::
|
|
3723
|
+
|
|
3724
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
3725
|
+
sage: H = Hom(A,A)
|
|
3726
|
+
sage: f = H([x,x])
|
|
3727
|
+
sage: f
|
|
3728
|
+
Graded Commutative Algebra endomorphism of Graded Commutative Algebra
|
|
3729
|
+
with generators ('x', 'y') in degrees (1, 2) over Rational Field
|
|
3730
|
+
Defn: (x, y) --> (x, x)
|
|
3731
|
+
sage: f.is_graded()
|
|
3732
|
+
False
|
|
3733
|
+
sage: TestSuite(f).run(skip='_test_category')
|
|
3734
|
+
|
|
3735
|
+
Since `x^2=0` but `y^2 \neq 0`, the following does not define a valid morphism::
|
|
3736
|
+
|
|
3737
|
+
sage: H([y,y])
|
|
3738
|
+
Traceback (most recent call last):
|
|
3739
|
+
...
|
|
3740
|
+
ValueError: the proposed morphism does not respect the relations
|
|
3741
|
+
|
|
3742
|
+
This is okay in characteristic two since then `x^2 \neq 0`::
|
|
3743
|
+
|
|
3744
|
+
sage: A2.<x,y> = GradedCommutativeAlgebra(GF(2), degrees=(1,2))
|
|
3745
|
+
sage: H2 = Hom(A2,A2)
|
|
3746
|
+
sage: H2([y,y])
|
|
3747
|
+
Graded Commutative Algebra endomorphism of Graded Commutative Algebra
|
|
3748
|
+
with generators ('x', 'y') in degrees (1, 2) over Finite Field of size 2
|
|
3749
|
+
Defn: (x, y) --> (y, y)
|
|
3750
|
+
|
|
3751
|
+
The "nc-relations" `a*b = -b*a`, for `a` and `b` in odd
|
|
3752
|
+
degree, are checked first, and we can see this when using more
|
|
3753
|
+
generators::
|
|
3754
|
+
|
|
3755
|
+
sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
3756
|
+
sage: Hom(A,A)([x,z,z])
|
|
3757
|
+
Traceback (most recent call last):
|
|
3758
|
+
...
|
|
3759
|
+
ValueError: the proposed morphism does not respect the nc-relations
|
|
3760
|
+
|
|
3761
|
+
Other relations::
|
|
3762
|
+
|
|
3763
|
+
sage: B.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1))
|
|
3764
|
+
sage: D = B.quotient(B.ideal(x*y))
|
|
3765
|
+
sage: H = Hom(D,D)
|
|
3766
|
+
sage: D.inject_variables()
|
|
3767
|
+
Defining x, y, z
|
|
3768
|
+
sage: H([x,z,z])
|
|
3769
|
+
Traceback (most recent call last):
|
|
3770
|
+
...
|
|
3771
|
+
ValueError: the proposed morphism does not respect the relations
|
|
3772
|
+
|
|
3773
|
+
The morphisms must respect the differentials, when present::
|
|
3774
|
+
|
|
3775
|
+
sage: B.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1))
|
|
3776
|
+
sage: C = B.cdg_algebra({z: x*y})
|
|
3777
|
+
sage: C.inject_variables()
|
|
3778
|
+
Defining x, y, z
|
|
3779
|
+
sage: H = Hom(C,C)
|
|
3780
|
+
sage: H([x,z,z])
|
|
3781
|
+
Traceback (most recent call last):
|
|
3782
|
+
...
|
|
3783
|
+
ValueError: the proposed morphism does not respect the differentials
|
|
3784
|
+
|
|
3785
|
+
In the case of only one generator, the cover ring is a polynomial ring,
|
|
3786
|
+
hence the noncommutativity relations should not be checked::
|
|
3787
|
+
|
|
3788
|
+
sage: A.<e1> = GradedCommutativeAlgebra(QQ)
|
|
3789
|
+
sage: A.cover_ring()
|
|
3790
|
+
Multivariate Polynomial Ring in e1 over Rational Field
|
|
3791
|
+
sage: A.hom([2*e1])
|
|
3792
|
+
Graded Commutative Algebra endomorphism of Graded Commutative Algebra
|
|
3793
|
+
with generators ('e1',) in degrees (1,) over Rational Field
|
|
3794
|
+
Defn: (e1,) --> (2*e1,)
|
|
3795
|
+
"""
|
|
3796
|
+
domain = parent.domain()
|
|
3797
|
+
codomain = parent.codomain()
|
|
3798
|
+
|
|
3799
|
+
# We use check=False here because checking of nc-relations is
|
|
3800
|
+
# not implemented in RingHomomorphism_im_gens.__init__.
|
|
3801
|
+
# We check these relations below.
|
|
3802
|
+
RingHomomorphism_im_gens.__init__(self, parent=parent,
|
|
3803
|
+
im_gens=im_gens,
|
|
3804
|
+
check=False)
|
|
3805
|
+
self._im_gens = tuple(im_gens)
|
|
3806
|
+
# Now check that the relations are respected.
|
|
3807
|
+
if check:
|
|
3808
|
+
if any(x not in codomain for x in im_gens):
|
|
3809
|
+
raise ValueError('not all elements of im_gens are in '
|
|
3810
|
+
'the codomain')
|
|
3811
|
+
R = domain.cover_ring()
|
|
3812
|
+
from_R = dict(zip(R.gens(), im_gens))
|
|
3813
|
+
if hasattr(R, 'free_algebra'):
|
|
3814
|
+
from_free = dict(zip(R.free_algebra().gens(), im_gens))
|
|
3815
|
+
# First check the nc-relations: x*y=-y*x for x, y in odd
|
|
3816
|
+
# degrees. These are in the form of a dictionary, with
|
|
3817
|
+
# typical entry left:right.
|
|
3818
|
+
for left in R.relations():
|
|
3819
|
+
zero = left.subs(from_free) - R.relations()[left].subs(from_R)
|
|
3820
|
+
if zero:
|
|
3821
|
+
raise ValueError('the proposed morphism does not respect '
|
|
3822
|
+
'the nc-relations')
|
|
3823
|
+
# Now check any extra relations, including x**2=0 for x in
|
|
3824
|
+
# odd degree. These are defined by a list of generators of
|
|
3825
|
+
# the defining ideal.
|
|
3826
|
+
for g in domain.defining_ideal().gens():
|
|
3827
|
+
zero = g.subs(from_R)
|
|
3828
|
+
if zero:
|
|
3829
|
+
raise ValueError('the proposed morphism does not respect '
|
|
3830
|
+
'the relations')
|
|
3831
|
+
# If the domain and codomain have differentials, check
|
|
3832
|
+
# those, too.
|
|
3833
|
+
if (isinstance(domain, DifferentialGCAlgebra)
|
|
3834
|
+
and isinstance(codomain, DifferentialGCAlgebra)):
|
|
3835
|
+
dom_diff = domain.differential()
|
|
3836
|
+
cod_diff = codomain.differential()
|
|
3837
|
+
if any(cod_diff(self(g)) != self(dom_diff(g))
|
|
3838
|
+
for g in domain.gens()):
|
|
3839
|
+
raise ValueError('the proposed morphism does not respect '
|
|
3840
|
+
'the differentials')
|
|
3841
|
+
|
|
3842
|
+
def _call_(self, x):
|
|
3843
|
+
"""
|
|
3844
|
+
Evaluate this morphism on ``x``.
|
|
3845
|
+
|
|
3846
|
+
INPUT:
|
|
3847
|
+
|
|
3848
|
+
- ``x`` -- an element of the domain
|
|
3849
|
+
|
|
3850
|
+
EXAMPLES::
|
|
3851
|
+
|
|
3852
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(GF(2))
|
|
3853
|
+
sage: H = Hom(A,A)
|
|
3854
|
+
sage: g = H([y,y])
|
|
3855
|
+
sage: g(x)
|
|
3856
|
+
y
|
|
3857
|
+
sage: g(x*y)
|
|
3858
|
+
y^2
|
|
3859
|
+
|
|
3860
|
+
sage: B.<x,y,z> = GradedCommutativeAlgebra(QQ)
|
|
3861
|
+
sage: H = Hom(B,B)
|
|
3862
|
+
sage: f = H([y,x,x])
|
|
3863
|
+
sage: f(x)
|
|
3864
|
+
y
|
|
3865
|
+
sage: f(3*x*y)
|
|
3866
|
+
-3*x*y
|
|
3867
|
+
sage: f(y*z)
|
|
3868
|
+
0
|
|
3869
|
+
sage: f(1)
|
|
3870
|
+
1
|
|
3871
|
+
"""
|
|
3872
|
+
codomain = self.codomain()
|
|
3873
|
+
result = codomain.zero()
|
|
3874
|
+
for mono, coeff in x.monomial_coefficients().items():
|
|
3875
|
+
term = prod([gen**y for (y, gen) in zip(mono, self.im_gens())],
|
|
3876
|
+
codomain.one())
|
|
3877
|
+
result += coeff * term
|
|
3878
|
+
return result
|
|
3879
|
+
|
|
3880
|
+
def is_graded(self, total=False):
|
|
3881
|
+
"""
|
|
3882
|
+
Return ``True`` if this morphism is graded.
|
|
3883
|
+
|
|
3884
|
+
That is, return ``True`` if `f(x)` is zero, or if `f(x)` is
|
|
3885
|
+
homogeneous and has the same degree as `x`, for each generator
|
|
3886
|
+
`x`.
|
|
3887
|
+
|
|
3888
|
+
INPUT:
|
|
3889
|
+
|
|
3890
|
+
- ``total`` -- boolean (default: ``False``); if ``True``, use
|
|
3891
|
+
the total degree to determine whether the morphism is graded
|
|
3892
|
+
(relevant only in the multigraded case)
|
|
3893
|
+
|
|
3894
|
+
EXAMPLES::
|
|
3895
|
+
|
|
3896
|
+
sage: C.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,1,2))
|
|
3897
|
+
sage: H = Hom(C,C)
|
|
3898
|
+
sage: H([a, b, a*b + 2*a]).is_graded()
|
|
3899
|
+
False
|
|
3900
|
+
sage: H([a, b, a*b]).is_graded()
|
|
3901
|
+
True
|
|
3902
|
+
|
|
3903
|
+
sage: A.<w,x> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (1,0)))
|
|
3904
|
+
sage: B.<y,z> = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0,1)))
|
|
3905
|
+
sage: H = Hom(A,B)
|
|
3906
|
+
sage: H([y,0]).is_graded()
|
|
3907
|
+
True
|
|
3908
|
+
sage: H([z,z]).is_graded()
|
|
3909
|
+
False
|
|
3910
|
+
sage: H([z,z]).is_graded(total=True)
|
|
3911
|
+
True
|
|
3912
|
+
"""
|
|
3913
|
+
return all(not y # zero is always allowed as an image
|
|
3914
|
+
or (y.is_homogeneous()
|
|
3915
|
+
and x.degree(total=total) == y.degree(total=total))
|
|
3916
|
+
for (x, y) in zip(self.domain().gens(), self.im_gens()))
|
|
3917
|
+
|
|
3918
|
+
def _repr_type(self):
|
|
3919
|
+
"""
|
|
3920
|
+
EXAMPLES::
|
|
3921
|
+
|
|
3922
|
+
sage: B.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1))
|
|
3923
|
+
sage: C = B.cdg_algebra({z: x*y})
|
|
3924
|
+
sage: Hom(B,B)([z,y,x])._repr_type()
|
|
3925
|
+
'Graded Commutative Algebra'
|
|
3926
|
+
sage: C.inject_variables()
|
|
3927
|
+
Defining x, y, z
|
|
3928
|
+
sage: Hom(C,C)([x,0,0])._repr_type()
|
|
3929
|
+
'Commutative Differential Graded Algebra'
|
|
3930
|
+
"""
|
|
3931
|
+
if (isinstance(self.domain(), DifferentialGCAlgebra)
|
|
3932
|
+
and isinstance(self.codomain(), DifferentialGCAlgebra)):
|
|
3933
|
+
return "Commutative Differential Graded Algebra"
|
|
3934
|
+
return "Graded Commutative Algebra"
|
|
3935
|
+
|
|
3936
|
+
def _repr_defn(self):
|
|
3937
|
+
"""
|
|
3938
|
+
EXAMPLES::
|
|
3939
|
+
|
|
3940
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ)
|
|
3941
|
+
sage: Hom(A,A)([y,x])._repr_defn()
|
|
3942
|
+
'(x, y) --> (y, x)'
|
|
3943
|
+
"""
|
|
3944
|
+
gens = self.domain().gens()
|
|
3945
|
+
return "{} --> {}".format(gens, self._im_gens)
|
|
3946
|
+
|
|
3947
|
+
|
|
3948
|
+
################################################
|
|
3949
|
+
# Homsets
|
|
3950
|
+
|
|
3951
|
+
class GCAlgebraHomset(RingHomset_generic):
|
|
3952
|
+
"""
|
|
3953
|
+
Set of morphisms between two graded commutative algebras.
|
|
3954
|
+
|
|
3955
|
+
.. NOTE::
|
|
3956
|
+
|
|
3957
|
+
Homsets (and thus morphisms) have only been implemented when
|
|
3958
|
+
the base fields are the same for the domain and codomain.
|
|
3959
|
+
|
|
3960
|
+
EXAMPLES::
|
|
3961
|
+
|
|
3962
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
3963
|
+
sage: H = Hom(A,A)
|
|
3964
|
+
sage: H([x,y]) == H.identity()
|
|
3965
|
+
True
|
|
3966
|
+
sage: H([x,x]) == H.identity()
|
|
3967
|
+
False
|
|
3968
|
+
|
|
3969
|
+
sage: A.<w,x> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
3970
|
+
sage: B.<y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1))
|
|
3971
|
+
sage: H = Hom(A,B)
|
|
3972
|
+
sage: H([y,0])
|
|
3973
|
+
Graded Commutative Algebra morphism:
|
|
3974
|
+
From: Graded Commutative Algebra with generators ('w', 'x')
|
|
3975
|
+
in degrees (1, 2) over Rational Field
|
|
3976
|
+
To: Graded Commutative Algebra with generators ('y', 'z')
|
|
3977
|
+
in degrees (1, 1) over Rational Field
|
|
3978
|
+
Defn: (w, x) --> (y, 0)
|
|
3979
|
+
sage: H([y,y*z])
|
|
3980
|
+
Graded Commutative Algebra morphism:
|
|
3981
|
+
From: Graded Commutative Algebra with generators ('w', 'x')
|
|
3982
|
+
in degrees (1, 2) over Rational Field
|
|
3983
|
+
To: Graded Commutative Algebra with generators ('y', 'z')
|
|
3984
|
+
in degrees (1, 1) over Rational Field
|
|
3985
|
+
Defn: (w, x) --> (y, y*z)
|
|
3986
|
+
"""
|
|
3987
|
+
|
|
3988
|
+
@cached_method
|
|
3989
|
+
def zero(self):
|
|
3990
|
+
"""
|
|
3991
|
+
Construct the "zero" morphism of this homset: the map sending each
|
|
3992
|
+
generator to zero.
|
|
3993
|
+
|
|
3994
|
+
EXAMPLES::
|
|
3995
|
+
|
|
3996
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
3997
|
+
sage: B.<a,b,c> = GradedCommutativeAlgebra(QQ, degrees=(1,1,1))
|
|
3998
|
+
sage: zero = Hom(A,B).zero()
|
|
3999
|
+
sage: zero(x) == zero(y) == 0
|
|
4000
|
+
True
|
|
4001
|
+
"""
|
|
4002
|
+
return GCAlgebraMorphism(self, [self.codomain().zero()]
|
|
4003
|
+
* self.domain().ngens())
|
|
4004
|
+
|
|
4005
|
+
@cached_method
|
|
4006
|
+
def identity(self):
|
|
4007
|
+
"""
|
|
4008
|
+
Construct the identity morphism of this homset.
|
|
4009
|
+
|
|
4010
|
+
EXAMPLES::
|
|
4011
|
+
|
|
4012
|
+
sage: A.<x,y> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
4013
|
+
sage: H = Hom(A,A)
|
|
4014
|
+
sage: H([x,y]) == H.identity()
|
|
4015
|
+
True
|
|
4016
|
+
sage: H([x,x]) == H.identity()
|
|
4017
|
+
False
|
|
4018
|
+
"""
|
|
4019
|
+
if self.domain() != self.codomain():
|
|
4020
|
+
raise TypeError('identity map is only defined for '
|
|
4021
|
+
'endomorphism sets')
|
|
4022
|
+
return GCAlgebraMorphism(self, self.domain().gens())
|
|
4023
|
+
|
|
4024
|
+
def __call__(self, im_gens, check=True):
|
|
4025
|
+
"""
|
|
4026
|
+
Create a homomorphism.
|
|
4027
|
+
|
|
4028
|
+
INPUT:
|
|
4029
|
+
|
|
4030
|
+
- ``im_gens`` -- the images of the generators of the domain
|
|
4031
|
+
|
|
4032
|
+
EXAMPLES::
|
|
4033
|
+
|
|
4034
|
+
sage: A.<w,x> = GradedCommutativeAlgebra(QQ, degrees=(1,2))
|
|
4035
|
+
sage: B.<y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,1))
|
|
4036
|
+
sage: H = Hom(A,B)
|
|
4037
|
+
sage: H([y,0])
|
|
4038
|
+
Graded Commutative Algebra morphism:
|
|
4039
|
+
From: Graded Commutative Algebra with generators ('w', 'x') in degrees (1, 2) over Rational Field
|
|
4040
|
+
To: Graded Commutative Algebra with generators ('y', 'z') in degrees (1, 1) over Rational Field
|
|
4041
|
+
Defn: (w, x) --> (y, 0)
|
|
4042
|
+
sage: H([y,y*z])
|
|
4043
|
+
Graded Commutative Algebra morphism:
|
|
4044
|
+
From: Graded Commutative Algebra with generators ('w', 'x') in degrees (1, 2) over Rational Field
|
|
4045
|
+
To: Graded Commutative Algebra with generators ('y', 'z') in degrees (1, 1) over Rational Field
|
|
4046
|
+
Defn: (w, x) --> (y, y*z)
|
|
4047
|
+
"""
|
|
4048
|
+
from sage.categories.map import Map
|
|
4049
|
+
if isinstance(im_gens, Map):
|
|
4050
|
+
return self._coerce_impl(im_gens)
|
|
4051
|
+
return GCAlgebraMorphism(self, im_gens, check=check)
|
|
4052
|
+
|
|
4053
|
+
|
|
4054
|
+
################################################
|
|
4055
|
+
# Miscellaneous utility classes and functions
|
|
4056
|
+
|
|
4057
|
+
class CohomologyClass(SageObject, CachedRepresentation):
|
|
4058
|
+
"""
|
|
4059
|
+
A class for representing cohomology classes.
|
|
4060
|
+
|
|
4061
|
+
This just has ``_repr_`` and ``_latex_`` methods which put
|
|
4062
|
+
brackets around the object's name.
|
|
4063
|
+
|
|
4064
|
+
EXAMPLES::
|
|
4065
|
+
|
|
4066
|
+
sage: from sage.algebras.commutative_dga import CohomologyClass
|
|
4067
|
+
sage: CohomologyClass(3)
|
|
4068
|
+
[3]
|
|
4069
|
+
sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(2,2,3,3))
|
|
4070
|
+
sage: CohomologyClass(x^2 + 2*y*z, A)
|
|
4071
|
+
[2*y*z + x^2]
|
|
4072
|
+
|
|
4073
|
+
TESTS:
|
|
4074
|
+
|
|
4075
|
+
In order for the cache to not confuse objects with the same representation,
|
|
4076
|
+
we can pass the parent of the representative as a parameter::
|
|
4077
|
+
|
|
4078
|
+
sage: A.<e1,e2,e3,e4,e5,e6> = GradedCommutativeAlgebra(QQ)
|
|
4079
|
+
sage: B1 = A.cdg_algebra({e5:e1*e2,e6:e3*e4})
|
|
4080
|
+
sage: B2 = A.cdg_algebra({e5:e1*e2,e6:e1*e2+e3*e4})
|
|
4081
|
+
sage: B1.minimal_model()
|
|
4082
|
+
Commutative Differential Graded Algebra morphism:
|
|
4083
|
+
From: Commutative Differential Graded Algebra with generators ('x1_0', 'x1_1', 'x1_2', 'x1_3', 'y1_0', 'y1_1') in degrees (1, 1, 1, 1, 1, 1) over Rational Field with differential:
|
|
4084
|
+
x1_0 --> 0
|
|
4085
|
+
x1_1 --> 0
|
|
4086
|
+
x1_2 --> 0
|
|
4087
|
+
x1_3 --> 0
|
|
4088
|
+
y1_0 --> x1_0*x1_1
|
|
4089
|
+
y1_1 --> x1_2*x1_3
|
|
4090
|
+
To: Commutative Differential Graded Algebra with generators ('e1', 'e2', 'e3', 'e4', 'e5', 'e6') in degrees (1, 1, 1, 1, 1, 1) over Rational Field with differential:
|
|
4091
|
+
e1 --> 0
|
|
4092
|
+
e2 --> 0
|
|
4093
|
+
e3 --> 0
|
|
4094
|
+
e4 --> 0
|
|
4095
|
+
e5 --> e1*e2
|
|
4096
|
+
e6 --> e3*e4
|
|
4097
|
+
Defn: (x1_0, x1_1, x1_2, x1_3, y1_0, y1_1) --> (e1, e2, e3, e4, e5, e6)
|
|
4098
|
+
sage: B2.minimal_model()
|
|
4099
|
+
Commutative Differential Graded Algebra morphism:
|
|
4100
|
+
From: Commutative Differential Graded Algebra with generators ('x1_0', 'x1_1', 'x1_2', 'x1_3', 'y1_0', 'y1_1') in degrees (1, 1, 1, 1, 1, 1) over Rational Field with differential:
|
|
4101
|
+
x1_0 --> 0
|
|
4102
|
+
x1_1 --> 0
|
|
4103
|
+
x1_2 --> 0
|
|
4104
|
+
x1_3 --> 0
|
|
4105
|
+
y1_0 --> x1_0*x1_1
|
|
4106
|
+
y1_1 --> x1_2*x1_3
|
|
4107
|
+
To: Commutative Differential Graded Algebra with generators ('e1', 'e2', 'e3', 'e4', 'e5', 'e6') in degrees (1, 1, 1, 1, 1, 1) over Rational Field with differential:
|
|
4108
|
+
e1 --> 0
|
|
4109
|
+
e2 --> 0
|
|
4110
|
+
e3 --> 0
|
|
4111
|
+
e4 --> 0
|
|
4112
|
+
e5 --> e1*e2
|
|
4113
|
+
e6 --> e1*e2 + e3*e4
|
|
4114
|
+
Defn: (x1_0, x1_1, x1_2, x1_3, y1_0, y1_1) --> (e1, e2, e3, e4, e5, -e5 + e6)
|
|
4115
|
+
"""
|
|
4116
|
+
def __init__(self, x, cdga=None):
|
|
4117
|
+
"""
|
|
4118
|
+
EXAMPLES::
|
|
4119
|
+
|
|
4120
|
+
sage: from sage.algebras.commutative_dga import CohomologyClass
|
|
4121
|
+
sage: CohomologyClass(x - 2) # needs sage.symbolic
|
|
4122
|
+
[x - 2]
|
|
4123
|
+
"""
|
|
4124
|
+
self._x = x
|
|
4125
|
+
self._cdga = cdga
|
|
4126
|
+
|
|
4127
|
+
def __hash__(self):
|
|
4128
|
+
r"""
|
|
4129
|
+
TESTS::
|
|
4130
|
+
|
|
4131
|
+
sage: from sage.algebras.commutative_dga import CohomologyClass
|
|
4132
|
+
sage: hash(CohomologyClass(sin)) == hash(sin) # needs sage.symbolic
|
|
4133
|
+
True
|
|
4134
|
+
"""
|
|
4135
|
+
return hash(self._x)
|
|
4136
|
+
|
|
4137
|
+
def _repr_(self):
|
|
4138
|
+
"""
|
|
4139
|
+
EXAMPLES::
|
|
4140
|
+
|
|
4141
|
+
sage: from sage.algebras.commutative_dga import CohomologyClass
|
|
4142
|
+
sage: CohomologyClass(sin) # needs sage.symbolic
|
|
4143
|
+
[sin]
|
|
4144
|
+
"""
|
|
4145
|
+
return '[{}]'.format(self._x)
|
|
4146
|
+
|
|
4147
|
+
def _latex_(self):
|
|
4148
|
+
r"""
|
|
4149
|
+
EXAMPLES::
|
|
4150
|
+
|
|
4151
|
+
sage: from sage.algebras.commutative_dga import CohomologyClass
|
|
4152
|
+
sage: latex(CohomologyClass(sin)) # needs sage.symbolic
|
|
4153
|
+
\left[ \sin \right]
|
|
4154
|
+
sage: latex(CohomologyClass(x^2)) # needs sage.symbolic
|
|
4155
|
+
\left[ x^{2} \right]
|
|
4156
|
+
"""
|
|
4157
|
+
from sage.misc.latex import latex
|
|
4158
|
+
return '\\left[ {} \\right]'.format(latex(self._x))
|
|
4159
|
+
|
|
4160
|
+
def representative(self):
|
|
4161
|
+
"""
|
|
4162
|
+
Return the representative of ``self``.
|
|
4163
|
+
|
|
4164
|
+
EXAMPLES::
|
|
4165
|
+
|
|
4166
|
+
sage: from sage.algebras.commutative_dga import CohomologyClass
|
|
4167
|
+
sage: x = CohomologyClass(sin) # needs sage.symbolic
|
|
4168
|
+
sage: x.representative() == sin # needs sage.symbolic
|
|
4169
|
+
True
|
|
4170
|
+
"""
|
|
4171
|
+
return self._x
|
|
4172
|
+
|
|
4173
|
+
|
|
4174
|
+
@cached_function
|
|
4175
|
+
def exterior_algebra_basis(n, degrees):
|
|
4176
|
+
"""
|
|
4177
|
+
Basis of an exterior algebra in degree ``n``, where the
|
|
4178
|
+
generators are in degrees ``degrees``.
|
|
4179
|
+
|
|
4180
|
+
INPUT:
|
|
4181
|
+
|
|
4182
|
+
- ``n`` -- integer
|
|
4183
|
+
- ``degrees`` -- iterable of integers
|
|
4184
|
+
|
|
4185
|
+
Return list of lists, each list representing exponents for the
|
|
4186
|
+
corresponding generators. (So each list consists of 0s and 1s.)
|
|
4187
|
+
|
|
4188
|
+
EXAMPLES::
|
|
4189
|
+
|
|
4190
|
+
sage: from sage.algebras.commutative_dga import exterior_algebra_basis
|
|
4191
|
+
sage: exterior_algebra_basis(1, (1,3,1))
|
|
4192
|
+
[[0, 0, 1], [1, 0, 0]]
|
|
4193
|
+
sage: exterior_algebra_basis(4, (1,3,1))
|
|
4194
|
+
[[0, 1, 1], [1, 1, 0]]
|
|
4195
|
+
sage: exterior_algebra_basis(10, (1,5,1,1))
|
|
4196
|
+
[]
|
|
4197
|
+
"""
|
|
4198
|
+
if n == 0:
|
|
4199
|
+
return [[0 for _ in degrees]]
|
|
4200
|
+
if len(degrees) == 1:
|
|
4201
|
+
if degrees[0] == n:
|
|
4202
|
+
return [[1]]
|
|
4203
|
+
return []
|
|
4204
|
+
if not degrees:
|
|
4205
|
+
return []
|
|
4206
|
+
if min(degrees) > n:
|
|
4207
|
+
return []
|
|
4208
|
+
if sum(degrees) < n:
|
|
4209
|
+
return []
|
|
4210
|
+
if sum(degrees) == n:
|
|
4211
|
+
return [[1 for _ in degrees]]
|
|
4212
|
+
i = len(degrees) // 2
|
|
4213
|
+
res = []
|
|
4214
|
+
for j in range(n + 1):
|
|
4215
|
+
v1 = exterior_algebra_basis(j, degrees[:i])
|
|
4216
|
+
v2 = exterior_algebra_basis(n - j, degrees[i:])
|
|
4217
|
+
res += [l1 + l2 for l1 in v1 for l2 in v2]
|
|
4218
|
+
res.sort()
|
|
4219
|
+
return res
|
|
4220
|
+
|
|
4221
|
+
|
|
4222
|
+
def total_degree(deg):
|
|
4223
|
+
"""
|
|
4224
|
+
Total degree of ``deg``.
|
|
4225
|
+
|
|
4226
|
+
INPUT:
|
|
4227
|
+
|
|
4228
|
+
- ``deg`` -- an element of a free abelian group
|
|
4229
|
+
|
|
4230
|
+
In fact, ``deg`` could be an integer, a Python int, a list, a
|
|
4231
|
+
tuple, a vector, etc. This function returns the sum of the
|
|
4232
|
+
components of ``deg``.
|
|
4233
|
+
|
|
4234
|
+
EXAMPLES::
|
|
4235
|
+
|
|
4236
|
+
sage: from sage.algebras.commutative_dga import total_degree
|
|
4237
|
+
sage: total_degree(12)
|
|
4238
|
+
12
|
|
4239
|
+
sage: total_degree(range(5))
|
|
4240
|
+
10
|
|
4241
|
+
sage: total_degree(vector(range(5)))
|
|
4242
|
+
10
|
|
4243
|
+
sage: G = AdditiveAbelianGroup((0,0))
|
|
4244
|
+
sage: x = G.gen(0); y = G.gen(1)
|
|
4245
|
+
sage: 3*x+4*y
|
|
4246
|
+
(3, 4)
|
|
4247
|
+
sage: total_degree(3*x+4*y)
|
|
4248
|
+
7
|
|
4249
|
+
"""
|
|
4250
|
+
if deg in ZZ:
|
|
4251
|
+
return deg
|
|
4252
|
+
return sum(deg)
|