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,3289 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ r"""
3
+ Tensors on free modules
4
+
5
+ The class :class:`FreeModuleTensor` implements tensors on a free module `M`
6
+ of finite rank over a commutative ring. A *tensor of type* `(k,l)` on `M`
7
+ is a multilinear map:
8
+
9
+ .. MATH::
10
+
11
+ \underbrace{M^*\times\cdots\times M^*}_{k\ \; \mbox{times}}
12
+ \times \underbrace{M\times\cdots\times M}_{l\ \; \mbox{times}}
13
+ \longrightarrow R
14
+
15
+ where `R` is the commutative ring over which the free module `M` is defined
16
+ and `M^* = \mathrm{Hom}_R(M,R)` is the dual of `M`. The integer `k + l` is
17
+ called the *tensor rank*. The set `T^{(k,l)}(M)` of tensors of type `(k,l)`
18
+ on `M` is a free module of finite rank over `R`, described by the
19
+ class :class:`~sage.tensor.modules.tensor_free_module.TensorFreeModule`.
20
+
21
+ Various derived classes of :class:`FreeModuleTensor` are devoted to specific
22
+ tensors:
23
+
24
+ * :class:`~sage.tensor.modules.alternating_contr_tensor.AlternatingContrTensor`
25
+ for fully antisymmetric type-`(k, 0)` tensors *(alternating contravariant
26
+ tensors)*;
27
+
28
+ - :class:`~sage.tensor.modules.free_module_element.FiniteRankFreeModuleElement`
29
+ for elements of `M`, considered as type-`(1,0)` tensors thanks to the
30
+ canonical identification `M^{**}=M` (which holds since `M` is a free module
31
+ of finite rank);
32
+
33
+ * :class:`~sage.tensor.modules.free_module_alt_form.FreeModuleAltForm` for
34
+ fully antisymmetric type-`(0, l)` tensors *(alternating forms)*;
35
+
36
+ * :class:`~sage.tensor.modules.free_module_automorphism.FreeModuleAutomorphism`
37
+ for type-`(1,1)` tensors representing invertible endomorphisms.
38
+
39
+ Each of these classes is a Sage *element* class, the corresponding *parent*
40
+ class being:
41
+
42
+ * :class:`~sage.tensor.modules.tensor_free_module.TensorFreeModule` for
43
+ :class:`FreeModuleTensor`;
44
+ * :class:`~sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule`
45
+ for :class:`~sage.tensor.modules.free_module_element.FiniteRankFreeModuleElement`;
46
+ * :class:`~sage.tensor.modules.ext_pow_free_module.ExtPowerFreeModule` for
47
+ :class:`~sage.tensor.modules.alternating_contr_tensor.AlternatingContrTensor`;
48
+ * :class:`~sage.tensor.modules.ext_pow_free_module.ExtPowerDualFreeModule` for
49
+ :class:`~sage.tensor.modules.free_module_alt_form.FreeModuleAltForm`;
50
+ * :class:`~sage.tensor.modules.free_module_linear_group.FreeModuleLinearGroup`
51
+ for
52
+ :class:`~sage.tensor.modules.free_module_automorphism.FreeModuleAutomorphism`.
53
+
54
+
55
+ AUTHORS:
56
+
57
+ - Eric Gourgoulhon, Michal Bejger (2014-2015): initial version
58
+ - Michael Jung (2019): improve treatment of the zero element; add method
59
+ ``copy_from``
60
+
61
+ REFERENCES:
62
+
63
+ - Chap. 21 of R. Godement : *Algebra* [God1968]_
64
+ - Chap. 12 of J. M. Lee: *Introduction to Smooth Manifolds* [Lee2013]_ (only
65
+ when the free module is a vector space)
66
+ - Chap. 2 of B. O'Neill: *Semi-Riemannian Geometry* [ONe1983]_
67
+
68
+ EXAMPLES:
69
+
70
+ A tensor of type `(1, 1)` on a rank-3 free module over `\ZZ`::
71
+
72
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
73
+ sage: t = M.tensor((1,1), name='t') ; t
74
+ Type-(1,1) tensor t on the Rank-3 free module M over the Integer Ring
75
+ sage: t.parent()
76
+ Free module of type-(1,1) tensors on the Rank-3 free module M
77
+ over the Integer Ring
78
+ sage: t.parent() is M.tensor_module(1,1)
79
+ True
80
+ sage: t in M.tensor_module(1,1)
81
+ True
82
+
83
+ Setting some component of the tensor in a given basis::
84
+
85
+ sage: e = M.basis('e') ; e
86
+ Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring
87
+ sage: t.set_comp(e)[0,0] = -3 # the component [0,0] w.r.t. basis e is set to -3
88
+
89
+ The unset components are assumed to be zero::
90
+
91
+ sage: t.comp(e)[:] # list of all components w.r.t. basis e
92
+ [-3 0 0]
93
+ [ 0 0 0]
94
+ [ 0 0 0]
95
+ sage: t.display(e) # displays the expansion of t on the basis e_i⊗e^j of T^(1,1)(M)
96
+ t = -3 e_0⊗e^0
97
+
98
+ The commands ``t.set_comp(e)`` and ``t.comp(e)`` can be abridged by providing
99
+ the basis as the first argument in the square brackets::
100
+
101
+ sage: t[e,0,0] = -3
102
+ sage: t[e,:]
103
+ [-3 0 0]
104
+ [ 0 0 0]
105
+ [ 0 0 0]
106
+
107
+ Actually, since ``e`` is ``M``'s default basis, the mention of ``e``
108
+ can be omitted::
109
+
110
+ sage: t[0,0] = -3
111
+ sage: t[:]
112
+ [-3 0 0]
113
+ [ 0 0 0]
114
+ [ 0 0 0]
115
+
116
+ For tensors of rank 2, the matrix of components w.r.t. a given basis is
117
+ obtained via the function ``matrix``::
118
+
119
+ sage: matrix(t.comp(e))
120
+ [-3 0 0]
121
+ [ 0 0 0]
122
+ [ 0 0 0]
123
+ sage: matrix(t.comp(e)).parent()
124
+ Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
125
+
126
+ Tensor components can be modified (reset) at any time::
127
+
128
+ sage: t[0,0] = 0
129
+ sage: t[:]
130
+ [0 0 0]
131
+ [0 0 0]
132
+ [0 0 0]
133
+
134
+ Checking that ``t`` is zero::
135
+
136
+ sage: t.is_zero()
137
+ True
138
+ sage: t == 0
139
+ True
140
+ sage: t == M.tensor_module(1,1).zero() # the zero element of the module of all type-(1,1) tensors on M
141
+ True
142
+
143
+ The components are managed by the class
144
+ :class:`~sage.tensor.modules.comp.Components`::
145
+
146
+ sage: type(t.comp(e))
147
+ <class 'sage.tensor.modules.comp.Components'>
148
+
149
+ Only nonzero components are actually stored, in the dictionary :attr:`_comp`
150
+ of class :class:`~sage.tensor.modules.comp.Components`, whose keys are
151
+ the indices::
152
+
153
+ sage: t.comp(e)._comp
154
+ {}
155
+ sage: t.set_comp(e)[0,0] = -3 ; t.set_comp(e)[1,2] = 2
156
+ sage: t.comp(e)._comp # random output order (dictionary)
157
+ {(0, 0): -3, (1, 2): 2}
158
+ sage: t.display(e)
159
+ t = -3 e_0⊗e^0 + 2 e_1⊗e^2
160
+
161
+ Further tests of the comparison operator::
162
+
163
+ sage: t.is_zero()
164
+ False
165
+ sage: t == 0
166
+ False
167
+ sage: t == M.tensor_module(1,1).zero()
168
+ False
169
+ sage: t1 = t.copy()
170
+ sage: t1 == t
171
+ True
172
+ sage: t1[2,0] = 4
173
+ sage: t1 == t
174
+ False
175
+
176
+ As a multilinear map `M^* \times M \rightarrow \ZZ`, the type-`(1,1)`
177
+ tensor ``t`` acts on pairs formed by a linear form and a module element::
178
+
179
+ sage: a = M.linear_form(name='a') ; a[:] = (2, 1, -3) ; a
180
+ Linear form a on the Rank-3 free module M over the Integer Ring
181
+ sage: b = M([1,-6,2], name='b') ; b
182
+ Element b of the Rank-3 free module M over the Integer Ring
183
+ sage: t(a,b)
184
+ -2
185
+ """
186
+ # *****************************************************************************
187
+ # Copyright (C) 2015 Eric Gourgoulhon <eric.gourgoulhon@obspm.fr>
188
+ # Copyright (C) 2015 Michal Bejger <bejger@camk.edu.pl>
189
+ #
190
+ # Distributed under the terms of the GNU General Public License (GPL)
191
+ # as published by the Free Software Foundation; either version 2 of
192
+ # the License, or (at your option) any later version.
193
+ # https://www.gnu.org/licenses/
194
+ # *****************************************************************************
195
+ from __future__ import annotations
196
+
197
+ from typing import TYPE_CHECKING, Optional, Union
198
+
199
+ from sage.parallel.decorate import parallel
200
+ from sage.parallel.parallelism import Parallelism
201
+ from sage.rings.integer import Integer
202
+ from sage.structure.element import ModuleElementWithMutability
203
+ from sage.tensor.modules.comp import (
204
+ CompFullyAntiSym,
205
+ CompFullySym,
206
+ Components,
207
+ CompWithSym,
208
+ )
209
+ from sage.tensor.modules.tensor_with_indices import TensorWithIndices
210
+
211
+ if TYPE_CHECKING:
212
+ from sage.symbolic.expression import Expression
213
+ from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule
214
+ from sage.tensor.modules.free_module_basis import FreeModuleBasis
215
+ from sage.manifolds.differentiable.metric import PseudoRiemannianMetric
216
+ from sage.manifolds.differentiable.poisson_tensor import PoissonTensorField
217
+ from sage.manifolds.differentiable.symplectic_form import SymplecticForm
218
+
219
+
220
+ class FreeModuleTensor(ModuleElementWithMutability):
221
+ r"""
222
+ Tensor over a free module of finite rank over a commutative ring.
223
+
224
+ This is a Sage *element* class, the corresponding *parent* class being
225
+ :class:`~sage.tensor.modules.tensor_free_module.TensorFreeModule`.
226
+
227
+ INPUT:
228
+
229
+ - ``fmodule`` -- free module `M` of finite rank over a commutative ring
230
+ `R`, as an instance of
231
+ :class:`~sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule`
232
+ - ``tensor_type`` -- pair ``(k, l)`` with ``k`` being the contravariant
233
+ rank and ``l`` the covariant rank
234
+ - ``name`` -- (default: ``None``) name given to the tensor
235
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the tensor;
236
+ if none is provided, the LaTeX symbol is set to ``name``
237
+ - ``sym`` -- (default: ``None``) a symmetry or a list of symmetries among
238
+ the tensor arguments: each symmetry is described by a tuple containing
239
+ the positions of the involved arguments, with the convention
240
+ ``position=0`` for the first argument. For instance:
241
+
242
+ * ``sym = (0,1)`` for a symmetry between the 1st and 2nd arguments;
243
+ * ``sym = [(0,2), (1,3,4)]`` for a symmetry between the 1st and 3rd
244
+ arguments and a symmetry between the 2nd, 4th and 5th arguments.
245
+
246
+ - ``antisym`` -- (default: ``None``) antisymmetry or list of antisymmetries
247
+ among the arguments, with the same convention as for ``sym``
248
+ - ``parent`` -- (default: ``None``) some specific parent (e.g. exterior
249
+ power for alternating forms); if ``None``, ``fmodule.tensor_module(k,l)``
250
+ is used
251
+
252
+ EXAMPLES:
253
+
254
+ A tensor of type `(1,1)` on a rank-3 free module over `\ZZ`::
255
+
256
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
257
+ sage: t = M.tensor((1,1), name='t') ; t
258
+ Type-(1,1) tensor t on the Rank-3 free module M over the Integer Ring
259
+
260
+ Tensors are *Element* objects whose parents are tensor free modules::
261
+
262
+ sage: t.parent()
263
+ Free module of type-(1,1) tensors on the
264
+ Rank-3 free module M over the Integer Ring
265
+ sage: t.parent() is M.tensor_module(1,1)
266
+ True
267
+ """
268
+ _fmodule: FiniteRankFreeModule
269
+
270
+ def __init__(
271
+ self,
272
+ fmodule: FiniteRankFreeModule,
273
+ tensor_type,
274
+ name: Optional[str] = None,
275
+ latex_name: Optional[str] = None,
276
+ sym=None,
277
+ antisym=None,
278
+ parent=None,
279
+ ):
280
+ r"""
281
+ TESTS::
282
+
283
+ sage: from sage.tensor.modules.free_module_tensor import FreeModuleTensor
284
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
285
+ sage: e = M.basis('e')
286
+ sage: t = FreeModuleTensor(M, (2,1), name='t', latex_name=r'\tau', sym=(0,1))
287
+ sage: t[e,0,0,0] = -3
288
+ sage: TestSuite(t).run(skip='_test_category') # see below
289
+
290
+ In the above test suite, _test_category fails because t is not an
291
+ instance of t.parent().category().element_class. Actually tensors
292
+ must be constructed via TensorFreeModule.element_class and
293
+ not by a direct call to FreeModuleTensor::
294
+
295
+ sage: t1 = M.tensor_module(2,1).element_class(M, (2,1), name='t',
296
+ ....: latex_name=r'\tau',
297
+ ....: sym=(0,1))
298
+ sage: t1[e,0,0,0] = -3
299
+ sage: TestSuite(t1).run()
300
+ """
301
+ if parent is None:
302
+ parent = fmodule.tensor_module(*tensor_type)
303
+ ModuleElementWithMutability.__init__(self, parent)
304
+ self._fmodule = fmodule
305
+ self._tensor_type = tuple(tensor_type)
306
+ self._tensor_rank = self._tensor_type[0] + self._tensor_type[1]
307
+ self._is_zero = False # a priori, may be changed below or via
308
+ # method __bool__()
309
+ self._name = name
310
+ if latex_name is None:
311
+ self._latex_name = self._name
312
+ else:
313
+ self._latex_name = latex_name
314
+ self._components: dict[FreeModuleBasis, Components] = {} # dict. of the sets of components on various
315
+ # bases, with the bases as keys (initially empty)
316
+
317
+ # Treatment of symmetry declarations:
318
+ self._sym, self._antisym = CompWithSym._canonicalize_sym_antisym(
319
+ self._tensor_rank, sym, antisym)
320
+
321
+ # Initialization of derived quantities:
322
+ FreeModuleTensor._init_derived(self)
323
+
324
+ ####### Required methods for ModuleElement (beside arithmetic) #######
325
+
326
+ def __bool__(self):
327
+ r"""
328
+ Return ``True`` if ``self`` is nonzero and ``False`` otherwise.
329
+
330
+ This method is called by ``self.is_zero()``.
331
+
332
+ EXAMPLES::
333
+
334
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
335
+ sage: e = M.basis('e')
336
+ sage: t = M.tensor((2,1))
337
+ sage: t.add_comp(e)
338
+ 3-indices components w.r.t. Basis (e_0,e_1,e_2) on the
339
+ Rank-3 free module M over the Integer Ring
340
+ sage: bool(t) # uninitialized components are zero
341
+ False
342
+ sage: t == 0
343
+ True
344
+ sage: t[e,1,0,2] = 4 # setting a nonzero component in basis e
345
+ sage: t.display()
346
+ 4 e_1⊗e_0⊗e^2
347
+ sage: bool(t)
348
+ True
349
+ sage: t == 0
350
+ False
351
+ sage: t[e,1,0,2] = 0
352
+ sage: t.display()
353
+ 0
354
+ sage: bool(t)
355
+ False
356
+ sage: t == 0
357
+ True
358
+ """
359
+ basis = self.pick_a_basis()
360
+ if not self._components[basis].is_zero():
361
+ self._is_zero = False
362
+ return True
363
+ self._is_zero = True
364
+ return False
365
+
366
+ ##### End of required methods for ModuleElement (beside arithmetic) #####
367
+
368
+ def _repr_(self):
369
+ r"""
370
+ Return a string representation of ``self``.
371
+
372
+ EXAMPLES::
373
+
374
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
375
+ sage: t = M.tensor((2,1), name='t')
376
+ sage: t
377
+ Type-(2,1) tensor t on the Rank-3 free module M over the Integer Ring
378
+ """
379
+ # Special cases
380
+ if self._tensor_type == (0,2) and self._sym == ((0,1),):
381
+ description = "Symmetric bilinear form "
382
+ else:
383
+ # Generic case
384
+ description = "Type-({},{}) tensor".format(
385
+ self._tensor_type[0], self._tensor_type[1])
386
+ if self._name is not None:
387
+ description += " " + self._name
388
+ description += " on the {}".format(self._fmodule)
389
+ return description
390
+
391
+ def _latex_(self):
392
+ r"""
393
+ LaTeX representation of the object.
394
+
395
+ EXAMPLES::
396
+
397
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
398
+ sage: t = M.tensor((2,1), name='t')
399
+ sage: t._latex_()
400
+ 't'
401
+ sage: latex(t)
402
+ t
403
+ sage: t = M.tensor((2,1), name='t', latex_name=r'\tau')
404
+ sage: t._latex_()
405
+ '\\tau'
406
+ sage: latex(t)
407
+ \tau
408
+ sage: t = M.tensor((2,1)) # unnamed tensor
409
+ sage: t._latex_()
410
+ '\\mbox{Type-(2,1) tensor on the Rank-3 free module M over the Integer Ring}'
411
+ """
412
+ if self._latex_name is None:
413
+ return r'\mbox{' + str(self) + r'}'
414
+ return self._latex_name
415
+
416
+ def _init_derived(self):
417
+ r"""
418
+ Initialize the derived quantities.
419
+
420
+ EXAMPLES::
421
+
422
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
423
+ sage: t = M.tensor((2,1), name='t')
424
+ sage: t._init_derived()
425
+ """
426
+ pass # no derived quantities
427
+
428
+ def _del_derived(self):
429
+ r"""
430
+ Delete the derived quantities.
431
+
432
+ EXAMPLES::
433
+
434
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
435
+ sage: t = M.tensor((2,1), name='t')
436
+ sage: t._del_derived()
437
+ """
438
+ pass # no derived quantities
439
+
440
+ #### Simple accessors ####
441
+
442
+ def tensor_type(self):
443
+ r"""
444
+ Return the tensor type of ``self``.
445
+
446
+ OUTPUT:
447
+
448
+ - pair ``(k, l)``, where ``k`` is the contravariant rank and ``l``
449
+ is the covariant rank
450
+
451
+ EXAMPLES::
452
+
453
+ sage: M = FiniteRankFreeModule(ZZ, 3)
454
+ sage: M.an_element().tensor_type()
455
+ (1, 0)
456
+ sage: t = M.tensor((2,1))
457
+ sage: t.tensor_type()
458
+ (2, 1)
459
+ """
460
+ return self._tensor_type
461
+
462
+ def tensor_rank(self):
463
+ r"""
464
+ Return the tensor rank of ``self``.
465
+
466
+ OUTPUT:
467
+
468
+ - integer ``k+l``, where ``k`` is the contravariant rank and ``l``
469
+ is the covariant rank
470
+
471
+ EXAMPLES::
472
+
473
+ sage: M = FiniteRankFreeModule(ZZ, 3)
474
+ sage: M.an_element().tensor_rank()
475
+ 1
476
+ sage: t = M.tensor((2,1))
477
+ sage: t.tensor_rank()
478
+ 3
479
+ """
480
+ return self._tensor_rank
481
+
482
+ def base_module(self):
483
+ r"""
484
+ Return the module on which ``self`` is defined.
485
+
486
+ OUTPUT:
487
+
488
+ - instance of :class:`FiniteRankFreeModule` representing the free
489
+ module on which the tensor is defined.
490
+
491
+ EXAMPLES::
492
+
493
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
494
+ sage: M.an_element().base_module()
495
+ Rank-3 free module M over the Integer Ring
496
+ sage: t = M.tensor((2,1))
497
+ sage: t.base_module()
498
+ Rank-3 free module M over the Integer Ring
499
+ sage: t.base_module() is M
500
+ True
501
+ """
502
+ return self._fmodule
503
+
504
+ def symmetries(self):
505
+ r"""
506
+ Print the list of symmetries and antisymmetries of ``self``.
507
+
508
+ EXAMPLES:
509
+
510
+ Various symmetries / antisymmetries for a rank-4 tensor::
511
+
512
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
513
+ sage: t = M.tensor((4,0), name='T') # no symmetry declared
514
+ sage: t.symmetries()
515
+ no symmetry; no antisymmetry
516
+ sage: t = M.tensor((4,0), name='T', sym=(0,1))
517
+ sage: t.symmetries()
518
+ symmetry: (0, 1); no antisymmetry
519
+ sage: t = M.tensor((4,0), name='T', sym=[(0,1), (2,3)])
520
+ sage: t.symmetries()
521
+ symmetries: [(0, 1), (2, 3)]; no antisymmetry
522
+ sage: t = M.tensor((4,0), name='T', sym=(0,1), antisym=(2,3))
523
+ sage: t.symmetries()
524
+ symmetry: (0, 1); antisymmetry: (2, 3)
525
+ """
526
+ if len(self._sym) == 0:
527
+ s = "no symmetry; "
528
+ elif len(self._sym) == 1:
529
+ s = "symmetry: {}; ".format(self._sym[0])
530
+ else:
531
+ s = "symmetries: {}; ".format(list(self._sym))
532
+ if len(self._antisym) == 0:
533
+ a = "no antisymmetry"
534
+ elif len(self._antisym) == 1:
535
+ a = "antisymmetry: {}".format(self._antisym[0])
536
+ else:
537
+ a = "antisymmetries: {}".format(list(self._antisym))
538
+ print(s+a)
539
+
540
+ #### End of simple accessors #####
541
+
542
+ def _preparse_display(self, basis=None, format_spec=None):
543
+ r"""
544
+ Helper function for display (to be used in the derived classes
545
+ FreeModuleAltForm and AlternatingContrTensor as well)
546
+
547
+ TESTS::
548
+
549
+ sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
550
+ sage: e = M.basis('e')
551
+ sage: f = M.basis('f')
552
+ sage: v = M([1,-2])
553
+ sage: v._preparse_display()
554
+ (Basis (e_0,e_1) on the Rank-2 free module M over the Integer Ring, None)
555
+ sage: v._preparse_display(f)
556
+ (Basis (f_0,f_1) on the Rank-2 free module M over the Integer Ring, None)
557
+ sage: v._preparse_display(e, 10)
558
+ (Basis (e_0,e_1) on the Rank-2 free module M over the Integer Ring, 10)
559
+ sage: v._preparse_display(format_spec=10)
560
+ (Basis (e_0,e_1) on the Rank-2 free module M over the Integer Ring, 10)
561
+ """
562
+ if basis is None:
563
+ basis = self._fmodule._def_basis
564
+ return (basis, format_spec)
565
+
566
+ def display(self, basis=None, format_spec=None):
567
+ r"""
568
+ Display ``self`` in terms of its expansion w.r.t. a given module basis.
569
+
570
+ The expansion is actually performed onto tensor products of elements
571
+ of the given basis and of elements of its dual basis (see examples
572
+ below).
573
+ The output is either text-formatted (console mode) or LaTeX-formatted
574
+ (notebook mode).
575
+
576
+ INPUT:
577
+
578
+ - ``basis`` -- (default: ``None``) basis of the free module with
579
+ respect to which the tensor is expanded; if none is provided,
580
+ the module's default basis is assumed
581
+ - ``format_spec`` -- (default: ``None``) format specification passed
582
+ to ``self._fmodule._output_formatter`` to format the output
583
+
584
+ EXAMPLES:
585
+
586
+ Display of a module element (type-`(1,0)` tensor)::
587
+
588
+ sage: M = FiniteRankFreeModule(QQ, 2, name='M', start_index=1)
589
+ sage: e = M.basis('e') ; e
590
+ Basis (e_1,e_2) on the 2-dimensional vector space M over the
591
+ Rational Field
592
+ sage: v = M([1/3,-2], name='v')
593
+ sage: v.display(e)
594
+ v = 1/3 e_1 - 2 e_2
595
+ sage: v.display() # a shortcut since e is M's default basis
596
+ v = 1/3 e_1 - 2 e_2
597
+ sage: latex(v.display()) # display in the notebook
598
+ v = \frac{1}{3} e_{1} -2 e_{2}
599
+
600
+ A shortcut is ``disp()``::
601
+
602
+ sage: v.disp()
603
+ v = 1/3 e_1 - 2 e_2
604
+
605
+ Display of a linear form (type-`(0,1)` tensor)::
606
+
607
+ sage: de = e.dual_basis() ; de
608
+ Dual basis (e^1,e^2) on the 2-dimensional vector space M over the
609
+ Rational Field
610
+ sage: w = - 3/4 * de[1] + de[2] ; w
611
+ Linear form on the 2-dimensional vector space M over the Rational
612
+ Field
613
+ sage: w.set_name('w', latex_name='\\omega')
614
+ sage: w.display()
615
+ w = -3/4 e^1 + e^2
616
+ sage: latex(w.display()) # display in the notebook
617
+ \omega = -\frac{3}{4} e^{1} +e^{2}
618
+
619
+ Display of a type-`(1,1)` tensor::
620
+
621
+ sage: t = v*w ; t # the type-(1,1) is formed as the tensor product of v by w
622
+ Type-(1,1) tensor v⊗w on the 2-dimensional vector space M over the
623
+ Rational Field
624
+ sage: t.display()
625
+ v⊗w = -1/4 e_1⊗e^1 + 1/3 e_1⊗e^2 + 3/2 e_2⊗e^1 - 2 e_2⊗e^2
626
+ sage: latex(t.display()) # display in the notebook
627
+ v\otimes \omega = -\frac{1}{4} e_{1}\otimes e^{1} +
628
+ \frac{1}{3} e_{1}\otimes e^{2} + \frac{3}{2} e_{2}\otimes e^{1}
629
+ -2 e_{2}\otimes e^{2}
630
+
631
+ Display in a basis which is not the default one::
632
+
633
+ sage: a = M.automorphism(matrix=[[1,2],[3,4]], basis=e)
634
+ sage: f = e.new_basis(a, 'f')
635
+ sage: v.display(f) # the components w.r.t basis f are first computed via the change-of-basis formula defined by a
636
+ v = -8/3 f_1 + 3/2 f_2
637
+ sage: w.display(f)
638
+ w = 9/4 f^1 + 5/2 f^2
639
+ sage: t.display(f)
640
+ v⊗w = -6 f_1⊗f^1 - 20/3 f_1⊗f^2 + 27/8 f_2⊗f^1 + 15/4 f_2⊗f^2
641
+
642
+ Parallel computation::
643
+
644
+ sage: Parallelism().set('tensor', nproc=2)
645
+ sage: t2 = v*w
646
+ sage: t2.display(f)
647
+ v⊗w = -6 f_1⊗f^1 - 20/3 f_1⊗f^2 + 27/8 f_2⊗f^1 + 15/4 f_2⊗f^2
648
+ sage: t2[f,:] == t[f,:] # check of the parallel computation
649
+ True
650
+ sage: Parallelism().set('tensor', nproc=1) # switch off parallelization
651
+
652
+ The output format can be set via the argument ``output_formatter``
653
+ passed at the module construction::
654
+
655
+ sage: N = FiniteRankFreeModule(QQ, 2, name='N', start_index=1,
656
+ ....: output_formatter=Rational.numerical_approx)
657
+ sage: e = N.basis('e')
658
+ sage: v = N([1/3,-2], name='v')
659
+ sage: v.display() # default format (53 bits of precision)
660
+ v = 0.333333333333333 e_1 - 2.00000000000000 e_2
661
+ sage: latex(v.display())
662
+ v = 0.333333333333333 e_{1} -2.00000000000000 e_{2}
663
+
664
+ The output format is then controlled by the argument ``format_spec`` of
665
+ the method :meth:`display`::
666
+
667
+ sage: v.display(format_spec=10) # 10 bits of precision
668
+ v = 0.33 e_1 - 2.0 e_2
669
+
670
+ Check that the bug reported in :issue:`22520` is fixed::
671
+
672
+ sage: # needs sage.symbolic
673
+ sage: M = FiniteRankFreeModule(SR, 3, name='M')
674
+ sage: e = M.basis('e')
675
+ sage: t = SR.var('t', domain='real')
676
+ sage: (t*e[0]).display()
677
+ t e_0
678
+ """
679
+ from sage.misc.latex import latex
680
+ from sage.typeset.unicode_characters import unicode_otimes
681
+ from .format_utilities import is_atomic, FormattedExpansion
682
+ basis, format_spec = self._preparse_display(basis=basis,
683
+ format_spec=format_spec)
684
+ cobasis = basis.dual_basis()
685
+ comp = self.comp(basis)
686
+ terms_txt = []
687
+ terms_latex = []
688
+ n_con = self._tensor_type[0]
689
+ for ind in comp.index_generator():
690
+ ind_arg = ind + (format_spec,)
691
+ coef = comp[ind_arg]
692
+ # Check whether the coefficient is zero, preferably via
693
+ # the fast method is_trivial_zero():
694
+ if hasattr(coef, 'is_trivial_zero'):
695
+ zero_coef = coef.is_trivial_zero()
696
+ else:
697
+ zero_coef = coef == 0
698
+ if not zero_coef:
699
+ bases_txt = []
700
+ bases_latex = []
701
+ for k in range(n_con):
702
+ bases_txt.append(basis[ind[k]]._name)
703
+ bases_latex.append(latex(basis[ind[k]]))
704
+ for k in range(n_con, self._tensor_rank):
705
+ bases_txt.append(cobasis[ind[k]]._name)
706
+ bases_latex.append(latex(cobasis[ind[k]]))
707
+ basis_term_txt = unicode_otimes.join(bases_txt)
708
+ basis_term_latex = r'\otimes '.join(bases_latex)
709
+ coef_txt = repr(coef)
710
+ if coef_txt == '1':
711
+ terms_txt.append(basis_term_txt)
712
+ terms_latex.append(basis_term_latex)
713
+ elif coef_txt == '-1':
714
+ terms_txt.append('-' + basis_term_txt)
715
+ terms_latex.append('-' + basis_term_latex)
716
+ else:
717
+ coef_latex = latex(coef)
718
+ if is_atomic(coef_txt):
719
+ terms_txt.append(coef_txt + ' ' + basis_term_txt)
720
+ else:
721
+ terms_txt.append('(' + coef_txt + ') ' +
722
+ basis_term_txt)
723
+ if is_atomic(coef_latex):
724
+ terms_latex.append(coef_latex + basis_term_latex)
725
+ else:
726
+ terms_latex.append(r'\left(' + coef_latex +
727
+ r'\right)' + basis_term_latex)
728
+ if terms_txt == []:
729
+ expansion_txt = '0'
730
+ else:
731
+ expansion_txt = terms_txt[0]
732
+ for term in terms_txt[1:]:
733
+ if term[0] == '-':
734
+ expansion_txt += ' - ' + term[1:]
735
+ else:
736
+ expansion_txt += ' + ' + term
737
+ if terms_latex == []:
738
+ expansion_latex = '0'
739
+ else:
740
+ expansion_latex = terms_latex[0]
741
+ for term in terms_latex[1:]:
742
+ if term[0] == '-':
743
+ expansion_latex += term
744
+ else:
745
+ expansion_latex += '+' + term
746
+ if self._name is None:
747
+ resu_txt = expansion_txt
748
+ else:
749
+ resu_txt = self._name + ' = ' + expansion_txt
750
+ if self._latex_name is None:
751
+ resu_latex = expansion_latex
752
+ else:
753
+ resu_latex = latex(self) + ' = ' + expansion_latex
754
+ return FormattedExpansion(resu_txt, resu_latex)
755
+
756
+ disp = display
757
+
758
+ def display_comp(self, basis=None, format_spec=None, symbol=None,
759
+ latex_symbol=None, index_labels=None,
760
+ index_latex_labels=None, only_nonzero=True,
761
+ only_nonredundant=False):
762
+ r"""
763
+ Display the tensor components with respect to a given module
764
+ basis, one per line.
765
+
766
+ The output is either text-formatted (console mode) or LaTeX-formatted
767
+ (notebook mode).
768
+
769
+ INPUT:
770
+
771
+ - ``basis`` -- (default: ``None``) basis of the free module with
772
+ respect to which the tensor components are defined; if ``None``,
773
+ the module's default basis is assumed
774
+ - ``format_spec`` -- (default: ``None``) format specification passed
775
+ to ``self._fmodule._output_formatter`` to format the output
776
+ - ``symbol`` -- (default: ``None``) string (typically a single letter)
777
+ specifying the symbol for the components; if ``None``, the tensor
778
+ name is used if it has been set, otherwise ``'X'`` is used
779
+ - ``latex_symbol`` -- (default: ``None``) string specifying the LaTeX
780
+ symbol for the components; if ``None``, the tensor LaTeX name
781
+ is used if it has been set, otherwise ``'X'`` is used
782
+ - ``index_labels`` -- (default: ``None``) list of strings representing
783
+ the labels of each of the individual indices; if ``None``, integer
784
+ labels are used
785
+ - ``index_latex_labels`` -- (default: ``None``) list of strings
786
+ representing the LaTeX labels of each of the individual indices; if
787
+ ``None``, integers labels are used
788
+ - ``only_nonzero`` -- boolean (default: ``True``); if ``True``, only
789
+ nonzero components are displayed
790
+ - ``only_nonredundant`` -- boolean (default: ``False``); if ``True``,
791
+ only nonredundant components are displayed in case of symmetries
792
+
793
+ EXAMPLES:
794
+
795
+ Display of the components of a type-`(2,1)` tensor on a rank 2
796
+ vector space over `\QQ`::
797
+
798
+ sage: FiniteRankFreeModule._clear_cache_() # for doctests only
799
+ sage: M = FiniteRankFreeModule(QQ, 2, name='M', start_index=1)
800
+ sage: e = M.basis('e')
801
+ sage: t = M.tensor((2,1), name='T', sym=(0,1))
802
+ sage: t[1,2,1], t[1,2,2], t[2,2,2] = 2/3, -1/4, 3
803
+ sage: t.display()
804
+ T = 2/3 e_1⊗e_2⊗e^1 - 1/4 e_1⊗e_2⊗e^2 + 2/3 e_2⊗e_1⊗e^1
805
+ - 1/4 e_2⊗e_1⊗e^2 + 3 e_2⊗e_2⊗e^2
806
+ sage: t.display_comp()
807
+ T^12_1 = 2/3
808
+ T^12_2 = -1/4
809
+ T^21_1 = 2/3
810
+ T^21_2 = -1/4
811
+ T^22_2 = 3
812
+
813
+ The LaTeX output for the notebook::
814
+
815
+ sage: latex(t.display_comp())
816
+ \begin{array}{lcl} {T}_{\phantom{\, 1}\phantom{\, 2}\,1}^{\,1\,2\phantom{\, 1}}
817
+ & = & \frac{2}{3} \\ {T}_{\phantom{\, 1}\phantom{\, 2}\,2}^{\,1\,2\phantom{\, 2}}
818
+ & = & -\frac{1}{4} \\ {T}_{\phantom{\, 2}\phantom{\, 1}\,1}^{\,2\,1\phantom{\, 1}}
819
+ & = & \frac{2}{3} \\ {T}_{\phantom{\, 2}\phantom{\, 1}\,2}^{\,2\,1\phantom{\, 2}}
820
+ & = & -\frac{1}{4} \\ {T}_{\phantom{\, 2}\phantom{\, 2}\,2}^{\,2\,2\phantom{\, 2}}
821
+ & = & 3 \end{array}
822
+
823
+ By default, only the non-vanishing components are displayed; to see
824
+ all the components, the argument ``only_nonzero`` must be set to
825
+ ``False``::
826
+
827
+ sage: t.display_comp(only_nonzero=False)
828
+ T^11_1 = 0
829
+ T^11_2 = 0
830
+ T^12_1 = 2/3
831
+ T^12_2 = -1/4
832
+ T^21_1 = 2/3
833
+ T^21_2 = -1/4
834
+ T^22_1 = 0
835
+ T^22_2 = 3
836
+
837
+ ``t`` being symmetric w.r.t. to its first two indices, one may ask to
838
+ skip the components that can be deduced by symmetry::
839
+
840
+ sage: t.display_comp(only_nonredundant=True)
841
+ T^12_1 = 2/3
842
+ T^12_2 = -1/4
843
+ T^22_2 = 3
844
+
845
+ The index symbols can be customized::
846
+
847
+ sage: t.display_comp(index_labels=['x', 'y'])
848
+ T^xy_x = 2/3
849
+ T^xy_y = -1/4
850
+ T^yx_x = 2/3
851
+ T^yx_y = -1/4
852
+ T^yy_y = 3
853
+
854
+ Display of the components w.r.t. a basis different from the
855
+ default one::
856
+
857
+ sage: f = M.basis('f', from_family=(-e[1]+e[2], e[1]+e[2]))
858
+ sage: t.display_comp(basis=f)
859
+ T^11_1 = 29/24
860
+ T^11_2 = 13/24
861
+ T^12_1 = 3/4
862
+ T^12_2 = 3/4
863
+ T^21_1 = 3/4
864
+ T^21_2 = 3/4
865
+ T^22_1 = 7/24
866
+ T^22_2 = 23/24
867
+ """
868
+ if basis is None:
869
+ basis = self._fmodule._def_basis
870
+ if symbol is None:
871
+ if self._name is not None:
872
+ symbol = self._name
873
+ else:
874
+ symbol = 'X'
875
+ if latex_symbol is None:
876
+ if self._latex_name is not None:
877
+ latex_symbol = r'{' + self._latex_name + r'}'
878
+ else:
879
+ latex_symbol = 'X'
880
+ index_positions = self._tensor_type[0]*'u' + self._tensor_type[1]*'d'
881
+ return self.comp(basis).display(symbol,
882
+ latex_symbol=latex_symbol,
883
+ index_positions=index_positions,
884
+ index_labels=index_labels,
885
+ index_latex_labels=index_latex_labels,
886
+ format_spec=format_spec,
887
+ only_nonzero=only_nonzero,
888
+ only_nonredundant=only_nonredundant)
889
+
890
+ def set_name(self, name: Optional[str] = None, latex_name: Optional[str] = None):
891
+ r"""
892
+ Set (or change) the text name and LaTeX name of ``self``.
893
+
894
+ INPUT:
895
+
896
+ - ``name`` -- (default: ``None``) string; name given to the tensor
897
+ - ``latex_name`` -- (default: ``None``) string; LaTeX symbol to denote
898
+ the tensor; if None while ``name`` is provided, the LaTeX symbol
899
+ is set to ``name``
900
+
901
+ EXAMPLES::
902
+
903
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
904
+ sage: t = M.tensor((2,1)) ; t
905
+ Type-(2,1) tensor on the Rank-3 free module M over the Integer Ring
906
+ sage: t.set_name('t') ; t
907
+ Type-(2,1) tensor t on the Rank-3 free module M over the Integer Ring
908
+ sage: latex(t)
909
+ t
910
+ sage: t.set_name(latex_name=r'\tau') ; t
911
+ Type-(2,1) tensor t on the Rank-3 free module M over the Integer Ring
912
+ sage: latex(t)
913
+ \tau
914
+ """
915
+ if name is not None:
916
+ self._name = name
917
+ if latex_name is None:
918
+ self._latex_name = self._name
919
+ if latex_name is not None:
920
+ self._latex_name = latex_name
921
+
922
+ def _new_instance(self):
923
+ r"""
924
+ Create a tensor of the same tensor type and with the same symmetries
925
+ as ``self``.
926
+
927
+ EXAMPLES::
928
+
929
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
930
+ sage: t = M.tensor((2,1), name='t')
931
+ sage: t._new_instance()
932
+ Type-(2,1) tensor on the Rank-3 free module M over the Integer Ring
933
+ sage: t._new_instance().parent() is t.parent()
934
+ True
935
+ """
936
+ return self.__class__(self._fmodule, self._tensor_type, sym=self._sym,
937
+ antisym=self._antisym)
938
+
939
+ def _new_comp(self, basis):
940
+ r"""
941
+ Create some (uninitialized) components of ``self`` w.r.t a given
942
+ module basis.
943
+
944
+ This method, to be called by :meth:`comp`, must be redefined by derived
945
+ classes to adapt the output to the relevant subclass of
946
+ :class:`~sage.tensor.modules.comp.Components`.
947
+
948
+ INPUT:
949
+
950
+ - ``basis`` -- basis of the free module on which ``self`` is defined
951
+
952
+ OUTPUT:
953
+
954
+ - an instance of :class:`~sage.tensor.modules.comp.Components`
955
+ (or of one of its subclasses)
956
+
957
+ EXAMPLES::
958
+
959
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
960
+ sage: t = M.tensor((2,1), name='t')
961
+ sage: e = M.basis('e')
962
+ sage: t._new_comp(e)
963
+ 3-indices components w.r.t. Basis (e_0,e_1,e_2) on the
964
+ Rank-3 free module M over the Integer Ring
965
+ sage: a = M.tensor((2,1), name='a', sym=(0,1))
966
+ sage: a._new_comp(e)
967
+ 3-indices components w.r.t. Basis (e_0,e_1,e_2) on the
968
+ Rank-3 free module M over the Integer Ring,
969
+ with symmetry on the index positions (0, 1)
970
+ """
971
+ fmodule = self._fmodule # the base free module
972
+ if not self._sym and not self._antisym:
973
+ return Components(fmodule._ring, basis, self._tensor_rank,
974
+ start_index=fmodule._sindex,
975
+ output_formatter=fmodule._output_formatter)
976
+ for isym in self._sym:
977
+ if len(isym) == self._tensor_rank:
978
+ return CompFullySym(fmodule._ring, basis, self._tensor_rank,
979
+ start_index=fmodule._sindex,
980
+ output_formatter=fmodule._output_formatter)
981
+ for isym in self._antisym:
982
+ if len(isym) == self._tensor_rank:
983
+ return CompFullyAntiSym(fmodule._ring, basis, self._tensor_rank,
984
+ start_index=fmodule._sindex,
985
+ output_formatter=fmodule._output_formatter)
986
+ return CompWithSym(fmodule._ring, basis, self._tensor_rank,
987
+ start_index=fmodule._sindex,
988
+ output_formatter=fmodule._output_formatter,
989
+ sym=self._sym, antisym=self._antisym)
990
+
991
+ def components(self, basis=None, from_basis=None) -> Components:
992
+ r"""
993
+ Return the components of ``self`` w.r.t to a given module basis.
994
+
995
+ If the components are not known already, they are computed by the
996
+ tensor change-of-basis formula from components in another basis.
997
+
998
+ INPUT:
999
+
1000
+ - ``basis`` -- (default: ``None``) basis in which the components are
1001
+ required; if none is provided, the components are assumed to refer
1002
+ to the module's default basis
1003
+ - ``from_basis`` -- (default: ``None``) basis from which the
1004
+ required components are computed, via the tensor change-of-basis
1005
+ formula, if they are not known already in the basis ``basis``;
1006
+ if none, a basis from which both the components and a change-of-basis
1007
+ to ``basis`` are known is selected.
1008
+
1009
+ OUTPUT:
1010
+
1011
+ - components in the basis ``basis``, as an instance of the
1012
+ class :class:`~sage.tensor.modules.comp.Components`
1013
+
1014
+ EXAMPLES:
1015
+
1016
+ Components of a tensor of type-`(1,1)`::
1017
+
1018
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
1019
+ sage: e = M.basis('e')
1020
+ sage: t = M.tensor((1,1), name='t')
1021
+ sage: t[1,2] = -3 ; t[3,3] = 2
1022
+ sage: t.components()
1023
+ 2-indices components w.r.t. Basis (e_1,e_2,e_3)
1024
+ on the Rank-3 free module M over the Integer Ring
1025
+ sage: t.components() is t.components(e) # since e is M's default basis
1026
+ True
1027
+ sage: t.components()[:]
1028
+ [ 0 -3 0]
1029
+ [ 0 0 0]
1030
+ [ 0 0 2]
1031
+
1032
+ A shortcut is ``t.comp()``::
1033
+
1034
+ sage: t.comp() is t.components()
1035
+ True
1036
+
1037
+ A direct access to the components w.r.t. the module's default basis is
1038
+ provided by the square brackets applied to the tensor itself::
1039
+
1040
+ sage: t[1,2] is t.comp(e)[1,2]
1041
+ True
1042
+ sage: t[:]
1043
+ [ 0 -3 0]
1044
+ [ 0 0 0]
1045
+ [ 0 0 2]
1046
+
1047
+ Components computed via a change-of-basis formula::
1048
+
1049
+ sage: a = M.automorphism()
1050
+ sage: a[:] = [[0,0,1], [1,0,0], [0,-1,0]]
1051
+ sage: f = e.new_basis(a, 'f')
1052
+ sage: t.comp(f)
1053
+ 2-indices components w.r.t. Basis (f_1,f_2,f_3)
1054
+ on the Rank-3 free module M over the Integer Ring
1055
+ sage: t.comp(f)[:]
1056
+ [ 0 0 0]
1057
+ [ 0 2 0]
1058
+ [-3 0 0]
1059
+ """
1060
+ fmodule = self._fmodule
1061
+ if basis is None:
1062
+ basis = fmodule._def_basis
1063
+ try:
1064
+ # Standard bases of tensor modules are keyed to the base module's basis,
1065
+ # not to the TensorFreeSubmoduleBasis_comp instance.
1066
+ basis = basis._base_module_basis
1067
+ except AttributeError:
1068
+ pass
1069
+ if basis not in self._components:
1070
+ # The components must be computed from
1071
+ # those in the basis from_basis
1072
+ if from_basis is None:
1073
+ for known_basis in self._components:
1074
+ if (known_basis, basis) in self._fmodule._basis_changes \
1075
+ and (basis, known_basis) in self._fmodule._basis_changes:
1076
+ from_basis = known_basis
1077
+ break
1078
+ if from_basis is None:
1079
+ raise ValueError("no basis could be found for computing " +
1080
+ "the components in the {}".format(basis))
1081
+ elif from_basis not in self._components:
1082
+ raise ValueError("the tensor components are not known in " +
1083
+ "the {}".format(from_basis))
1084
+ (n_con, n_cov) = self._tensor_type
1085
+ pp = None
1086
+ if n_cov > 0:
1087
+ if (from_basis, basis) not in fmodule._basis_changes:
1088
+ raise ValueError("the change-of-basis matrix from the " +
1089
+ "{} to the {}".format(from_basis, basis)
1090
+ + " has not been set")
1091
+ pp = \
1092
+ fmodule._basis_changes[(from_basis, basis)].comp(from_basis)
1093
+ # pp not used if n_cov = 0 (pure contravariant tensor)
1094
+ ppinv = None
1095
+ if n_con > 0:
1096
+ if (basis, from_basis) not in fmodule._basis_changes:
1097
+ raise ValueError("the change-of-basis matrix from the " +
1098
+ "{} to the {}".format(basis, from_basis) +
1099
+ " has not been set")
1100
+ ppinv = \
1101
+ fmodule._basis_changes[(basis, from_basis)].comp(from_basis)
1102
+ # ppinv not used if n_con = 0 (pure covariant tensor)
1103
+ old_comp = self._components[from_basis]
1104
+ new_comp = self._new_comp(basis)
1105
+ rank = self._tensor_rank
1106
+ # loop on the new components:
1107
+ nproc = Parallelism().get('tensor')
1108
+
1109
+ if nproc != 1:
1110
+ # Parallel computation
1111
+ lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)]
1112
+ ind_list = list(new_comp.non_redundant_index_generator())
1113
+ ind_step = max(1, int(len(ind_list)/nproc/2))
1114
+ local_list = lol(ind_list, ind_step)
1115
+ # list of input parameters
1116
+ listParalInput = [(old_comp, ppinv, pp, n_con, rank, ii) for ii in local_list]
1117
+
1118
+ @parallel(p_iter='multiprocessing', ncpus=nproc)
1119
+ def paral_newcomp(old_comp, ppinv, pp, n_con, rank, local_list_ind):
1120
+ partial = []
1121
+ for ind in local_list_ind:
1122
+ res = 0
1123
+ # Summation on the old components multiplied by the proper
1124
+ # change-of-basis matrix elements (tensor formula):
1125
+ for ind_old in old_comp.index_generator():
1126
+ t = old_comp[[ind_old]]
1127
+ for i in range(n_con): # loop on contravariant indices
1128
+ t *= ppinv[[ind[i], ind_old[i]]]
1129
+ for i in range(n_con,rank): # loop on covariant indices
1130
+ t *= pp[[ind_old[i], ind[i]]]
1131
+ res += t
1132
+ partial.append([ind,res])
1133
+ return partial
1134
+
1135
+ for ii,val in paral_newcomp(listParalInput):
1136
+ for jj in val:
1137
+ new_comp[[jj[0]]] = jj[1]
1138
+
1139
+ else:
1140
+ # Sequential computation
1141
+ for ind_new in new_comp.non_redundant_index_generator():
1142
+ # Summation on the old components multiplied by the proper
1143
+ # change-of-basis matrix elements (tensor formula):
1144
+ res = 0
1145
+ for ind_old in old_comp.index_generator():
1146
+ t = old_comp[[ind_old]]
1147
+ for i in range(n_con): # loop on contravariant indices
1148
+ t *= ppinv[[ind_new[i], ind_old[i]]]
1149
+ for i in range(n_con,rank): # loop on covariant indices
1150
+ t *= pp[[ind_old[i], ind_new[i]]]
1151
+ res += t
1152
+ new_comp[ind_new] = res
1153
+
1154
+ self._components[basis] = new_comp
1155
+ # end of case where the computation was necessary
1156
+ return self._components[basis]
1157
+
1158
+ comp = components
1159
+
1160
+ def _set_comp_unsafe(self, basis=None):
1161
+ r"""
1162
+ Return the components of ``self`` w.r.t. a given module basis for
1163
+ assignment. This private method invokes no security check. Use
1164
+ this method at your own risk.
1165
+
1166
+ The components with respect to other bases are deleted, in order to
1167
+ avoid any inconsistency. To keep them, use the method
1168
+ :meth:`_add_comp_unsafe` instead.
1169
+
1170
+ INPUT:
1171
+
1172
+ - ``basis`` -- (default: ``None``) basis in which the components are
1173
+ defined; if none is provided, the components are assumed to refer to
1174
+ the module's default basis
1175
+
1176
+ OUTPUT:
1177
+
1178
+ - components in the given basis, as an instance of the
1179
+ class :class:`~sage.tensor.modules.comp.Components`; if such
1180
+ components did not exist previously, they are created.
1181
+
1182
+ TESTS:
1183
+
1184
+ Setting components of a type-`(1,1)` tensor::
1185
+
1186
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1187
+ sage: e = M.basis('e')
1188
+ sage: t = M.tensor((1,1), name='t')
1189
+ sage: t._set_comp_unsafe()[0,1] = -3
1190
+ sage: t.display()
1191
+ t = -3 e_0⊗e^1
1192
+ sage: t._set_comp_unsafe()[1,2] = 2
1193
+ sage: t.display()
1194
+ t = -3 e_0⊗e^1 + 2 e_1⊗e^2
1195
+ sage: t._set_comp_unsafe(e)
1196
+ 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the
1197
+ Rank-3 free module M over the Integer Ring
1198
+
1199
+ Setting components in a new basis::
1200
+
1201
+ sage: f = M.basis('f')
1202
+ sage: t._set_comp_unsafe(f)[0,1] = 4
1203
+ sage: list(t._components) # the components w.r.t. basis e have been deleted
1204
+ [Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
1205
+ sage: t.display(f)
1206
+ t = 4 f_0⊗f^1
1207
+
1208
+ The components w.r.t. basis e can be deduced from those w.r.t. basis f,
1209
+ once a relation between the two bases has been set::
1210
+
1211
+ sage: a = M.automorphism()
1212
+ sage: a[:] = [[0,0,1], [1,0,0], [0,-1,0]]
1213
+ sage: M.set_change_of_basis(e, f, a)
1214
+ sage: t.display(e)
1215
+ t = -4 e_1⊗e^2
1216
+ sage: sorted(t._components, key=repr)
1217
+ [Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring,
1218
+ Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
1219
+ """
1220
+ if basis is None:
1221
+ basis = self._fmodule._def_basis
1222
+ if basis not in self._components:
1223
+ if basis not in self._fmodule._known_bases:
1224
+ raise ValueError("the {} has not been ".format(basis) +
1225
+ "defined on the {}".format(self._fmodule))
1226
+ self._components[basis] = self._new_comp(basis)
1227
+ self._del_derived() # deletes the derived quantities
1228
+ self.del_other_comp(basis)
1229
+ return self._components[basis]
1230
+
1231
+ def set_comp(self, basis=None):
1232
+ r"""
1233
+ Return the components of ``self`` w.r.t. a given module basis for
1234
+ assignment.
1235
+
1236
+ The components with respect to other bases are deleted, in order to
1237
+ avoid any inconsistency. To keep them, use the method :meth:`add_comp`
1238
+ instead.
1239
+
1240
+ INPUT:
1241
+
1242
+ - ``basis`` -- (default: ``None``) basis in which the components are
1243
+ defined; if none is provided, the components are assumed to refer to
1244
+ the module's default basis
1245
+
1246
+ OUTPUT:
1247
+
1248
+ - components in the given basis, as an instance of the
1249
+ class :class:`~sage.tensor.modules.comp.Components`; if such
1250
+ components did not exist previously, they are created.
1251
+
1252
+ EXAMPLES:
1253
+
1254
+ Setting components of a type-`(1,1)` tensor::
1255
+
1256
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1257
+ sage: e = M.basis('e')
1258
+ sage: t = M.tensor((1,1), name='t')
1259
+ sage: t.set_comp()[0,1] = -3
1260
+ sage: t.display()
1261
+ t = -3 e_0⊗e^1
1262
+ sage: t.set_comp()[1,2] = 2
1263
+ sage: t.display()
1264
+ t = -3 e_0⊗e^1 + 2 e_1⊗e^2
1265
+ sage: t.set_comp(e)
1266
+ 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the
1267
+ Rank-3 free module M over the Integer Ring
1268
+
1269
+ Setting components in a new basis::
1270
+
1271
+ sage: f = M.basis('f')
1272
+ sage: t.set_comp(f)[0,1] = 4
1273
+ sage: list(t._components) # the components w.r.t. basis e have been deleted
1274
+ [Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
1275
+ sage: t.display(f)
1276
+ t = 4 f_0⊗f^1
1277
+
1278
+ The components w.r.t. basis e can be deduced from those w.r.t. basis f,
1279
+ once a relation between the two bases has been set::
1280
+
1281
+ sage: a = M.automorphism()
1282
+ sage: a[:] = [[0,0,1], [1,0,0], [0,-1,0]]
1283
+ sage: M.set_change_of_basis(e, f, a)
1284
+ sage: t.display(e)
1285
+ t = -4 e_1⊗e^2
1286
+ sage: sorted(t._components, key=repr)
1287
+ [Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring,
1288
+ Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
1289
+
1290
+ Since zero is an immutable element, its components cannot be changed::
1291
+
1292
+ sage: z = M.tensor_module(1, 1).zero()
1293
+ sage: z.set_comp(e)[0,1] = 1
1294
+ Traceback (most recent call last):
1295
+ ...
1296
+ ValueError: the components of an immutable element cannot be changed
1297
+ """
1298
+ if self.is_immutable():
1299
+ raise ValueError("the components of an immutable element "
1300
+ "cannot be changed")
1301
+ self._is_zero = False # a priori
1302
+ return self._set_comp_unsafe(basis)
1303
+
1304
+ def _add_comp_unsafe(self, basis=None):
1305
+ r"""
1306
+ Return the components of ``self`` w.r.t. a given module basis for
1307
+ assignment, keeping the components w.r.t. other bases. This private
1308
+ method invokes no security check. Use this method at your own risk.
1309
+
1310
+ To delete the components w.r.t. other bases, use the method
1311
+ :meth:`_set_comp_unsafe` instead.
1312
+
1313
+ INPUT:
1314
+
1315
+ - ``basis`` -- (default: ``None``) basis in which the components are
1316
+ defined; if none is provided, the components are assumed to refer to
1317
+ the module's default basis
1318
+
1319
+ OUTPUT:
1320
+
1321
+ - components in the given basis, as an instance of the
1322
+ class :class:`~sage.tensor.modules.comp.Components`;
1323
+ if such components did not exist previously, they are created
1324
+
1325
+ TESTS:
1326
+
1327
+ Setting components of a type-`(1,1)` tensor::
1328
+
1329
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1330
+ sage: e = M.basis('e')
1331
+ sage: t = M.tensor((1,1), name='t')
1332
+ sage: t._add_comp_unsafe()[0,1] = -3
1333
+ sage: t.display()
1334
+ t = -3 e_0⊗e^1
1335
+ sage: t._add_comp_unsafe()[1,2] = 2
1336
+ sage: t.display()
1337
+ t = -3 e_0⊗e^1 + 2 e_1⊗e^2
1338
+ sage: t._add_comp_unsafe(e)
1339
+ 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the
1340
+ Rank-3 free module M over the Integer Ring
1341
+
1342
+ Adding components in a new basis::
1343
+
1344
+ sage: f = M.basis('f')
1345
+ sage: t._add_comp_unsafe(f)[0,1] = 4
1346
+
1347
+ The components w.r.t. basis e have been kept::
1348
+
1349
+ sage: sorted(t._components, key=repr)
1350
+ [Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring,
1351
+ Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
1352
+ sage: t.display(f)
1353
+ t = 4 f_0⊗f^1
1354
+ sage: t.display(e)
1355
+ t = -3 e_0⊗e^1 + 2 e_1⊗e^2
1356
+ """
1357
+ if basis is None:
1358
+ basis = self._fmodule._def_basis
1359
+ if basis not in self._components:
1360
+ if basis not in self._fmodule._known_bases:
1361
+ raise ValueError("the {} has not been ".format(basis) +
1362
+ "defined on the {}".format(self._fmodule))
1363
+ self._components[basis] = self._new_comp(basis)
1364
+ self._del_derived() # deletes the derived quantities
1365
+ return self._components[basis]
1366
+
1367
+ def add_comp(self, basis=None):
1368
+ r"""
1369
+ Return the components of ``self`` w.r.t. a given module basis for
1370
+ assignment, keeping the components w.r.t. other bases.
1371
+
1372
+ To delete the components w.r.t. other bases, use the method
1373
+ :meth:`set_comp` instead.
1374
+
1375
+ INPUT:
1376
+
1377
+ - ``basis`` -- (default: ``None``) basis in which the components are
1378
+ defined; if none is provided, the components are assumed to refer to
1379
+ the module's default basis
1380
+
1381
+ .. WARNING::
1382
+
1383
+ If the tensor has already components in other bases, it
1384
+ is the user's responsibility to make sure that the components
1385
+ to be added are consistent with them.
1386
+
1387
+ OUTPUT:
1388
+
1389
+ - components in the given basis, as an instance of the
1390
+ class :class:`~sage.tensor.modules.comp.Components`;
1391
+ if such components did not exist previously, they are created
1392
+
1393
+ EXAMPLES:
1394
+
1395
+ Setting components of a type-`(1,1)` tensor::
1396
+
1397
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1398
+ sage: e = M.basis('e')
1399
+ sage: t = M.tensor((1,1), name='t')
1400
+ sage: t.add_comp()[0,1] = -3
1401
+ sage: t.display()
1402
+ t = -3 e_0⊗e^1
1403
+ sage: t.add_comp()[1,2] = 2
1404
+ sage: t.display()
1405
+ t = -3 e_0⊗e^1 + 2 e_1⊗e^2
1406
+ sage: t.add_comp(e)
1407
+ 2-indices components w.r.t. Basis (e_0,e_1,e_2) on the
1408
+ Rank-3 free module M over the Integer Ring
1409
+
1410
+ Adding components in a new basis::
1411
+
1412
+ sage: f = M.basis('f')
1413
+ sage: t.add_comp(f)[0,1] = 4
1414
+
1415
+ The components w.r.t. basis e have been kept::
1416
+
1417
+ sage: sorted(t._components, key=repr)
1418
+ [Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring,
1419
+ Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
1420
+ sage: t.display(f)
1421
+ t = 4 f_0⊗f^1
1422
+ sage: t.display(e)
1423
+ t = -3 e_0⊗e^1 + 2 e_1⊗e^2
1424
+
1425
+ Since zero is an immutable element, its components cannot be changed::
1426
+
1427
+ sage: z = M.tensor_module(1, 1).zero()
1428
+ sage: z.add_comp(e)[0,1] = 1
1429
+ Traceback (most recent call last):
1430
+ ...
1431
+ ValueError: the components of an immutable element cannot be changed
1432
+ """
1433
+ if self.is_immutable():
1434
+ raise ValueError("the components of an immutable element "
1435
+ "cannot be changed")
1436
+ self._is_zero = False # a priori
1437
+ return self._add_comp_unsafe(basis)
1438
+
1439
+ def del_other_comp(self, basis=None):
1440
+ r"""
1441
+ Delete all the components but those corresponding to ``basis``.
1442
+
1443
+ INPUT:
1444
+
1445
+ - ``basis`` -- (default: ``None``) basis in which the components are
1446
+ kept; if none the module's default basis is assumed
1447
+
1448
+ EXAMPLES:
1449
+
1450
+ Deleting components of a module element::
1451
+
1452
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
1453
+ sage: e = M.basis('e')
1454
+ sage: u = M([2,1,-5])
1455
+ sage: f = M.basis('f')
1456
+ sage: u.add_comp(f)[:] = [0,4,2]
1457
+ sage: sorted(u._components, key=repr)
1458
+ [Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring,
1459
+ Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring]
1460
+ sage: u.del_other_comp(f)
1461
+ sage: list(u._components)
1462
+ [Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring]
1463
+
1464
+ Let us restore the components w.r.t. e and delete those w.r.t. f::
1465
+
1466
+ sage: u.add_comp(e)[:] = [2,1,-5]
1467
+ sage: sorted(u._components, key=repr)
1468
+ [Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring,
1469
+ Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring]
1470
+ sage: u.del_other_comp() # default argument: basis = e
1471
+ sage: list(u._components)
1472
+ [Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring]
1473
+ """
1474
+ if basis is None:
1475
+ basis = self._fmodule._def_basis
1476
+ if basis not in self._components:
1477
+ raise ValueError(f"the components w.r.t. the {basis}"
1478
+ " have not been defined")
1479
+ to_be_deleted = [other_basis for other_basis in self._components
1480
+ if other_basis != basis]
1481
+ for other_basis in to_be_deleted:
1482
+ del self._components[other_basis]
1483
+
1484
+ def __getitem__(self, args) -> Components:
1485
+ r"""
1486
+ Return a component w.r.t. some basis.
1487
+
1488
+ NB: if ``args`` is a string, this method acts as a shortcut for
1489
+ tensor contractions and symmetrizations, the string containing
1490
+ abstract indices.
1491
+
1492
+ INPUT:
1493
+
1494
+ - ``args`` -- list of indices defining the component; if ``[:]`` is
1495
+ provided, all the components are returned. The basis can be passed
1496
+ as the first item of ``args``; if not, the free module's default
1497
+ basis is assumed.
1498
+
1499
+ EXAMPLES::
1500
+
1501
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1502
+ sage: t = M.tensor((2,1), name='t')
1503
+ sage: e = M.basis('e')
1504
+ sage: t.add_comp(e)
1505
+ 3-indices components w.r.t. Basis (e_0,e_1,e_2) on the
1506
+ Rank-3 free module M over the Integer Ring
1507
+ sage: t.__getitem__((1,2,0)) # uninitialized components are zero
1508
+ 0
1509
+ sage: t.__getitem__((e,1,2,0)) # same as above since e in the default basis
1510
+ 0
1511
+ sage: t[1,2,0] = -4
1512
+ sage: t.__getitem__((e,1,2,0))
1513
+ -4
1514
+ sage: v = M([3,-5,2])
1515
+ sage: v.__getitem__(slice(None))
1516
+ [3, -5, 2]
1517
+ sage: v.__getitem__(slice(None)) == v[:]
1518
+ True
1519
+ sage: v.__getitem__((e, slice(None)))
1520
+ [3, -5, 2]
1521
+ """
1522
+ if isinstance(args, str): # tensor with specified indices
1523
+ return TensorWithIndices(self, args).update()
1524
+ if isinstance(args, list): # case of [[...]] syntax
1525
+ if isinstance(args[0], (int, Integer, slice)):
1526
+ basis = self._fmodule._def_basis
1527
+ else:
1528
+ basis = args[0]
1529
+ args = args[1:]
1530
+ else:
1531
+ if isinstance(args, (int, Integer, slice)):
1532
+ basis = self._fmodule._def_basis
1533
+ elif not isinstance(args[0], (int, Integer, slice)):
1534
+ basis = args[0]
1535
+ args = args[1:]
1536
+ if len(args) == 1:
1537
+ args = args[0] # to accommodate for [e,:] syntax
1538
+ else:
1539
+ basis = self._fmodule._def_basis
1540
+ return self.comp(basis)[args]
1541
+
1542
+ def __setitem__(self, args, value):
1543
+ r"""
1544
+ Set a component w.r.t. some basis.
1545
+
1546
+ INPUT:
1547
+
1548
+ - ``args`` -- list of indices defining the component; if ``[:]`` is
1549
+ provided, all the components are set. The basis can be passed
1550
+ as the first item of ``args``; if not, the free module's default
1551
+ basis is assumed
1552
+ - ``value`` -- the value to be set or a list of values if
1553
+ ``args = [:]``
1554
+
1555
+ EXAMPLES::
1556
+
1557
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1558
+ sage: t = M.tensor((0,2), name='t')
1559
+ sage: e = M.basis('e')
1560
+ sage: t.__setitem__((e,0,1), 5)
1561
+ sage: t.display()
1562
+ t = 5 e^0⊗e^1
1563
+ sage: t.__setitem__((0,1), 5) # equivalent to above since e is the default basis
1564
+ sage: t.display()
1565
+ t = 5 e^0⊗e^1
1566
+ sage: t[0,1] = 5 # end-user usage
1567
+ sage: t.display()
1568
+ t = 5 e^0⊗e^1
1569
+ sage: t.__setitem__(slice(None), [[1,-2,3], [-4,5,-6], [7,-8,9]])
1570
+ sage: t[:]
1571
+ [ 1 -2 3]
1572
+ [-4 5 -6]
1573
+ [ 7 -8 9]
1574
+ """
1575
+ if isinstance(args, list): # case of [[...]] syntax
1576
+ if isinstance(args[0], (int, Integer, slice, tuple)):
1577
+ basis = self._fmodule._def_basis
1578
+ else:
1579
+ basis = args[0]
1580
+ args = args[1:]
1581
+ else:
1582
+ if isinstance(args, (int, Integer, slice)):
1583
+ basis = self._fmodule._def_basis
1584
+ elif not isinstance(args[0], (int, Integer, slice)):
1585
+ basis = args[0]
1586
+ args = args[1:]
1587
+ if len(args) == 1:
1588
+ args = args[0] # to accommodate for [e,:] syntax
1589
+ else:
1590
+ basis = self._fmodule._def_basis
1591
+ self.set_comp(basis)[args] = value
1592
+
1593
+ def copy_from(self, other):
1594
+ r"""
1595
+ Make ``self`` to a copy from ``other``.
1596
+
1597
+ INPUT:
1598
+
1599
+ - ``other`` -- other tensor in the very same module from which
1600
+ ``self`` should be a copy of
1601
+
1602
+ .. WARNING::
1603
+
1604
+ All previous defined components will be deleted!
1605
+
1606
+ EXAMPLES::
1607
+
1608
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
1609
+ sage: e = M.basis('e')
1610
+ sage: t = M.tensor((1,1), name='t')
1611
+ sage: t[1,2] = -3 ; t[3,3] = 2
1612
+ sage: s = M.tensor((1,1), name='s')
1613
+ sage: s.copy_from(t)
1614
+ sage: s[:]
1615
+ [ 0 -3 0]
1616
+ [ 0 0 0]
1617
+ [ 0 0 2]
1618
+ sage: s == t
1619
+ True
1620
+
1621
+ If the original tensor is modified, the copy is not::
1622
+
1623
+ sage: t[2,2] = 4
1624
+ sage: s[:]
1625
+ [ 0 -3 0]
1626
+ [ 0 0 0]
1627
+ [ 0 0 2]
1628
+ sage: s == t
1629
+ False
1630
+ """
1631
+ if self.is_immutable():
1632
+ raise ValueError("the components of an immutable element "
1633
+ "cannot be changed")
1634
+ if other not in self.parent():
1635
+ raise TypeError("the original must be an element "
1636
+ + "of {}".format(self.parent()))
1637
+ self._del_derived()
1638
+ self._components.clear()
1639
+ for basis, comp in other._components.items():
1640
+ self._components[basis] = comp.copy()
1641
+ self._is_zero = other._is_zero
1642
+
1643
+ def copy(self, name=None, latex_name=None):
1644
+ r"""
1645
+ Return an exact copy of ``self``.
1646
+
1647
+ The name and the derived quantities are not copied.
1648
+
1649
+ INPUT:
1650
+
1651
+ - ``name`` -- (default: ``None``) name given to the copy
1652
+ - ``latex_name`` -- (default: ``None``) LaTeX symbol to denote the
1653
+ copy; if none is provided, the LaTeX symbol is set to ``name``
1654
+
1655
+ EXAMPLES:
1656
+
1657
+ Copy of a tensor of type `(1,1)`::
1658
+
1659
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
1660
+ sage: e = M.basis('e')
1661
+ sage: t = M.tensor((1,1), name='t')
1662
+ sage: t[1,2] = -3 ; t[3,3] = 2
1663
+ sage: t1 = t.copy()
1664
+ sage: t1[:]
1665
+ [ 0 -3 0]
1666
+ [ 0 0 0]
1667
+ [ 0 0 2]
1668
+ sage: t1 == t
1669
+ True
1670
+
1671
+ If the original tensor is modified, the copy is not::
1672
+
1673
+ sage: t[2,2] = 4
1674
+ sage: t1[:]
1675
+ [ 0 -3 0]
1676
+ [ 0 0 0]
1677
+ [ 0 0 2]
1678
+ sage: t1 == t
1679
+ False
1680
+ """
1681
+ resu = self._new_instance()
1682
+ resu.set_name(name=name, latex_name=latex_name)
1683
+ for basis, comp in self._components.items():
1684
+ resu._components[basis] = comp.copy()
1685
+ resu._is_zero = self._is_zero
1686
+ return resu
1687
+
1688
+ def common_basis(self, other):
1689
+ r"""
1690
+ Find a common basis for the components of ``self`` and ``other``.
1691
+
1692
+ In case of multiple common bases, the free module's default basis is
1693
+ privileged. If the current components of ``self`` and ``other``
1694
+ are all relative to different bases, a common basis is searched
1695
+ by performing a component transformation, via the transformations
1696
+ listed in ``self._fmodule._basis_changes``, still privileging
1697
+ transformations to the free module's default basis.
1698
+
1699
+ INPUT:
1700
+
1701
+ - ``other`` -- a tensor (instance of :class:`FreeModuleTensor`)
1702
+
1703
+ OUTPUT:
1704
+
1705
+ - instance of
1706
+ :class:`~sage.tensor.modules.free_module_basis.FreeModuleBasis`
1707
+ representing the common basis; if no common basis is found, ``None``
1708
+ is returned
1709
+
1710
+ EXAMPLES:
1711
+
1712
+ Common basis for the components of two module elements::
1713
+
1714
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1)
1715
+ sage: e = M.basis('e')
1716
+ sage: u = M([2,1,-5])
1717
+ sage: f = M.basis('f')
1718
+ sage: M._basis_changes.clear() # to ensure that bases e and f are unrelated at this stage
1719
+ sage: v = M([0,4,2], basis=f)
1720
+ sage: u.common_basis(v)
1721
+
1722
+ The above result is ``None`` since ``u`` and ``v`` have been defined
1723
+ on different bases and no connection between these bases have
1724
+ been set::
1725
+
1726
+ sage: list(u._components)
1727
+ [Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring]
1728
+ sage: list(v._components)
1729
+ [Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring]
1730
+
1731
+ Linking bases ``e`` and ``f`` changes the result::
1732
+
1733
+ sage: a = M.automorphism()
1734
+ sage: a[:] = [[0,0,1], [1,0,0], [0,-1,0]]
1735
+ sage: M.set_change_of_basis(e, f, a)
1736
+ sage: u.common_basis(v)
1737
+ Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring
1738
+
1739
+ Indeed, v is now known in basis e::
1740
+
1741
+ sage: sorted(v._components, key=repr)
1742
+ [Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring,
1743
+ Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring]
1744
+ """
1745
+ # Compatibility checks:
1746
+ if not isinstance(other, FreeModuleTensor):
1747
+ raise TypeError("the argument must be a tensor on a free module")
1748
+ fmodule = self._fmodule
1749
+ if other._fmodule != fmodule:
1750
+ raise TypeError("the two tensors are not defined on the same " +
1751
+ "free module")
1752
+ def_basis = fmodule._def_basis
1753
+
1754
+ # 1/ Search for a common basis among the existing components, i.e.
1755
+ # without performing any component transformation.
1756
+ # -------------------------------------------------------------
1757
+ if def_basis in self._components and def_basis in other._components:
1758
+ return def_basis # the module's default basis is privileged
1759
+ for basis1 in self._components:
1760
+ if basis1 in other._components:
1761
+ return basis1
1762
+
1763
+ # 2/ Search for a common basis via one component transformation
1764
+ # ----------------------------------------------------------
1765
+ # If this point is reached, it is indeed necessary to perform at least
1766
+ # one component transformation to get a common basis
1767
+ if def_basis in self._components:
1768
+ for obasis in other._components:
1769
+ if (obasis, def_basis) in fmodule._basis_changes:
1770
+ other.comp(def_basis, from_basis=obasis)
1771
+ return def_basis
1772
+ if def_basis in other._components:
1773
+ for sbasis in self._components:
1774
+ if (sbasis, def_basis) in fmodule._basis_changes:
1775
+ self.comp(def_basis, from_basis=sbasis)
1776
+ return def_basis
1777
+ # If this point is reached, then def_basis cannot be a common basis
1778
+ # via a single component transformation
1779
+ for sbasis in self._components:
1780
+ for obasis in other._components:
1781
+ if (obasis, sbasis) in fmodule._basis_changes:
1782
+ other.comp(sbasis, from_basis=obasis)
1783
+ return sbasis
1784
+ if (sbasis, obasis) in fmodule._basis_changes:
1785
+ self.comp(obasis, from_basis=sbasis)
1786
+ return obasis
1787
+
1788
+ # 3/ Search for a common basis via two component transformations
1789
+ # -----------------------------------------------------------
1790
+ # If this point is reached, it is indeed necessary to perform at two
1791
+ # component transformation to get a common basis
1792
+ for sbasis in self._components:
1793
+ for obasis in other._components:
1794
+ if (sbasis, def_basis) in fmodule._basis_changes and \
1795
+ (obasis, def_basis) in fmodule._basis_changes:
1796
+ self.comp(def_basis, from_basis=sbasis)
1797
+ other.comp(def_basis, from_basis=obasis)
1798
+ return def_basis
1799
+ for basis in fmodule._known_bases:
1800
+ if (sbasis, basis) in fmodule._basis_changes and \
1801
+ (obasis, basis) in fmodule._basis_changes:
1802
+ self.comp(basis, from_basis=sbasis)
1803
+ other.comp(basis, from_basis=obasis)
1804
+ return basis
1805
+
1806
+ # If this point is reached, no common basis could be found, even at
1807
+ # the price of component transformations:
1808
+ return None
1809
+
1810
+ def pick_a_basis(self):
1811
+ r"""
1812
+ Return a basis in which the tensor components are defined.
1813
+
1814
+ The free module's default basis is privileged.
1815
+
1816
+ OUTPUT:
1817
+
1818
+ - instance of
1819
+ :class:`~sage.tensor.modules.free_module_basis.FreeModuleBasis`
1820
+ representing the basis
1821
+
1822
+ EXAMPLES::
1823
+
1824
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1825
+ sage: t = M.tensor((2,0), name='t')
1826
+ sage: e = M.basis('e')
1827
+ sage: t[0,1] = 4 # component set in the default basis (e)
1828
+ sage: t.pick_a_basis()
1829
+ Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring
1830
+ sage: f = M.basis('f')
1831
+ sage: t.add_comp(f)[2,1] = -4 # the components in basis e are not erased
1832
+ sage: t.pick_a_basis()
1833
+ Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring
1834
+ sage: t.set_comp(f)[2,1] = -4 # the components in basis e not erased
1835
+ sage: t.pick_a_basis()
1836
+ Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring
1837
+ """
1838
+ if self._fmodule._def_basis in self._components:
1839
+ return self._fmodule._def_basis # the default basis is privileged
1840
+ else:
1841
+ # a basis is picked arbitrarily:
1842
+ return next(iter(self._components.items()))[0]
1843
+
1844
+ def __eq__(self, other):
1845
+ r"""
1846
+ Comparison (equality) operator.
1847
+
1848
+ INPUT:
1849
+
1850
+ - ``other`` -- a tensor or 0
1851
+
1852
+ OUTPUT: ``True`` if ``self`` is equal to ``other`` and ``False`` otherwise
1853
+
1854
+ EXAMPLES::
1855
+
1856
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1857
+ sage: t = M.tensor((2,0), name='t')
1858
+ sage: e = M.basis('e')
1859
+ sage: t[0,1] = 7
1860
+ sage: t.__eq__(0)
1861
+ False
1862
+ sage: t[0,1] = 0
1863
+ sage: t.__eq__(0)
1864
+ True
1865
+ sage: a = M.tensor((0,2), name='a')
1866
+ sage: a[0,1] = 7
1867
+ sage: t[0,1] = 7
1868
+ sage: a[:], t[:]
1869
+ (
1870
+ [0 7 0] [0 7 0]
1871
+ [0 0 0] [0 0 0]
1872
+ [0 0 0], [0 0 0]
1873
+ )
1874
+ sage: t.__eq__(a) # False since t and a do not have the same tensor type
1875
+ False
1876
+ sage: a = M.tensor((2,0), name='a') # same tensor type as t
1877
+ sage: a[0,1] = 7
1878
+ sage: t.__eq__(a)
1879
+ True
1880
+ """
1881
+ if self is other:
1882
+ return True
1883
+
1884
+ if self._tensor_rank == 0:
1885
+ raise NotImplementedError("scalar comparison not implemented")
1886
+ if isinstance(other, (int, Integer)): # other should be 0
1887
+ if other == 0:
1888
+ return self.is_zero()
1889
+ else:
1890
+ return False
1891
+ elif not isinstance(other, FreeModuleTensor):
1892
+ return False
1893
+ else: # other is another tensor
1894
+ if other._fmodule != self._fmodule:
1895
+ return False
1896
+ if other._tensor_type != self._tensor_type:
1897
+ return False
1898
+ basis = self.common_basis(other)
1899
+ if basis is None:
1900
+ raise ValueError("no common basis for the comparison")
1901
+ return bool(self._components[basis] == other._components[basis])
1902
+
1903
+ def __ne__(self, other):
1904
+ r"""
1905
+ Inequality operator.
1906
+
1907
+ INPUT:
1908
+
1909
+ - ``other`` -- a tensor or 0
1910
+
1911
+ OUTPUT:
1912
+
1913
+ - ``True`` if ``self`` is different from ``other`` and ``False``
1914
+ otherwise
1915
+
1916
+ EXAMPLES::
1917
+
1918
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1919
+ sage: t = M.tensor((2,0), name='t')
1920
+ sage: e = M.basis('e')
1921
+ sage: t[0,1] = 7
1922
+ sage: t.__ne__(0)
1923
+ True
1924
+ sage: t[0,1] = 0
1925
+ sage: t.__ne__(0)
1926
+ False
1927
+ sage: a = M.tensor((2,0), name='a') # same tensor type as t
1928
+ sage: a[0,1] = 7
1929
+ sage: t.__ne__(a)
1930
+ True
1931
+ sage: t[0,1] = 7
1932
+ sage: t.__ne__(a)
1933
+ False
1934
+ """
1935
+ return not self == other
1936
+
1937
+ def __pos__(self):
1938
+ r"""
1939
+ Unary plus operator.
1940
+
1941
+ OUTPUT: an exact copy of ``self``
1942
+
1943
+ EXAMPLES::
1944
+
1945
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1946
+ sage: t = M.tensor((2,0), name='t')
1947
+ sage: e = M.basis('e')
1948
+ sage: t[0,1] = 7
1949
+ sage: p = t.__pos__() ; p
1950
+ Type-(2,0) tensor +t on the Rank-3 free module M over the Integer Ring
1951
+ sage: p.display()
1952
+ +t = 7 e_0⊗e_1
1953
+ sage: p == t
1954
+ True
1955
+ sage: p is t
1956
+ False
1957
+ """
1958
+ result = self._new_instance()
1959
+ for basis in self._components:
1960
+ result._components[basis] = + self._components[basis]
1961
+ if self._name is not None:
1962
+ result._name = '+' + self._name
1963
+ if self._latex_name is not None:
1964
+ result._latex_name = '+' + self._latex_name
1965
+ return result
1966
+
1967
+ def __neg__(self):
1968
+ r"""
1969
+ Unary minus operator.
1970
+
1971
+ OUTPUT: the tensor `-T`, where `T` is ``self``
1972
+
1973
+ EXAMPLES::
1974
+
1975
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
1976
+ sage: t = M.tensor((2,0), name='t')
1977
+ sage: e = M.basis('e')
1978
+ sage: t[0,1], t[1,2] = 7, -4
1979
+ sage: t.display()
1980
+ t = 7 e_0⊗e_1 - 4 e_1⊗e_2
1981
+ sage: a = t.__neg__() ; a
1982
+ Type-(2,0) tensor -t on the Rank-3 free module M over the Integer Ring
1983
+ sage: a.display()
1984
+ -t = -7 e_0⊗e_1 + 4 e_1⊗e_2
1985
+ sage: a == -t
1986
+ True
1987
+ """
1988
+ result = self._new_instance()
1989
+ for basis in self._components:
1990
+ result._components[basis] = - self._components[basis]
1991
+ if self._name is not None:
1992
+ result._name = '-' + self._name
1993
+ if self._latex_name is not None:
1994
+ result._latex_name = '-' + self._latex_name
1995
+ return result
1996
+
1997
+ ######### ModuleElement arithmetic operators ########
1998
+
1999
+ def _add_(self, other):
2000
+ r"""
2001
+ Tensor addition.
2002
+
2003
+ INPUT:
2004
+
2005
+ - ``other`` -- a tensor, of the same type as ``self``
2006
+
2007
+ OUTPUT: the tensor resulting from the addition of ``self`` and ``other``
2008
+
2009
+ EXAMPLES::
2010
+
2011
+ sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
2012
+ sage: e = M.basis('e')
2013
+ sage: a = M.tensor((2,0), name='a')
2014
+ sage: a[:] = [[4,0], [-2,5]]
2015
+ sage: b = M.tensor((2,0), name='b')
2016
+ sage: b[:] = [[0,1], [2,3]]
2017
+ sage: s = a._add_(b) ; s
2018
+ Type-(2,0) tensor a+b on the Rank-2 free module M over the Integer Ring
2019
+ sage: s[:]
2020
+ [4 1]
2021
+ [0 8]
2022
+ sage: a._add_(-a) == 0
2023
+ True
2024
+ sage: a._add_(a) == 2*a
2025
+ True
2026
+ """
2027
+ # No need for consistency check since self and other are guaranteed
2028
+ # to belong to the same tensor module
2029
+ #
2030
+ # Case zero:
2031
+ if self._is_zero:
2032
+ return other
2033
+ if other._is_zero:
2034
+ return self
2035
+ # Generic case:
2036
+ basis = self.common_basis(other)
2037
+ if basis is None:
2038
+ raise ValueError("no common basis for the addition")
2039
+ comp_result = self._components[basis] + other._components[basis]
2040
+ result = self._fmodule.tensor_from_comp(self._tensor_type, comp_result)
2041
+ if self._name is not None and other._name is not None:
2042
+ result._name = self._name + '+' + other._name
2043
+ if self._latex_name is not None and other._latex_name is not None:
2044
+ result._latex_name = self._latex_name + '+' + other._latex_name
2045
+ return result
2046
+
2047
+ def _sub_(self, other):
2048
+ r"""
2049
+ Tensor subtraction.
2050
+
2051
+ INPUT:
2052
+
2053
+ - ``other`` -- a tensor, of the same type as ``self``
2054
+
2055
+ OUTPUT: the tensor resulting from the subtraction of ``other`` from ``self``
2056
+
2057
+ EXAMPLES::
2058
+
2059
+ sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
2060
+ sage: e = M.basis('e')
2061
+ sage: a = M.tensor((2,0), name='a')
2062
+ sage: a[:] = [[4,0], [-2,5]]
2063
+ sage: b = M.tensor((2,0), name='b')
2064
+ sage: b[:] = [[0,1], [2,3]]
2065
+ sage: s = a._sub_(b) ; s
2066
+ Type-(2,0) tensor a-b on the Rank-2 free module M over the Integer Ring
2067
+ sage: s[:]
2068
+ [ 4 -1]
2069
+ [-4 2]
2070
+ sage: b._sub_(a) == -s
2071
+ True
2072
+ sage: a._sub_(a) == 0
2073
+ True
2074
+ sage: a._sub_(-a) == 2*a
2075
+ True
2076
+
2077
+ TESTS:
2078
+
2079
+ Check for when there is not a basis, but the same object::
2080
+
2081
+ sage: M = FiniteRankFreeModule(QQ, 3, name='M')
2082
+ sage: t = M.tensor((2,1), name='t')
2083
+ sage: t == t
2084
+ True
2085
+ """
2086
+ # No need for consistency check since self and other are guaranteed
2087
+ # to belong to the same tensor module
2088
+ #
2089
+ # Case zero:
2090
+ if self._is_zero:
2091
+ return -other
2092
+ if other._is_zero:
2093
+ return self
2094
+ # Generic case:
2095
+ basis = self.common_basis(other)
2096
+ if basis is None:
2097
+ raise ValueError("no common basis for the subtraction")
2098
+ comp_result = self._components[basis] - other._components[basis]
2099
+ result = self._fmodule.tensor_from_comp(self._tensor_type, comp_result)
2100
+ if self._name is not None and other._name is not None:
2101
+ result._name = self._name + '-' + other._name
2102
+ if self._latex_name is not None and other._latex_name is not None:
2103
+ result._latex_name = self._latex_name + '-' + other._latex_name
2104
+ return result
2105
+
2106
+ def _rmul_(self, other):
2107
+ r"""
2108
+ Multiplication on the left by ``other``.
2109
+
2110
+ EXAMPLES::
2111
+
2112
+ sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
2113
+ sage: e = M.basis('e')
2114
+ sage: a = M.tensor((2,0), name='a')
2115
+ sage: a[:] = [[4,0], [-2,5]]
2116
+ sage: s = a._rmul_(2) ; s
2117
+ Type-(2,0) tensor on the Rank-2 free module M over the Integer Ring
2118
+ sage: s[:]
2119
+ [ 8 0]
2120
+ [-4 10]
2121
+ sage: s == a + a
2122
+ True
2123
+ sage: a._rmul_(0)
2124
+ Type-(2,0) tensor on the Rank-2 free module M over the Integer Ring
2125
+ sage: a._rmul_(0) == 0
2126
+ True
2127
+ sage: a._rmul_(1) == a
2128
+ True
2129
+ sage: a._rmul_(-1) == -a
2130
+ True
2131
+ """
2132
+ #!# The following test is probably not necessary:
2133
+ if isinstance(other, FreeModuleTensor):
2134
+ raise NotImplementedError("left tensor product not implemented")
2135
+ # Left multiplication by a scalar:
2136
+ result = self._new_instance()
2137
+ for basis in self._components:
2138
+ result._components[basis] = other * self._components[basis]
2139
+ # If other has a name, set the name of the result:
2140
+ try:
2141
+ from .format_utilities import format_mul_txt, format_mul_latex
2142
+ result_name = format_mul_txt(other._name, '*', self._name)
2143
+ result_latex = format_mul_latex(other._latex_name, r' \cdot ',
2144
+ self._latex_name)
2145
+ result.set_name(name=result_name, latex_name=result_latex)
2146
+ except AttributeError:
2147
+ pass
2148
+ return result
2149
+
2150
+ ######### End of ModuleElement arithmetic operators ########
2151
+
2152
+ def __mul__(self, other):
2153
+ r"""
2154
+ Tensor product.
2155
+
2156
+ EXAMPLES::
2157
+
2158
+ sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
2159
+ sage: e = M.basis('e')
2160
+ sage: a = M.tensor((2,0), name='a')
2161
+ sage: a[:] = [[4,0], [-2,5]]
2162
+ sage: b = M.tensor((0,2), name='b', antisym=(0,1))
2163
+ sage: b[0,1] = 3
2164
+ sage: s = a.__mul__(b) ; s
2165
+ Type-(2,2) tensor a⊗b on the Rank-2 free module M over the Integer Ring
2166
+ sage: s.symmetries()
2167
+ no symmetry; antisymmetry: (2, 3)
2168
+ sage: s[:]
2169
+ [[[[0, 12], [-12, 0]], [[0, 0], [0, 0]]],
2170
+ [[[0, -6], [6, 0]], [[0, 15], [-15, 0]]]]
2171
+ """
2172
+ from sage.typeset.unicode_characters import unicode_otimes
2173
+ from .format_utilities import format_mul_txt, format_mul_latex
2174
+ if isinstance(other, FreeModuleTensor):
2175
+ basis = self.common_basis(other)
2176
+ if basis is None:
2177
+ raise ValueError("no common basis for the tensor product")
2178
+ comp_prov = self._components[basis] * other._components[basis]
2179
+ # Reordering of the contravariant and covariant indices:
2180
+ k1, l1 = self._tensor_type
2181
+ k2, l2 = other._tensor_type
2182
+ if l1 != 0:
2183
+ comp_result = comp_prov.swap_adjacent_indices(k1,
2184
+ self._tensor_rank,
2185
+ self._tensor_rank+k2)
2186
+ else:
2187
+ comp_result = comp_prov # no reordering is necessary
2188
+ result = self._fmodule.tensor_from_comp((k1+k2, l1+l2),
2189
+ comp_result)
2190
+ result._name = format_mul_txt(self._name, unicode_otimes, other._name)
2191
+ result._latex_name = format_mul_latex(self._latex_name,
2192
+ r'\otimes ', other._latex_name)
2193
+ return result
2194
+
2195
+ # multiplication by a scalar:
2196
+ return FreeModuleTensor._rmul_(self, other)
2197
+
2198
+ def __truediv__(self, other):
2199
+ r"""
2200
+ Division (by a scalar).
2201
+
2202
+ EXAMPLES::
2203
+
2204
+ sage: M = FiniteRankFreeModule(QQ, 2, name='M')
2205
+ sage: e = M.basis('e')
2206
+ sage: a = M.tensor((2,0), name='a')
2207
+ sage: a[:] = [[4,0], [-2,5]]
2208
+ sage: s = a.__truediv__(4) ; s
2209
+ Type-(2,0) tensor on the 2-dimensional vector space M over the
2210
+ Rational Field
2211
+ sage: s[:]
2212
+ [ 1 0]
2213
+ [-1/2 5/4]
2214
+ sage: 4*s == a
2215
+ True
2216
+ sage: s == a/4
2217
+ True
2218
+ """
2219
+ result = self._new_instance()
2220
+ for basis in self._components:
2221
+ result._components[basis] = self._components[basis] / other
2222
+ return result
2223
+
2224
+ def __call__(self, *args) -> Expression:
2225
+ r"""
2226
+ The tensor acting on linear forms and module elements as a multilinear
2227
+ map.
2228
+
2229
+ INPUT:
2230
+
2231
+ - ``*args`` -- list of `k` linear forms and `l` module elements
2232
+ with ``self`` being a tensor of type `(k, l)`
2233
+
2234
+ EXAMPLES:
2235
+
2236
+ Action of a type-`(2,1)` tensor::
2237
+
2238
+ sage: M = FiniteRankFreeModule(ZZ, 2, name='M')
2239
+ sage: e = M.basis('e')
2240
+ sage: t = M.tensor((2,1), name='t', antisym=(0,1))
2241
+ sage: t[0,1,0], t[0,1,1] = 3, 2
2242
+ sage: t.display()
2243
+ t = 3 e_0⊗e_1⊗e^0 + 2 e_0⊗e_1⊗e^1 - 3 e_1⊗e_0⊗e^0 - 2 e_1⊗e_0⊗e^1
2244
+ sage: a = M.linear_form()
2245
+ sage: a[:] = 1, 2
2246
+ sage: b = M.linear_form()
2247
+ sage: b[:] = 3, -1
2248
+ sage: v = M([-2,1])
2249
+ sage: t.__call__(a,b,v)
2250
+ 28
2251
+ sage: t(a,b,v) == t.__call__(a,b,v)
2252
+ True
2253
+ sage: t(a,b,v) == t.contract(v).contract(b).contract(a)
2254
+ True
2255
+
2256
+ Action of a linear form on a vector::
2257
+
2258
+ sage: a.__call__(v)
2259
+ 0
2260
+ sage: a.__call__(v) == a(v)
2261
+ True
2262
+ sage: a(v) == a.contract(v)
2263
+ True
2264
+ sage: b.__call__(v)
2265
+ -7
2266
+ sage: b.__call__(v) == b(v)
2267
+ True
2268
+ sage: b(v) == b.contract(v)
2269
+ True
2270
+
2271
+ Action of a vector on a linear form::
2272
+
2273
+ sage: v.__call__(a)
2274
+ 0
2275
+ sage: v.__call__(b)
2276
+ -7
2277
+ """
2278
+ # Consistency checks:
2279
+ p = len(args)
2280
+ if p != self._tensor_rank:
2281
+ raise TypeError(str(self._tensor_rank) +
2282
+ " arguments must be provided")
2283
+ for i in range(self._tensor_type[0]):
2284
+ if not isinstance(args[i], FreeModuleTensor):
2285
+ raise TypeError("the argument no. " + str(i+1) +
2286
+ " must be a linear form")
2287
+ if args[i]._tensor_type != (0,1):
2288
+ raise TypeError("the argument no. " + str(i+1) +
2289
+ " must be a linear form")
2290
+ for i in range(self._tensor_type[0], p):
2291
+ if not isinstance(args[i], FreeModuleTensor):
2292
+ raise TypeError("the argument no. " + str(i+1) +
2293
+ " must be a module element")
2294
+ if args[i]._tensor_type != (1,0):
2295
+ raise TypeError("the argument no. " + str(i+1) +
2296
+ " must be a module element")
2297
+ fmodule = self._fmodule
2298
+ #
2299
+ # Specific case of a linear form acting on a vector (for efficiency):
2300
+ #
2301
+ if self._tensor_type == (0,1):
2302
+ vector = args[0]
2303
+ basis = self.common_basis(vector)
2304
+ if basis is None:
2305
+ raise ValueError("no common basis for the components")
2306
+ omega = self._components[basis]
2307
+ vv = vector._components[basis]
2308
+ resu = 0
2309
+ for i in fmodule.irange():
2310
+ resu += omega[[i]]*vv[[i]]
2311
+ # Name and LaTeX symbol of the output:
2312
+ if hasattr(resu, '_name'):
2313
+ if self._name is not None and vector._name is not None:
2314
+ resu._name = self._name + "(" + vector._name + ")"
2315
+ if hasattr(resu, '_latex_name'):
2316
+ if self._latex_name is not None and \
2317
+ vector._latex_name is not None:
2318
+ resu._latex_name = self._latex_name + r"\left(" + \
2319
+ vector._latex_name + r"\right)"
2320
+ return resu
2321
+ #
2322
+ # Generic case
2323
+ #
2324
+ # Search for a common basis
2325
+ basis = None
2326
+ # First try with the module's default basis
2327
+ def_basis = fmodule._def_basis
2328
+ if def_basis in self._components:
2329
+ basis = def_basis
2330
+ for arg in args:
2331
+ if def_basis not in arg._components:
2332
+ basis = None
2333
+ break
2334
+ if basis is None:
2335
+ # Search for another basis:
2336
+ for bas in self._components:
2337
+ basis = bas
2338
+ for arg in args:
2339
+ if bas not in arg._components:
2340
+ basis = None
2341
+ break
2342
+ if basis is not None: # common basis found !
2343
+ break
2344
+ if basis is None:
2345
+ # A last attempt to find a common basis, possibly via a
2346
+ # change-of-components transformation
2347
+ for arg in args:
2348
+ self.common_basis(arg) # to trigger some change of components
2349
+ for bas in self._components:
2350
+ basis = bas
2351
+ for arg in args:
2352
+ if bas not in arg._components:
2353
+ basis = None
2354
+ break
2355
+ if basis is not None: # common basis found !
2356
+ break
2357
+ if basis is None:
2358
+ raise ValueError("no common basis for the components")
2359
+ t = self._components[basis]
2360
+ v = [args[i]._components[basis] for i in range(p)]
2361
+ res = 0
2362
+ for ind in t.index_generator():
2363
+ prod = t[[ind]]
2364
+ for i in range(p):
2365
+ prod *= v[i][[ind[i]]]
2366
+ res += prod
2367
+ # Name of the output:
2368
+ if hasattr(res, '_name'):
2369
+ res_name = None
2370
+ if self._name is not None:
2371
+ res_name = self._name + "("
2372
+ for i in range(p-1):
2373
+ if args[i]._name is not None:
2374
+ res_name += args[i]._name + ","
2375
+ else:
2376
+ res_name = None
2377
+ break
2378
+ if res_name is not None:
2379
+ if args[p-1]._name is not None:
2380
+ res_name += args[p-1]._name + ")"
2381
+ else:
2382
+ res_name = None
2383
+ res._name = res_name
2384
+ # LaTeX symbol of the output:
2385
+ if hasattr(res, '_latex_name'):
2386
+ res_latex = None
2387
+ if self._latex_name is not None:
2388
+ res_latex = self._latex_name + r"\left("
2389
+ for i in range(p-1):
2390
+ if args[i]._latex_name is not None:
2391
+ res_latex += args[i]._latex_name + ","
2392
+ else:
2393
+ res_latex = None
2394
+ break
2395
+ if res_latex is not None:
2396
+ if args[p-1]._latex_name is not None:
2397
+ res_latex += args[p-1]._latex_name + r"\right)"
2398
+ else:
2399
+ res_latex = None
2400
+ res._latex_name = res_latex
2401
+ return res
2402
+
2403
+ def trace(
2404
+ self,
2405
+ pos1: int = 0,
2406
+ pos2: int = 1,
2407
+ using: Optional[
2408
+ Union[PseudoRiemannianMetric, SymplecticForm, PoissonTensorField]
2409
+ ] = None,
2410
+ ):
2411
+ r"""
2412
+ Trace (contraction) on two slots of the tensor.
2413
+
2414
+ If a non-degenerate form is provided, the trace of a type-`(0,2)` tensor
2415
+ is computed by first raising the last index.
2416
+
2417
+ INPUT:
2418
+
2419
+ - ``pos1`` -- (default: 0) position of the first index for the
2420
+ contraction, with the convention ``pos1=0`` for the first slot
2421
+
2422
+ - ``pos2`` -- (default: 1) position of the second index for the
2423
+ contraction, with the same convention as for ``pos1``; the variance
2424
+ type of ``pos2`` must be opposite to that of ``pos1``
2425
+
2426
+ - ``using`` -- (default: ``None``) a non-degenerate form
2427
+
2428
+ OUTPUT:
2429
+
2430
+ - tensor or scalar resulting from the ``(pos1, pos2)`` contraction
2431
+
2432
+ EXAMPLES:
2433
+
2434
+ Trace of a type-`(1,1)` tensor::
2435
+
2436
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
2437
+ sage: e = M.basis('e') ; e
2438
+ Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring
2439
+ sage: a = M.tensor((1,1), name='a') ; a
2440
+ Type-(1,1) tensor a on the Rank-3 free module M over the Integer Ring
2441
+ sage: a[:] = [[1,2,3], [4,5,6], [7,8,9]]
2442
+ sage: a.trace()
2443
+ 15
2444
+ sage: a.trace(0,1) # equivalent to above (contraction of slot 0 with slot 1)
2445
+ 15
2446
+ sage: a.trace(1,0) # the order of the slots does not matter
2447
+ 15
2448
+
2449
+ Instead of the explicit call to the method :meth:`trace`, one
2450
+ may use the index notation with Einstein convention (summation over
2451
+ repeated indices); it suffices to pass the indices as a string inside
2452
+ square brackets::
2453
+
2454
+ sage: a['^i_i']
2455
+ 15
2456
+
2457
+ The letter 'i' to denote the repeated index can be replaced by any
2458
+ other letter::
2459
+
2460
+ sage: a['^s_s']
2461
+ 15
2462
+
2463
+ Moreover, the symbol ``^`` can be omitted::
2464
+
2465
+ sage: a['i_i']
2466
+ 15
2467
+
2468
+ The contraction on two slots having the same tensor type cannot occur::
2469
+
2470
+ sage: b = M.tensor((2,0), name='b') ; b
2471
+ Type-(2,0) tensor b on the Rank-3 free module M over the Integer Ring
2472
+ sage: b[:] = [[1,2,3], [4,5,6], [7,8,9]]
2473
+ sage: b.trace(0,1)
2474
+ Traceback (most recent call last):
2475
+ ...
2476
+ IndexError: contraction on two contravariant indices is not allowed
2477
+
2478
+ The contraction either preserves or destroys the symmetries::
2479
+
2480
+ sage: b = M.alternating_form(2, 'b') ; b
2481
+ Alternating form b of degree 2 on the Rank-3 free module M
2482
+ over the Integer Ring
2483
+ sage: b[0,1], b[0,2], b[1,2] = 3, 2, 1
2484
+ sage: t = a*b ; t
2485
+ Type-(1,3) tensor a⊗b on the Rank-3 free module M
2486
+ over the Integer Ring
2487
+
2488
+ By construction, ``t`` is a tensor field antisymmetric w.r.t. its
2489
+ last two slots::
2490
+
2491
+ sage: t.symmetries()
2492
+ no symmetry; antisymmetry: (2, 3)
2493
+ sage: s = t.trace(0,1) ; s # contraction on the first two slots
2494
+ Alternating form of degree 2 on the
2495
+ Rank-3 free module M over the Integer Ring
2496
+ sage: s.symmetries() # the antisymmetry is preserved
2497
+ no symmetry; antisymmetry: (0, 1)
2498
+ sage: s[:]
2499
+ [ 0 45 30]
2500
+ [-45 0 15]
2501
+ [-30 -15 0]
2502
+ sage: s == 15*b # check
2503
+ True
2504
+ sage: s = t.trace(0,2) ; s # contraction on the first and third slots
2505
+ Type-(0,2) tensor on the Rank-3 free module M over the Integer Ring
2506
+ sage: s.symmetries() # the antisymmetry has been destroyed by the above contraction:
2507
+ no symmetry; no antisymmetry
2508
+ sage: s[:] # indeed:
2509
+ [-26 -4 6]
2510
+ [-31 -2 9]
2511
+ [-36 0 12]
2512
+ sage: s[:] == matrix( [[sum(t[k,i,k,j] for k in M.irange())
2513
+ ....: for j in M.irange()] for i in M.irange()] ) # check
2514
+ True
2515
+
2516
+ Use of index notation instead of :meth:`trace`::
2517
+
2518
+ sage: t['^k_kij'] == t.trace(0,1)
2519
+ True
2520
+ sage: t['^k_{kij}'] == t.trace(0,1) # LaTeX notation
2521
+ True
2522
+ sage: t['^k_ikj'] == t.trace(0,2)
2523
+ True
2524
+ sage: t['^k_ijk'] == t.trace(0,3)
2525
+ True
2526
+
2527
+ Index symbols not involved in the contraction may be replaced by
2528
+ dots::
2529
+
2530
+ sage: t['^k_k..'] == t.trace(0,1)
2531
+ True
2532
+ sage: t['^k_.k.'] == t.trace(0,2)
2533
+ True
2534
+ sage: t['^k_..k'] == t.trace(0,3)
2535
+ True
2536
+ """
2537
+ if using is not None:
2538
+ if self.tensor_type() != (0, 2):
2539
+ raise ValueError(
2540
+ "trace with respect to a non-degenerate form is only defined for type-(0,2) tensor"
2541
+ )
2542
+ return self.up(using, 1).trace()
2543
+
2544
+ # The indices at pos1 and pos2 must be of different types:
2545
+ k_con = self._tensor_type[0]
2546
+ l_cov = self._tensor_type[1]
2547
+ if pos1 < k_con and pos2 < k_con:
2548
+ raise IndexError("contraction on two contravariant indices is " +
2549
+ "not allowed")
2550
+ if pos1 >= k_con and pos2 >= k_con:
2551
+ raise IndexError("contraction on two covariant indices is " +
2552
+ "not allowed")
2553
+ # Frame selection for the computation:
2554
+ if self._fmodule._def_basis in self._components:
2555
+ basis = self._fmodule._def_basis
2556
+ else: # a basis is picked arbitrarily:
2557
+ basis = self.pick_a_basis()
2558
+ resu_comp = self._components[basis].trace(pos1, pos2)
2559
+ if self._tensor_rank == 2: # result is a scalar
2560
+ return resu_comp
2561
+ else:
2562
+ return self._fmodule.tensor_from_comp((k_con-1, l_cov-1),
2563
+ resu_comp)
2564
+
2565
+ def contract(self, *args):
2566
+ r"""
2567
+ Contraction on one or more indices with another tensor.
2568
+
2569
+ INPUT:
2570
+
2571
+ - ``pos1`` -- positions of the indices in ``self`` involved in the
2572
+ contraction; ``pos1`` must be a sequence of integers, with 0 standing
2573
+ for the first index position, 1 for the second one, etc; if ``pos1``
2574
+ is not provided, a single contraction on the last index position of
2575
+ ``self`` is assumed
2576
+ - ``other`` -- the tensor to contract with
2577
+ - ``pos2`` -- positions of the indices in ``other`` involved in the
2578
+ contraction, with the same conventions as for ``pos1``; if ``pos2``
2579
+ is not provided, a single contraction on the first index position of
2580
+ ``other`` is assumed
2581
+
2582
+ OUTPUT:
2583
+
2584
+ - tensor resulting from the contraction at the positions ``pos1`` and
2585
+ ``pos2`` of ``self`` with ``other``
2586
+
2587
+ EXAMPLES:
2588
+
2589
+ Contraction of a tensor of type `(0,1)` with a tensor of type `(1,0)`::
2590
+
2591
+ sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
2592
+ sage: e = M.basis('e')
2593
+ sage: a = M.linear_form() # tensor of type (0,1) is a linear form
2594
+ sage: a[:] = [-3,2,1]
2595
+ sage: b = M([2,5,-2]) # tensor of type (1,0) is a module element
2596
+ sage: s = a.contract(b) ; s
2597
+ 2
2598
+ sage: s in M.base_ring()
2599
+ True
2600
+ sage: s == a[0]*b[0] + a[1]*b[1] + a[2]*b[2] # check of the computation
2601
+ True
2602
+
2603
+ The positions of the contraction indices can be set explicitly::
2604
+
2605
+ sage: s == a.contract(0, b, 0)
2606
+ True
2607
+ sage: s == a.contract(0, b)
2608
+ True
2609
+ sage: s == a.contract(b, 0)
2610
+ True
2611
+
2612
+ Instead of the explicit call to the method :meth:`contract`, the index
2613
+ notation can be used to specify the contraction, via Einstein
2614
+ convention (summation on repeated indices); it suffices to pass the
2615
+ indices as a string inside square brackets::
2616
+
2617
+ sage: s1 = a['_i']*b['^i'] ; s1
2618
+ 2
2619
+ sage: s1 == s
2620
+ True
2621
+
2622
+ In the present case, performing the contraction is identical to
2623
+ applying the linear form to the module element::
2624
+
2625
+ sage: a.contract(b) == a(b)
2626
+ True
2627
+
2628
+ or to applying the module element, considered as a tensor of type
2629
+ `(1,0)`, to the linear form::
2630
+
2631
+ sage: a.contract(b) == b(a)
2632
+ True
2633
+
2634
+ We have also::
2635
+
2636
+ sage: a.contract(b) == b.contract(a)
2637
+ True
2638
+
2639
+ Contraction of a tensor of type `(1,1)` with a tensor of type `(1,0)`::
2640
+
2641
+ sage: a = M.tensor((1,1))
2642
+ sage: a[:] = [[-1,2,3],[4,-5,6],[7,8,9]]
2643
+ sage: s = a.contract(b) ; s
2644
+ Element of the Rank-3 free module M over the Integer Ring
2645
+ sage: s.display()
2646
+ 2 e_0 - 29 e_1 + 36 e_2
2647
+
2648
+ Since the index positions have not been specified, the contraction
2649
+ takes place on the last position of a (i.e. no. 1) and the first
2650
+ position of ``b`` (i.e. no. 0)::
2651
+
2652
+ sage: a.contract(b) == a.contract(1, b, 0)
2653
+ True
2654
+ sage: a.contract(b) == b.contract(0, a, 1)
2655
+ True
2656
+ sage: a.contract(b) == b.contract(a, 1)
2657
+ True
2658
+
2659
+ Using the index notation with Einstein convention::
2660
+
2661
+ sage: a['^i_j']*b['^j'] == a.contract(b)
2662
+ True
2663
+
2664
+ The index ``i`` can be replaced by a dot::
2665
+
2666
+ sage: a['^._j']*b['^j'] == a.contract(b)
2667
+ True
2668
+
2669
+ and the symbol ``^`` may be omitted, the distinction between
2670
+ contravariant and covariant indices being the position with respect to
2671
+ the symbol ``_``::
2672
+
2673
+ sage: a['._j']*b['j'] == a.contract(b)
2674
+ True
2675
+
2676
+ Contraction is possible only between a contravariant index and a
2677
+ covariant one::
2678
+
2679
+ sage: a.contract(0, b)
2680
+ Traceback (most recent call last):
2681
+ ...
2682
+ TypeError: contraction on two contravariant indices not permitted
2683
+
2684
+ Contraction of a tensor of type `(2,1)` with a tensor of type `(0,2)`::
2685
+
2686
+ sage: a = a*b ; a
2687
+ Type-(2,1) tensor on the Rank-3 free module M over the Integer Ring
2688
+ sage: b = M.tensor((0,2))
2689
+ sage: b[:] = [[-2,3,1], [0,-2,3], [4,-7,6]]
2690
+ sage: s = a.contract(1, b, 1) ; s
2691
+ Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring
2692
+ sage: s[:]
2693
+ [[[-9, 16, 39], [18, -32, -78], [27, -48, -117]],
2694
+ [[36, -64, -156], [-45, 80, 195], [54, -96, -234]],
2695
+ [[63, -112, -273], [72, -128, -312], [81, -144, -351]]]
2696
+
2697
+ Check of the computation::
2698
+
2699
+ sage: all(s[i,j,k] == a[i,0,j]*b[k,0]+a[i,1,j]*b[k,1]+a[i,2,j]*b[k,2]
2700
+ ....: for i in range(3) for j in range(3) for k in range(3))
2701
+ True
2702
+
2703
+ Using index notation::
2704
+
2705
+ sage: a['il_j']*b['_kl'] == a.contract(1, b, 1)
2706
+ True
2707
+
2708
+ LaTeX notation are allowed::
2709
+
2710
+ sage: a['^{il}_j']*b['_{kl}'] == a.contract(1, b, 1)
2711
+ True
2712
+
2713
+ Indices not involved in the contraction may be replaced by dots::
2714
+
2715
+ sage: a['.l_.']*b['_.l'] == a.contract(1, b, 1)
2716
+ True
2717
+
2718
+ The two tensors do not have to be defined on the same basis for the
2719
+ contraction to take place, reflecting the fact that the contraction is
2720
+ basis-independent::
2721
+
2722
+ sage: A = M.automorphism()
2723
+ sage: A[:] = [[0,0,1], [1,0,0], [0,-1,0]]
2724
+ sage: h = e.new_basis(A, 'h')
2725
+ sage: b.comp(h)[:] # forces the computation of b's components w.r.t. basis h
2726
+ [-2 -3 0]
2727
+ [ 7 6 -4]
2728
+ [ 3 -1 -2]
2729
+ sage: b.del_other_comp(h) # deletes components w.r.t. basis e
2730
+ sage: list(b._components) # indeed:
2731
+ [Basis (h_0,h_1,h_2) on the Rank-3 free module M over the Integer Ring]
2732
+ sage: list(a._components) # while a is known only in basis e:
2733
+ [Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring]
2734
+ sage: s1 = a.contract(1, b, 1) ; s1 # yet the computation is possible
2735
+ Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring
2736
+ sage: s1 == s # ... and yields the same result as previously:
2737
+ True
2738
+
2739
+ The contraction can be performed on more than a single index; for
2740
+ instance a `2`-indices contraction of a type-`(2,1)` tensor with a
2741
+ type-`(1,2)` one is::
2742
+
2743
+ sage: a # a is a tensor of type-(2,1)
2744
+ Type-(2,1) tensor on the Rank-3 free module M over the Integer Ring
2745
+ sage: b = M([1,-1,2])*b ; b # a tensor of type (1,2)
2746
+ Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring
2747
+ sage: s = a.contract(1,2,b,1,0) ; s # the double contraction
2748
+ Type-(1,1) tensor on the Rank-3 free module M over the Integer Ring
2749
+ sage: s[:]
2750
+ [ -36 30 15]
2751
+ [-252 210 105]
2752
+ [-204 170 85]
2753
+ sage: s == a['^.k_l']*b['^l_k.'] # the same thing in index notation
2754
+ True
2755
+ """
2756
+ #
2757
+ # Treatment of the input
2758
+ #
2759
+ nargs = len(args)
2760
+ for i, arg in enumerate(args):
2761
+ if isinstance(arg, FreeModuleTensor):
2762
+ other = arg
2763
+ it = i
2764
+ break
2765
+ else:
2766
+ raise TypeError("a tensor must be provided in the argument list")
2767
+ if it == 0:
2768
+ pos1 = (self._tensor_rank - 1,)
2769
+ else:
2770
+ pos1 = args[:it]
2771
+ if it == nargs-1:
2772
+ pos2 = (0,)
2773
+ else:
2774
+ pos2 = args[it+1:]
2775
+ ncontr = len(pos1) # number of contractions
2776
+ if len(pos2) != ncontr:
2777
+ raise TypeError("different number of indices for the contraction")
2778
+ k1, l1 = self._tensor_type
2779
+ k2, l2 = other._tensor_type
2780
+ for i in range(ncontr):
2781
+ p1 = pos1[i]
2782
+ p2 = pos2[i]
2783
+ if p1 < k1 and p2 < k2:
2784
+ raise TypeError("contraction on two contravariant indices " +
2785
+ "not permitted")
2786
+ if p1 >= k1 and p2 >= k2:
2787
+ raise TypeError("contraction on two covariant indices " +
2788
+ "not permitted")
2789
+ #
2790
+ # Contraction at the component level
2791
+ #
2792
+ basis = self.common_basis(other)
2793
+ if basis is None:
2794
+ raise ValueError("no common basis for the contraction")
2795
+ args = pos1 + (other._components[basis],) + pos2
2796
+ cmp_res = self._components[basis].contract(*args)
2797
+ if self._tensor_rank + other._tensor_rank - 2*ncontr == 0:
2798
+ # Case of scalar output:
2799
+ return cmp_res
2800
+ #
2801
+ # Reordering of the indices to have all contravariant indices first:
2802
+ #
2803
+ nb_cov_s = 0 # Number of covariant indices of self not involved in the
2804
+ # contraction
2805
+ for pos in range(k1, k1 + l1):
2806
+ if pos not in pos1:
2807
+ nb_cov_s += 1
2808
+ nb_con_o = 0 # Number of contravariant indices of other not involved
2809
+ # in the contraction
2810
+ for pos in range(k2):
2811
+ if pos not in pos2:
2812
+ nb_con_o += 1
2813
+ if nb_cov_s != 0 and nb_con_o != 0:
2814
+ # some reordering is necessary:
2815
+ p2 = k1 + l1 - ncontr
2816
+ p1 = p2 - nb_cov_s
2817
+ p3 = p2 + nb_con_o
2818
+ cmp_res = cmp_res.swap_adjacent_indices(p1, p2, p3)
2819
+ type_res = (k1+k2-ncontr, l1+l2-ncontr)
2820
+ return self._fmodule.tensor_from_comp(type_res, cmp_res)
2821
+
2822
+ def symmetrize(self, *pos, **kwargs):
2823
+ r"""
2824
+ Symmetrization over some arguments.
2825
+
2826
+ INPUT:
2827
+
2828
+ - ``pos`` -- list of argument positions involved in the
2829
+ symmetrization (with the convention ``position=0`` for the first
2830
+ argument); if none, the symmetrization is performed over all the
2831
+ arguments
2832
+ - ``basis`` -- (default: ``None``) module basis with respect to which
2833
+ the component computation is to be performed; if none, the module's
2834
+ default basis is used if the tensor field has already components
2835
+ in it; otherwise another basis w.r.t. which the tensor has
2836
+ components will be picked
2837
+
2838
+ OUTPUT:
2839
+
2840
+ - the symmetrized tensor (instance of :class:`FreeModuleTensor`)
2841
+
2842
+ EXAMPLES:
2843
+
2844
+ Symmetrization of a tensor of type `(2,0)`::
2845
+
2846
+ sage: M = FiniteRankFreeModule(QQ, 3, name='M')
2847
+ sage: e = M.basis('e')
2848
+ sage: t = M.tensor((2,0))
2849
+ sage: t[:] = [[2,1,-3],[0,-4,5],[-1,4,2]]
2850
+ sage: s = t.symmetrize() ; s
2851
+ Type-(2,0) tensor on the 3-dimensional vector space M over the
2852
+ Rational Field
2853
+ sage: t[:], s[:]
2854
+ (
2855
+ [ 2 1 -3] [ 2 1/2 -2]
2856
+ [ 0 -4 5] [1/2 -4 9/2]
2857
+ [-1 4 2], [ -2 9/2 2]
2858
+ )
2859
+ sage: s.symmetries()
2860
+ symmetry: (0, 1); no antisymmetry
2861
+ sage: all(s[i,j] == 1/2*(t[i,j]+t[j,i]) # check:
2862
+ ....: for i in range(3) for j in range(3))
2863
+ True
2864
+
2865
+ Instead of invoking the method :meth:`symmetrize`, one may use the
2866
+ index notation with parentheses to denote the symmetrization; it
2867
+ suffices to pass the indices as a string inside square brackets::
2868
+
2869
+ sage: t['(ij)']
2870
+ Type-(2,0) tensor on the 3-dimensional vector space M over the
2871
+ Rational Field
2872
+ sage: t['(ij)'].symmetries()
2873
+ symmetry: (0, 1); no antisymmetry
2874
+ sage: t['(ij)'] == t.symmetrize()
2875
+ True
2876
+
2877
+ The indices names are not significant; they can even be replaced by
2878
+ dots::
2879
+
2880
+ sage: t['(..)'] == t.symmetrize()
2881
+ True
2882
+
2883
+ The LaTeX notation can be used as well::
2884
+
2885
+ sage: t['^{(ij)}'] == t.symmetrize()
2886
+ True
2887
+
2888
+ Symmetrization of a tensor of type `(0,3)` on the first two arguments::
2889
+
2890
+ sage: t = M.tensor((0,3))
2891
+ sage: t[:] = [[[1,2,3], [-4,5,6], [7,8,-9]],
2892
+ ....: [[10,-11,12], [13,14,-15], [16,17,18]],
2893
+ ....: [[19,-20,-21], [-22,23,24], [25,26,-27]]]
2894
+ sage: s = t.symmetrize(0,1) ; s # (0,1) = the first two arguments
2895
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
2896
+ Rational Field
2897
+ sage: s.symmetries()
2898
+ symmetry: (0, 1); no antisymmetry
2899
+ sage: s[:]
2900
+ [[[1, 2, 3], [3, -3, 9], [13, -6, -15]],
2901
+ [[3, -3, 9], [13, 14, -15], [-3, 20, 21]],
2902
+ [[13, -6, -15], [-3, 20, 21], [25, 26, -27]]]
2903
+ sage: all(s[i,j,k] == 1/2*(t[i,j,k]+t[j,i,k]) # Check:
2904
+ ....: for i in range(3) for j in range(3) for k in range(3))
2905
+ True
2906
+ sage: s.symmetrize(0,1) == s # another test
2907
+ True
2908
+
2909
+ Again the index notation can be used::
2910
+
2911
+ sage: t['_(ij)k'] == t.symmetrize(0,1)
2912
+ True
2913
+ sage: t['_(..).'] == t.symmetrize(0,1) # no index name
2914
+ True
2915
+ sage: t['_{(ij)k}'] == t.symmetrize(0,1) # LaTeX notation
2916
+ True
2917
+ sage: t['_{(..).}'] == t.symmetrize(0,1) # this also allowed
2918
+ True
2919
+
2920
+ Symmetrization of a tensor of type `(0,3)` on the first and
2921
+ last arguments::
2922
+
2923
+ sage: s = t.symmetrize(0,2) ; s # (0,2) = first and last arguments
2924
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
2925
+ Rational Field
2926
+ sage: s.symmetries()
2927
+ symmetry: (0, 2); no antisymmetry
2928
+ sage: s[:]
2929
+ [[[1, 6, 11], [-4, 9, -8], [7, 12, 8]],
2930
+ [[6, -11, -4], [9, 14, 4], [12, 17, 22]],
2931
+ [[11, -4, -21], [-8, 4, 24], [8, 22, -27]]]
2932
+ sage: all(s[i,j,k] == 1/2*(t[i,j,k]+t[k,j,i])
2933
+ ....: for i in range(3) for j in range(3) for k in range(3))
2934
+ True
2935
+ sage: s.symmetrize(0,2) == s # another test
2936
+ True
2937
+
2938
+ Symmetrization of a tensor of type `(0,3)` on the last two arguments::
2939
+
2940
+ sage: s = t.symmetrize(1,2) ; s # (1,2) = the last two arguments
2941
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
2942
+ Rational Field
2943
+ sage: s.symmetries()
2944
+ symmetry: (1, 2); no antisymmetry
2945
+ sage: s[:]
2946
+ [[[1, -1, 5], [-1, 5, 7], [5, 7, -9]],
2947
+ [[10, 1, 14], [1, 14, 1], [14, 1, 18]],
2948
+ [[19, -21, 2], [-21, 23, 25], [2, 25, -27]]]
2949
+ sage: all(s[i,j,k] == 1/2*(t[i,j,k]+t[i,k,j]) # Check:
2950
+ ....: for i in range(3) for j in range(3) for k in range(3))
2951
+ True
2952
+ sage: s.symmetrize(1,2) == s # another test
2953
+ True
2954
+
2955
+ Use of the index notation::
2956
+
2957
+ sage: t['_i(jk)'] == t.symmetrize(1,2)
2958
+ True
2959
+ sage: t['_.(..)'] == t.symmetrize(1,2)
2960
+ True
2961
+ sage: t['_{i(jk)}'] == t.symmetrize(1,2) # LaTeX notation
2962
+ True
2963
+
2964
+ Full symmetrization of a tensor of type `(0,3)`::
2965
+
2966
+ sage: s = t.symmetrize() ; s
2967
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
2968
+ Rational Field
2969
+ sage: s.symmetries()
2970
+ symmetry: (0, 1, 2); no antisymmetry
2971
+ sage: s[:]
2972
+ [[[1, 8/3, 29/3], [8/3, 7/3, 0], [29/3, 0, -5/3]],
2973
+ [[8/3, 7/3, 0], [7/3, 14, 25/3], [0, 25/3, 68/3]],
2974
+ [[29/3, 0, -5/3], [0, 25/3, 68/3], [-5/3, 68/3, -27]]]
2975
+ sage: all(s[i,j,k] == 1/6*(t[i,j,k]+t[i,k,j]+t[j,k,i]+t[j,i,k]+t[k,i,j]+t[k,j,i]) # Check:
2976
+ ....: for i in range(3) for j in range(3) for k in range(3))
2977
+ True
2978
+ sage: s.symmetrize() == s # another test
2979
+ True
2980
+
2981
+ Index notation for the full symmetrization::
2982
+
2983
+ sage: t['_(ijk)'] == t.symmetrize()
2984
+ True
2985
+ sage: t['_{(ijk)}'] == t.symmetrize() # LaTeX notation
2986
+ True
2987
+
2988
+ Symmetrization can be performed only on arguments on the same type::
2989
+
2990
+ sage: t = M.tensor((1,2))
2991
+ sage: t[:] = [[[1,2,3], [-4,5,6], [7,8,-9]],
2992
+ ....: [[10,-11,12], [13,14,-15], [16,17,18]],
2993
+ ....: [[19,-20,-21], [-22,23,24], [25,26,-27]]]
2994
+ sage: s = t.symmetrize(0,1)
2995
+ Traceback (most recent call last):
2996
+ ...
2997
+ TypeError: 0 is a contravariant position, while 1 is a covariant position;
2998
+ symmetrization is meaningful only on tensor arguments of the same type
2999
+ sage: s = t.symmetrize(1,2) # OK: both 1 and 2 are covariant positions
3000
+
3001
+ The order of positions does not matter::
3002
+
3003
+ sage: t.symmetrize(2,1) == t.symmetrize(1,2)
3004
+ True
3005
+
3006
+ Use of the index notation::
3007
+
3008
+ sage: t['^i_(jk)'] == t.symmetrize(1,2)
3009
+ True
3010
+ sage: t['^._(..)'] == t.symmetrize(1,2)
3011
+ True
3012
+
3013
+ The character ``^`` can be skipped, the character ``_`` being
3014
+ sufficient to separate contravariant indices from covariant ones::
3015
+
3016
+ sage: t['i_(jk)'] == t.symmetrize(1,2)
3017
+ True
3018
+
3019
+ The LaTeX notation can be employed::
3020
+
3021
+ sage: t['^{i}_{(jk)}'] == t.symmetrize(1,2)
3022
+ True
3023
+ """
3024
+ if not pos:
3025
+ pos = range(self._tensor_rank)
3026
+ # check whether the symmetrization is possible:
3027
+ pos_cov = self._tensor_type[0] # first covariant position
3028
+ pos0 = pos[0]
3029
+ if pos0 < pos_cov: # pos0 is a contravariant position
3030
+ for k in range(1,len(pos)):
3031
+ if pos[k] >= pos_cov:
3032
+ raise TypeError(
3033
+ str(pos[0]) + " is a contravariant position, while " +
3034
+ str(pos[k]) + " is a covariant position; \n"
3035
+ "symmetrization is meaningful only on tensor " +
3036
+ "arguments of the same type")
3037
+ else: # pos0 is a covariant position
3038
+ for k in range(1,len(pos)):
3039
+ if pos[k] < pos_cov:
3040
+ raise TypeError(
3041
+ str(pos[0]) + " is a covariant position, while " +
3042
+ str(pos[k]) + " is a contravariant position; \n"
3043
+ "symmetrization is meaningful only on tensor " +
3044
+ "arguments of the same type")
3045
+ if 'basis' in kwargs:
3046
+ basis = kwargs['basis']
3047
+ else:
3048
+ basis = self.pick_a_basis()
3049
+ res_comp = self._components[basis].symmetrize(*pos)
3050
+ return self._fmodule.tensor_from_comp(self._tensor_type, res_comp)
3051
+
3052
+ def antisymmetrize(self, *pos, **kwargs):
3053
+ r"""
3054
+ Antisymmetrization over some arguments.
3055
+
3056
+ INPUT:
3057
+
3058
+ - ``pos`` -- list of argument positions involved in the
3059
+ antisymmetrization (with the convention ``position=0`` for the first
3060
+ argument); if none, the antisymmetrization is performed over all the
3061
+ arguments
3062
+ - ``basis`` -- (default: ``None``) module basis with respect to which
3063
+ the component computation is to be performed; if none, the module's
3064
+ default basis is used if the tensor field has already components
3065
+ in it; otherwise another basis w.r.t. which the tensor has
3066
+ components will be picked
3067
+
3068
+ OUTPUT:
3069
+
3070
+ - the antisymmetrized tensor (instance of :class:`FreeModuleTensor`)
3071
+
3072
+ EXAMPLES:
3073
+
3074
+ Antisymmetrization of a tensor of type `(2,0)`::
3075
+
3076
+ sage: M = FiniteRankFreeModule(QQ, 3, name='M')
3077
+ sage: e = M.basis('e')
3078
+ sage: t = M.tensor((2,0))
3079
+ sage: t[:] = [[1,-2,3], [4,5,6], [7,8,-9]]
3080
+ sage: s = t.antisymmetrize() ; s
3081
+ Alternating contravariant tensor of degree 2 on the 3-dimensional
3082
+ vector space M over the Rational Field
3083
+ sage: s.symmetries()
3084
+ no symmetry; antisymmetry: (0, 1)
3085
+ sage: t[:], s[:]
3086
+ (
3087
+ [ 1 -2 3] [ 0 -3 -2]
3088
+ [ 4 5 6] [ 3 0 -1]
3089
+ [ 7 8 -9], [ 2 1 0]
3090
+ )
3091
+ sage: all(s[i,j] == 1/2*(t[i,j]-t[j,i]) # Check:
3092
+ ....: for i in range(3) for j in range(3))
3093
+ True
3094
+ sage: s.antisymmetrize() == s # another test
3095
+ True
3096
+ sage: t.antisymmetrize() == t.antisymmetrize(0,1)
3097
+ True
3098
+
3099
+ Antisymmetrization of a tensor of type `(0, 3)` over the first two
3100
+ arguments::
3101
+
3102
+ sage: t = M.tensor((0,3))
3103
+ sage: t[:] = [[[1,2,3], [-4,5,6], [7,8,-9]],
3104
+ ....: [[10,-11,12], [13,14,-15], [16,17,18]],
3105
+ ....: [[19,-20,-21], [-22,23,24], [25,26,-27]]]
3106
+ sage: s = t.antisymmetrize(0,1) ; s # (0,1) = the first two arguments
3107
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
3108
+ Rational Field
3109
+ sage: s.symmetries()
3110
+ no symmetry; antisymmetry: (0, 1)
3111
+ sage: s[:]
3112
+ [[[0, 0, 0], [-7, 8, -3], [-6, 14, 6]],
3113
+ [[7, -8, 3], [0, 0, 0], [19, -3, -3]],
3114
+ [[6, -14, -6], [-19, 3, 3], [0, 0, 0]]]
3115
+ sage: all(s[i,j,k] == 1/2*(t[i,j,k]-t[j,i,k]) # Check:
3116
+ ....: for i in range(3) for j in range(3) for k in range(3))
3117
+ True
3118
+ sage: s.antisymmetrize(0,1) == s # another test
3119
+ True
3120
+ sage: s.symmetrize(0,1) == 0 # of course
3121
+ True
3122
+
3123
+ Instead of invoking the method :meth:`antisymmetrize`, one can use
3124
+ the index notation with square brackets denoting the
3125
+ antisymmetrization; it suffices to pass the indices as a string
3126
+ inside square brackets::
3127
+
3128
+ sage: s1 = t['_[ij]k'] ; s1
3129
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
3130
+ Rational Field
3131
+ sage: s1.symmetries()
3132
+ no symmetry; antisymmetry: (0, 1)
3133
+ sage: s1 == s
3134
+ True
3135
+
3136
+ The LaTeX notation is recognized::
3137
+
3138
+ sage: t['_{[ij]k}'] == s
3139
+ True
3140
+
3141
+ Note that in the index notation, the name of the indices is irrelevant;
3142
+ they can even be replaced by dots::
3143
+
3144
+ sage: t['_[..].'] == s
3145
+ True
3146
+
3147
+ Antisymmetrization of a tensor of type `(0,3)` over the first and last
3148
+ arguments::
3149
+
3150
+ sage: s = t.antisymmetrize(0,2) ; s # (0,2) = first and last arguments
3151
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
3152
+ Rational Field
3153
+ sage: s.symmetries()
3154
+ no symmetry; antisymmetry: (0, 2)
3155
+ sage: s[:]
3156
+ [[[0, -4, -8], [0, -4, 14], [0, -4, -17]],
3157
+ [[4, 0, 16], [4, 0, -19], [4, 0, -4]],
3158
+ [[8, -16, 0], [-14, 19, 0], [17, 4, 0]]]
3159
+ sage: all(s[i,j,k] == 1/2*(t[i,j,k]-t[k,j,i]) # Check:
3160
+ ....: for i in range(3) for j in range(3) for k in range(3))
3161
+ True
3162
+ sage: s.antisymmetrize(0,2) == s # another test
3163
+ True
3164
+ sage: s.symmetrize(0,2) == 0 # of course
3165
+ True
3166
+ sage: s.symmetrize(0,1) == 0 # no reason for this to hold
3167
+ False
3168
+
3169
+ Antisymmetrization of a tensor of type `(0,3)` over the last two
3170
+ arguments::
3171
+
3172
+ sage: s = t.antisymmetrize(1,2) ; s # (1,2) = the last two arguments
3173
+ Type-(0,3) tensor on the 3-dimensional vector space M over the
3174
+ Rational Field
3175
+ sage: s.symmetries()
3176
+ no symmetry; antisymmetry: (1, 2)
3177
+ sage: s[:]
3178
+ [[[0, 3, -2], [-3, 0, -1], [2, 1, 0]],
3179
+ [[0, -12, -2], [12, 0, -16], [2, 16, 0]],
3180
+ [[0, 1, -23], [-1, 0, -1], [23, 1, 0]]]
3181
+ sage: all(s[i,j,k] == 1/2*(t[i,j,k]-t[i,k,j]) # Check:
3182
+ ....: for i in range(3) for j in range(3) for k in range(3))
3183
+ True
3184
+ sage: s.antisymmetrize(1,2) == s # another test
3185
+ True
3186
+ sage: s.symmetrize(1,2) == 0 # of course
3187
+ True
3188
+
3189
+ The index notation can be used instead of the explicit call to
3190
+ :meth:`antisymmetrize`::
3191
+
3192
+ sage: t['_i[jk]'] == t.antisymmetrize(1,2)
3193
+ True
3194
+
3195
+ Full antisymmetrization of a tensor of type `(0,3)`::
3196
+
3197
+ sage: s = t.antisymmetrize() ; s
3198
+ Alternating form of degree 3 on the 3-dimensional vector space M
3199
+ over the Rational Field
3200
+ sage: s.symmetries()
3201
+ no symmetry; antisymmetry: (0, 1, 2)
3202
+ sage: s[:]
3203
+ [[[0, 0, 0], [0, 0, 2/3], [0, -2/3, 0]],
3204
+ [[0, 0, -2/3], [0, 0, 0], [2/3, 0, 0]],
3205
+ [[0, 2/3, 0], [-2/3, 0, 0], [0, 0, 0]]]
3206
+ sage: all(s[i,j,k] == 1/6*(t[i,j,k]-t[i,k,j]+t[j,k,i]-t[j,i,k]
3207
+ ....: +t[k,i,j]-t[k,j,i])
3208
+ ....: for i in range(3) for j in range(3) for k in range(3))
3209
+ True
3210
+ sage: s.antisymmetrize() == s # another test
3211
+ True
3212
+ sage: s.symmetrize(0,1) == 0 # of course
3213
+ True
3214
+ sage: s.symmetrize(0,2) == 0 # of course
3215
+ True
3216
+ sage: s.symmetrize(1,2) == 0 # of course
3217
+ True
3218
+ sage: t.antisymmetrize() == t.antisymmetrize(0,1,2)
3219
+ True
3220
+
3221
+ The index notation can be used instead of the explicit call to
3222
+ :meth:`antisymmetrize`::
3223
+
3224
+ sage: t['_[ijk]'] == t.antisymmetrize()
3225
+ True
3226
+ sage: t['_[abc]'] == t.antisymmetrize()
3227
+ True
3228
+ sage: t['_[...]'] == t.antisymmetrize()
3229
+ True
3230
+ sage: t['_{[ijk]}'] == t.antisymmetrize() # LaTeX notation
3231
+ True
3232
+
3233
+ Antisymmetrization can be performed only on arguments on the same type::
3234
+
3235
+ sage: t = M.tensor((1,2))
3236
+ sage: t[:] = [[[1,2,3], [-4,5,6], [7,8,-9]],
3237
+ ....: [[10,-11,12], [13,14,-15], [16,17,18]],
3238
+ ....: [[19,-20,-21], [-22,23,24], [25,26,-27]]]
3239
+ sage: s = t.antisymmetrize(0,1)
3240
+ Traceback (most recent call last):
3241
+ ...
3242
+ TypeError: 0 is a contravariant position, while 1 is a covariant position;
3243
+ antisymmetrization is meaningful only on tensor arguments of the same type
3244
+ sage: s = t.antisymmetrize(1,2) # OK: both 1 and 2 are covariant positions
3245
+
3246
+ The order of positions does not matter::
3247
+
3248
+ sage: t.antisymmetrize(2,1) == t.antisymmetrize(1,2)
3249
+ True
3250
+
3251
+ Again, the index notation can be used::
3252
+
3253
+ sage: t['^i_[jk]'] == t.antisymmetrize(1,2)
3254
+ True
3255
+ sage: t['^i_{[jk]}'] == t.antisymmetrize(1,2) # LaTeX notation
3256
+ True
3257
+
3258
+ The character '^' can be skipped::
3259
+
3260
+ sage: t['i_[jk]'] == t.antisymmetrize(1,2)
3261
+ True
3262
+ """
3263
+ if not pos:
3264
+ pos = range(self._tensor_rank)
3265
+ # check whether the antisymmetrization is possible:
3266
+ pos_cov = self._tensor_type[0] # first covariant position
3267
+ pos0 = pos[0]
3268
+ if pos0 < pos_cov: # pos0 is a contravariant position
3269
+ for k in range(1,len(pos)):
3270
+ if pos[k] >= pos_cov:
3271
+ raise TypeError(
3272
+ str(pos[0]) + " is a contravariant position, while " +
3273
+ str(pos[k]) + " is a covariant position; \n"
3274
+ "antisymmetrization is meaningful only on tensor " +
3275
+ "arguments of the same type")
3276
+ else: # pos0 is a covariant position
3277
+ for k in range(1,len(pos)):
3278
+ if pos[k] < pos_cov:
3279
+ raise TypeError(
3280
+ str(pos[0]) + " is a covariant position, while " +
3281
+ str(pos[k]) + " is a contravariant position; \n"
3282
+ "antisymmetrization is meaningful only on tensor " +
3283
+ "arguments of the same type")
3284
+ if 'basis' in kwargs:
3285
+ basis = kwargs['basis']
3286
+ else:
3287
+ basis = self.pick_a_basis()
3288
+ res_comp = self._components[basis].antisymmetrize(*pos)
3289
+ return self._fmodule.tensor_from_comp(self._tensor_type, res_comp)