passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-modules might be problematic. Click here for more details.

Files changed (808) hide show
  1. passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
  2. passagemath_modules-10.6.31rc3.dist-info/RECORD +808 -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-0cd532bd.so.1 +0 -0
  6. passagemath_modules.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
  7. passagemath_modules.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  8. passagemath_modules.libs/libgsl-42cda06f.so.28.0.0 +0 -0
  9. passagemath_modules.libs/libmpc-d8ebe4b5.so.3.3.1 +0 -0
  10. passagemath_modules.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
  11. passagemath_modules.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
  12. passagemath_modules.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
  13. sage/algebras/all__sagemath_modules.py +20 -0
  14. sage/algebras/catalog.py +148 -0
  15. sage/algebras/clifford_algebra.py +3107 -0
  16. sage/algebras/clifford_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  17. sage/algebras/clifford_algebra_element.pxd +16 -0
  18. sage/algebras/clifford_algebra_element.pyx +997 -0
  19. sage/algebras/commutative_dga.py +4252 -0
  20. sage/algebras/exterior_algebra_groebner.cpython-314-x86_64-linux-musl.so +0 -0
  21. sage/algebras/exterior_algebra_groebner.pxd +55 -0
  22. sage/algebras/exterior_algebra_groebner.pyx +727 -0
  23. sage/algebras/finite_dimensional_algebras/all.py +2 -0
  24. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
  25. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  26. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
  27. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
  28. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
  29. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
  30. sage/algebras/finite_gca.py +528 -0
  31. sage/algebras/group_algebra.py +232 -0
  32. sage/algebras/lie_algebras/abelian.py +197 -0
  33. sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
  34. sage/algebras/lie_algebras/all.py +25 -0
  35. sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
  36. sage/algebras/lie_algebras/bch.py +177 -0
  37. sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
  38. sage/algebras/lie_algebras/bgg_resolution.py +232 -0
  39. sage/algebras/lie_algebras/center_uea.py +767 -0
  40. sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
  41. sage/algebras/lie_algebras/examples.py +683 -0
  42. sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
  43. sage/algebras/lie_algebras/heisenberg.py +820 -0
  44. sage/algebras/lie_algebras/lie_algebra.py +1562 -0
  45. sage/algebras/lie_algebras/lie_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  46. sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
  47. sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
  48. sage/algebras/lie_algebras/morphism.py +661 -0
  49. sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
  50. sage/algebras/lie_algebras/onsager.py +1324 -0
  51. sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
  52. sage/algebras/lie_algebras/quotient.py +462 -0
  53. sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
  54. sage/algebras/lie_algebras/representation.py +1040 -0
  55. sage/algebras/lie_algebras/structure_coefficients.py +459 -0
  56. sage/algebras/lie_algebras/subalgebra.py +967 -0
  57. sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
  58. sage/algebras/lie_algebras/verma_module.py +1630 -0
  59. sage/algebras/lie_algebras/virasoro.py +1186 -0
  60. sage/algebras/octonion_algebra.cpython-314-x86_64-linux-musl.so +0 -0
  61. sage/algebras/octonion_algebra.pxd +20 -0
  62. sage/algebras/octonion_algebra.pyx +987 -0
  63. sage/algebras/orlik_solomon.py +907 -0
  64. sage/algebras/orlik_terao.py +779 -0
  65. sage/algebras/steenrod/all.py +7 -0
  66. sage/algebras/steenrod/steenrod_algebra.py +4258 -0
  67. sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
  68. sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
  69. sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
  70. sage/algebras/weyl_algebra.py +1126 -0
  71. sage/all__sagemath_modules.py +62 -0
  72. sage/calculus/all__sagemath_modules.py +19 -0
  73. sage/calculus/expr.py +205 -0
  74. sage/calculus/integration.cpython-314-x86_64-linux-musl.so +0 -0
  75. sage/calculus/integration.pyx +698 -0
  76. sage/calculus/interpolation.cpython-314-x86_64-linux-musl.so +0 -0
  77. sage/calculus/interpolation.pxd +13 -0
  78. sage/calculus/interpolation.pyx +387 -0
  79. sage/calculus/interpolators.cpython-314-x86_64-linux-musl.so +0 -0
  80. sage/calculus/interpolators.pyx +326 -0
  81. sage/calculus/ode.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/calculus/ode.pxd +5 -0
  83. sage/calculus/ode.pyx +610 -0
  84. sage/calculus/riemann.cpython-314-x86_64-linux-musl.so +0 -0
  85. sage/calculus/riemann.pyx +1521 -0
  86. sage/calculus/test_sympy.py +201 -0
  87. sage/calculus/transforms/all.py +7 -0
  88. sage/calculus/transforms/dft.py +844 -0
  89. sage/calculus/transforms/dwt.cpython-314-x86_64-linux-musl.so +0 -0
  90. sage/calculus/transforms/dwt.pxd +7 -0
  91. sage/calculus/transforms/dwt.pyx +160 -0
  92. sage/calculus/transforms/fft.cpython-314-x86_64-linux-musl.so +0 -0
  93. sage/calculus/transforms/fft.pxd +12 -0
  94. sage/calculus/transforms/fft.pyx +487 -0
  95. sage/calculus/wester.py +662 -0
  96. sage/coding/abstract_code.py +1108 -0
  97. sage/coding/ag_code.py +868 -0
  98. sage/coding/ag_code_decoders.cpython-314-x86_64-linux-musl.so +0 -0
  99. sage/coding/ag_code_decoders.pyx +2639 -0
  100. sage/coding/all.py +15 -0
  101. sage/coding/bch_code.py +494 -0
  102. sage/coding/binary_code.cpython-314-x86_64-linux-musl.so +0 -0
  103. sage/coding/binary_code.pxd +124 -0
  104. sage/coding/binary_code.pyx +4139 -0
  105. sage/coding/bounds_catalog.py +43 -0
  106. sage/coding/channel.py +819 -0
  107. sage/coding/channels_catalog.py +29 -0
  108. sage/coding/code_bounds.py +755 -0
  109. sage/coding/code_constructions.py +804 -0
  110. sage/coding/codes_catalog.py +111 -0
  111. sage/coding/cyclic_code.py +1329 -0
  112. sage/coding/databases.py +316 -0
  113. sage/coding/decoder.py +373 -0
  114. sage/coding/decoders_catalog.py +88 -0
  115. sage/coding/delsarte_bounds.py +709 -0
  116. sage/coding/encoder.py +390 -0
  117. sage/coding/encoders_catalog.py +64 -0
  118. sage/coding/extended_code.py +468 -0
  119. sage/coding/gabidulin_code.py +1058 -0
  120. sage/coding/golay_code.py +404 -0
  121. sage/coding/goppa_code.py +441 -0
  122. sage/coding/grs_code.py +2371 -0
  123. sage/coding/guava.py +107 -0
  124. sage/coding/guruswami_sudan/all.py +1 -0
  125. sage/coding/guruswami_sudan/gs_decoder.py +897 -0
  126. sage/coding/guruswami_sudan/interpolation.py +409 -0
  127. sage/coding/guruswami_sudan/utils.py +176 -0
  128. sage/coding/hamming_code.py +176 -0
  129. sage/coding/information_set_decoder.py +1032 -0
  130. sage/coding/kasami_codes.cpython-314-x86_64-linux-musl.so +0 -0
  131. sage/coding/kasami_codes.pyx +351 -0
  132. sage/coding/linear_code.py +3067 -0
  133. sage/coding/linear_code_no_metric.py +1354 -0
  134. sage/coding/linear_rank_metric.py +961 -0
  135. sage/coding/parity_check_code.py +353 -0
  136. sage/coding/punctured_code.py +719 -0
  137. sage/coding/reed_muller_code.py +999 -0
  138. sage/coding/self_dual_codes.py +942 -0
  139. sage/coding/source_coding/all.py +2 -0
  140. sage/coding/source_coding/huffman.py +553 -0
  141. sage/coding/subfield_subcode.py +423 -0
  142. sage/coding/two_weight_db.py +399 -0
  143. sage/combinat/all__sagemath_modules.py +7 -0
  144. sage/combinat/cartesian_product.py +347 -0
  145. sage/combinat/family.py +11 -0
  146. sage/combinat/free_module.py +1977 -0
  147. sage/combinat/root_system/all.py +147 -0
  148. sage/combinat/root_system/ambient_space.py +527 -0
  149. sage/combinat/root_system/associahedron.py +471 -0
  150. sage/combinat/root_system/braid_move_calculator.py +143 -0
  151. sage/combinat/root_system/braid_orbit.cpython-314-x86_64-linux-musl.so +0 -0
  152. sage/combinat/root_system/braid_orbit.pyx +144 -0
  153. sage/combinat/root_system/branching_rules.py +2301 -0
  154. sage/combinat/root_system/cartan_matrix.py +1245 -0
  155. sage/combinat/root_system/cartan_type.py +3069 -0
  156. sage/combinat/root_system/coxeter_group.py +162 -0
  157. sage/combinat/root_system/coxeter_matrix.py +1261 -0
  158. sage/combinat/root_system/coxeter_type.py +681 -0
  159. sage/combinat/root_system/dynkin_diagram.py +900 -0
  160. sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
  161. sage/combinat/root_system/fundamental_group.py +795 -0
  162. sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
  163. sage/combinat/root_system/integrable_representations.py +1227 -0
  164. sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
  165. sage/combinat/root_system/pieri_factors.py +1147 -0
  166. sage/combinat/root_system/plot.py +1615 -0
  167. sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
  168. sage/combinat/root_system/root_lattice_realizations.py +4628 -0
  169. sage/combinat/root_system/root_space.py +487 -0
  170. sage/combinat/root_system/root_system.py +882 -0
  171. sage/combinat/root_system/type_A.py +348 -0
  172. sage/combinat/root_system/type_A_affine.py +227 -0
  173. sage/combinat/root_system/type_A_infinity.py +241 -0
  174. sage/combinat/root_system/type_B.py +347 -0
  175. sage/combinat/root_system/type_BC_affine.py +287 -0
  176. sage/combinat/root_system/type_B_affine.py +216 -0
  177. sage/combinat/root_system/type_C.py +317 -0
  178. sage/combinat/root_system/type_C_affine.py +188 -0
  179. sage/combinat/root_system/type_D.py +357 -0
  180. sage/combinat/root_system/type_D_affine.py +208 -0
  181. sage/combinat/root_system/type_E.py +641 -0
  182. sage/combinat/root_system/type_E_affine.py +231 -0
  183. sage/combinat/root_system/type_F.py +387 -0
  184. sage/combinat/root_system/type_F_affine.py +137 -0
  185. sage/combinat/root_system/type_G.py +293 -0
  186. sage/combinat/root_system/type_G_affine.py +132 -0
  187. sage/combinat/root_system/type_H.py +105 -0
  188. sage/combinat/root_system/type_I.py +110 -0
  189. sage/combinat/root_system/type_Q.py +150 -0
  190. sage/combinat/root_system/type_affine.py +509 -0
  191. sage/combinat/root_system/type_dual.py +704 -0
  192. sage/combinat/root_system/type_folded.py +301 -0
  193. sage/combinat/root_system/type_marked.py +748 -0
  194. sage/combinat/root_system/type_reducible.py +601 -0
  195. sage/combinat/root_system/type_relabel.py +730 -0
  196. sage/combinat/root_system/type_super_A.py +837 -0
  197. sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
  198. sage/combinat/root_system/weight_space.py +639 -0
  199. sage/combinat/root_system/weyl_characters.py +2238 -0
  200. sage/crypto/__init__.py +4 -0
  201. sage/crypto/all.py +28 -0
  202. sage/crypto/block_cipher/all.py +7 -0
  203. sage/crypto/block_cipher/des.py +1065 -0
  204. sage/crypto/block_cipher/miniaes.py +2171 -0
  205. sage/crypto/block_cipher/present.py +909 -0
  206. sage/crypto/block_cipher/sdes.py +1527 -0
  207. sage/crypto/boolean_function.cpython-314-x86_64-linux-musl.so +0 -0
  208. sage/crypto/boolean_function.pxd +10 -0
  209. sage/crypto/boolean_function.pyx +1487 -0
  210. sage/crypto/cipher.py +78 -0
  211. sage/crypto/classical.py +3668 -0
  212. sage/crypto/classical_cipher.py +569 -0
  213. sage/crypto/cryptosystem.py +387 -0
  214. sage/crypto/key_exchange/all.py +7 -0
  215. sage/crypto/key_exchange/catalog.py +24 -0
  216. sage/crypto/key_exchange/diffie_hellman.py +323 -0
  217. sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
  218. sage/crypto/lattice.py +312 -0
  219. sage/crypto/lfsr.py +295 -0
  220. sage/crypto/lwe.py +840 -0
  221. sage/crypto/mq/__init__.py +4 -0
  222. sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
  223. sage/crypto/mq/rijndael_gf.py +2345 -0
  224. sage/crypto/mq/sbox.py +7 -0
  225. sage/crypto/mq/sr.py +3344 -0
  226. sage/crypto/public_key/all.py +5 -0
  227. sage/crypto/public_key/blum_goldwasser.py +776 -0
  228. sage/crypto/sbox.cpython-314-x86_64-linux-musl.so +0 -0
  229. sage/crypto/sbox.pyx +2090 -0
  230. sage/crypto/sboxes.py +2090 -0
  231. sage/crypto/stream.py +390 -0
  232. sage/crypto/stream_cipher.py +297 -0
  233. sage/crypto/util.py +519 -0
  234. sage/ext/all__sagemath_modules.py +1 -0
  235. sage/ext/interpreters/__init__.py +1 -0
  236. sage/ext/interpreters/all__sagemath_modules.py +2 -0
  237. sage/ext/interpreters/wrapper_cc.cpython-314-x86_64-linux-musl.so +0 -0
  238. sage/ext/interpreters/wrapper_cc.pxd +30 -0
  239. sage/ext/interpreters/wrapper_cc.pyx +252 -0
  240. sage/ext/interpreters/wrapper_cdf.cpython-314-x86_64-linux-musl.so +0 -0
  241. sage/ext/interpreters/wrapper_cdf.pxd +26 -0
  242. sage/ext/interpreters/wrapper_cdf.pyx +245 -0
  243. sage/ext/interpreters/wrapper_rdf.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/ext/interpreters/wrapper_rdf.pxd +23 -0
  245. sage/ext/interpreters/wrapper_rdf.pyx +221 -0
  246. sage/ext/interpreters/wrapper_rr.cpython-314-x86_64-linux-musl.so +0 -0
  247. sage/ext/interpreters/wrapper_rr.pxd +28 -0
  248. sage/ext/interpreters/wrapper_rr.pyx +335 -0
  249. sage/geometry/all__sagemath_modules.py +5 -0
  250. sage/geometry/toric_lattice.py +1745 -0
  251. sage/geometry/toric_lattice_element.cpython-314-x86_64-linux-musl.so +0 -0
  252. sage/geometry/toric_lattice_element.pyx +432 -0
  253. sage/groups/abelian_gps/abelian_group.py +1925 -0
  254. sage/groups/abelian_gps/abelian_group_element.py +164 -0
  255. sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
  256. sage/groups/abelian_gps/dual_abelian_group.py +421 -0
  257. sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
  258. sage/groups/abelian_gps/element_base.py +341 -0
  259. sage/groups/abelian_gps/values.py +488 -0
  260. sage/groups/additive_abelian/additive_abelian_group.py +476 -0
  261. sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
  262. sage/groups/additive_abelian/all.py +4 -0
  263. sage/groups/additive_abelian/qmodnz.py +231 -0
  264. sage/groups/additive_abelian/qmodnz_element.py +349 -0
  265. sage/groups/affine_gps/affine_group.py +535 -0
  266. sage/groups/affine_gps/all.py +1 -0
  267. sage/groups/affine_gps/catalog.py +17 -0
  268. sage/groups/affine_gps/euclidean_group.py +246 -0
  269. sage/groups/affine_gps/group_element.py +562 -0
  270. sage/groups/all__sagemath_modules.py +12 -0
  271. sage/groups/galois_group.py +479 -0
  272. sage/groups/matrix_gps/all.py +4 -0
  273. sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
  274. sage/groups/matrix_gps/catalog.py +26 -0
  275. sage/groups/matrix_gps/coxeter_group.py +927 -0
  276. sage/groups/matrix_gps/finitely_generated.py +487 -0
  277. sage/groups/matrix_gps/group_element.cpython-314-x86_64-linux-musl.so +0 -0
  278. sage/groups/matrix_gps/group_element.pxd +11 -0
  279. sage/groups/matrix_gps/group_element.pyx +431 -0
  280. sage/groups/matrix_gps/linear.py +440 -0
  281. sage/groups/matrix_gps/matrix_group.py +617 -0
  282. sage/groups/matrix_gps/named_group.py +296 -0
  283. sage/groups/matrix_gps/orthogonal.py +544 -0
  284. sage/groups/matrix_gps/symplectic.py +251 -0
  285. sage/groups/matrix_gps/unitary.py +436 -0
  286. sage/groups/misc_gps/all__sagemath_modules.py +1 -0
  287. sage/groups/misc_gps/argument_groups.py +1905 -0
  288. sage/groups/misc_gps/imaginary_groups.py +479 -0
  289. sage/groups/perm_gps/all__sagemath_modules.py +1 -0
  290. sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
  291. sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-x86_64-linux-musl.so +0 -0
  292. sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
  293. sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
  294. sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-x86_64-linux-musl.so +0 -0
  295. sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
  296. sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
  297. sage/homology/algebraic_topological_model.py +595 -0
  298. sage/homology/all.py +2 -0
  299. sage/homology/all__sagemath_modules.py +8 -0
  300. sage/homology/chain_complex.py +2148 -0
  301. sage/homology/chain_complex_homspace.py +165 -0
  302. sage/homology/chain_complex_morphism.py +629 -0
  303. sage/homology/chain_homotopy.py +604 -0
  304. sage/homology/chains.py +653 -0
  305. sage/homology/free_resolution.py +923 -0
  306. sage/homology/graded_resolution.py +567 -0
  307. sage/homology/hochschild_complex.py +756 -0
  308. sage/homology/homology_group.py +188 -0
  309. sage/homology/homology_morphism.py +422 -0
  310. sage/homology/homology_vector_space_with_basis.py +1454 -0
  311. sage/homology/koszul_complex.py +169 -0
  312. sage/homology/matrix_utils.py +205 -0
  313. sage/libs/all__sagemath_modules.py +1 -0
  314. sage/libs/gsl/__init__.py +1 -0
  315. sage/libs/gsl/airy.pxd +56 -0
  316. sage/libs/gsl/all.pxd +66 -0
  317. sage/libs/gsl/array.cpython-314-x86_64-linux-musl.so +0 -0
  318. sage/libs/gsl/array.pxd +5 -0
  319. sage/libs/gsl/array.pyx +102 -0
  320. sage/libs/gsl/bessel.pxd +208 -0
  321. sage/libs/gsl/blas.pxd +116 -0
  322. sage/libs/gsl/blas_types.pxd +34 -0
  323. sage/libs/gsl/block.pxd +52 -0
  324. sage/libs/gsl/chebyshev.pxd +37 -0
  325. sage/libs/gsl/clausen.pxd +12 -0
  326. sage/libs/gsl/combination.pxd +47 -0
  327. sage/libs/gsl/complex.pxd +151 -0
  328. sage/libs/gsl/coulomb.pxd +30 -0
  329. sage/libs/gsl/coupling.pxd +21 -0
  330. sage/libs/gsl/dawson.pxd +12 -0
  331. sage/libs/gsl/debye.pxd +24 -0
  332. sage/libs/gsl/dilog.pxd +14 -0
  333. sage/libs/gsl/eigen.pxd +46 -0
  334. sage/libs/gsl/elementary.pxd +12 -0
  335. sage/libs/gsl/ellint.pxd +48 -0
  336. sage/libs/gsl/elljac.pxd +8 -0
  337. sage/libs/gsl/erf.pxd +32 -0
  338. sage/libs/gsl/errno.pxd +26 -0
  339. sage/libs/gsl/exp.pxd +44 -0
  340. sage/libs/gsl/expint.pxd +44 -0
  341. sage/libs/gsl/fermi_dirac.pxd +44 -0
  342. sage/libs/gsl/fft.pxd +121 -0
  343. sage/libs/gsl/fit.pxd +50 -0
  344. sage/libs/gsl/gamma.pxd +94 -0
  345. sage/libs/gsl/gegenbauer.pxd +26 -0
  346. sage/libs/gsl/histogram.pxd +176 -0
  347. sage/libs/gsl/hyperg.pxd +52 -0
  348. sage/libs/gsl/integration.pxd +69 -0
  349. sage/libs/gsl/interp.pxd +109 -0
  350. sage/libs/gsl/laguerre.pxd +24 -0
  351. sage/libs/gsl/lambert.pxd +16 -0
  352. sage/libs/gsl/legendre.pxd +90 -0
  353. sage/libs/gsl/linalg.pxd +185 -0
  354. sage/libs/gsl/log.pxd +26 -0
  355. sage/libs/gsl/math.pxd +43 -0
  356. sage/libs/gsl/matrix.pxd +143 -0
  357. sage/libs/gsl/matrix_complex.pxd +130 -0
  358. sage/libs/gsl/min.pxd +67 -0
  359. sage/libs/gsl/monte.pxd +56 -0
  360. sage/libs/gsl/ntuple.pxd +32 -0
  361. sage/libs/gsl/odeiv.pxd +70 -0
  362. sage/libs/gsl/permutation.pxd +78 -0
  363. sage/libs/gsl/poly.pxd +40 -0
  364. sage/libs/gsl/pow_int.pxd +12 -0
  365. sage/libs/gsl/psi.pxd +28 -0
  366. sage/libs/gsl/qrng.pxd +29 -0
  367. sage/libs/gsl/random.pxd +257 -0
  368. sage/libs/gsl/rng.pxd +100 -0
  369. sage/libs/gsl/roots.pxd +72 -0
  370. sage/libs/gsl/sort.pxd +36 -0
  371. sage/libs/gsl/statistics.pxd +59 -0
  372. sage/libs/gsl/sum.pxd +55 -0
  373. sage/libs/gsl/synchrotron.pxd +16 -0
  374. sage/libs/gsl/transport.pxd +24 -0
  375. sage/libs/gsl/trig.pxd +58 -0
  376. sage/libs/gsl/types.pxd +137 -0
  377. sage/libs/gsl/vector.pxd +101 -0
  378. sage/libs/gsl/vector_complex.pxd +83 -0
  379. sage/libs/gsl/wavelet.pxd +49 -0
  380. sage/libs/gsl/zeta.pxd +28 -0
  381. sage/libs/mpc/__init__.pxd +114 -0
  382. sage/libs/mpc/types.pxd +28 -0
  383. sage/libs/mpfr/__init__.pxd +299 -0
  384. sage/libs/mpfr/types.pxd +26 -0
  385. sage/libs/mpmath/__init__.py +1 -0
  386. sage/libs/mpmath/all.py +27 -0
  387. sage/libs/mpmath/all__sagemath_modules.py +1 -0
  388. sage/libs/mpmath/utils.cpython-314-x86_64-linux-musl.so +0 -0
  389. sage/libs/mpmath/utils.pxd +4 -0
  390. sage/libs/mpmath/utils.pyx +319 -0
  391. sage/matrix/action.cpython-314-x86_64-linux-musl.so +0 -0
  392. sage/matrix/action.pxd +26 -0
  393. sage/matrix/action.pyx +596 -0
  394. sage/matrix/all.py +9 -0
  395. sage/matrix/args.cpython-314-x86_64-linux-musl.so +0 -0
  396. sage/matrix/args.pxd +144 -0
  397. sage/matrix/args.pyx +1668 -0
  398. sage/matrix/benchmark.py +1258 -0
  399. sage/matrix/berlekamp_massey.py +95 -0
  400. sage/matrix/compute_J_ideal.py +926 -0
  401. sage/matrix/constructor.cpython-314-x86_64-linux-musl.so +0 -0
  402. sage/matrix/constructor.pyx +750 -0
  403. sage/matrix/docs.py +430 -0
  404. sage/matrix/echelon_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  405. sage/matrix/echelon_matrix.pyx +155 -0
  406. sage/matrix/matrix.pxd +2 -0
  407. sage/matrix/matrix0.cpython-314-x86_64-linux-musl.so +0 -0
  408. sage/matrix/matrix0.pxd +68 -0
  409. sage/matrix/matrix0.pyx +6324 -0
  410. sage/matrix/matrix1.cpython-314-x86_64-linux-musl.so +0 -0
  411. sage/matrix/matrix1.pxd +8 -0
  412. sage/matrix/matrix1.pyx +2851 -0
  413. sage/matrix/matrix2.cpython-314-x86_64-linux-musl.so +0 -0
  414. sage/matrix/matrix2.pxd +25 -0
  415. sage/matrix/matrix2.pyx +20181 -0
  416. sage/matrix/matrix_cdv.cpython-314-x86_64-linux-musl.so +0 -0
  417. sage/matrix/matrix_cdv.pxd +4 -0
  418. sage/matrix/matrix_cdv.pyx +93 -0
  419. sage/matrix/matrix_complex_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  420. sage/matrix/matrix_complex_double_dense.pxd +5 -0
  421. sage/matrix/matrix_complex_double_dense.pyx +98 -0
  422. sage/matrix/matrix_dense.cpython-314-x86_64-linux-musl.so +0 -0
  423. sage/matrix/matrix_dense.pxd +5 -0
  424. sage/matrix/matrix_dense.pyx +343 -0
  425. sage/matrix/matrix_domain_dense.pxd +5 -0
  426. sage/matrix/matrix_domain_sparse.pxd +5 -0
  427. sage/matrix/matrix_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  428. sage/matrix/matrix_double_dense.pxd +7 -0
  429. sage/matrix/matrix_double_dense.pyx +3906 -0
  430. sage/matrix/matrix_double_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  431. sage/matrix/matrix_double_sparse.pxd +6 -0
  432. sage/matrix/matrix_double_sparse.pyx +248 -0
  433. sage/matrix/matrix_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
  434. sage/matrix/matrix_generic_dense.pxd +7 -0
  435. sage/matrix/matrix_generic_dense.pyx +354 -0
  436. sage/matrix/matrix_generic_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  437. sage/matrix/matrix_generic_sparse.pxd +7 -0
  438. sage/matrix/matrix_generic_sparse.pyx +461 -0
  439. sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-x86_64-linux-musl.so +0 -0
  440. sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
  441. sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
  442. sage/matrix/matrix_misc.py +313 -0
  443. sage/matrix/matrix_numpy_dense.cpython-314-x86_64-linux-musl.so +0 -0
  444. sage/matrix/matrix_numpy_dense.pxd +14 -0
  445. sage/matrix/matrix_numpy_dense.pyx +450 -0
  446. sage/matrix/matrix_numpy_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  447. sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
  448. sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
  449. sage/matrix/matrix_polynomial_dense.cpython-314-x86_64-linux-musl.so +0 -0
  450. sage/matrix/matrix_polynomial_dense.pxd +5 -0
  451. sage/matrix/matrix_polynomial_dense.pyx +5341 -0
  452. sage/matrix/matrix_real_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  453. sage/matrix/matrix_real_double_dense.pxd +7 -0
  454. sage/matrix/matrix_real_double_dense.pyx +122 -0
  455. sage/matrix/matrix_space.py +2848 -0
  456. sage/matrix/matrix_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  457. sage/matrix/matrix_sparse.pxd +5 -0
  458. sage/matrix/matrix_sparse.pyx +1222 -0
  459. sage/matrix/matrix_window.cpython-314-x86_64-linux-musl.so +0 -0
  460. sage/matrix/matrix_window.pxd +37 -0
  461. sage/matrix/matrix_window.pyx +242 -0
  462. sage/matrix/misc_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  463. sage/matrix/misc_mpfr.pyx +80 -0
  464. sage/matrix/operation_table.py +1182 -0
  465. sage/matrix/special.py +3666 -0
  466. sage/matrix/strassen.cpython-314-x86_64-linux-musl.so +0 -0
  467. sage/matrix/strassen.pyx +851 -0
  468. sage/matrix/symplectic_basis.py +541 -0
  469. sage/matrix/template.pxd +6 -0
  470. sage/matrix/tests.py +71 -0
  471. sage/matroids/advanced.py +77 -0
  472. sage/matroids/all.py +13 -0
  473. sage/matroids/basis_exchange_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  474. sage/matroids/basis_exchange_matroid.pxd +96 -0
  475. sage/matroids/basis_exchange_matroid.pyx +2344 -0
  476. sage/matroids/basis_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  477. sage/matroids/basis_matroid.pxd +45 -0
  478. sage/matroids/basis_matroid.pyx +1217 -0
  479. sage/matroids/catalog.py +44 -0
  480. sage/matroids/chow_ring.py +473 -0
  481. sage/matroids/chow_ring_ideal.py +849 -0
  482. sage/matroids/circuit_closures_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  483. sage/matroids/circuit_closures_matroid.pxd +16 -0
  484. sage/matroids/circuit_closures_matroid.pyx +559 -0
  485. sage/matroids/circuits_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  486. sage/matroids/circuits_matroid.pxd +38 -0
  487. sage/matroids/circuits_matroid.pyx +947 -0
  488. sage/matroids/constructor.py +1086 -0
  489. sage/matroids/database_collections.py +365 -0
  490. sage/matroids/database_matroids.py +5338 -0
  491. sage/matroids/dual_matroid.py +583 -0
  492. sage/matroids/extension.cpython-314-x86_64-linux-musl.so +0 -0
  493. sage/matroids/extension.pxd +34 -0
  494. sage/matroids/extension.pyx +519 -0
  495. sage/matroids/flats_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  496. sage/matroids/flats_matroid.pxd +28 -0
  497. sage/matroids/flats_matroid.pyx +715 -0
  498. sage/matroids/gammoid.py +600 -0
  499. sage/matroids/graphic_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  500. sage/matroids/graphic_matroid.pxd +39 -0
  501. sage/matroids/graphic_matroid.pyx +2024 -0
  502. sage/matroids/lean_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  503. sage/matroids/lean_matrix.pxd +126 -0
  504. sage/matroids/lean_matrix.pyx +3667 -0
  505. sage/matroids/linear_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  506. sage/matroids/linear_matroid.pxd +180 -0
  507. sage/matroids/linear_matroid.pyx +6649 -0
  508. sage/matroids/matroid.cpython-314-x86_64-linux-musl.so +0 -0
  509. sage/matroids/matroid.pxd +243 -0
  510. sage/matroids/matroid.pyx +8759 -0
  511. sage/matroids/matroids_catalog.py +190 -0
  512. sage/matroids/matroids_plot_helpers.py +890 -0
  513. sage/matroids/minor_matroid.py +480 -0
  514. sage/matroids/minorfix.h +9 -0
  515. sage/matroids/named_matroids.py +5 -0
  516. sage/matroids/rank_matroid.py +268 -0
  517. sage/matroids/set_system.cpython-314-x86_64-linux-musl.so +0 -0
  518. sage/matroids/set_system.pxd +38 -0
  519. sage/matroids/set_system.pyx +800 -0
  520. sage/matroids/transversal_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  521. sage/matroids/transversal_matroid.pxd +14 -0
  522. sage/matroids/transversal_matroid.pyx +893 -0
  523. sage/matroids/union_matroid.cpython-314-x86_64-linux-musl.so +0 -0
  524. sage/matroids/union_matroid.pxd +20 -0
  525. sage/matroids/union_matroid.pyx +331 -0
  526. sage/matroids/unpickling.cpython-314-x86_64-linux-musl.so +0 -0
  527. sage/matroids/unpickling.pyx +843 -0
  528. sage/matroids/utilities.py +809 -0
  529. sage/misc/all__sagemath_modules.py +20 -0
  530. sage/misc/c3.cpython-314-x86_64-linux-musl.so +0 -0
  531. sage/misc/c3.pyx +238 -0
  532. sage/misc/compat.py +87 -0
  533. sage/misc/element_with_label.py +173 -0
  534. sage/misc/func_persist.py +79 -0
  535. sage/misc/pickle_old.cpython-314-x86_64-linux-musl.so +0 -0
  536. sage/misc/pickle_old.pyx +19 -0
  537. sage/misc/proof.py +7 -0
  538. sage/misc/replace_dot_all.py +472 -0
  539. sage/misc/sagedoc_conf.py +168 -0
  540. sage/misc/sphinxify.py +167 -0
  541. sage/misc/test_class_pickling.py +85 -0
  542. sage/modules/all.py +42 -0
  543. sage/modules/complex_double_vector.py +25 -0
  544. sage/modules/diamond_cutting.py +380 -0
  545. sage/modules/fg_pid/all.py +1 -0
  546. sage/modules/fg_pid/fgp_element.py +456 -0
  547. sage/modules/fg_pid/fgp_module.py +2091 -0
  548. sage/modules/fg_pid/fgp_morphism.py +550 -0
  549. sage/modules/filtered_vector_space.py +1271 -0
  550. sage/modules/finite_submodule_iter.cpython-314-x86_64-linux-musl.so +0 -0
  551. sage/modules/finite_submodule_iter.pxd +27 -0
  552. sage/modules/finite_submodule_iter.pyx +452 -0
  553. sage/modules/fp_graded/all.py +1 -0
  554. sage/modules/fp_graded/element.py +346 -0
  555. sage/modules/fp_graded/free_element.py +298 -0
  556. sage/modules/fp_graded/free_homspace.py +53 -0
  557. sage/modules/fp_graded/free_module.py +1060 -0
  558. sage/modules/fp_graded/free_morphism.py +217 -0
  559. sage/modules/fp_graded/homspace.py +563 -0
  560. sage/modules/fp_graded/module.py +1340 -0
  561. sage/modules/fp_graded/morphism.py +1990 -0
  562. sage/modules/fp_graded/steenrod/all.py +1 -0
  563. sage/modules/fp_graded/steenrod/homspace.py +65 -0
  564. sage/modules/fp_graded/steenrod/module.py +477 -0
  565. sage/modules/fp_graded/steenrod/morphism.py +404 -0
  566. sage/modules/fp_graded/steenrod/profile.py +241 -0
  567. sage/modules/free_module.py +8447 -0
  568. sage/modules/free_module_element.cpython-314-x86_64-linux-musl.so +0 -0
  569. sage/modules/free_module_element.pxd +22 -0
  570. sage/modules/free_module_element.pyx +5445 -0
  571. sage/modules/free_module_homspace.py +369 -0
  572. sage/modules/free_module_integer.py +896 -0
  573. sage/modules/free_module_morphism.py +823 -0
  574. sage/modules/free_module_pseudohomspace.py +352 -0
  575. sage/modules/free_module_pseudomorphism.py +578 -0
  576. sage/modules/free_quadratic_module.py +1706 -0
  577. sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
  578. sage/modules/matrix_morphism.py +1745 -0
  579. sage/modules/misc.py +103 -0
  580. sage/modules/module_functors.py +192 -0
  581. sage/modules/multi_filtered_vector_space.py +719 -0
  582. sage/modules/ore_module.py +2208 -0
  583. sage/modules/ore_module_element.py +178 -0
  584. sage/modules/ore_module_homspace.py +147 -0
  585. sage/modules/ore_module_morphism.py +968 -0
  586. sage/modules/quotient_module.py +699 -0
  587. sage/modules/real_double_vector.py +22 -0
  588. sage/modules/submodule.py +255 -0
  589. sage/modules/tensor_operations.py +567 -0
  590. sage/modules/torsion_quadratic_module.py +1352 -0
  591. sage/modules/tutorial_free_modules.py +248 -0
  592. sage/modules/vector_complex_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  593. sage/modules/vector_complex_double_dense.pxd +6 -0
  594. sage/modules/vector_complex_double_dense.pyx +117 -0
  595. sage/modules/vector_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  596. sage/modules/vector_double_dense.pxd +6 -0
  597. sage/modules/vector_double_dense.pyx +604 -0
  598. sage/modules/vector_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  599. sage/modules/vector_integer_dense.pxd +15 -0
  600. sage/modules/vector_integer_dense.pyx +361 -0
  601. sage/modules/vector_integer_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  602. sage/modules/vector_integer_sparse.pxd +29 -0
  603. sage/modules/vector_integer_sparse.pyx +406 -0
  604. sage/modules/vector_modn_dense.cpython-314-x86_64-linux-musl.so +0 -0
  605. sage/modules/vector_modn_dense.pxd +12 -0
  606. sage/modules/vector_modn_dense.pyx +394 -0
  607. sage/modules/vector_modn_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  608. sage/modules/vector_modn_sparse.pxd +21 -0
  609. sage/modules/vector_modn_sparse.pyx +298 -0
  610. sage/modules/vector_numpy_dense.cpython-314-x86_64-linux-musl.so +0 -0
  611. sage/modules/vector_numpy_dense.pxd +15 -0
  612. sage/modules/vector_numpy_dense.pyx +304 -0
  613. sage/modules/vector_numpy_integer_dense.cpython-314-x86_64-linux-musl.so +0 -0
  614. sage/modules/vector_numpy_integer_dense.pxd +7 -0
  615. sage/modules/vector_numpy_integer_dense.pyx +54 -0
  616. sage/modules/vector_rational_dense.cpython-314-x86_64-linux-musl.so +0 -0
  617. sage/modules/vector_rational_dense.pxd +15 -0
  618. sage/modules/vector_rational_dense.pyx +387 -0
  619. sage/modules/vector_rational_sparse.cpython-314-x86_64-linux-musl.so +0 -0
  620. sage/modules/vector_rational_sparse.pxd +30 -0
  621. sage/modules/vector_rational_sparse.pyx +413 -0
  622. sage/modules/vector_real_double_dense.cpython-314-x86_64-linux-musl.so +0 -0
  623. sage/modules/vector_real_double_dense.pxd +6 -0
  624. sage/modules/vector_real_double_dense.pyx +126 -0
  625. sage/modules/vector_space_homspace.py +430 -0
  626. sage/modules/vector_space_morphism.py +989 -0
  627. sage/modules/with_basis/all.py +15 -0
  628. sage/modules/with_basis/cell_module.py +494 -0
  629. sage/modules/with_basis/indexed_element.cpython-314-x86_64-linux-musl.so +0 -0
  630. sage/modules/with_basis/indexed_element.pxd +13 -0
  631. sage/modules/with_basis/indexed_element.pyx +1058 -0
  632. sage/modules/with_basis/invariant.py +1075 -0
  633. sage/modules/with_basis/morphism.py +1636 -0
  634. sage/modules/with_basis/representation.py +2939 -0
  635. sage/modules/with_basis/subquotient.py +685 -0
  636. sage/numerical/all__sagemath_modules.py +6 -0
  637. sage/numerical/gauss_legendre.cpython-314-x86_64-linux-musl.so +0 -0
  638. sage/numerical/gauss_legendre.pyx +381 -0
  639. sage/numerical/optimize.py +910 -0
  640. sage/probability/all.py +10 -0
  641. sage/probability/probability_distribution.cpython-314-x86_64-linux-musl.so +0 -0
  642. sage/probability/probability_distribution.pyx +1242 -0
  643. sage/probability/random_variable.py +411 -0
  644. sage/quadratic_forms/all.py +4 -0
  645. sage/quadratic_forms/all__sagemath_modules.py +15 -0
  646. sage/quadratic_forms/binary_qf.py +2042 -0
  647. sage/quadratic_forms/bqf_class_group.py +748 -0
  648. sage/quadratic_forms/constructions.py +93 -0
  649. sage/quadratic_forms/count_local_2.cpython-314-x86_64-linux-musl.so +0 -0
  650. sage/quadratic_forms/count_local_2.pyx +365 -0
  651. sage/quadratic_forms/extras.py +195 -0
  652. sage/quadratic_forms/quadratic_form.py +1753 -0
  653. sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
  654. sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
  655. sage/quadratic_forms/quadratic_form__evaluate.cpython-314-x86_64-linux-musl.so +0 -0
  656. sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
  657. sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
  658. sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
  659. sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
  660. sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
  661. sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
  662. sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
  663. sage/quadratic_forms/quadratic_form__theta.py +352 -0
  664. sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
  665. sage/quadratic_forms/random_quadraticform.py +209 -0
  666. sage/quadratic_forms/ternary.cpython-314-x86_64-linux-musl.so +0 -0
  667. sage/quadratic_forms/ternary.pyx +1154 -0
  668. sage/quadratic_forms/ternary_qf.py +2027 -0
  669. sage/rings/all__sagemath_modules.py +28 -0
  670. sage/rings/asymptotic/all__sagemath_modules.py +1 -0
  671. sage/rings/asymptotic/misc.py +1252 -0
  672. sage/rings/cc.py +4 -0
  673. sage/rings/cfinite_sequence.py +1306 -0
  674. sage/rings/complex_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  675. sage/rings/complex_conversion.pxd +8 -0
  676. sage/rings/complex_conversion.pyx +23 -0
  677. sage/rings/complex_double.cpython-314-x86_64-linux-musl.so +0 -0
  678. sage/rings/complex_double.pxd +21 -0
  679. sage/rings/complex_double.pyx +2654 -0
  680. sage/rings/complex_mpc.cpython-314-x86_64-linux-musl.so +0 -0
  681. sage/rings/complex_mpc.pxd +21 -0
  682. sage/rings/complex_mpc.pyx +2576 -0
  683. sage/rings/complex_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  684. sage/rings/complex_mpfr.pxd +18 -0
  685. sage/rings/complex_mpfr.pyx +3602 -0
  686. sage/rings/derivation.py +2334 -0
  687. sage/rings/finite_rings/all__sagemath_modules.py +1 -0
  688. sage/rings/finite_rings/maps_finite_field.py +191 -0
  689. sage/rings/function_field/all__sagemath_modules.py +8 -0
  690. sage/rings/function_field/derivations.py +102 -0
  691. sage/rings/function_field/derivations_rational.py +132 -0
  692. sage/rings/function_field/differential.py +853 -0
  693. sage/rings/function_field/divisor.py +1107 -0
  694. sage/rings/function_field/drinfeld_modules/action.py +199 -0
  695. sage/rings/function_field/drinfeld_modules/all.py +1 -0
  696. sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
  697. sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
  698. sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
  699. sage/rings/function_field/drinfeld_modules/homset.py +420 -0
  700. sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
  701. sage/rings/function_field/hermite_form_polynomial.cpython-314-x86_64-linux-musl.so +0 -0
  702. sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
  703. sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-linux-musl.so +0 -0
  704. sage/rings/function_field/khuri_makdisi.pyx +935 -0
  705. sage/rings/invariants/all.py +4 -0
  706. sage/rings/invariants/invariant_theory.py +4597 -0
  707. sage/rings/invariants/reconstruction.py +395 -0
  708. sage/rings/polynomial/all__sagemath_modules.py +17 -0
  709. sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
  710. sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-x86_64-linux-musl.so +0 -0
  711. sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
  712. sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
  713. sage/rings/polynomial/ore_function_element.py +952 -0
  714. sage/rings/polynomial/ore_function_field.py +1028 -0
  715. sage/rings/polynomial/ore_polynomial_element.cpython-314-x86_64-linux-musl.so +0 -0
  716. sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
  717. sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
  718. sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
  719. sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-x86_64-linux-musl.so +0 -0
  720. sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
  721. sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
  722. sage/rings/polynomial/skew_polynomial_element.cpython-314-x86_64-linux-musl.so +0 -0
  723. sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
  724. sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
  725. sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-x86_64-linux-musl.so +0 -0
  726. sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
  727. sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
  728. sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-x86_64-linux-musl.so +0 -0
  729. sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
  730. sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
  731. sage/rings/polynomial/skew_polynomial_ring.py +908 -0
  732. sage/rings/real_double_element_gsl.cpython-314-x86_64-linux-musl.so +0 -0
  733. sage/rings/real_double_element_gsl.pxd +8 -0
  734. sage/rings/real_double_element_gsl.pyx +794 -0
  735. sage/rings/real_field.py +58 -0
  736. sage/rings/real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  737. sage/rings/real_mpfr.pxd +29 -0
  738. sage/rings/real_mpfr.pyx +6122 -0
  739. sage/rings/ring_extension.cpython-314-x86_64-linux-musl.so +0 -0
  740. sage/rings/ring_extension.pxd +42 -0
  741. sage/rings/ring_extension.pyx +2779 -0
  742. sage/rings/ring_extension_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  743. sage/rings/ring_extension_conversion.pxd +16 -0
  744. sage/rings/ring_extension_conversion.pyx +462 -0
  745. sage/rings/ring_extension_element.cpython-314-x86_64-linux-musl.so +0 -0
  746. sage/rings/ring_extension_element.pxd +21 -0
  747. sage/rings/ring_extension_element.pyx +1635 -0
  748. sage/rings/ring_extension_homset.py +64 -0
  749. sage/rings/ring_extension_morphism.cpython-314-x86_64-linux-musl.so +0 -0
  750. sage/rings/ring_extension_morphism.pxd +35 -0
  751. sage/rings/ring_extension_morphism.pyx +920 -0
  752. sage/schemes/all__sagemath_modules.py +1 -0
  753. sage/schemes/projective/all__sagemath_modules.py +1 -0
  754. sage/schemes/projective/coherent_sheaf.py +300 -0
  755. sage/schemes/projective/cohomology.py +510 -0
  756. sage/stats/all.py +15 -0
  757. sage/stats/basic_stats.py +489 -0
  758. sage/stats/distributions/all.py +7 -0
  759. sage/stats/distributions/catalog.py +34 -0
  760. sage/stats/distributions/dgs.h +50 -0
  761. sage/stats/distributions/dgs.pxd +111 -0
  762. sage/stats/distributions/dgs_bern.h +400 -0
  763. sage/stats/distributions/dgs_gauss.h +614 -0
  764. sage/stats/distributions/dgs_misc.h +104 -0
  765. sage/stats/distributions/discrete_gaussian_integer.cpython-314-x86_64-linux-musl.so +0 -0
  766. sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
  767. sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
  768. sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
  769. sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
  770. sage/stats/hmm/all.py +15 -0
  771. sage/stats/hmm/chmm.cpython-314-x86_64-linux-musl.so +0 -0
  772. sage/stats/hmm/chmm.pyx +1595 -0
  773. sage/stats/hmm/distributions.cpython-314-x86_64-linux-musl.so +0 -0
  774. sage/stats/hmm/distributions.pxd +29 -0
  775. sage/stats/hmm/distributions.pyx +531 -0
  776. sage/stats/hmm/hmm.cpython-314-x86_64-linux-musl.so +0 -0
  777. sage/stats/hmm/hmm.pxd +17 -0
  778. sage/stats/hmm/hmm.pyx +1388 -0
  779. sage/stats/hmm/util.cpython-314-x86_64-linux-musl.so +0 -0
  780. sage/stats/hmm/util.pxd +7 -0
  781. sage/stats/hmm/util.pyx +165 -0
  782. sage/stats/intlist.cpython-314-x86_64-linux-musl.so +0 -0
  783. sage/stats/intlist.pxd +14 -0
  784. sage/stats/intlist.pyx +588 -0
  785. sage/stats/r.py +49 -0
  786. sage/stats/time_series.cpython-314-x86_64-linux-musl.so +0 -0
  787. sage/stats/time_series.pxd +6 -0
  788. sage/stats/time_series.pyx +2546 -0
  789. sage/tensor/all.py +2 -0
  790. sage/tensor/modules/all.py +8 -0
  791. sage/tensor/modules/alternating_contr_tensor.py +761 -0
  792. sage/tensor/modules/comp.py +5598 -0
  793. sage/tensor/modules/ext_pow_free_module.py +824 -0
  794. sage/tensor/modules/finite_rank_free_module.py +3589 -0
  795. sage/tensor/modules/format_utilities.py +333 -0
  796. sage/tensor/modules/free_module_alt_form.py +858 -0
  797. sage/tensor/modules/free_module_automorphism.py +1207 -0
  798. sage/tensor/modules/free_module_basis.py +1074 -0
  799. sage/tensor/modules/free_module_element.py +284 -0
  800. sage/tensor/modules/free_module_homset.py +652 -0
  801. sage/tensor/modules/free_module_linear_group.py +564 -0
  802. sage/tensor/modules/free_module_morphism.py +1581 -0
  803. sage/tensor/modules/free_module_tensor.py +3289 -0
  804. sage/tensor/modules/reflexive_module.py +386 -0
  805. sage/tensor/modules/tensor_free_module.py +780 -0
  806. sage/tensor/modules/tensor_free_submodule.py +538 -0
  807. sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
  808. sage/tensor/modules/tensor_with_indices.py +1043 -0
@@ -0,0 +1,2148 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ r"""
3
+ Chain complexes
4
+
5
+ This module implements bounded chain complexes of free `R`-modules,
6
+ for any commutative ring `R` (although the interesting things, like
7
+ homology, only work if `R` is the integers or a field).
8
+
9
+ Fix a ring `R`. A chain complex over `R` is a collection of
10
+ `R`-modules `\{C_n\}` indexed by the integers, with `R`-module maps
11
+ `d_n : C_n \rightarrow C_{n+1}` such that `d_{n+1} \circ d_n = 0` for
12
+ all `n`. The maps `d_n` are called *differentials*.
13
+
14
+ One can vary this somewhat: the differentials may decrease degree by
15
+ one instead of increasing it: sometimes a chain complex is defined
16
+ with `d_n : C_n \rightarrow C_{n-1}` for each `n`. Indeed, the
17
+ differentials may change dimension by any fixed integer.
18
+
19
+ Also, the modules may be indexed over an abelian group other than the
20
+ integers, e.g., `\ZZ^{m}` for some integer `m \geq 1`, in which case
21
+ the differentials may change the grading by any element of that
22
+ grading group. The elements of the grading group are generally called
23
+ degrees, so `C_n` is the module in degree `n` and so on.
24
+
25
+ In this implementation, the ring `R` must be commutative and the
26
+ modules `C_n` must be free `R`-modules. As noted above, homology
27
+ calculations will only work if the ring `R` is either `\ZZ` or a
28
+ field. The modules may be indexed by any free abelian group. The
29
+ differentials may increase degree by 1 or decrease it, or indeed
30
+ change it by any fixed amount: this is controlled by the
31
+ ``degree_of_differential`` parameter used in defining the chain
32
+ complex.
33
+
34
+ AUTHORS:
35
+
36
+ - John H. Palmieri (2009-04): initial implementation
37
+ """
38
+
39
+ # ****************************************************************************
40
+ # Copyright (C) 2013 John H. Palmieri <palmieri@math.washington.edu>
41
+ # Volker Braun <vbraun.name@gmail.com>
42
+ #
43
+ # This program is free software: you can redistribute it and/or modify
44
+ # it under the terms of the GNU General Public License as published by
45
+ # the Free Software Foundation, either version 2 of the License, or
46
+ # (at your option) any later version.
47
+ # https://www.gnu.org/licenses/
48
+ # ****************************************************************************
49
+
50
+ from copy import copy
51
+ from functools import reduce
52
+
53
+ from sage.structure.parent import Parent
54
+ from sage.structure.element import ModuleElement, Vector, coercion_model
55
+ from sage.misc.cachefunc import cached_method
56
+
57
+ from sage.rings.integer_ring import ZZ
58
+ from sage.modules.free_module import FreeModule
59
+ from sage.modules.free_module_element import vector
60
+ from sage.matrix.matrix0 import Matrix
61
+ from sage.matrix.constructor import matrix
62
+ from sage.misc.latex import latex
63
+ from sage.rings.fast_arith import prime_range
64
+ from sage.homology.homology_group import HomologyGroup
65
+ from sage.misc.persist import register_unpickle_override
66
+
67
+
68
+ def _latex_module(R, m):
69
+ """
70
+ LaTeX string representing a free module over ``R`` of rank ``m``.
71
+
72
+ INPUT:
73
+
74
+ - ``R`` -- a commutative ring
75
+ - ``m`` -- nonnegative integer
76
+
77
+ This is used by the ``_latex_`` method for chain complexes.
78
+
79
+ EXAMPLES::
80
+
81
+ sage: from sage.homology.chain_complex import _latex_module
82
+ sage: _latex_module(ZZ, 3)
83
+ '\\Bold{Z}^{3}'
84
+ sage: _latex_module(ZZ, 0)
85
+ '0'
86
+ sage: _latex_module(GF(3), 1)
87
+ '\\Bold{F}_{3}^{1}'
88
+ """
89
+ if m == 0:
90
+ return str(latex(0))
91
+ return str(latex(FreeModule(R, m)))
92
+
93
+
94
+ def ChainComplex(data=None, base_ring=None, grading_group=None,
95
+ degree_of_differential=1, degree=1,
96
+ check=True):
97
+ r"""
98
+ Define a chain complex.
99
+
100
+ INPUT:
101
+
102
+ - ``data`` -- the data defining the chain complex; see below for
103
+ more details
104
+
105
+ The following keyword arguments are supported:
106
+
107
+ - ``base_ring`` -- a commutative ring (optional); the ring over
108
+ which the chain complex is defined. If this is not specified,
109
+ it is determined by the data defining the chain complex.
110
+
111
+ - ``grading_group`` -- a additive free abelian group (optional,
112
+ default ``ZZ``); the group over which the chain complex is
113
+ indexed
114
+
115
+ - ``degree_of_differential`` -- element of grading_group
116
+ (default: ``1``); the degree of the differential
117
+
118
+ - ``degree`` -- alias for ``degree_of_differential``
119
+
120
+ - ``check`` -- boolean (default: ``True``); if ``True``,
121
+ check that each consecutive pair of differentials are
122
+ composable and have composite equal to zero
123
+
124
+ OUTPUT: a chain complex
125
+
126
+ .. WARNING::
127
+
128
+ Right now, homology calculations will only work if the base
129
+ ring is either `\ZZ` or a field, so please take this into account
130
+ when defining a chain complex.
131
+
132
+ Use data to define the chain complex. This may be in any of the
133
+ following forms.
134
+
135
+ 1. a dictionary with integers (or more generally, elements of
136
+ grading_group) for keys, and with ``data[n]`` a matrix representing
137
+ (via left multiplication) the differential coming from degree
138
+ `n`. (Note that the shape of the matrix then determines the
139
+ rank of the free modules `C_n` and `C_{n+d}`.)
140
+
141
+ 2. a list/tuple/iterable of the form `[C_0, d_0, C_1, d_1, C_2,
142
+ d_2, ...]`, where each `C_i` is a free module and each `d_i` is
143
+ a matrix, as above. This only makes sense if ``grading_group``
144
+ is `\ZZ` and ``degree`` is 1.
145
+
146
+ 3. a list/tuple/iterable of the form `[r_0, d_0, r_1, d_1, r_2,
147
+ d_2, \ldots]`, where `r_i` is the rank of the free module `C_i`
148
+ and each `d_i` is a matrix, as above. This only makes sense if
149
+ ``grading_group`` is `\ZZ` and ``degree`` is 1.
150
+
151
+ 4. a list/tuple/iterable of the form `[d_0, d_1, d_2, \ldots]` where
152
+ each `d_i` is a matrix, as above. This only makes sense if
153
+ ``grading_group`` is `\ZZ` and ``degree`` is 1.
154
+
155
+ .. NOTE::
156
+
157
+ In fact, the free modules `C_i` in case 2 and the ranks `r_i`
158
+ in case 3 are ignored: only the matrices are kept, and from
159
+ their shapes, the ranks of the modules are determined.
160
+ (Indeed, if ``data`` is a list or tuple, then any element which
161
+ is not a matrix is discarded; thus the list may have any number
162
+ of different things in it, and all of the non-matrices will be
163
+ ignored.) No error checking is done to make sure, for
164
+ instance, that the given modules have the appropriate ranks for
165
+ the given matrices. However, as long as ``check`` is True, the
166
+ code checks to see if the matrices are composable and that each
167
+ appropriate composite is zero.
168
+
169
+ If the base ring is not specified, then the matrices are examined
170
+ to determine a ring over which they are all naturally defined, and
171
+ this becomes the base ring for the complex. If no such ring can
172
+ be found, an error is raised. If the base ring is specified, then
173
+ the matrices are converted automatically to this ring when
174
+ defining the chain complex. If some matrix cannot be converted,
175
+ then an error is raised.
176
+
177
+ EXAMPLES::
178
+
179
+ sage: ChainComplex()
180
+ Trivial chain complex over Integer Ring
181
+
182
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
183
+ sage: C
184
+ Chain complex with at most 2 nonzero terms over Integer Ring
185
+
186
+ sage: m = matrix(ZZ, 2, 2, [0, 1, 0, 0])
187
+ sage: D = ChainComplex([m, m], base_ring=GF(2)); D
188
+ Chain complex with at most 3 nonzero terms over Finite Field of size 2
189
+ sage: D == loads(dumps(D))
190
+ True
191
+ sage: D.differential(0)==m, m.is_immutable(), D.differential(0).is_immutable()
192
+ (True, False, True)
193
+
194
+ Note that when a chain complex is defined in Sage, new
195
+ differentials may be created: every nonzero module in the chain
196
+ complex must have a differential coming from it, even if that
197
+ differential is zero::
198
+
199
+ sage: IZ = ChainComplex({0: identity_matrix(ZZ, 1)})
200
+ sage: diff = IZ.differential() # the differentials in the chain complex
201
+ sage: diff[-1], diff[0], diff[1]
202
+ ([], [1], [])
203
+ sage: IZ.differential(1).parent()
204
+ Full MatrixSpace of 0 by 1 dense matrices over Integer Ring
205
+ sage: mat = ChainComplex({0: matrix(ZZ, 3, 4)}).differential(1)
206
+ sage: mat.nrows(), mat.ncols()
207
+ (0, 3)
208
+
209
+ Defining the base ring implicitly::
210
+
211
+ sage: ChainComplex([matrix(QQ, 3, 1), matrix(ZZ, 4, 3)])
212
+ Chain complex with at most 3 nonzero terms over Rational Field
213
+ sage: ChainComplex([matrix(GF(125, 'a'), 3, 1), matrix(ZZ, 4, 3)]) # needs sage.rings.finite_rings
214
+ Chain complex with at most 3 nonzero terms over Finite Field in a of size 5^3
215
+
216
+ If the matrices are defined over incompatible rings, an error results::
217
+
218
+ sage: ChainComplex([matrix(GF(125, 'a'), 3, 1), matrix(QQ, 4, 3)]) # needs sage.rings.finite_rings
219
+ Traceback (most recent call last):
220
+ ...
221
+ TypeError: no common canonical parent for objects with parents:
222
+ 'Finite Field in a of size 5^3' and 'Rational Field'
223
+
224
+ If the base ring is given explicitly but is not compatible with
225
+ the matrices, an error results::
226
+
227
+ sage: ChainComplex([matrix(GF(125, 'a'), 3, 1)], base_ring=QQ) # needs sage.rings.finite_rings
228
+ Traceback (most recent call last):
229
+ ...
230
+ TypeError: unable to convert 0 to a rational
231
+ """
232
+ if grading_group is None:
233
+ grading_group = ZZ
234
+ if degree_of_differential != 1 and degree != 1:
235
+ raise ValueError('specify only one of degree_of_differential or degree, not both')
236
+ if degree_of_differential != 1:
237
+ degree = degree_of_differential
238
+ try:
239
+ degree = grading_group(degree)
240
+ except Exception:
241
+ raise ValueError('degree is not an element of the grading group')
242
+
243
+ # transform data into data_dict
244
+ if data is None or (isinstance(data, (list, tuple)) and len(data) == 0):
245
+ data_dict = {}
246
+ elif isinstance(data, dict): # data is dictionary
247
+ data_dict = data
248
+ else: # data is list/tuple/iterable
249
+ data_matrices = [x for x in data if isinstance(x, Matrix)]
250
+ if degree != 1:
251
+ raise ValueError('degree must be +1 if the data argument is a list or tuple')
252
+ if grading_group != ZZ:
253
+ raise ValueError('grading_group must be ZZ if the data argument is a list or tuple')
254
+ data_dict = {grading_group(i): m for i, m in enumerate(data_matrices)}
255
+
256
+ if base_ring is None:
257
+ if not data_dict:
258
+ base_ring = ZZ
259
+ else:
260
+ bases = tuple(x.base_ring() for x in data_dict.values())
261
+ base_ring = coercion_model.common_parent(*bases)
262
+
263
+ # make sure values in data_dict are appropriate matrices
264
+ for n in list(data_dict):
265
+ if n not in grading_group:
266
+ raise ValueError('one of the dictionary keys is not an element of the grading group')
267
+ mat = data_dict[n]
268
+ if not isinstance(mat, Matrix):
269
+ raise TypeError('one of the differentials in the data is not a matrix')
270
+ if mat.base_ring() is base_ring:
271
+ if not mat.is_immutable():
272
+ mat = copy(mat) # do not make any arguments passed immutable
273
+ mat.set_immutable()
274
+ else:
275
+ mat = mat.change_ring(base_ring)
276
+ mat.set_immutable()
277
+ data_dict[n] = mat
278
+
279
+ # include any "obvious" zero matrices that are not 0x0
280
+ for n in list(data_dict): # note: data_dict will be mutated in this loop
281
+ mat1 = data_dict[n]
282
+ if (mat1.nrows(), mat1.ncols()) == (0, 0):
283
+ del data_dict[n]
284
+ if (mat1.nrows() != 0) and (n+degree not in data_dict):
285
+ if n+2*degree in data_dict:
286
+ mat2 = matrix(base_ring, data_dict[n+2*degree].ncols(), mat1.nrows())
287
+ else:
288
+ mat2 = matrix(base_ring, 0, mat1.nrows())
289
+ mat2.set_immutable()
290
+ data_dict[n+degree] = mat2
291
+ if (mat1.ncols() != 0) and (n-degree not in data_dict):
292
+ if n-2*degree in data_dict:
293
+ mat0 = matrix(base_ring, mat1.ncols(), data_dict[n-2*degree].nrows())
294
+ else:
295
+ mat0 = matrix(base_ring, mat1.ncols(), 0)
296
+ mat0.set_immutable()
297
+ data_dict[n-degree] = mat0
298
+
299
+ # check that this is a complex: going twice is zero
300
+ if check:
301
+ for n in data_dict:
302
+ mat0 = data_dict[n]
303
+ try:
304
+ mat1 = data_dict[n+degree]
305
+ except KeyError:
306
+ continue
307
+ try:
308
+ prod = mat1 * mat0
309
+ except TypeError:
310
+ raise TypeError('the differentials d_{{{}}} and d_{{{}}} are not compatible: '
311
+ 'their product is not defined'.format(n, n+degree))
312
+ if not prod.is_zero():
313
+ raise ValueError('the differentials d_{{{}}} and d_{{{}}} are not compatible: '
314
+ 'their composition is not zero.'.format(n, n+degree))
315
+
316
+ return ChainComplex_class(grading_group, degree, base_ring, data_dict)
317
+
318
+
319
+ class Chain_class(ModuleElement):
320
+
321
+ def __init__(self, parent, vectors, check=True):
322
+ r"""
323
+ A Chain in a Chain Complex.
324
+
325
+ A chain is collection of module elements for each module `C_n`
326
+ of the chain complex `(C_n, d_n)`. There is no restriction on
327
+ how the differentials `d_n` act on the elements of the chain.
328
+
329
+ .. NOTE::
330
+
331
+ You must use the chain complex to construct chains.
332
+
333
+ EXAMPLES::
334
+
335
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])},
336
+ ....: base_ring=GF(7))
337
+ sage: C.category()
338
+ Category of chain complexes over Finite Field of size 7
339
+
340
+ TESTS::
341
+
342
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
343
+ sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])})
344
+ sage: TestSuite(c).run()
345
+ """
346
+ # only nonzero vectors shall be stored, ensuring this is the
347
+ # job of the _element constructor_
348
+ assert all(v.is_immutable() and not v.is_zero()
349
+ and v.base_ring() is parent.base_ring()
350
+ for v in vectors.values())
351
+ self._vec = vectors
352
+ super().__init__(parent)
353
+
354
+ def vector(self, degree):
355
+ """
356
+ Return the free module element in ``degree``.
357
+
358
+ EXAMPLES::
359
+
360
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
361
+ sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])})
362
+ sage: c.vector(0)
363
+ (1, 2, 3)
364
+ sage: c.vector(1)
365
+ (4, 5)
366
+ sage: c.vector(2)
367
+ ()
368
+ """
369
+ try:
370
+ return self._vec[degree]
371
+ except KeyError:
372
+ return self.parent().free_module(degree).zero()
373
+
374
+ def _repr_(self):
375
+ """
376
+ Print representation.
377
+
378
+ EXAMPLES::
379
+
380
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
381
+ sage: C()
382
+ Trivial chain
383
+ sage: C({0: vector([1, 2, 3])})
384
+ Chain(0:(1, 2, 3))
385
+ sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])}); c
386
+ Chain with 2 nonzero terms over Integer Ring
387
+ sage: c._repr_()
388
+ 'Chain with 2 nonzero terms over Integer Ring'
389
+ """
390
+ n = len(self._vec)
391
+ if n == 0:
392
+ return 'Trivial chain'
393
+
394
+ if n == 1:
395
+ deg, vec = next(iter(self._vec.items()))
396
+ return 'Chain({0}:{1})'.format(deg, vec)
397
+
398
+ return 'Chain with {0} nonzero terms over {1}'.format(
399
+ n, self.parent().base_ring())
400
+
401
+ def _ascii_art_(self):
402
+ """
403
+ Return an ascii art representation.
404
+
405
+ Note that arrows go to the left so that composition of
406
+ differentials is the usual matrix multiplication.
407
+
408
+ EXAMPLES::
409
+
410
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]),
411
+ ....: 1: zero_matrix(1,2)})
412
+ sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])})
413
+ sage: ascii_art(c)
414
+ d_2 d_1 d_0 [1] d_-1
415
+ 0 <---- [0] <---- [4] <---- [2] <----- 0
416
+ [5] [3]
417
+
418
+ TESTS:
419
+
420
+ check that :issue:`37678` is fixed::
421
+
422
+ sage: C = ChainComplex(base_ring=ZZ)
423
+ sage: ascii_art(C())
424
+ 0
425
+ """
426
+ from sage.typeset.ascii_art import AsciiArt
427
+
428
+ def arrow_art(d):
429
+ d_str = [' d_{0} '.format(d)]
430
+ arrow = ' <' + '-'*(len(d_str[0])-3) + ' '
431
+ d_str.append(arrow)
432
+ return AsciiArt(d_str, baseline=0)
433
+
434
+ def vector_art(d):
435
+ v = self.vector(d)
436
+ if v.degree() == 0:
437
+ return AsciiArt(['0'])
438
+ v = str(v.column()).splitlines()
439
+ return AsciiArt(v, baseline=len(v)//2)
440
+
441
+ result = []
442
+ chain_complex = self.parent()
443
+ for ordered in chain_complex.ordered_degrees():
444
+ ordered = list(reversed(ordered))
445
+ if len(ordered) == 0:
446
+ return AsciiArt(['0'])
447
+ result_ordered = vector_art(ordered[0] + chain_complex.degree_of_differential())
448
+ for n in ordered:
449
+ result_ordered += arrow_art(n) + vector_art(n)
450
+ result = [result_ordered] + result
451
+ if len(result) == 0:
452
+ return AsciiArt(['0'])
453
+ concatenated = result[0]
454
+ for r in result[1:]:
455
+ concatenated += AsciiArt([' ... ']) + r
456
+ return concatenated
457
+
458
+ def _unicode_art_(self):
459
+ """
460
+ Return a unicode art representation.
461
+
462
+ Note that arrows go to the left so that composition of
463
+ differentials is the usual matrix multiplication.
464
+
465
+ EXAMPLES::
466
+
467
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]),
468
+ ....: 1: zero_matrix(1,2)})
469
+ sage: c = C({0: vector([1, 2, 3]), 1: vector([4, 5])})
470
+ sage: unicode_art(c)
471
+ ⎛1⎞
472
+ d_2 d_1 ⎛4⎞ d_0 ⎜2⎟ d_-1
473
+ 0 <──── (0) <──── ⎝5⎠ <──── ⎝3⎠ <───── 0
474
+ sage: unicode_art(C())
475
+ ⎛0⎞
476
+ d_2 d_1 ⎛0⎞ d_0 ⎜0⎟ d_-1
477
+ 0 <──── (0) <──── ⎝0⎠ <──── ⎝0⎠ <───── 0
478
+ sage: unicode_art(ChainComplex())
479
+ 0
480
+ """
481
+ from sage.typeset.unicode_art import UnicodeArt
482
+
483
+ def arrow_art(d):
484
+ d_str = [' d_{0} '.format(d)]
485
+ arrow = ' <' + '─' * (len(d_str[0]) - 3) + ' '
486
+ d_str.append(arrow)
487
+ return UnicodeArt(d_str, baseline=0)
488
+
489
+ def vector_art(d):
490
+ v = self.vector(d)
491
+ if not v.degree():
492
+ return UnicodeArt(['0'])
493
+ w = matrix(v).transpose()
494
+ return w._unicode_art_()
495
+
496
+ result = []
497
+ chain_complex = self.parent()
498
+ for ordered in chain_complex.ordered_degrees():
499
+ ordered = list(reversed(ordered))
500
+ if not ordered:
501
+ return UnicodeArt(['0'])
502
+ result_ordered = vector_art(ordered[0] +
503
+ chain_complex.degree_of_differential())
504
+ for n in ordered:
505
+ result_ordered += arrow_art(n) + vector_art(n)
506
+ result = [result_ordered] + result
507
+ if len(result) == 0:
508
+ return UnicodeArt(['0'])
509
+ concatenated = result[0]
510
+ for r in result[1:]:
511
+ concatenated += UnicodeArt([' ... ']) + r
512
+ return concatenated
513
+
514
+ def is_cycle(self):
515
+ """
516
+ Return whether the chain is a cycle.
517
+
518
+ OUTPUT: boolean; whether the elements of the chain are in the kernel
519
+ of the differentials
520
+
521
+ EXAMPLES::
522
+
523
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
524
+ sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])})
525
+ sage: c.is_cycle()
526
+ True
527
+ """
528
+ chain_complex = self.parent()
529
+ for d, v in self._vec.items():
530
+ dv = chain_complex.differential(d) * v
531
+ if not dv.is_zero():
532
+ return False
533
+ return True
534
+
535
+ def is_boundary(self):
536
+ """
537
+ Return whether the chain is a boundary.
538
+
539
+ OUTPUT:
540
+
541
+ boolean; whether the elements of the chain are in the image of
542
+ the differentials.
543
+
544
+ EXAMPLES::
545
+
546
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
547
+ sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])})
548
+ sage: c.is_boundary()
549
+ False
550
+ sage: z3 = C({1:(1, 0)})
551
+ sage: z3.is_cycle()
552
+ True
553
+ sage: (2*z3).is_boundary()
554
+ False
555
+ sage: (3*z3).is_boundary()
556
+ True
557
+ """
558
+ chain_complex = self.parent()
559
+ for d, v in self._vec.items():
560
+ d = chain_complex.differential(d - chain_complex.degree_of_differential()).transpose()
561
+ if v not in d.image():
562
+ return False
563
+ return True
564
+
565
+ def _add_(self, other):
566
+ """
567
+ Module addition.
568
+
569
+ EXAMPLES::
570
+
571
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
572
+ sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])})
573
+ sage: c + c
574
+ Chain with 2 nonzero terms over Integer Ring
575
+ sage: ascii_art(c + c)
576
+ d_1 d_0 [0] d_-1
577
+ 0 <---- [6] <---- [2] <----- 0
578
+ [8] [4]
579
+ """
580
+ vectors = {}
581
+ for d in set(list(self._vec) + list(other._vec)):
582
+ v = self.vector(d) + other.vector(d)
583
+ if not v.is_zero():
584
+ v.set_immutable()
585
+ vectors[d] = v
586
+ parent = self.parent()
587
+ return parent.element_class(parent, vectors)
588
+
589
+ def _lmul_(self, scalar):
590
+ """
591
+ Scalar multiplication.
592
+
593
+ EXAMPLES::
594
+
595
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
596
+ sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])})
597
+ sage: 2 * c
598
+ Chain with 2 nonzero terms over Integer Ring
599
+ sage: 2 * c == c + c == c * 2
600
+ True
601
+ """
602
+ vectors = dict()
603
+ for d, v in self._vec.items():
604
+ v = scalar * v
605
+ if not v.is_zero():
606
+ v.set_immutable()
607
+ vectors[d] = v
608
+ parent = self.parent()
609
+ return parent.element_class(parent, vectors)
610
+
611
+ def __eq__(self, other):
612
+ """
613
+ Return ``True`` if this chain is equal to ``other``.
614
+
615
+ EXAMPLES::
616
+
617
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
618
+ sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])})
619
+ sage: c == c
620
+ True
621
+ sage: c == C(0)
622
+ False
623
+ """
624
+ if type(self) is not type(other) or self.parent() != other.parent():
625
+ return False
626
+ return self._vec == other._vec
627
+
628
+ def __ne__(self, other):
629
+ """
630
+ Return ``True`` if this chain is not equal to ``other``.
631
+
632
+ EXAMPLES::
633
+
634
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
635
+ sage: c = C({0: vector([0, 1, 2]), 1: vector([3, 4])})
636
+ sage: c != c
637
+ False
638
+ sage: c != C(0)
639
+ True
640
+ """
641
+ return not self == other
642
+
643
+
644
+ class ChainComplex_class(Parent):
645
+ r"""
646
+ See :func:`ChainComplex` for full documentation.
647
+
648
+ The differentials are required to be in the following canonical form:
649
+
650
+ * All differentials that are not `0 \times 0` must be specified
651
+ (even if they have zero rows or zero columns), and
652
+
653
+ * Differentials that are `0 \times 0` must not be specified.
654
+
655
+ * Immutable matrices over the ``base_ring``
656
+
657
+ This and more is ensured by the assertions in the
658
+ constructor. The :func:`ChainComplex` factory function must
659
+ ensure that only valid input is passed.
660
+
661
+ EXAMPLES::
662
+
663
+ sage: C = ChainComplex(); C
664
+ Trivial chain complex over Integer Ring
665
+
666
+ sage: D = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
667
+ sage: D
668
+ Chain complex with at most 2 nonzero terms over Integer Ring
669
+ """
670
+ def __init__(self, grading_group, degree_of_differential, base_ring, differentials):
671
+ """
672
+ Initialize ``self``.
673
+
674
+ TESTS::
675
+
676
+ sage: ChainComplex().base_ring()
677
+ Integer Ring
678
+
679
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
680
+ sage: TestSuite(C).run()
681
+ """
682
+ if any(d.base_ring() != base_ring or not d.is_immutable() or
683
+ (d.ncols(), d.nrows()) == (0, 0)
684
+ for d in differentials.values()):
685
+ raise ValueError('invalid differentials')
686
+ if degree_of_differential.parent() is not grading_group:
687
+ raise ValueError('the degree_of_differential.parent() must be grading_group')
688
+ if grading_group is not ZZ and grading_group.is_multiplicative():
689
+ raise ValueError('grading_group must be either ZZ or multiplicative')
690
+ # all differentials (excluding the 0x0 ones) must be specified to the constructor
691
+ if any(dim+degree_of_differential not in differentials and d.nrows() != 0
692
+ for dim, d in differentials.items()):
693
+ raise ValueError('invalid differentials')
694
+ if any(dim-degree_of_differential not in differentials and d.ncols() != 0
695
+ for dim, d in differentials.items()):
696
+ raise ValueError('invalid differentials')
697
+ self._grading_group = grading_group
698
+ self._degree_of_differential = degree_of_differential
699
+ self._diff = differentials
700
+
701
+ from sage.categories.chain_complexes import ChainComplexes
702
+ category = ChainComplexes(base_ring)
703
+ super().__init__(base=base_ring, category=category)
704
+
705
+ Element = Chain_class
706
+
707
+ def _element_constructor_(self, vectors, check=True):
708
+ """
709
+ The element constructor.
710
+
711
+ This is part of the Parent/Element framework. Calling the
712
+ parent uses this method to construct elements.
713
+
714
+ TESTS::
715
+
716
+ sage: D = ChainComplex({0: matrix(ZZ, 2, 2, [1,0,0,2])})
717
+ sage: D._element_constructor_(0)
718
+ Trivial chain
719
+ sage: D({0:[2, 3]})
720
+ Chain(0:(2, 3))
721
+ """
722
+ if not vectors: # special case: the zero chain
723
+ return self.element_class(self, {})
724
+ if isinstance(vectors, Chain_class):
725
+ vectors = vectors._vec
726
+ data = dict()
727
+ for degree, vec in vectors.items():
728
+ if not isinstance(vec, Vector):
729
+ vec = vector(self.base_ring(), vec)
730
+ vec.set_immutable()
731
+ if check and vec.degree() != self.free_module_rank(degree):
732
+ raise ValueError('vector dimension does not match module dimension')
733
+ if vec.is_zero():
734
+ continue
735
+ if vec.base_ring() != self.base_ring():
736
+ vec = vec.change_ring(self.base_ring())
737
+ if not vec.is_immutable():
738
+ vec = copy(vec)
739
+ vec.set_immutable()
740
+ data[degree] = vec
741
+ return self.element_class(self, data)
742
+
743
+ def random_element(self):
744
+ """
745
+ Return a random element.
746
+
747
+ EXAMPLES::
748
+
749
+ sage: D = ChainComplex({0: matrix(ZZ, 2, 2, [1,0,0,2])})
750
+ sage: D.random_element() # random output
751
+ Chain with 1 nonzero terms over Integer Ring
752
+ """
753
+ vec = dict()
754
+ for d in self.nonzero_degrees():
755
+ vec[d] = self.free_module(d).random_element()
756
+ return self(vec)
757
+
758
+ _an_element_ = random_element
759
+
760
+ @cached_method
761
+ def rank(self, degree, ring=None):
762
+ r"""
763
+ Return the rank of a differential.
764
+
765
+ INPUT:
766
+
767
+ - ``degree`` -- an element `\delta` of the grading
768
+ group. Which differential `d_{\delta}` we want to know the
769
+ rank of
770
+
771
+ - ``ring`` -- (optional) a commutative ring `S`;
772
+ if specified, the rank is computed after changing to this ring
773
+
774
+ OUTPUT:
775
+
776
+ The rank of the differential `d_{\delta} \otimes_R S`, where
777
+ `R` is the base ring of the chain complex.
778
+
779
+ EXAMPLES::
780
+
781
+ sage: C = ChainComplex({0:matrix(ZZ, [[2]])})
782
+ sage: C.differential(0)
783
+ [2]
784
+ sage: C.rank(0)
785
+ 1
786
+ sage: C.rank(0, ring=GF(2))
787
+ 0
788
+ """
789
+ degree = self.grading_group()(degree)
790
+ try:
791
+ d = self._diff[degree]
792
+ except IndexError:
793
+ return ZZ.zero()
794
+ if d.nrows() == 0 or d.ncols() == 0:
795
+ return ZZ.zero()
796
+ if ring is None:
797
+ return d.rank()
798
+ return d.change_ring(ring).rank()
799
+
800
+ def grading_group(self):
801
+ r"""
802
+ Return the grading group.
803
+
804
+ OUTPUT:
805
+
806
+ The discrete abelian group that indexes the individual modules
807
+ of the complex. Usually `\ZZ`.
808
+
809
+ EXAMPLES::
810
+
811
+ sage: G = AdditiveAbelianGroup([0, 3])
812
+ sage: C = ChainComplex(grading_group=G, degree=G(vector([1,2])))
813
+ sage: C.grading_group() # needs sage.libs.pari
814
+ Additive abelian group isomorphic to Z + Z/3
815
+ sage: C.degree_of_differential()
816
+ (1, 2)
817
+ """
818
+ return self._grading_group
819
+
820
+ @cached_method
821
+ def nonzero_degrees(self):
822
+ r"""
823
+ Return the degrees in which the module is non-trivial.
824
+
825
+ See also :meth:`ordered_degrees`.
826
+
827
+ OUTPUT:
828
+
829
+ The tuple containing all degrees `n` (grading group elements)
830
+ such that the module `C_n` of the chain is non-trivial.
831
+
832
+ EXAMPLES::
833
+
834
+ sage: one = matrix(ZZ, [[1]])
835
+ sage: D = ChainComplex({0: one, 2: one, 6:one})
836
+ sage: ascii_art(D)
837
+ [1] [1] [0] [1]
838
+ 0 <-- C_7 <---- C_6 <-- 0 ... 0 <-- C_3 <---- C_2 <---- C_1 <---- C_0 <-- 0
839
+ sage: D.nonzero_degrees()
840
+ (0, 1, 2, 3, 6, 7)
841
+ """
842
+ return tuple(sorted(n for n, d in self._diff.items()
843
+ if d.ncols()))
844
+
845
+ @cached_method
846
+ def ordered_degrees(self, start=None, exclude_first=False):
847
+ r"""
848
+ Sort the degrees in the order determined by the differential.
849
+
850
+ INPUT:
851
+
852
+ - ``start`` -- (default: ``None``) a degree (element of the grading
853
+ group) or ``None``
854
+
855
+ - ``exclude_first`` -- boolean (optional; default:
856
+ ``False``); whether to exclude the lowest degree -- this is a
857
+ handy way to just get the degrees of the nonzero modules,
858
+ as the domain of the first differential is zero.
859
+
860
+ OUTPUT: if ``start`` has been specified, the longest tuple of degrees
861
+
862
+ * containing ``start`` (unless ``start`` would be the first
863
+ and ``exclude_first=True``),
864
+
865
+ * in ascending order relative to :meth:`degree_of_differential`, and
866
+
867
+ * such that none of the corresponding differentials are `0\times 0`.
868
+
869
+ If ``start`` has not been specified, a tuple of such tuples of
870
+ degrees. One for each sequence of nonzero differentials. They
871
+ are returned in sort order.
872
+
873
+ EXAMPLES::
874
+
875
+ sage: one = matrix(ZZ, [[1]])
876
+ sage: D = ChainComplex({0: one, 2: one, 6:one})
877
+ sage: ascii_art(D)
878
+ [1] [1] [0] [1]
879
+ 0 <-- C_7 <---- C_6 <-- 0 ... 0 <-- C_3 <---- C_2 <---- C_1 <---- C_0 <-- 0
880
+ sage: D.ordered_degrees()
881
+ ((-1, 0, 1, 2, 3), (5, 6, 7))
882
+ sage: D.ordered_degrees(exclude_first=True)
883
+ ((0, 1, 2, 3), (6, 7))
884
+ sage: D.ordered_degrees(6)
885
+ (5, 6, 7)
886
+ sage: D.ordered_degrees(5, exclude_first=True)
887
+ (6, 7)
888
+ """
889
+ if start is None:
890
+ result = []
891
+ degrees = set(self._diff)
892
+ while degrees:
893
+ ordered = self.ordered_degrees(degrees.pop())
894
+ degrees.difference_update(ordered)
895
+ if exclude_first:
896
+ ordered = tuple(ordered[1:])
897
+ result.append(ordered)
898
+ result.sort()
899
+ return tuple(result)
900
+
901
+ from collections import deque
902
+ result = deque()
903
+ result.append(start)
904
+
905
+ next_deg = start + self.degree_of_differential()
906
+ while next_deg in self._diff:
907
+ result.append(next_deg)
908
+ next_deg += self.degree_of_differential()
909
+
910
+ prev_deg = start - self.degree_of_differential()
911
+ while prev_deg in self._diff:
912
+ result.appendleft(prev_deg)
913
+ prev_deg -= self.degree_of_differential()
914
+
915
+ if exclude_first:
916
+ result.popleft()
917
+ return tuple(result)
918
+
919
+ def degree_of_differential(self):
920
+ """
921
+ Return the degree of the differentials of the complex.
922
+
923
+ OUTPUT: an element of the grading group
924
+
925
+ EXAMPLES::
926
+
927
+ sage: D = ChainComplex({0: matrix(ZZ, 2, 2, [1,0,0,2])})
928
+ sage: D.degree_of_differential()
929
+ 1
930
+ """
931
+ return self._degree_of_differential
932
+
933
+ def differential(self, dim=None):
934
+ """
935
+ The differentials which make up the chain complex.
936
+
937
+ INPUT:
938
+
939
+ - ``dim`` -- element of the grading group (default:
940
+ ``None``); if this is ``None``, return a dictionary of all
941
+ of the differentials, or if this is a single element, return
942
+ the differential starting in that dimension
943
+
944
+ OUTPUT:
945
+
946
+ Either a dictionary of all of the differentials or a single
947
+ differential (i.e., a matrix).
948
+
949
+ EXAMPLES::
950
+
951
+ sage: D = ChainComplex({0: matrix(ZZ, 2, 2, [1,0,0,2])})
952
+ sage: D.differential(0)
953
+ [1 0]
954
+ [0 2]
955
+ sage: D.differential(-1)
956
+ []
957
+ sage: C = ChainComplex({0: identity_matrix(ZZ, 40)})
958
+ sage: diff = C.differential()
959
+ sage: diff[-1]
960
+ 40 x 0 dense matrix over Integer Ring (use the '.str()' method to see the entries)
961
+ sage: diff[0]
962
+ 40 x 40 dense matrix over Integer Ring (use the '.str()' method to see the entries)
963
+ sage: diff[1]
964
+ []
965
+ """
966
+ if dim is None:
967
+ return copy(self._diff)
968
+ dim = self.grading_group()(dim)
969
+ try:
970
+ return self._diff[dim]
971
+ except KeyError:
972
+ pass
973
+ # all differentials that are not 0x0 are in self._diff
974
+ # TODO: turn differentials into morphisms between free modules?
975
+ return matrix(self.base_ring(), 0, 0)
976
+
977
+ def dual(self):
978
+ """
979
+ The dual chain complex to ``self``.
980
+
981
+ Since all modules in ``self`` are free of finite rank, the
982
+ dual in dimension `n` is isomorphic to the original chain
983
+ complex in dimension `n`, and the corresponding boundary
984
+ matrix is the transpose of the matrix in the original complex.
985
+ This converts a chain complex to a cochain complex and vice versa.
986
+
987
+ EXAMPLES::
988
+
989
+ sage: C = ChainComplex({2: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
990
+ sage: C.degree_of_differential()
991
+ 1
992
+ sage: C.differential(2)
993
+ [3 0 0]
994
+ [0 0 0]
995
+ sage: C.dual().degree_of_differential()
996
+ -1
997
+ sage: C.dual().differential(3)
998
+ [3 0]
999
+ [0 0]
1000
+ [0 0]
1001
+ """
1002
+ data = {}
1003
+ deg = self.degree_of_differential()
1004
+ for d in self.differential():
1005
+ data[(d+deg)] = self.differential()[d].transpose()
1006
+ return ChainComplex(data, degree=-deg)
1007
+
1008
+ def free_module_rank(self, degree):
1009
+ r"""
1010
+ Return the rank of the free module at the given ``degree``.
1011
+
1012
+ INPUT:
1013
+
1014
+ - ``degree`` -- an element of the grading group
1015
+
1016
+ OUTPUT:
1017
+
1018
+ Integer. The rank of the free module `C_n` at the given degree
1019
+ `n`.
1020
+
1021
+ EXAMPLES::
1022
+
1023
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), 1: matrix(ZZ, [[0, 1]])})
1024
+ sage: [C.free_module_rank(i) for i in range(-2, 5)]
1025
+ [0, 0, 3, 2, 1, 0, 0]
1026
+ """
1027
+ try:
1028
+ return self._diff[degree].ncols()
1029
+ except KeyError:
1030
+ return ZZ.zero()
1031
+
1032
+ def free_module(self, degree=None):
1033
+ r"""
1034
+ Return the free module at fixed ``degree``, or their sum.
1035
+
1036
+ INPUT:
1037
+
1038
+ - ``degree`` -- an element of the grading group or ``None`` (default)
1039
+
1040
+ OUTPUT:
1041
+
1042
+ The free module `C_n` at the given degree `n`. If the degree
1043
+ is not specified, the sum `\bigoplus C_n` is returned.
1044
+
1045
+ EXAMPLES::
1046
+
1047
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), 1: matrix(ZZ, [[0, 1]])})
1048
+ sage: C.free_module()
1049
+ Ambient free module of rank 6 over the principal ideal domain Integer Ring
1050
+ sage: C.free_module(0)
1051
+ Ambient free module of rank 3 over the principal ideal domain Integer Ring
1052
+ sage: C.free_module(1)
1053
+ Ambient free module of rank 2 over the principal ideal domain Integer Ring
1054
+ sage: C.free_module(2)
1055
+ Ambient free module of rank 1 over the principal ideal domain Integer Ring
1056
+ """
1057
+ if degree is None:
1058
+ rank = sum([mat.ncols() for mat in self.differential().values()])
1059
+ else:
1060
+ rank = self.free_module_rank(degree)
1061
+ return FreeModule(self.base_ring(), rank)
1062
+
1063
+ def __hash__(self):
1064
+ """
1065
+ The hash is formed by combining the hashes of.
1066
+
1067
+ - the base ring
1068
+ - the differentials -- the matrices and their degrees
1069
+ - the degree of the differential of the chain complex
1070
+
1071
+ EXAMPLES::
1072
+
1073
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1074
+ sage: D = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1075
+ sage: hash(C) == hash(D)
1076
+ True
1077
+ """
1078
+ return (hash(self.base_ring())
1079
+ ^ hash(tuple(self.differential().items()))
1080
+ ^ hash(self.degree_of_differential()))
1081
+
1082
+ def __eq__(self, other):
1083
+ """
1084
+ Return ``True`` iff this chain complex is the same as other: that
1085
+ is, if the base rings and the matrices of the two are the
1086
+ same.
1087
+
1088
+ EXAMPLES::
1089
+
1090
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])},
1091
+ ....: base_ring=GF(2))
1092
+ sage: D = ChainComplex({0: matrix(GF(2), 2, 3, [1, 0, 0, 0, 0, 0]),
1093
+ ....: 1: matrix(ZZ, 0, 2),
1094
+ ....: 3: matrix(ZZ, 0, 0)}) # base_ring determined from the matrices
1095
+ sage: C == D
1096
+ True
1097
+ """
1098
+ if not isinstance(other, ChainComplex_class) or self.base_ring() != other.base_ring():
1099
+ return False
1100
+ R = self.base_ring()
1101
+ equal = True
1102
+ for d, mat in self.differential().items():
1103
+ if d not in other.differential():
1104
+ equal = equal and mat.ncols() == 0 and mat.nrows() == 0
1105
+ else:
1106
+ equal = (equal and
1107
+ other.differential()[d].change_ring(R) == mat.change_ring(R))
1108
+ for d, mat in other.differential().items():
1109
+ if d not in self.differential():
1110
+ equal = equal and mat.ncols() == 0 and mat.nrows() == 0
1111
+ return equal
1112
+
1113
+ def __ne__(self, other):
1114
+ """
1115
+ Return ``True`` iff this chain complex is not the same as other.
1116
+
1117
+ EXAMPLES::
1118
+
1119
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])},
1120
+ ....: base_ring=GF(2))
1121
+ sage: D = ChainComplex({0: matrix(GF(2), 2, 3, [1, 0, 0, 0, 0, 0]),
1122
+ ....: 1: matrix(ZZ, 0, 2),
1123
+ ....: 3: matrix(ZZ, 0, 0)}) # base_ring determined from the matrices
1124
+ sage: C != D
1125
+ False
1126
+ sage: E = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])},
1127
+ ....: base_ring=ZZ)
1128
+ sage: C != E
1129
+ True
1130
+ """
1131
+ return not self == other
1132
+
1133
+ def homology(self, deg=None, base_ring=None, generators=False,
1134
+ verbose=False, algorithm='pari'):
1135
+ r"""
1136
+ The homology of the chain complex.
1137
+
1138
+ INPUT:
1139
+
1140
+ - ``deg`` -- an element of the grading group for the chain
1141
+ complex (default: ``None``); the degree in which
1142
+ to compute homology -- if this is ``None``, return the
1143
+ homology in every degree in which the chain complex is
1144
+ possibly nonzero.
1145
+
1146
+ - ``base_ring`` -- a commutative ring (default: the
1147
+ base ring for the chain complex); must be either the
1148
+ integers `\ZZ` or a field
1149
+
1150
+ - ``generators`` -- boolean (default: ``False``); if
1151
+ ``True``, return generators for the homology groups along with
1152
+ the groups. See :issue:`6100`
1153
+
1154
+ - ``verbose`` -- boolean (default: ``False``); if
1155
+ ``True``, print some messages as the homology is computed
1156
+
1157
+ - ``algorithm`` -- string (default: ``'pari'``); the
1158
+ options are:
1159
+
1160
+ * ``'auto'``
1161
+ * ``'dhsw'``
1162
+ * ``'pari'``
1163
+
1164
+ See below for descriptions.
1165
+
1166
+ OUTPUT:
1167
+
1168
+ If the degree is specified, the homology in degree ``deg``.
1169
+ Otherwise, the homology in every dimension as a dictionary
1170
+ indexed by dimension.
1171
+
1172
+ ALGORITHM:
1173
+
1174
+ Over a
1175
+ field, just compute ranks and nullities, thus obtaining
1176
+ dimensions of the homology groups as vector spaces. Over the
1177
+ integers, compute Smith normal form of the boundary matrices
1178
+ defining the chain complex according to the value of
1179
+ ``algorithm``. If ``algorithm`` is ``'auto'``,
1180
+ then for each relatively small matrix, use the standard Sage
1181
+ method, which calls the Pari package. For any large matrix,
1182
+ reduce it using the Dumas, Heckenbach, Saunders, and Welker
1183
+ elimination algorithm [DHSW2003]_: see
1184
+ :func:`~sage.homology.matrix_utils.dhsw_snf` for details.
1185
+
1186
+ ``'no_chomp'`` is a synonym for ``'auto'``, maintained for
1187
+ backward-compatibility.
1188
+
1189
+ ``algorithm`` may also be ``'pari'`` or ``'dhsw'``, which
1190
+ forces the named algorithm to be used regardless of the size
1191
+ of the matrices.
1192
+
1193
+ As of this writing, ``'pari'`` is the fastest standard option.
1194
+
1195
+ .. WARNING::
1196
+
1197
+ This only works if the base ring is the integers or a
1198
+ field. Other values will return an error.
1199
+
1200
+ EXAMPLES::
1201
+
1202
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1203
+ sage: C.homology() # needs sage.libs.pari
1204
+ {0: Z x Z, 1: Z x C3}
1205
+ sage: C.homology(deg=1, base_ring=GF(3)) # needs sage.libs.pari
1206
+ Vector space of dimension 2 over Finite Field of size 3
1207
+ sage: D = ChainComplex({0: identity_matrix(ZZ, 4), 4: identity_matrix(ZZ, 30)})
1208
+ sage: D.homology() # needs sage.libs.pari
1209
+ {0: 0, 1: 0, 4: 0, 5: 0}
1210
+
1211
+ Generators: generators are given as a list of cycles, each of
1212
+ which is an element in the appropriate free module, and hence
1213
+ is represented as a vector. Each summand of the homology is
1214
+ listed separately, with a corresponding generator::
1215
+
1216
+ sage: C.homology(1, generators=True) # needs sage.libs.pari
1217
+ [(C3, Chain(1:(1, 0))), (Z, Chain(1:(0, 1)))]
1218
+
1219
+ Tests for :issue:`6100`, the Klein bottle with generators::
1220
+
1221
+ sage: d0 = matrix(ZZ, 0,1)
1222
+ sage: d1 = matrix(ZZ, 1,3, [[0,0,0]])
1223
+ sage: d2 = matrix(ZZ, 3,2, [[1,1], [1,-1], [-1,1]])
1224
+ sage: C_k = ChainComplex({0:d0, 1:d1, 2:d2}, degree=-1)
1225
+ sage: C_k.homology(generators=true) # needs sage.libs.pari
1226
+ {0: [(Z, Chain(0:(1)))],
1227
+ 1: [(C2, Chain(1:(0, 1, -1))), (Z, Chain(1:(0, 1, 0)))],
1228
+ 2: []}
1229
+
1230
+ From a torus using a field::
1231
+
1232
+ sage: T = simplicial_complexes.Torus() # needs sage.graphs
1233
+ sage: C_t = T.chain_complex() # needs sage.graphs
1234
+ sage: C_t.homology(base_ring=QQ, generators=True) # needs sage.graphs sage.libs.pari
1235
+ {0: [(Vector space of dimension 1 over Rational Field,
1236
+ Chain(0:(0, 0, 0, 0, 0, 0, 1)))],
1237
+ 1: [(Vector space of dimension 1 over Rational Field,
1238
+ Chain(1:(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 1))),
1239
+ (Vector space of dimension 1 over Rational Field,
1240
+ Chain(1:(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, -1, 0)))],
1241
+ 2: [(Vector space of dimension 1 over Rational Field,
1242
+ Chain(2:(1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1)))]}
1243
+ """
1244
+ if deg is not None and deg not in self.grading_group():
1245
+ raise ValueError('degree is not an element of the grading group')
1246
+
1247
+ if base_ring is None:
1248
+ base_ring = self.base_ring()
1249
+ if not (base_ring.is_field() or base_ring is ZZ):
1250
+ raise NotImplementedError('can only compute homology if the base ring is the integers or a field')
1251
+
1252
+ if algorithm not in ['dhsw', 'pari', 'auto', 'no_chomp']:
1253
+ raise NotImplementedError('algorithm not recognized')
1254
+
1255
+ if deg is None:
1256
+ deg = self.nonzero_degrees()
1257
+ if isinstance(deg, (list, tuple)):
1258
+ answer = {}
1259
+ for deg in self.nonzero_degrees():
1260
+ answer[deg] = self._homology_in_degree(deg, base_ring, verbose, generators, algorithm)
1261
+ return answer
1262
+ else:
1263
+ return self._homology_in_degree(deg, base_ring, verbose, generators, algorithm)
1264
+
1265
+ def _homology_in_degree(self, deg, base_ring, verbose, generators, algorithm):
1266
+ """
1267
+ Helper method for :meth:`homology`.
1268
+
1269
+ EXAMPLES::
1270
+
1271
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1272
+ sage: C.homology(1) == C._homology_in_degree(1, ZZ, False, False, 'auto') # needs sage.libs.pari
1273
+ True
1274
+ """
1275
+ if deg not in self.nonzero_degrees():
1276
+ zero_homology = HomologyGroup(0, base_ring)
1277
+ if generators:
1278
+ return (zero_homology, vector(base_ring, []))
1279
+ else:
1280
+ return zero_homology
1281
+ if verbose:
1282
+ print('Computing homology of the chain complex in dimension %s...' % deg)
1283
+
1284
+ fraction_field = base_ring.fraction_field()
1285
+
1286
+ def change_ring(X):
1287
+ if X.base_ring() is base_ring:
1288
+ return X
1289
+ return X.change_ring(base_ring)
1290
+
1291
+ # d_out is the differential going out of degree deg,
1292
+ # d_in is the differential entering degree deg
1293
+ differential = self.degree_of_differential()
1294
+ d_in = change_ring(self.differential(deg - differential))
1295
+ d_out = change_ring(self.differential(deg))
1296
+ d_out_rank = self.rank(deg, ring=fraction_field)
1297
+ d_out_nullity = d_out.ncols() - d_out_rank
1298
+
1299
+ if d_in.is_zero():
1300
+ if generators: # Include the generators of the nullspace
1301
+ return [(HomologyGroup(1, base_ring), self({deg: gen}))
1302
+ for gen in d_out.right_kernel().basis()]
1303
+ else:
1304
+ return HomologyGroup(d_out_nullity, base_ring)
1305
+
1306
+ if generators:
1307
+ orders, gens = self._homology_generators_snf(d_in, d_out, d_out_rank)
1308
+ answer = [(HomologyGroup(1, base_ring, [order]), self({deg: gen}))
1309
+ for order, gen in zip(orders, gens)]
1310
+ else:
1311
+ if base_ring.is_field():
1312
+ d_in_rank = self.rank(deg-differential, ring=base_ring)
1313
+ answer = HomologyGroup(d_out_nullity - d_in_rank, base_ring)
1314
+ elif base_ring == ZZ:
1315
+ if d_in.ncols() == 0:
1316
+ all_divs = [0] * d_out_nullity
1317
+ else:
1318
+ if algorithm in ['auto', 'no_chomp']:
1319
+ if ((d_in.ncols() > 300 and d_in.nrows() > 300)
1320
+ or (min(d_in.ncols(), d_in.nrows()) > 100 and
1321
+ d_in.ncols() + d_in.nrows() > 600)):
1322
+ algorithm = 'dhsw'
1323
+ else:
1324
+ algorithm = 'pari'
1325
+ if algorithm == 'dhsw':
1326
+ from sage.homology.matrix_utils import dhsw_snf
1327
+ all_divs = dhsw_snf(d_in, verbose=verbose)
1328
+ elif algorithm == 'pari':
1329
+ all_divs = d_in.elementary_divisors(algorithm)
1330
+ else:
1331
+ raise ValueError('unsupported algorithm')
1332
+ all_divs = all_divs[:d_out_nullity]
1333
+ # divisors equal to 1 produce trivial
1334
+ # summands, so filter them out
1335
+ divisors = [x for x in all_divs if x != 1]
1336
+ answer = HomologyGroup(len(divisors), base_ring, divisors)
1337
+ else:
1338
+ raise NotImplementedError('only base rings ZZ and fields are supported')
1339
+ return answer
1340
+
1341
+ def _homology_generators_snf(self, d_in, d_out, d_out_rank):
1342
+ """
1343
+ Compute the homology generators using the Smith normal form.
1344
+
1345
+ EXAMPLES::
1346
+
1347
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1348
+ sage: C.homology(1) # needs sage.libs.pari
1349
+ Z x C3
1350
+ sage: C._homology_generators_snf(C.differential(0), C.differential(1), 0) # needs sage.libs.pari
1351
+ ([3, 0], [(1, 0), (0, 1)])
1352
+ """
1353
+ # Find the kernel of the out-going differential.
1354
+ K = d_out.right_kernel().matrix().transpose().change_ring(d_out.base_ring())
1355
+
1356
+ # Compute the induced map to the kernel
1357
+ S = K.augment(d_in).hermite_form()
1358
+ d_in_induced = S.submatrix(row=0, nrows=d_in.nrows()-d_out_rank,
1359
+ col=d_in.nrows()-d_out_rank, ncols=d_in.ncols())
1360
+
1361
+ # Find the SNF of the induced matrix and appropriate generators
1362
+ (N, P, Q) = d_in_induced.smith_form()
1363
+ all_divs = [0]*N.nrows()
1364
+ non_triv = 0
1365
+ for i in range(0, N.nrows()):
1366
+ if i >= N.ncols():
1367
+ break
1368
+ all_divs[i] = N[i][i]
1369
+ if N[i][i] == 1:
1370
+ non_triv = non_triv + 1
1371
+ divisors = [x for x in all_divs if x != 1]
1372
+ gens = (K * P.inverse().submatrix(col=non_triv)).columns()
1373
+ return divisors, gens
1374
+
1375
+ def betti(self, deg=None, base_ring=None):
1376
+ """
1377
+ The Betti number of the chain complex.
1378
+
1379
+ That is, write the homology in this degree as a direct sum
1380
+ of a free module and a torsion module; the Betti number is the
1381
+ rank of the free summand.
1382
+
1383
+ INPUT:
1384
+
1385
+ - ``deg`` -- an element of the grading group for the chain
1386
+ complex or ``None`` (default: ``None``); if ``None``,
1387
+ then return every Betti number, as a dictionary indexed by
1388
+ degree, or if an element of the grading group, then return
1389
+ the Betti number in that degree
1390
+
1391
+ - ``base_ring`` -- a commutative ring (default: the
1392
+ base ring for the chain complex); compute homology with
1393
+ these coefficients -- must be either the integers or a
1394
+ field
1395
+
1396
+ OUTPUT:
1397
+
1398
+ The Betti number in degree ``deg`` -- the rank of the free
1399
+ part of the homology module in this degree.
1400
+
1401
+ EXAMPLES::
1402
+
1403
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1404
+ sage: C.betti(0)
1405
+ 2
1406
+ sage: [C.betti(n) for n in range(5)]
1407
+ [2, 1, 0, 0, 0]
1408
+ sage: C.betti()
1409
+ {0: 2, 1: 1}
1410
+
1411
+ sage: D = ChainComplex({0: matrix(GF(5), [[3, 1],[1, 2]])})
1412
+ sage: D.betti()
1413
+ {0: 1, 1: 1}
1414
+ """
1415
+ if base_ring is None:
1416
+ base_ring = self.base_ring()
1417
+ try:
1418
+ base_ring = base_ring.fraction_field()
1419
+ except AttributeError:
1420
+ raise NotImplementedError('only implemented if the base ring is ZZ or a field')
1421
+ H = self.homology(deg, base_ring=base_ring)
1422
+ if isinstance(H, dict):
1423
+ return {deg: homology_group.dimension()
1424
+ for deg, homology_group in H.items()}
1425
+ else:
1426
+ return H.dimension()
1427
+
1428
+ def torsion_list(self, max_prime, min_prime=2):
1429
+ r"""
1430
+ Look for torsion in this chain complex by computing its mod `p`
1431
+ homology for a range of primes `p`.
1432
+
1433
+ INPUT:
1434
+
1435
+ - ``max_prime`` -- prime number; search for torsion mod `p` for
1436
+ all `p` strictly less than this number
1437
+
1438
+ - ``min_prime`` -- prime (default: 2); search for
1439
+ torsion mod `p` for primes at least as big as this
1440
+
1441
+ Return a list of pairs `(p, d)` where `p` is a prime at which
1442
+ there is torsion and `d` is a list of dimensions in which this
1443
+ torsion occurs.
1444
+
1445
+ The base ring for the chain complex must be the integers; if
1446
+ not, an error is raised.
1447
+
1448
+ ALGORITHM:
1449
+
1450
+ Let `C` denote the chain complex. Let `P` equal
1451
+ ``max_prime``. Compute the mod `P` homology of `C`, and use
1452
+ this as the base-line computation: the assumption is that this
1453
+ is isomorphic to the integral homology tensored with
1454
+ `\GF{P}`. Then compute the mod `p` homology for a range of
1455
+ primes `p`, and record whenever the answer differs from the
1456
+ base-line answer.
1457
+
1458
+ EXAMPLES::
1459
+
1460
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1461
+ sage: C.homology() # needs sage.libs.pari
1462
+ {0: Z x Z, 1: Z x C3}
1463
+ sage: C.torsion_list(11) # needs sage.rings.finite_rings
1464
+ [(3, [1])]
1465
+ sage: C = ChainComplex([matrix(ZZ, 1, 1, [2]), matrix(ZZ, 1, 1), matrix(1, 1, [3])])
1466
+ sage: C.homology(1) # needs sage.libs.pari
1467
+ C2
1468
+ sage: C.homology(3) # needs sage.libs.pari
1469
+ C3
1470
+ sage: C.torsion_list(5) # needs sage.rings.finite_rings
1471
+ [(2, [1]), (3, [3])]
1472
+ """
1473
+ if self.base_ring() != ZZ:
1474
+ raise NotImplementedError('only implemented for base ring the integers')
1475
+
1476
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
1477
+
1478
+ answer = []
1479
+ torsion_free = self.betti(base_ring=GF(max_prime))
1480
+ for p in prime_range(min_prime, max_prime):
1481
+ mod_p_betti = self.betti(base_ring=GF(p))
1482
+ if mod_p_betti != torsion_free:
1483
+ diff_dict = {}
1484
+ temp_diff = {}
1485
+ D = self.degree_of_differential()
1486
+ for i in torsion_free:
1487
+ temp_diff[i] = mod_p_betti.get(i, 0) - torsion_free[i]
1488
+ for i in temp_diff:
1489
+ if temp_diff[i] > 0:
1490
+ if i+D in diff_dict:
1491
+ lower = diff_dict[i+D]
1492
+ else:
1493
+ lower = 0
1494
+ current = temp_diff[i]
1495
+ if current > lower:
1496
+ diff_dict[i] = current - lower
1497
+ if i-D in diff_dict:
1498
+ diff_dict[i-D] -= current - lower
1499
+ differences = [i for i, di in diff_dict.items() if di != 0]
1500
+ answer.append((p, differences))
1501
+ return answer
1502
+
1503
+ def _Hom_(self, other, category=None):
1504
+ """
1505
+ Return the set of chain maps between chain complexes ``self``
1506
+ and ``other``.
1507
+
1508
+ EXAMPLES::
1509
+
1510
+ sage: # needs sage.graphs
1511
+ sage: S = simplicial_complexes.Sphere(2)
1512
+ sage: T = simplicial_complexes.Torus()
1513
+ sage: C = S.chain_complex(augmented=True, cochain=True)
1514
+ sage: D = T.chain_complex(augmented=True, cochain=True)
1515
+ sage: Hom(C, D) # indirect doctest
1516
+ Set of Morphisms from Chain complex with at most 4 nonzero terms over
1517
+ Integer Ring to Chain complex with at most 4 nonzero terms over Integer
1518
+ Ring in Category of chain complexes over Integer Ring
1519
+ """
1520
+ from sage.homology.chain_complex_homspace import ChainComplexHomspace
1521
+ return ChainComplexHomspace(self, other)
1522
+
1523
+ def _flip_(self):
1524
+ """
1525
+ Flip chain complex upside down (degree `n` gets changed to
1526
+ degree `-n`), thus turning a chain complex into a cochain complex
1527
+ without changing the homology (except for flipping it, too).
1528
+
1529
+ EXAMPLES::
1530
+
1531
+ sage: C = ChainComplex({2: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1532
+ sage: C.degree_of_differential()
1533
+ 1
1534
+ sage: C.differential(2)
1535
+ [3 0 0]
1536
+ [0 0 0]
1537
+ sage: C._flip_().degree_of_differential()
1538
+ -1
1539
+ sage: C._flip_().differential(-2)
1540
+ [3 0 0]
1541
+ [0 0 0]
1542
+ """
1543
+ data = {}
1544
+ deg = self.degree_of_differential()
1545
+ for d in self.differential():
1546
+ data[-d] = self.differential()[d]
1547
+ return ChainComplex(data, degree=-deg)
1548
+
1549
+ def shift(self, n=1):
1550
+ """
1551
+ Shift this chain complex `n` times.
1552
+
1553
+ INPUT:
1554
+
1555
+ - ``n`` -- integer (default: 1)
1556
+
1557
+ The *shift* operation is also sometimes called *translation* or
1558
+ *suspension*.
1559
+
1560
+ To shift a chain complex by `n`, shift its entries up by `n`
1561
+ (if it is a chain complex) or down by `n` (if it is a cochain
1562
+ complex); that is, shifting by 1 always shifts in the opposite
1563
+ direction of the differential. In symbols, if `C` is a chain
1564
+ complex and `C[n]` is its `n`-th shift, then `C[n]_j =
1565
+ C_{j-n}`. The differential in the shift `C[n]` is obtained by
1566
+ multiplying each differential in `C` by `(-1)^n`.
1567
+
1568
+ Caveat: different sources use different conventions for
1569
+ shifting: what we call `C[n]` might be called `C[-n]` in some
1570
+ places. See for example.
1571
+ https://ncatlab.org/nlab/show/suspension+of+a+chain+complex
1572
+ (which uses `C[n]` as we do but acknowledges `C[-n]`) or 1.2.8
1573
+ in [Wei1994]_ (which uses `C[-n]`).
1574
+
1575
+ EXAMPLES::
1576
+
1577
+ sage: # needs sage.graphs
1578
+ sage: S1 = simplicial_complexes.Sphere(1).chain_complex()
1579
+ sage: S1.shift(1).differential(2) == -S1.differential(1)
1580
+ True
1581
+ sage: S1.shift(2).differential(3) == S1.differential(1)
1582
+ True
1583
+ sage: S1.shift(3).homology(4)
1584
+ Z
1585
+
1586
+ For cochain complexes, shifting goes in the other
1587
+ direction. Topologically, this makes sense if we grade the
1588
+ cochain complex for a space negatively::
1589
+
1590
+ sage: # needs sage.graphs
1591
+ sage: T = simplicial_complexes.Torus()
1592
+ sage: co_T = T.chain_complex()._flip_()
1593
+ sage: co_T.homology()
1594
+ {-2: Z, -1: Z x Z, 0: Z}
1595
+ sage: co_T.degree_of_differential()
1596
+ 1
1597
+ sage: co_T.shift(2).homology()
1598
+ {-4: Z, -3: Z x Z, -2: Z}
1599
+
1600
+ You can achieve the same result by tensoring (on the left, to
1601
+ get the signs right) with a rank one free module in degree
1602
+ ``-n * deg``, if ``deg`` is the degree of the differential::
1603
+
1604
+ sage: C = ChainComplex({-2: matrix(ZZ, 0, 1)})
1605
+ sage: C.tensor(co_T).homology() # needs sage.graphs
1606
+ {-4: Z, -3: Z x Z, -2: Z}
1607
+ """
1608
+ deg = self.degree_of_differential()
1609
+ shift = n * deg
1610
+ sgn = (-1)**n
1611
+ return ChainComplex({k-shift: sgn * self._diff[k] for k in self._diff},
1612
+ degree_of_differential=deg)
1613
+
1614
+ def _repr_(self):
1615
+ """
1616
+ Print representation.
1617
+
1618
+ EXAMPLES::
1619
+
1620
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1621
+ sage: C
1622
+ Chain complex with at most 2 nonzero terms over Integer Ring
1623
+ """
1624
+ diffs = [mat for mat in self._diff.values() if mat.nrows() + mat.ncols() > 0]
1625
+ if len(diffs) == 0:
1626
+ s = 'Trivial chain complex'
1627
+ else:
1628
+ s = 'Chain complex with at most {0} nonzero terms'.format(len(diffs)-1)
1629
+ s += ' over {0}'.format(self.base_ring())
1630
+ return s
1631
+
1632
+ def _ascii_art_(self):
1633
+ """
1634
+ Return an ascii art representation.
1635
+
1636
+ Note that arrows go to the left so that composition of
1637
+ differentials is the usual matrix multiplication.
1638
+
1639
+ EXAMPLES::
1640
+
1641
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), 1:zero_matrix(1,2)})
1642
+ sage: ascii_art(C)
1643
+ [3 0 0]
1644
+ [0 0] [0 0 0]
1645
+ 0 <-- C_2 <------ C_1 <-------- C_0 <-- 0
1646
+
1647
+ sage: one = matrix(ZZ, [[1]])
1648
+ sage: D = ChainComplex({0: one, 2: one, 6:one})
1649
+ sage: ascii_art(D)
1650
+ [1] [1] [0] [1]
1651
+ 0 <-- C_7 <---- C_6 <-- 0 ... 0 <-- C_3 <---- C_2 <---- C_1 <---- C_0 <-- 0
1652
+ sage: ascii_art(ChainComplex(base_ring=ZZ))
1653
+ 0
1654
+ """
1655
+ from sage.typeset.ascii_art import AsciiArt
1656
+
1657
+ def arrow_art(n):
1658
+ d_n = self.differential(n)
1659
+ if d_n.nrows() == 0 or d_n.ncols() == 0:
1660
+ return AsciiArt(['<--'])
1661
+ d_str = [' '+line+' ' for line in str(d_n).splitlines()]
1662
+ arrow = '<' + '-'*(len(d_str[0])-1)
1663
+ d_str.append(arrow)
1664
+ return AsciiArt(d_str)
1665
+
1666
+ def module_art(n):
1667
+ C_n = self.free_module(n)
1668
+ if C_n.rank() == 0:
1669
+ return AsciiArt([' 0 '])
1670
+ else:
1671
+ return AsciiArt([' C_{0} '.format(n)])
1672
+
1673
+ result = []
1674
+ for ordered in self.ordered_degrees():
1675
+ ordered = list(reversed(ordered))
1676
+ if len(ordered) == 0:
1677
+ return AsciiArt(['0'])
1678
+ result_ordered = module_art(ordered[0] + self.degree_of_differential())
1679
+ for n in ordered:
1680
+ result_ordered += arrow_art(n) + module_art(n)
1681
+ result = [result_ordered] + result
1682
+ if len(result) == 0:
1683
+ return AsciiArt(['0'])
1684
+ concatenated = result[0]
1685
+ for r in result[1:]:
1686
+ concatenated += AsciiArt([' ... ']) + r
1687
+ return concatenated
1688
+
1689
+ def _unicode_art_(self):
1690
+ """
1691
+ Return a unicode art representation.
1692
+
1693
+ Note that arrows go to the left so that composition of
1694
+ differentials is the usual matrix multiplication.
1695
+
1696
+ EXAMPLES::
1697
+
1698
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0]), 1:zero_matrix(1,2)})
1699
+ sage: unicode_art(C)
1700
+ ⎛3 0 0⎞
1701
+ (0 0) ⎝0 0 0⎠
1702
+ 0 <── C_2 <──── C_1 <────── C_0 <── 0
1703
+
1704
+ sage: one = matrix(ZZ, [[1]])
1705
+ sage: D = ChainComplex({0: one, 2: one, 6:one})
1706
+ sage: unicode_art(D)
1707
+ (1) (1) (0) (1)
1708
+ 0 <── C_7 <── C_6 <── 0 ... 0 <── C_3 <── C_2 <── C_1 <── C_0 <── 0
1709
+
1710
+ TESTS:
1711
+
1712
+ check that :issue:`37678` is fixed::
1713
+
1714
+ sage: C = ChainComplex(base_ring=ZZ)
1715
+ sage: unicode_art(C)
1716
+ 0
1717
+ """
1718
+ from sage.typeset.unicode_art import UnicodeArt
1719
+
1720
+ def arrow_art(n):
1721
+ d_n = self.differential(n)
1722
+ if not d_n.nrows() or not d_n.ncols():
1723
+ return UnicodeArt(['<──'])
1724
+ d_str = list(d_n._unicode_art_())
1725
+ arrow = '<' + '─' * (len(d_str[0]) - 1)
1726
+ d_str.append(arrow)
1727
+ return UnicodeArt(d_str)
1728
+
1729
+ def module_art(n):
1730
+ C_n = self.free_module(n)
1731
+ if not C_n.rank():
1732
+ return UnicodeArt([' 0 '])
1733
+ else:
1734
+ return UnicodeArt([' C_{0} '.format(n)])
1735
+
1736
+ result = []
1737
+ for ordered in self.ordered_degrees():
1738
+ ordered = list(reversed(ordered))
1739
+ if not ordered:
1740
+ return UnicodeArt(['0'])
1741
+ result_ordered = module_art(ordered[0] + self.degree_of_differential())
1742
+ for n in ordered:
1743
+ result_ordered += arrow_art(n) + module_art(n)
1744
+ result = [result_ordered] + result
1745
+ if len(result) == 0:
1746
+ return UnicodeArt(['0'])
1747
+ concatenated = result[0]
1748
+ for r in result[1:]:
1749
+ concatenated += UnicodeArt([' ... ']) + r
1750
+ return concatenated
1751
+
1752
+ def _latex_(self):
1753
+ """
1754
+ LaTeX print representation.
1755
+
1756
+ EXAMPLES::
1757
+
1758
+ sage: C = ChainComplex({0: matrix(ZZ, 2, 3, [3, 0, 0, 0, 0, 0])})
1759
+ sage: C._latex_()
1760
+ '\\Bold{Z}^{3} \\xrightarrow{d_{0}} \\Bold{Z}^{2}'
1761
+
1762
+ sage: ChainComplex()._latex_()
1763
+ '0'
1764
+
1765
+ sage: G = AdditiveAbelianGroup([0, 0])
1766
+ sage: m = matrix([0])
1767
+ sage: C = ChainComplex(grading_group=G, degree=G(vector([1,2])), data={G.zero(): m}) # needs sage.libs.pari
1768
+ sage: C._latex_() # needs sage.libs.pari
1769
+ '\\Bold{Z}^{1} \\xrightarrow{d_{\\text{\\texttt{(0,{ }0)}}}} \\Bold{Z}^{1}'
1770
+ """
1771
+ # Warning: this is likely to screw up if, for example, the
1772
+ # degree of the differential is 2 and there are nonzero terms
1773
+ # in consecutive dimensions (e.g., in dimensions 0 and 1). In
1774
+ # such cases, the representation might show a differential
1775
+ # connecting these terms, although the differential goes from
1776
+ # dimension 0 to dimension 2, and from dimension 1 to
1777
+ # dimension 3, etc. I don't know how much effort should be
1778
+ # put into trying to fix this.
1779
+ string = ""
1780
+ diffs = self._diff
1781
+ if len(diffs) == 0:
1782
+ return "0"
1783
+ deg = self.degree_of_differential()
1784
+ ring = self.base_ring()
1785
+ backwards = bool(deg < 0)
1786
+ sorted_list = sorted(diffs.keys(), reverse=backwards)
1787
+ if len(diffs) <= 6:
1788
+ for n in sorted_list[1:-1]:
1789
+ mat = diffs[n]
1790
+ string += _latex_module(ring, mat.ncols())
1791
+ string += " \\xrightarrow{d_{%s}} " % latex(n)
1792
+ mat = diffs[sorted_list[-1]]
1793
+ string += _latex_module(ring, mat.ncols())
1794
+ else:
1795
+ for n in sorted_list[:2]:
1796
+ mat = diffs[n]
1797
+ string += _latex_module(ring, mat.ncols())
1798
+ string += " \\xrightarrow{d_{%s}} " % latex(n)
1799
+ string += "\\dots "
1800
+ n = sorted_list[-2]
1801
+ string += "\\xrightarrow{d_{%s}} " % latex(n)
1802
+ mat = diffs[sorted_list[-1]]
1803
+ string += _latex_module(ring, mat.ncols())
1804
+ return string
1805
+
1806
+ def cartesian_product(self, *factors, **kwds):
1807
+ r"""
1808
+ Return the direct sum (Cartesian product) of ``self`` with ``D``.
1809
+
1810
+ Let `C` and `D` be two chain complexes with differentials
1811
+ `\partial_C` and `\partial_D`, respectively, of the same degree (so
1812
+ they must also have the same grading group).
1813
+ The direct sum `S = C \oplus D` is a chain complex given by
1814
+ `S_i = C_i \oplus D_i` with differential
1815
+ `\partial = \partial_C \oplus \partial_D`.
1816
+
1817
+ INPUT:
1818
+
1819
+ - ``subdivide`` -- boolean (default: ``False``); whether to subdivide the
1820
+ the differential matrices
1821
+
1822
+ EXAMPLES::
1823
+
1824
+ sage: R.<x,y> = QQ[]
1825
+ sage: C = ChainComplex([matrix([[-y],[x]]), matrix([[x, y]])])
1826
+ sage: D = ChainComplex([matrix([[x-y]]), matrix([[0], [0]])])
1827
+ sage: ascii_art(C.cartesian_product(D))
1828
+ [x y 0] [ -y 0]
1829
+ [0 0 0] [ x 0]
1830
+ [0 0 0] [ 0 x - y]
1831
+ 0 <-- C_2 <-------- C_1 <-------------- C_0 <-- 0
1832
+
1833
+ sage: D = ChainComplex({1:matrix([[x-y]]), 4:matrix([[x], [y]])})
1834
+ sage: ascii_art(D)
1835
+ [x]
1836
+ [y] [x - y]
1837
+ 0 <-- C_5 <---- C_4 <-- 0 <-- C_2 <-------- C_1 <-- 0
1838
+ sage: ascii_art(cartesian_product([C, D]))
1839
+ [-y]
1840
+ [x] [ x y 0] [ x]
1841
+ [y] [ 0 0 x - y] [ 0]
1842
+ 0 <-- C_5 <---- C_4 <-- 0 <-- C_2 <-------------------- C_1 <----- C_0 <-- 0
1843
+
1844
+ The degrees of the differentials must agree::
1845
+
1846
+ sage: C = ChainComplex({1:matrix([[x]])}, degree_of_differential=-1)
1847
+ sage: D = ChainComplex({1:matrix([[x]])}, degree_of_differential=1)
1848
+ sage: C.cartesian_product(D)
1849
+ Traceback (most recent call last):
1850
+ ...
1851
+ ValueError: the degrees of the differentials must match
1852
+
1853
+ TESTS::
1854
+
1855
+ sage: C = ChainComplex({2:matrix([[-1],[2]]), 1:matrix([[2, 1]])},
1856
+ ....: degree_of_differential=-1)
1857
+ sage: ascii_art(C.cartesian_product(C, subdivide=True))
1858
+ [-1| 0]
1859
+ [ 2| 0]
1860
+ [2 1|0 0] [--+--]
1861
+ [---+---] [ 0|-1]
1862
+ [0 0|2 1] [ 0| 2]
1863
+ 0 <-- C_0 <---------- C_1 <-------- C_2 <-- 0
1864
+
1865
+ ::
1866
+
1867
+ sage: R.<x,y,z> = QQ[]
1868
+ sage: C1 = ChainComplex({1:matrix([[x]])})
1869
+ sage: C2 = ChainComplex({1:matrix([[y]])})
1870
+ sage: C3 = ChainComplex({1:matrix([[z]])})
1871
+ sage: ascii_art(cartesian_product([C1, C2, C3]))
1872
+ [x 0 0]
1873
+ [0 y 0]
1874
+ [0 0 z]
1875
+ 0 <-- C_2 <-------- C_1 <-- 0
1876
+ sage: ascii_art(C1.cartesian_product([C2, C3], subdivide=True))
1877
+ [x|0|0]
1878
+ [-+-+-]
1879
+ [0|y|0]
1880
+ [-+-+-]
1881
+ [0|0|z]
1882
+ 0 <-- C_2 <-------- C_1 <-- 0
1883
+
1884
+ ::
1885
+
1886
+ sage: # needs sage.libs.pari
1887
+ sage: R.<x> = ZZ[]
1888
+ sage: G = AdditiveAbelianGroup([0,7])
1889
+ sage: d = {G(vector([1,1])):matrix([[x]])}
1890
+ sage: C = ChainComplex(d, grading_group=G, degree=G(vector([2,1])))
1891
+ sage: ascii_art(C.cartesian_product(C))
1892
+ [x 0]
1893
+ [0 x]
1894
+ 0 <-- C_(3, 2) <------ C_(1, 1) <-- 0
1895
+ """
1896
+ if not factors:
1897
+ return self
1898
+ if isinstance(factors[0], (list, tuple)):
1899
+ factors = factors[0]
1900
+ deg_diff = self.degree_of_differential()
1901
+ if any(D.degree_of_differential() != deg_diff for D in factors):
1902
+ raise ValueError("the degrees of the differentials must match")
1903
+ if any(D.grading_group() != self._grading_group for D in factors):
1904
+ raise ValueError("the grading groups must match")
1905
+
1906
+ factors = [self] + list(factors)
1907
+ R = self.base_ring()
1908
+ zero = matrix(R, [])
1909
+ subdivide = kwds.get('subdivide', False)
1910
+ diffs = [D.differential() for D in factors]
1911
+ keys = reduce(lambda X, d: X.union(d.keys()), diffs, set())
1912
+ ret = {k: matrix.block_diagonal([d.get(k, zero) for d in diffs],
1913
+ subdivide=subdivide)
1914
+ for k in keys}
1915
+ return ChainComplex(ret, degree_of_differential=deg_diff,
1916
+ grading_group=self._grading_group)
1917
+
1918
+ def tensor(self, *factors, **kwds):
1919
+ r"""
1920
+ Return the tensor product of ``self`` with ``D``.
1921
+
1922
+ Let `C` and `D` be two chain complexes with differentials
1923
+ `\partial_C` and `\partial_D`, respectively, of the same degree (so
1924
+ they must also have the same grading group).
1925
+ The tensor product `S = C \otimes D` is a chain complex given by
1926
+
1927
+ .. MATH::
1928
+
1929
+ S_i = \bigoplus_{a+b=i} C_a \otimes D_b
1930
+
1931
+ with differential
1932
+
1933
+ .. MATH::
1934
+
1935
+ \partial(x \otimes y) = \partial_C x \otimes y
1936
+ + (-1)^{|a| \cdot |\partial_D|} x \otimes \partial_D y
1937
+
1938
+ for `x \in C_a` and `y \in D_b`, where `|a|` is the degree of `a` and
1939
+ `|\partial_D|` is the degree of `\partial_D`.
1940
+
1941
+ .. WARNING::
1942
+
1943
+ If the degree of the differential is even, then this may not
1944
+ result in a valid chain complex.
1945
+
1946
+ INPUT:
1947
+
1948
+ - ``subdivide`` -- boolean (default: ``False``); whether to subdivide the
1949
+ the differential matrices
1950
+
1951
+ .. TODO::
1952
+
1953
+ Make subdivision work correctly on multiple factors.
1954
+
1955
+ EXAMPLES::
1956
+
1957
+ sage: R.<x,y,z> = QQ[]
1958
+ sage: C1 = ChainComplex({1:matrix([[x]])}, degree_of_differential=-1)
1959
+ sage: C2 = ChainComplex({1:matrix([[y]])}, degree_of_differential=-1)
1960
+ sage: C3 = ChainComplex({1:matrix([[z]])}, degree_of_differential=-1)
1961
+ sage: ascii_art(C1.tensor(C2))
1962
+ [ x]
1963
+ [y x] [-y]
1964
+ 0 <-- C_0 <------ C_1 <----- C_2 <-- 0
1965
+ sage: ascii_art(C1.tensor(C2).tensor(C3))
1966
+ [ y x 0] [ x]
1967
+ [-z 0 x] [-y]
1968
+ [z y x] [ 0 -z -y] [ z]
1969
+ 0 <-- C_0 <-------- C_1 <----------- C_2 <----- C_3 <-- 0
1970
+
1971
+ ::
1972
+
1973
+ sage: C = ChainComplex({2:matrix([[-y],[x]]), 1:matrix([[x, y]])},
1974
+ ....: degree_of_differential=-1); ascii_art(C)
1975
+ [-y]
1976
+ [x y] [ x]
1977
+ 0 <-- C_0 <------ C_1 <----- C_2 <-- 0
1978
+ sage: T = C.tensor(C)
1979
+ sage: T.differential(1)
1980
+ [x y x y]
1981
+ sage: T.differential(2)
1982
+ [-y x 0 y 0 0]
1983
+ [ x 0 x 0 y 0]
1984
+ [ 0 -x -y 0 0 -y]
1985
+ [ 0 0 0 -x -y x]
1986
+ sage: T.differential(3)
1987
+ [ x y 0 0]
1988
+ [ y 0 -y 0]
1989
+ [-x 0 0 -y]
1990
+ [ 0 y x 0]
1991
+ [ 0 -x 0 x]
1992
+ [ 0 0 x y]
1993
+ sage: T.differential(4)
1994
+ [-y]
1995
+ [ x]
1996
+ [-y]
1997
+ [ x]
1998
+
1999
+ The degrees of the differentials must agree::
2000
+
2001
+ sage: C1p = ChainComplex({1:matrix([[x]])}, degree_of_differential=1)
2002
+ sage: C1.tensor(C1p)
2003
+ Traceback (most recent call last):
2004
+ ...
2005
+ ValueError: the degrees of the differentials must match
2006
+
2007
+ TESTS::
2008
+
2009
+ sage: R.<x,y,z> = QQ[]
2010
+ sage: C1 = ChainComplex({1:matrix([[x]])})
2011
+ sage: C2 = ChainComplex({1:matrix([[y]])})
2012
+ sage: C3 = ChainComplex({1:matrix([[z]])})
2013
+ sage: ascii_art(tensor([C1, C2, C3]))
2014
+ [-y -z 0] [ z]
2015
+ [ x 0 -z] [-y]
2016
+ [x y z] [ 0 x y] [ x]
2017
+ 0 <-- C_6 <-------- C_5 <----------- C_4 <----- C_3 <-- 0
2018
+
2019
+ ::
2020
+
2021
+ sage: # needs sage.libs.pari
2022
+ sage: R.<x,y> = ZZ[]
2023
+ sage: G = AdditiveAbelianGroup([0,7])
2024
+ sage: d1 = {G(vector([1,1])):matrix([[x]])}
2025
+ sage: C1 = ChainComplex(d1, grading_group=G, degree=G(vector([2,1])))
2026
+ sage: d2 = {G(vector([3,0])):matrix([[y]])}
2027
+ sage: C2 = ChainComplex(d2, grading_group=G, degree=G(vector([2,1])))
2028
+ sage: ascii_art(C1.tensor(C2))
2029
+ [y]
2030
+ [ x -y] [x]
2031
+ 0 <-- C_(8, 3) <-------- C_(6, 2) <---- C_(4, 1) <-- 0
2032
+
2033
+ Check that :issue:`21760` is fixed::
2034
+
2035
+ sage: C = ChainComplex({0: matrix(ZZ, 0, 2)}, degree=-1)
2036
+ sage: ascii_art(C)
2037
+ 0 <-- C_0 <-- 0
2038
+ sage: T = C.tensor(C)
2039
+ sage: ascii_art(T)
2040
+ 0 <-- C_0 <-- 0
2041
+ sage: T.free_module_rank(0)
2042
+ 4
2043
+ """
2044
+ if not factors:
2045
+ return self
2046
+ if isinstance(factors[0], (list, tuple)):
2047
+ factors = factors[0]
2048
+ deg_diff = self.degree_of_differential()
2049
+ if any(D.degree_of_differential() != deg_diff for D in factors):
2050
+ raise ValueError("the degrees of the differentials must match")
2051
+ if any(D.grading_group() != self._grading_group for D in factors):
2052
+ raise ValueError("the grading groups must match")
2053
+
2054
+ R = self.base_ring()
2055
+ zero = R.zero()
2056
+ subdivide = kwds.get('subdivide', False)
2057
+ ret = self
2058
+
2059
+ if self._grading_group is ZZ:
2060
+ def scalar(a):
2061
+ return (-1)**(a * deg_diff)
2062
+ else:
2063
+ def scalar(a):
2064
+ return (-1)**(sum(a) * sum(deg_diff))
2065
+
2066
+ for D in factors:
2067
+ # Setup
2068
+ d = ret.differential()
2069
+ dD = D.differential()
2070
+ deg = sorted((k, ret.free_module_rank(k)) for k in d
2071
+ if ret.free_module_rank(k) > 0)
2072
+ degD = sorted((k, D.free_module_rank(k)) for k in dD
2073
+ if D.free_module_rank(k) > 0)
2074
+ diff = {}
2075
+
2076
+ # Our choice for tensor products will be x # y = x1 * y + x2 * y + ...
2077
+
2078
+ # Generate the data for the differential
2079
+ for a, r in deg:
2080
+ for b, s in degD:
2081
+ rp = d[a].nrows()
2082
+ sp = dD[b].nrows()
2083
+ if a+b not in diff:
2084
+ diff[a+b] = {}
2085
+ mor = diff[a+b]
2086
+ cur = {}
2087
+ cur[(a+deg_diff, b)] = []
2088
+ cur[(a, b+deg_diff)] = []
2089
+
2090
+ for i in range(r):
2091
+ for j in range(s):
2092
+ # \partial x_i \otimes y_j
2093
+ vec = [zero]*(rp*s)
2094
+ for k, val in enumerate(d[a].column(i)):
2095
+ vec[s*k+j] += val
2096
+ cur[(a+deg_diff, b)].append(vec)
2097
+
2098
+ # (-1)^a x_i \otimes \partial y_j
2099
+ vec = [zero]*(r*sp)
2100
+ for k, val in enumerate(dD[b].column(j)):
2101
+ vec[sp*i+k] += scalar(a) * val
2102
+ cur[(a, b+deg_diff)].append(vec)
2103
+
2104
+ mor[a, b] = cur
2105
+
2106
+ # Parse the data into matrices
2107
+ to_delete = []
2108
+ for k in diff:
2109
+ # Get the data and interchange the indices
2110
+ mor = diff[k]
2111
+ row_keys = sorted(mor.keys())
2112
+ cols = {}
2113
+ col_widths = {}
2114
+ for dom in mor:
2115
+ c = mor[dom]
2116
+ for im in c:
2117
+ if im not in cols:
2118
+ cols[im] = {}
2119
+ col_widths[im] = len(c[im])
2120
+ cols[im][dom] = c[im]
2121
+ col_keys = sorted(cols.keys())
2122
+ # Now build the matrix
2123
+ M = []
2124
+ for ck in col_keys:
2125
+ M.append([])
2126
+ col = cols[ck]
2127
+ for rk in row_keys:
2128
+ if rk in col:
2129
+ M[-1].append(matrix(R, col[rk]).transpose())
2130
+ else:
2131
+ M[-1].append(zero)
2132
+ diff[k] = matrix.block(M, subdivide=subdivide)
2133
+
2134
+ # Flag for removal any 0x0 matrices
2135
+ if diff[k].nrows() == 0 and diff[k].ncols() == 0:
2136
+ to_delete.append(k)
2137
+
2138
+ # Delete the 0x0 matrices
2139
+ for k in to_delete:
2140
+ del diff[k]
2141
+
2142
+ ret = ChainComplex(diff, degree_of_differential=deg_diff,
2143
+ grading_group=self._grading_group)
2144
+
2145
+ return ret
2146
+
2147
+
2148
+ register_unpickle_override('sage.homology.chain_complex', 'ChainComplex', ChainComplex_class)