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.

Files changed (807) hide show
  1. passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
  2. passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
  3. passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
  4. passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
  7. passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  8. passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
  9. passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
  10. passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
  11. passagemath_modules.libs/libopenblasp-r0-503f0c35.3.29.so +0 -0
  12. sage/algebras/all__sagemath_modules.py +20 -0
  13. sage/algebras/catalog.py +148 -0
  14. sage/algebras/clifford_algebra.py +3107 -0
  15. sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  16. sage/algebras/clifford_algebra_element.pxd +16 -0
  17. sage/algebras/clifford_algebra_element.pyx +997 -0
  18. sage/algebras/commutative_dga.py +4252 -0
  19. sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-musl.so +0 -0
  20. sage/algebras/exterior_algebra_groebner.pxd +55 -0
  21. sage/algebras/exterior_algebra_groebner.pyx +727 -0
  22. sage/algebras/finite_dimensional_algebras/all.py +2 -0
  23. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
  24. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  25. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
  26. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
  27. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
  28. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
  29. sage/algebras/finite_gca.py +528 -0
  30. sage/algebras/group_algebra.py +232 -0
  31. sage/algebras/lie_algebras/abelian.py +197 -0
  32. sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
  33. sage/algebras/lie_algebras/all.py +25 -0
  34. sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
  35. sage/algebras/lie_algebras/bch.py +177 -0
  36. sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
  37. sage/algebras/lie_algebras/bgg_resolution.py +232 -0
  38. sage/algebras/lie_algebras/center_uea.py +767 -0
  39. sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
  40. sage/algebras/lie_algebras/examples.py +683 -0
  41. sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
  42. sage/algebras/lie_algebras/heisenberg.py +820 -0
  43. sage/algebras/lie_algebras/lie_algebra.py +1562 -0
  44. sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  45. sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
  46. sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
  47. sage/algebras/lie_algebras/morphism.py +661 -0
  48. sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
  49. sage/algebras/lie_algebras/onsager.py +1324 -0
  50. sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
  51. sage/algebras/lie_algebras/quotient.py +462 -0
  52. sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
  53. sage/algebras/lie_algebras/representation.py +1040 -0
  54. sage/algebras/lie_algebras/structure_coefficients.py +459 -0
  55. sage/algebras/lie_algebras/subalgebra.py +967 -0
  56. sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
  57. sage/algebras/lie_algebras/verma_module.py +1630 -0
  58. sage/algebras/lie_algebras/virasoro.py +1186 -0
  59. sage/algebras/octonion_algebra.cpython-314-aarch64-linux-musl.so +0 -0
  60. sage/algebras/octonion_algebra.pxd +20 -0
  61. sage/algebras/octonion_algebra.pyx +987 -0
  62. sage/algebras/orlik_solomon.py +907 -0
  63. sage/algebras/orlik_terao.py +779 -0
  64. sage/algebras/steenrod/all.py +7 -0
  65. sage/algebras/steenrod/steenrod_algebra.py +4258 -0
  66. sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
  67. sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
  68. sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
  69. sage/algebras/weyl_algebra.py +1126 -0
  70. sage/all__sagemath_modules.py +62 -0
  71. sage/calculus/all__sagemath_modules.py +19 -0
  72. sage/calculus/expr.py +205 -0
  73. sage/calculus/integration.cpython-314-aarch64-linux-musl.so +0 -0
  74. sage/calculus/integration.pyx +698 -0
  75. sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
  76. sage/calculus/interpolation.pxd +13 -0
  77. sage/calculus/interpolation.pyx +387 -0
  78. sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
  79. sage/calculus/interpolators.pyx +326 -0
  80. sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
  81. sage/calculus/ode.pxd +5 -0
  82. sage/calculus/ode.pyx +610 -0
  83. sage/calculus/riemann.cpython-314-aarch64-linux-musl.so +0 -0
  84. sage/calculus/riemann.pyx +1521 -0
  85. sage/calculus/test_sympy.py +201 -0
  86. sage/calculus/transforms/all.py +7 -0
  87. sage/calculus/transforms/dft.py +844 -0
  88. sage/calculus/transforms/dwt.cpython-314-aarch64-linux-musl.so +0 -0
  89. sage/calculus/transforms/dwt.pxd +7 -0
  90. sage/calculus/transforms/dwt.pyx +160 -0
  91. sage/calculus/transforms/fft.cpython-314-aarch64-linux-musl.so +0 -0
  92. sage/calculus/transforms/fft.pxd +12 -0
  93. sage/calculus/transforms/fft.pyx +487 -0
  94. sage/calculus/wester.py +662 -0
  95. sage/coding/abstract_code.py +1108 -0
  96. sage/coding/ag_code.py +868 -0
  97. sage/coding/ag_code_decoders.cpython-314-aarch64-linux-musl.so +0 -0
  98. sage/coding/ag_code_decoders.pyx +2639 -0
  99. sage/coding/all.py +15 -0
  100. sage/coding/bch_code.py +494 -0
  101. sage/coding/binary_code.cpython-314-aarch64-linux-musl.so +0 -0
  102. sage/coding/binary_code.pxd +124 -0
  103. sage/coding/binary_code.pyx +4139 -0
  104. sage/coding/bounds_catalog.py +43 -0
  105. sage/coding/channel.py +819 -0
  106. sage/coding/channels_catalog.py +29 -0
  107. sage/coding/code_bounds.py +755 -0
  108. sage/coding/code_constructions.py +804 -0
  109. sage/coding/codes_catalog.py +111 -0
  110. sage/coding/cyclic_code.py +1329 -0
  111. sage/coding/databases.py +316 -0
  112. sage/coding/decoder.py +373 -0
  113. sage/coding/decoders_catalog.py +88 -0
  114. sage/coding/delsarte_bounds.py +709 -0
  115. sage/coding/encoder.py +390 -0
  116. sage/coding/encoders_catalog.py +64 -0
  117. sage/coding/extended_code.py +468 -0
  118. sage/coding/gabidulin_code.py +1058 -0
  119. sage/coding/golay_code.py +404 -0
  120. sage/coding/goppa_code.py +441 -0
  121. sage/coding/grs_code.py +2371 -0
  122. sage/coding/guava.py +107 -0
  123. sage/coding/guruswami_sudan/all.py +1 -0
  124. sage/coding/guruswami_sudan/gs_decoder.py +897 -0
  125. sage/coding/guruswami_sudan/interpolation.py +409 -0
  126. sage/coding/guruswami_sudan/utils.py +176 -0
  127. sage/coding/hamming_code.py +176 -0
  128. sage/coding/information_set_decoder.py +1032 -0
  129. sage/coding/kasami_codes.cpython-314-aarch64-linux-musl.so +0 -0
  130. sage/coding/kasami_codes.pyx +351 -0
  131. sage/coding/linear_code.py +3067 -0
  132. sage/coding/linear_code_no_metric.py +1354 -0
  133. sage/coding/linear_rank_metric.py +961 -0
  134. sage/coding/parity_check_code.py +353 -0
  135. sage/coding/punctured_code.py +719 -0
  136. sage/coding/reed_muller_code.py +999 -0
  137. sage/coding/self_dual_codes.py +942 -0
  138. sage/coding/source_coding/all.py +2 -0
  139. sage/coding/source_coding/huffman.py +553 -0
  140. sage/coding/subfield_subcode.py +423 -0
  141. sage/coding/two_weight_db.py +399 -0
  142. sage/combinat/all__sagemath_modules.py +7 -0
  143. sage/combinat/cartesian_product.py +347 -0
  144. sage/combinat/family.py +11 -0
  145. sage/combinat/free_module.py +1977 -0
  146. sage/combinat/root_system/all.py +147 -0
  147. sage/combinat/root_system/ambient_space.py +527 -0
  148. sage/combinat/root_system/associahedron.py +471 -0
  149. sage/combinat/root_system/braid_move_calculator.py +143 -0
  150. sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-musl.so +0 -0
  151. sage/combinat/root_system/braid_orbit.pyx +144 -0
  152. sage/combinat/root_system/branching_rules.py +2301 -0
  153. sage/combinat/root_system/cartan_matrix.py +1245 -0
  154. sage/combinat/root_system/cartan_type.py +3069 -0
  155. sage/combinat/root_system/coxeter_group.py +162 -0
  156. sage/combinat/root_system/coxeter_matrix.py +1261 -0
  157. sage/combinat/root_system/coxeter_type.py +681 -0
  158. sage/combinat/root_system/dynkin_diagram.py +900 -0
  159. sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
  160. sage/combinat/root_system/fundamental_group.py +795 -0
  161. sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
  162. sage/combinat/root_system/integrable_representations.py +1227 -0
  163. sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
  164. sage/combinat/root_system/pieri_factors.py +1147 -0
  165. sage/combinat/root_system/plot.py +1615 -0
  166. sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
  167. sage/combinat/root_system/root_lattice_realizations.py +4628 -0
  168. sage/combinat/root_system/root_space.py +487 -0
  169. sage/combinat/root_system/root_system.py +882 -0
  170. sage/combinat/root_system/type_A.py +348 -0
  171. sage/combinat/root_system/type_A_affine.py +227 -0
  172. sage/combinat/root_system/type_A_infinity.py +241 -0
  173. sage/combinat/root_system/type_B.py +347 -0
  174. sage/combinat/root_system/type_BC_affine.py +287 -0
  175. sage/combinat/root_system/type_B_affine.py +216 -0
  176. sage/combinat/root_system/type_C.py +317 -0
  177. sage/combinat/root_system/type_C_affine.py +188 -0
  178. sage/combinat/root_system/type_D.py +357 -0
  179. sage/combinat/root_system/type_D_affine.py +208 -0
  180. sage/combinat/root_system/type_E.py +641 -0
  181. sage/combinat/root_system/type_E_affine.py +231 -0
  182. sage/combinat/root_system/type_F.py +387 -0
  183. sage/combinat/root_system/type_F_affine.py +137 -0
  184. sage/combinat/root_system/type_G.py +293 -0
  185. sage/combinat/root_system/type_G_affine.py +132 -0
  186. sage/combinat/root_system/type_H.py +105 -0
  187. sage/combinat/root_system/type_I.py +110 -0
  188. sage/combinat/root_system/type_Q.py +150 -0
  189. sage/combinat/root_system/type_affine.py +509 -0
  190. sage/combinat/root_system/type_dual.py +704 -0
  191. sage/combinat/root_system/type_folded.py +301 -0
  192. sage/combinat/root_system/type_marked.py +748 -0
  193. sage/combinat/root_system/type_reducible.py +601 -0
  194. sage/combinat/root_system/type_relabel.py +730 -0
  195. sage/combinat/root_system/type_super_A.py +837 -0
  196. sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
  197. sage/combinat/root_system/weight_space.py +639 -0
  198. sage/combinat/root_system/weyl_characters.py +2238 -0
  199. sage/crypto/__init__.py +4 -0
  200. sage/crypto/all.py +28 -0
  201. sage/crypto/block_cipher/all.py +7 -0
  202. sage/crypto/block_cipher/des.py +1065 -0
  203. sage/crypto/block_cipher/miniaes.py +2171 -0
  204. sage/crypto/block_cipher/present.py +909 -0
  205. sage/crypto/block_cipher/sdes.py +1527 -0
  206. sage/crypto/boolean_function.cpython-314-aarch64-linux-musl.so +0 -0
  207. sage/crypto/boolean_function.pxd +10 -0
  208. sage/crypto/boolean_function.pyx +1487 -0
  209. sage/crypto/cipher.py +78 -0
  210. sage/crypto/classical.py +3668 -0
  211. sage/crypto/classical_cipher.py +569 -0
  212. sage/crypto/cryptosystem.py +387 -0
  213. sage/crypto/key_exchange/all.py +7 -0
  214. sage/crypto/key_exchange/catalog.py +24 -0
  215. sage/crypto/key_exchange/diffie_hellman.py +323 -0
  216. sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
  217. sage/crypto/lattice.py +312 -0
  218. sage/crypto/lfsr.py +295 -0
  219. sage/crypto/lwe.py +840 -0
  220. sage/crypto/mq/__init__.py +4 -0
  221. sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
  222. sage/crypto/mq/rijndael_gf.py +2345 -0
  223. sage/crypto/mq/sbox.py +7 -0
  224. sage/crypto/mq/sr.py +3344 -0
  225. sage/crypto/public_key/all.py +5 -0
  226. sage/crypto/public_key/blum_goldwasser.py +776 -0
  227. sage/crypto/sbox.cpython-314-aarch64-linux-musl.so +0 -0
  228. sage/crypto/sbox.pyx +2090 -0
  229. sage/crypto/sboxes.py +2090 -0
  230. sage/crypto/stream.py +390 -0
  231. sage/crypto/stream_cipher.py +297 -0
  232. sage/crypto/util.py +519 -0
  233. sage/ext/all__sagemath_modules.py +1 -0
  234. sage/ext/interpreters/__init__.py +1 -0
  235. sage/ext/interpreters/all__sagemath_modules.py +2 -0
  236. sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-musl.so +0 -0
  237. sage/ext/interpreters/wrapper_cc.pxd +30 -0
  238. sage/ext/interpreters/wrapper_cc.pyx +252 -0
  239. sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-musl.so +0 -0
  240. sage/ext/interpreters/wrapper_cdf.pxd +26 -0
  241. sage/ext/interpreters/wrapper_cdf.pyx +245 -0
  242. sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-musl.so +0 -0
  243. sage/ext/interpreters/wrapper_rdf.pxd +23 -0
  244. sage/ext/interpreters/wrapper_rdf.pyx +221 -0
  245. sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-musl.so +0 -0
  246. sage/ext/interpreters/wrapper_rr.pxd +28 -0
  247. sage/ext/interpreters/wrapper_rr.pyx +335 -0
  248. sage/geometry/all__sagemath_modules.py +5 -0
  249. sage/geometry/toric_lattice.py +1745 -0
  250. sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-musl.so +0 -0
  251. sage/geometry/toric_lattice_element.pyx +432 -0
  252. sage/groups/abelian_gps/abelian_group.py +1925 -0
  253. sage/groups/abelian_gps/abelian_group_element.py +164 -0
  254. sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
  255. sage/groups/abelian_gps/dual_abelian_group.py +421 -0
  256. sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
  257. sage/groups/abelian_gps/element_base.py +341 -0
  258. sage/groups/abelian_gps/values.py +488 -0
  259. sage/groups/additive_abelian/additive_abelian_group.py +476 -0
  260. sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
  261. sage/groups/additive_abelian/all.py +4 -0
  262. sage/groups/additive_abelian/qmodnz.py +231 -0
  263. sage/groups/additive_abelian/qmodnz_element.py +349 -0
  264. sage/groups/affine_gps/affine_group.py +535 -0
  265. sage/groups/affine_gps/all.py +1 -0
  266. sage/groups/affine_gps/catalog.py +17 -0
  267. sage/groups/affine_gps/euclidean_group.py +246 -0
  268. sage/groups/affine_gps/group_element.py +562 -0
  269. sage/groups/all__sagemath_modules.py +12 -0
  270. sage/groups/galois_group.py +479 -0
  271. sage/groups/matrix_gps/all.py +4 -0
  272. sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
  273. sage/groups/matrix_gps/catalog.py +26 -0
  274. sage/groups/matrix_gps/coxeter_group.py +927 -0
  275. sage/groups/matrix_gps/finitely_generated.py +487 -0
  276. sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-musl.so +0 -0
  277. sage/groups/matrix_gps/group_element.pxd +11 -0
  278. sage/groups/matrix_gps/group_element.pyx +431 -0
  279. sage/groups/matrix_gps/linear.py +440 -0
  280. sage/groups/matrix_gps/matrix_group.py +617 -0
  281. sage/groups/matrix_gps/named_group.py +296 -0
  282. sage/groups/matrix_gps/orthogonal.py +544 -0
  283. sage/groups/matrix_gps/symplectic.py +251 -0
  284. sage/groups/matrix_gps/unitary.py +436 -0
  285. sage/groups/misc_gps/all__sagemath_modules.py +1 -0
  286. sage/groups/misc_gps/argument_groups.py +1905 -0
  287. sage/groups/misc_gps/imaginary_groups.py +479 -0
  288. sage/groups/perm_gps/all__sagemath_modules.py +1 -0
  289. sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
  290. sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-musl.so +0 -0
  291. sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
  292. sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
  293. sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-musl.so +0 -0
  294. sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
  295. sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
  296. sage/homology/algebraic_topological_model.py +595 -0
  297. sage/homology/all.py +2 -0
  298. sage/homology/all__sagemath_modules.py +8 -0
  299. sage/homology/chain_complex.py +2148 -0
  300. sage/homology/chain_complex_homspace.py +165 -0
  301. sage/homology/chain_complex_morphism.py +629 -0
  302. sage/homology/chain_homotopy.py +604 -0
  303. sage/homology/chains.py +653 -0
  304. sage/homology/free_resolution.py +923 -0
  305. sage/homology/graded_resolution.py +567 -0
  306. sage/homology/hochschild_complex.py +756 -0
  307. sage/homology/homology_group.py +188 -0
  308. sage/homology/homology_morphism.py +422 -0
  309. sage/homology/homology_vector_space_with_basis.py +1454 -0
  310. sage/homology/koszul_complex.py +169 -0
  311. sage/homology/matrix_utils.py +205 -0
  312. sage/libs/all__sagemath_modules.py +1 -0
  313. sage/libs/gsl/__init__.py +1 -0
  314. sage/libs/gsl/airy.pxd +56 -0
  315. sage/libs/gsl/all.pxd +66 -0
  316. sage/libs/gsl/array.cpython-314-aarch64-linux-musl.so +0 -0
  317. sage/libs/gsl/array.pxd +5 -0
  318. sage/libs/gsl/array.pyx +102 -0
  319. sage/libs/gsl/bessel.pxd +208 -0
  320. sage/libs/gsl/blas.pxd +116 -0
  321. sage/libs/gsl/blas_types.pxd +34 -0
  322. sage/libs/gsl/block.pxd +52 -0
  323. sage/libs/gsl/chebyshev.pxd +37 -0
  324. sage/libs/gsl/clausen.pxd +12 -0
  325. sage/libs/gsl/combination.pxd +47 -0
  326. sage/libs/gsl/complex.pxd +151 -0
  327. sage/libs/gsl/coulomb.pxd +30 -0
  328. sage/libs/gsl/coupling.pxd +21 -0
  329. sage/libs/gsl/dawson.pxd +12 -0
  330. sage/libs/gsl/debye.pxd +24 -0
  331. sage/libs/gsl/dilog.pxd +14 -0
  332. sage/libs/gsl/eigen.pxd +46 -0
  333. sage/libs/gsl/elementary.pxd +12 -0
  334. sage/libs/gsl/ellint.pxd +48 -0
  335. sage/libs/gsl/elljac.pxd +8 -0
  336. sage/libs/gsl/erf.pxd +32 -0
  337. sage/libs/gsl/errno.pxd +26 -0
  338. sage/libs/gsl/exp.pxd +44 -0
  339. sage/libs/gsl/expint.pxd +44 -0
  340. sage/libs/gsl/fermi_dirac.pxd +44 -0
  341. sage/libs/gsl/fft.pxd +121 -0
  342. sage/libs/gsl/fit.pxd +50 -0
  343. sage/libs/gsl/gamma.pxd +94 -0
  344. sage/libs/gsl/gegenbauer.pxd +26 -0
  345. sage/libs/gsl/histogram.pxd +176 -0
  346. sage/libs/gsl/hyperg.pxd +52 -0
  347. sage/libs/gsl/integration.pxd +69 -0
  348. sage/libs/gsl/interp.pxd +109 -0
  349. sage/libs/gsl/laguerre.pxd +24 -0
  350. sage/libs/gsl/lambert.pxd +16 -0
  351. sage/libs/gsl/legendre.pxd +90 -0
  352. sage/libs/gsl/linalg.pxd +185 -0
  353. sage/libs/gsl/log.pxd +26 -0
  354. sage/libs/gsl/math.pxd +43 -0
  355. sage/libs/gsl/matrix.pxd +143 -0
  356. sage/libs/gsl/matrix_complex.pxd +130 -0
  357. sage/libs/gsl/min.pxd +67 -0
  358. sage/libs/gsl/monte.pxd +56 -0
  359. sage/libs/gsl/ntuple.pxd +32 -0
  360. sage/libs/gsl/odeiv.pxd +70 -0
  361. sage/libs/gsl/permutation.pxd +78 -0
  362. sage/libs/gsl/poly.pxd +40 -0
  363. sage/libs/gsl/pow_int.pxd +12 -0
  364. sage/libs/gsl/psi.pxd +28 -0
  365. sage/libs/gsl/qrng.pxd +29 -0
  366. sage/libs/gsl/random.pxd +257 -0
  367. sage/libs/gsl/rng.pxd +100 -0
  368. sage/libs/gsl/roots.pxd +72 -0
  369. sage/libs/gsl/sort.pxd +36 -0
  370. sage/libs/gsl/statistics.pxd +59 -0
  371. sage/libs/gsl/sum.pxd +55 -0
  372. sage/libs/gsl/synchrotron.pxd +16 -0
  373. sage/libs/gsl/transport.pxd +24 -0
  374. sage/libs/gsl/trig.pxd +58 -0
  375. sage/libs/gsl/types.pxd +137 -0
  376. sage/libs/gsl/vector.pxd +101 -0
  377. sage/libs/gsl/vector_complex.pxd +83 -0
  378. sage/libs/gsl/wavelet.pxd +49 -0
  379. sage/libs/gsl/zeta.pxd +28 -0
  380. sage/libs/mpc/__init__.pxd +114 -0
  381. sage/libs/mpc/types.pxd +28 -0
  382. sage/libs/mpfr/__init__.pxd +299 -0
  383. sage/libs/mpfr/types.pxd +26 -0
  384. sage/libs/mpmath/__init__.py +1 -0
  385. sage/libs/mpmath/all.py +27 -0
  386. sage/libs/mpmath/all__sagemath_modules.py +1 -0
  387. sage/libs/mpmath/utils.cpython-314-aarch64-linux-musl.so +0 -0
  388. sage/libs/mpmath/utils.pxd +4 -0
  389. sage/libs/mpmath/utils.pyx +319 -0
  390. sage/matrix/action.cpython-314-aarch64-linux-musl.so +0 -0
  391. sage/matrix/action.pxd +26 -0
  392. sage/matrix/action.pyx +596 -0
  393. sage/matrix/all.py +9 -0
  394. sage/matrix/args.cpython-314-aarch64-linux-musl.so +0 -0
  395. sage/matrix/args.pxd +144 -0
  396. sage/matrix/args.pyx +1668 -0
  397. sage/matrix/benchmark.py +1258 -0
  398. sage/matrix/berlekamp_massey.py +95 -0
  399. sage/matrix/compute_J_ideal.py +926 -0
  400. sage/matrix/constructor.cpython-314-aarch64-linux-musl.so +0 -0
  401. sage/matrix/constructor.pyx +750 -0
  402. sage/matrix/docs.py +430 -0
  403. sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
  404. sage/matrix/echelon_matrix.pyx +155 -0
  405. sage/matrix/matrix.pxd +2 -0
  406. sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
  407. sage/matrix/matrix0.pxd +68 -0
  408. sage/matrix/matrix0.pyx +6324 -0
  409. sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
  410. sage/matrix/matrix1.pxd +8 -0
  411. sage/matrix/matrix1.pyx +2851 -0
  412. sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
  413. sage/matrix/matrix2.pxd +25 -0
  414. sage/matrix/matrix2.pyx +20181 -0
  415. sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.so +0 -0
  416. sage/matrix/matrix_cdv.pxd +4 -0
  417. sage/matrix/matrix_cdv.pyx +93 -0
  418. sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  419. sage/matrix/matrix_complex_double_dense.pxd +5 -0
  420. sage/matrix/matrix_complex_double_dense.pyx +98 -0
  421. sage/matrix/matrix_dense.cpython-314-aarch64-linux-musl.so +0 -0
  422. sage/matrix/matrix_dense.pxd +5 -0
  423. sage/matrix/matrix_dense.pyx +343 -0
  424. sage/matrix/matrix_domain_dense.pxd +5 -0
  425. sage/matrix/matrix_domain_sparse.pxd +5 -0
  426. sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  427. sage/matrix/matrix_double_dense.pxd +7 -0
  428. sage/matrix/matrix_double_dense.pyx +3906 -0
  429. sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  430. sage/matrix/matrix_double_sparse.pxd +6 -0
  431. sage/matrix/matrix_double_sparse.pyx +248 -0
  432. sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-musl.so +0 -0
  433. sage/matrix/matrix_generic_dense.pxd +7 -0
  434. sage/matrix/matrix_generic_dense.pyx +354 -0
  435. sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  436. sage/matrix/matrix_generic_sparse.pxd +7 -0
  437. sage/matrix/matrix_generic_sparse.pyx +461 -0
  438. sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
  439. sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
  440. sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
  441. sage/matrix/matrix_misc.py +313 -0
  442. sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
  443. sage/matrix/matrix_numpy_dense.pxd +14 -0
  444. sage/matrix/matrix_numpy_dense.pyx +450 -0
  445. sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  446. sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
  447. sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
  448. sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
  449. sage/matrix/matrix_polynomial_dense.pxd +5 -0
  450. sage/matrix/matrix_polynomial_dense.pyx +5341 -0
  451. sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  452. sage/matrix/matrix_real_double_dense.pxd +7 -0
  453. sage/matrix/matrix_real_double_dense.pyx +122 -0
  454. sage/matrix/matrix_space.py +2848 -0
  455. sage/matrix/matrix_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  456. sage/matrix/matrix_sparse.pxd +5 -0
  457. sage/matrix/matrix_sparse.pyx +1222 -0
  458. sage/matrix/matrix_window.cpython-314-aarch64-linux-musl.so +0 -0
  459. sage/matrix/matrix_window.pxd +37 -0
  460. sage/matrix/matrix_window.pyx +242 -0
  461. sage/matrix/misc_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  462. sage/matrix/misc_mpfr.pyx +80 -0
  463. sage/matrix/operation_table.py +1182 -0
  464. sage/matrix/special.py +3666 -0
  465. sage/matrix/strassen.cpython-314-aarch64-linux-musl.so +0 -0
  466. sage/matrix/strassen.pyx +851 -0
  467. sage/matrix/symplectic_basis.py +541 -0
  468. sage/matrix/template.pxd +6 -0
  469. sage/matrix/tests.py +71 -0
  470. sage/matroids/advanced.py +77 -0
  471. sage/matroids/all.py +13 -0
  472. sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  473. sage/matroids/basis_exchange_matroid.pxd +96 -0
  474. sage/matroids/basis_exchange_matroid.pyx +2344 -0
  475. sage/matroids/basis_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  476. sage/matroids/basis_matroid.pxd +45 -0
  477. sage/matroids/basis_matroid.pyx +1217 -0
  478. sage/matroids/catalog.py +44 -0
  479. sage/matroids/chow_ring.py +473 -0
  480. sage/matroids/chow_ring_ideal.py +849 -0
  481. sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  482. sage/matroids/circuit_closures_matroid.pxd +16 -0
  483. sage/matroids/circuit_closures_matroid.pyx +559 -0
  484. sage/matroids/circuits_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  485. sage/matroids/circuits_matroid.pxd +38 -0
  486. sage/matroids/circuits_matroid.pyx +947 -0
  487. sage/matroids/constructor.py +1086 -0
  488. sage/matroids/database_collections.py +365 -0
  489. sage/matroids/database_matroids.py +5338 -0
  490. sage/matroids/dual_matroid.py +583 -0
  491. sage/matroids/extension.cpython-314-aarch64-linux-musl.so +0 -0
  492. sage/matroids/extension.pxd +34 -0
  493. sage/matroids/extension.pyx +519 -0
  494. sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  495. sage/matroids/flats_matroid.pxd +28 -0
  496. sage/matroids/flats_matroid.pyx +715 -0
  497. sage/matroids/gammoid.py +600 -0
  498. sage/matroids/graphic_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  499. sage/matroids/graphic_matroid.pxd +39 -0
  500. sage/matroids/graphic_matroid.pyx +2024 -0
  501. sage/matroids/lean_matrix.cpython-314-aarch64-linux-musl.so +0 -0
  502. sage/matroids/lean_matrix.pxd +126 -0
  503. sage/matroids/lean_matrix.pyx +3667 -0
  504. sage/matroids/linear_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  505. sage/matroids/linear_matroid.pxd +180 -0
  506. sage/matroids/linear_matroid.pyx +6649 -0
  507. sage/matroids/matroid.cpython-314-aarch64-linux-musl.so +0 -0
  508. sage/matroids/matroid.pxd +243 -0
  509. sage/matroids/matroid.pyx +8759 -0
  510. sage/matroids/matroids_catalog.py +190 -0
  511. sage/matroids/matroids_plot_helpers.py +890 -0
  512. sage/matroids/minor_matroid.py +480 -0
  513. sage/matroids/minorfix.h +9 -0
  514. sage/matroids/named_matroids.py +5 -0
  515. sage/matroids/rank_matroid.py +268 -0
  516. sage/matroids/set_system.cpython-314-aarch64-linux-musl.so +0 -0
  517. sage/matroids/set_system.pxd +38 -0
  518. sage/matroids/set_system.pyx +800 -0
  519. sage/matroids/transversal_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  520. sage/matroids/transversal_matroid.pxd +14 -0
  521. sage/matroids/transversal_matroid.pyx +893 -0
  522. sage/matroids/union_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  523. sage/matroids/union_matroid.pxd +20 -0
  524. sage/matroids/union_matroid.pyx +331 -0
  525. sage/matroids/unpickling.cpython-314-aarch64-linux-musl.so +0 -0
  526. sage/matroids/unpickling.pyx +843 -0
  527. sage/matroids/utilities.py +809 -0
  528. sage/misc/all__sagemath_modules.py +20 -0
  529. sage/misc/c3.cpython-314-aarch64-linux-musl.so +0 -0
  530. sage/misc/c3.pyx +238 -0
  531. sage/misc/compat.py +87 -0
  532. sage/misc/element_with_label.py +173 -0
  533. sage/misc/func_persist.py +79 -0
  534. sage/misc/pickle_old.cpython-314-aarch64-linux-musl.so +0 -0
  535. sage/misc/pickle_old.pyx +19 -0
  536. sage/misc/proof.py +7 -0
  537. sage/misc/replace_dot_all.py +472 -0
  538. sage/misc/sagedoc_conf.py +168 -0
  539. sage/misc/sphinxify.py +167 -0
  540. sage/misc/test_class_pickling.py +85 -0
  541. sage/modules/all.py +42 -0
  542. sage/modules/complex_double_vector.py +25 -0
  543. sage/modules/diamond_cutting.py +380 -0
  544. sage/modules/fg_pid/all.py +1 -0
  545. sage/modules/fg_pid/fgp_element.py +456 -0
  546. sage/modules/fg_pid/fgp_module.py +2091 -0
  547. sage/modules/fg_pid/fgp_morphism.py +550 -0
  548. sage/modules/filtered_vector_space.py +1271 -0
  549. sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-musl.so +0 -0
  550. sage/modules/finite_submodule_iter.pxd +27 -0
  551. sage/modules/finite_submodule_iter.pyx +452 -0
  552. sage/modules/fp_graded/all.py +1 -0
  553. sage/modules/fp_graded/element.py +346 -0
  554. sage/modules/fp_graded/free_element.py +298 -0
  555. sage/modules/fp_graded/free_homspace.py +53 -0
  556. sage/modules/fp_graded/free_module.py +1060 -0
  557. sage/modules/fp_graded/free_morphism.py +217 -0
  558. sage/modules/fp_graded/homspace.py +563 -0
  559. sage/modules/fp_graded/module.py +1340 -0
  560. sage/modules/fp_graded/morphism.py +1990 -0
  561. sage/modules/fp_graded/steenrod/all.py +1 -0
  562. sage/modules/fp_graded/steenrod/homspace.py +65 -0
  563. sage/modules/fp_graded/steenrod/module.py +477 -0
  564. sage/modules/fp_graded/steenrod/morphism.py +404 -0
  565. sage/modules/fp_graded/steenrod/profile.py +241 -0
  566. sage/modules/free_module.py +8447 -0
  567. sage/modules/free_module_element.cpython-314-aarch64-linux-musl.so +0 -0
  568. sage/modules/free_module_element.pxd +22 -0
  569. sage/modules/free_module_element.pyx +5445 -0
  570. sage/modules/free_module_homspace.py +369 -0
  571. sage/modules/free_module_integer.py +896 -0
  572. sage/modules/free_module_morphism.py +823 -0
  573. sage/modules/free_module_pseudohomspace.py +352 -0
  574. sage/modules/free_module_pseudomorphism.py +578 -0
  575. sage/modules/free_quadratic_module.py +1706 -0
  576. sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
  577. sage/modules/matrix_morphism.py +1745 -0
  578. sage/modules/misc.py +103 -0
  579. sage/modules/module_functors.py +192 -0
  580. sage/modules/multi_filtered_vector_space.py +719 -0
  581. sage/modules/ore_module.py +2208 -0
  582. sage/modules/ore_module_element.py +178 -0
  583. sage/modules/ore_module_homspace.py +147 -0
  584. sage/modules/ore_module_morphism.py +968 -0
  585. sage/modules/quotient_module.py +699 -0
  586. sage/modules/real_double_vector.py +22 -0
  587. sage/modules/submodule.py +255 -0
  588. sage/modules/tensor_operations.py +567 -0
  589. sage/modules/torsion_quadratic_module.py +1352 -0
  590. sage/modules/tutorial_free_modules.py +248 -0
  591. sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  592. sage/modules/vector_complex_double_dense.pxd +6 -0
  593. sage/modules/vector_complex_double_dense.pyx +117 -0
  594. sage/modules/vector_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  595. sage/modules/vector_double_dense.pxd +6 -0
  596. sage/modules/vector_double_dense.pyx +604 -0
  597. sage/modules/vector_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  598. sage/modules/vector_integer_dense.pxd +15 -0
  599. sage/modules/vector_integer_dense.pyx +361 -0
  600. sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  601. sage/modules/vector_integer_sparse.pxd +29 -0
  602. sage/modules/vector_integer_sparse.pyx +406 -0
  603. sage/modules/vector_modn_dense.cpython-314-aarch64-linux-musl.so +0 -0
  604. sage/modules/vector_modn_dense.pxd +12 -0
  605. sage/modules/vector_modn_dense.pyx +394 -0
  606. sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  607. sage/modules/vector_modn_sparse.pxd +21 -0
  608. sage/modules/vector_modn_sparse.pyx +298 -0
  609. sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
  610. sage/modules/vector_numpy_dense.pxd +15 -0
  611. sage/modules/vector_numpy_dense.pyx +304 -0
  612. sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  613. sage/modules/vector_numpy_integer_dense.pxd +7 -0
  614. sage/modules/vector_numpy_integer_dense.pyx +54 -0
  615. sage/modules/vector_rational_dense.cpython-314-aarch64-linux-musl.so +0 -0
  616. sage/modules/vector_rational_dense.pxd +15 -0
  617. sage/modules/vector_rational_dense.pyx +387 -0
  618. sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  619. sage/modules/vector_rational_sparse.pxd +30 -0
  620. sage/modules/vector_rational_sparse.pyx +413 -0
  621. sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  622. sage/modules/vector_real_double_dense.pxd +6 -0
  623. sage/modules/vector_real_double_dense.pyx +126 -0
  624. sage/modules/vector_space_homspace.py +430 -0
  625. sage/modules/vector_space_morphism.py +989 -0
  626. sage/modules/with_basis/all.py +15 -0
  627. sage/modules/with_basis/cell_module.py +494 -0
  628. sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-musl.so +0 -0
  629. sage/modules/with_basis/indexed_element.pxd +13 -0
  630. sage/modules/with_basis/indexed_element.pyx +1058 -0
  631. sage/modules/with_basis/invariant.py +1075 -0
  632. sage/modules/with_basis/morphism.py +1636 -0
  633. sage/modules/with_basis/representation.py +2939 -0
  634. sage/modules/with_basis/subquotient.py +685 -0
  635. sage/numerical/all__sagemath_modules.py +6 -0
  636. sage/numerical/gauss_legendre.cpython-314-aarch64-linux-musl.so +0 -0
  637. sage/numerical/gauss_legendre.pyx +381 -0
  638. sage/numerical/optimize.py +910 -0
  639. sage/probability/all.py +10 -0
  640. sage/probability/probability_distribution.cpython-314-aarch64-linux-musl.so +0 -0
  641. sage/probability/probability_distribution.pyx +1242 -0
  642. sage/probability/random_variable.py +411 -0
  643. sage/quadratic_forms/all.py +4 -0
  644. sage/quadratic_forms/all__sagemath_modules.py +15 -0
  645. sage/quadratic_forms/binary_qf.py +2042 -0
  646. sage/quadratic_forms/bqf_class_group.py +748 -0
  647. sage/quadratic_forms/constructions.py +93 -0
  648. sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-musl.so +0 -0
  649. sage/quadratic_forms/count_local_2.pyx +365 -0
  650. sage/quadratic_forms/extras.py +195 -0
  651. sage/quadratic_forms/quadratic_form.py +1753 -0
  652. sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
  653. sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
  654. sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-musl.so +0 -0
  655. sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
  656. sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
  657. sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
  658. sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
  659. sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
  660. sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
  661. sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
  662. sage/quadratic_forms/quadratic_form__theta.py +352 -0
  663. sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
  664. sage/quadratic_forms/random_quadraticform.py +209 -0
  665. sage/quadratic_forms/ternary.cpython-314-aarch64-linux-musl.so +0 -0
  666. sage/quadratic_forms/ternary.pyx +1154 -0
  667. sage/quadratic_forms/ternary_qf.py +2027 -0
  668. sage/rings/all__sagemath_modules.py +28 -0
  669. sage/rings/asymptotic/all__sagemath_modules.py +1 -0
  670. sage/rings/asymptotic/misc.py +1252 -0
  671. sage/rings/cc.py +4 -0
  672. sage/rings/cfinite_sequence.py +1306 -0
  673. sage/rings/complex_conversion.cpython-314-aarch64-linux-musl.so +0 -0
  674. sage/rings/complex_conversion.pxd +8 -0
  675. sage/rings/complex_conversion.pyx +23 -0
  676. sage/rings/complex_double.cpython-314-aarch64-linux-musl.so +0 -0
  677. sage/rings/complex_double.pxd +21 -0
  678. sage/rings/complex_double.pyx +2654 -0
  679. sage/rings/complex_mpc.cpython-314-aarch64-linux-musl.so +0 -0
  680. sage/rings/complex_mpc.pxd +21 -0
  681. sage/rings/complex_mpc.pyx +2576 -0
  682. sage/rings/complex_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  683. sage/rings/complex_mpfr.pxd +18 -0
  684. sage/rings/complex_mpfr.pyx +3602 -0
  685. sage/rings/derivation.py +2334 -0
  686. sage/rings/finite_rings/all__sagemath_modules.py +1 -0
  687. sage/rings/finite_rings/maps_finite_field.py +191 -0
  688. sage/rings/function_field/all__sagemath_modules.py +8 -0
  689. sage/rings/function_field/derivations.py +102 -0
  690. sage/rings/function_field/derivations_rational.py +132 -0
  691. sage/rings/function_field/differential.py +853 -0
  692. sage/rings/function_field/divisor.py +1107 -0
  693. sage/rings/function_field/drinfeld_modules/action.py +199 -0
  694. sage/rings/function_field/drinfeld_modules/all.py +1 -0
  695. sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
  696. sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
  697. sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
  698. sage/rings/function_field/drinfeld_modules/homset.py +420 -0
  699. sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
  700. sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-musl.so +0 -0
  701. sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
  702. sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.so +0 -0
  703. sage/rings/function_field/khuri_makdisi.pyx +935 -0
  704. sage/rings/invariants/all.py +4 -0
  705. sage/rings/invariants/invariant_theory.py +4597 -0
  706. sage/rings/invariants/reconstruction.py +395 -0
  707. sage/rings/polynomial/all__sagemath_modules.py +17 -0
  708. sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
  709. sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-musl.so +0 -0
  710. sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
  711. sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
  712. sage/rings/polynomial/ore_function_element.py +952 -0
  713. sage/rings/polynomial/ore_function_field.py +1028 -0
  714. sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
  715. sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
  716. sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
  717. sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
  718. sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-musl.so +0 -0
  719. sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
  720. sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
  721. sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
  722. sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
  723. sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
  724. sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-musl.so +0 -0
  725. sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
  726. sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
  727. sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-musl.so +0 -0
  728. sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
  729. sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
  730. sage/rings/polynomial/skew_polynomial_ring.py +908 -0
  731. sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-musl.so +0 -0
  732. sage/rings/real_double_element_gsl.pxd +8 -0
  733. sage/rings/real_double_element_gsl.pyx +794 -0
  734. sage/rings/real_field.py +58 -0
  735. sage/rings/real_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  736. sage/rings/real_mpfr.pxd +29 -0
  737. sage/rings/real_mpfr.pyx +6122 -0
  738. sage/rings/ring_extension.cpython-314-aarch64-linux-musl.so +0 -0
  739. sage/rings/ring_extension.pxd +42 -0
  740. sage/rings/ring_extension.pyx +2779 -0
  741. sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-musl.so +0 -0
  742. sage/rings/ring_extension_conversion.pxd +16 -0
  743. sage/rings/ring_extension_conversion.pyx +462 -0
  744. sage/rings/ring_extension_element.cpython-314-aarch64-linux-musl.so +0 -0
  745. sage/rings/ring_extension_element.pxd +21 -0
  746. sage/rings/ring_extension_element.pyx +1635 -0
  747. sage/rings/ring_extension_homset.py +64 -0
  748. sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-musl.so +0 -0
  749. sage/rings/ring_extension_morphism.pxd +35 -0
  750. sage/rings/ring_extension_morphism.pyx +920 -0
  751. sage/schemes/all__sagemath_modules.py +1 -0
  752. sage/schemes/projective/all__sagemath_modules.py +1 -0
  753. sage/schemes/projective/coherent_sheaf.py +300 -0
  754. sage/schemes/projective/cohomology.py +510 -0
  755. sage/stats/all.py +15 -0
  756. sage/stats/basic_stats.py +489 -0
  757. sage/stats/distributions/all.py +7 -0
  758. sage/stats/distributions/catalog.py +34 -0
  759. sage/stats/distributions/dgs.h +50 -0
  760. sage/stats/distributions/dgs.pxd +111 -0
  761. sage/stats/distributions/dgs_bern.h +400 -0
  762. sage/stats/distributions/dgs_gauss.h +614 -0
  763. sage/stats/distributions/dgs_misc.h +104 -0
  764. sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-musl.so +0 -0
  765. sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
  766. sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
  767. sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
  768. sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
  769. sage/stats/hmm/all.py +15 -0
  770. sage/stats/hmm/chmm.cpython-314-aarch64-linux-musl.so +0 -0
  771. sage/stats/hmm/chmm.pyx +1595 -0
  772. sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.so +0 -0
  773. sage/stats/hmm/distributions.pxd +29 -0
  774. sage/stats/hmm/distributions.pyx +531 -0
  775. sage/stats/hmm/hmm.cpython-314-aarch64-linux-musl.so +0 -0
  776. sage/stats/hmm/hmm.pxd +17 -0
  777. sage/stats/hmm/hmm.pyx +1388 -0
  778. sage/stats/hmm/util.cpython-314-aarch64-linux-musl.so +0 -0
  779. sage/stats/hmm/util.pxd +7 -0
  780. sage/stats/hmm/util.pyx +165 -0
  781. sage/stats/intlist.cpython-314-aarch64-linux-musl.so +0 -0
  782. sage/stats/intlist.pxd +14 -0
  783. sage/stats/intlist.pyx +588 -0
  784. sage/stats/r.py +49 -0
  785. sage/stats/time_series.cpython-314-aarch64-linux-musl.so +0 -0
  786. sage/stats/time_series.pxd +6 -0
  787. sage/stats/time_series.pyx +2546 -0
  788. sage/tensor/all.py +2 -0
  789. sage/tensor/modules/all.py +8 -0
  790. sage/tensor/modules/alternating_contr_tensor.py +761 -0
  791. sage/tensor/modules/comp.py +5598 -0
  792. sage/tensor/modules/ext_pow_free_module.py +824 -0
  793. sage/tensor/modules/finite_rank_free_module.py +3589 -0
  794. sage/tensor/modules/format_utilities.py +333 -0
  795. sage/tensor/modules/free_module_alt_form.py +858 -0
  796. sage/tensor/modules/free_module_automorphism.py +1207 -0
  797. sage/tensor/modules/free_module_basis.py +1074 -0
  798. sage/tensor/modules/free_module_element.py +284 -0
  799. sage/tensor/modules/free_module_homset.py +652 -0
  800. sage/tensor/modules/free_module_linear_group.py +564 -0
  801. sage/tensor/modules/free_module_morphism.py +1581 -0
  802. sage/tensor/modules/free_module_tensor.py +3289 -0
  803. sage/tensor/modules/reflexive_module.py +386 -0
  804. sage/tensor/modules/tensor_free_module.py +780 -0
  805. sage/tensor/modules/tensor_free_submodule.py +538 -0
  806. sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
  807. 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)