passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_aarch64.whl

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

Potentially problematic release.


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

Files changed (807) hide show
  1. passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
  2. passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
  3. passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
  4. passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
  5. passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
  7. passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  8. passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
  9. passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
  10. passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
  11. passagemath_modules.libs/libopenblasp-r0-503f0c35.3.29.so +0 -0
  12. sage/algebras/all__sagemath_modules.py +20 -0
  13. sage/algebras/catalog.py +148 -0
  14. sage/algebras/clifford_algebra.py +3107 -0
  15. sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  16. sage/algebras/clifford_algebra_element.pxd +16 -0
  17. sage/algebras/clifford_algebra_element.pyx +997 -0
  18. sage/algebras/commutative_dga.py +4252 -0
  19. sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-musl.so +0 -0
  20. sage/algebras/exterior_algebra_groebner.pxd +55 -0
  21. sage/algebras/exterior_algebra_groebner.pyx +727 -0
  22. sage/algebras/finite_dimensional_algebras/all.py +2 -0
  23. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
  24. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  25. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
  26. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
  27. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
  28. sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
  29. sage/algebras/finite_gca.py +528 -0
  30. sage/algebras/group_algebra.py +232 -0
  31. sage/algebras/lie_algebras/abelian.py +197 -0
  32. sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
  33. sage/algebras/lie_algebras/all.py +25 -0
  34. sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
  35. sage/algebras/lie_algebras/bch.py +177 -0
  36. sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
  37. sage/algebras/lie_algebras/bgg_resolution.py +232 -0
  38. sage/algebras/lie_algebras/center_uea.py +767 -0
  39. sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
  40. sage/algebras/lie_algebras/examples.py +683 -0
  41. sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
  42. sage/algebras/lie_algebras/heisenberg.py +820 -0
  43. sage/algebras/lie_algebras/lie_algebra.py +1562 -0
  44. sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
  45. sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
  46. sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
  47. sage/algebras/lie_algebras/morphism.py +661 -0
  48. sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
  49. sage/algebras/lie_algebras/onsager.py +1324 -0
  50. sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
  51. sage/algebras/lie_algebras/quotient.py +462 -0
  52. sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
  53. sage/algebras/lie_algebras/representation.py +1040 -0
  54. sage/algebras/lie_algebras/structure_coefficients.py +459 -0
  55. sage/algebras/lie_algebras/subalgebra.py +967 -0
  56. sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
  57. sage/algebras/lie_algebras/verma_module.py +1630 -0
  58. sage/algebras/lie_algebras/virasoro.py +1186 -0
  59. sage/algebras/octonion_algebra.cpython-314-aarch64-linux-musl.so +0 -0
  60. sage/algebras/octonion_algebra.pxd +20 -0
  61. sage/algebras/octonion_algebra.pyx +987 -0
  62. sage/algebras/orlik_solomon.py +907 -0
  63. sage/algebras/orlik_terao.py +779 -0
  64. sage/algebras/steenrod/all.py +7 -0
  65. sage/algebras/steenrod/steenrod_algebra.py +4258 -0
  66. sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
  67. sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
  68. sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
  69. sage/algebras/weyl_algebra.py +1126 -0
  70. sage/all__sagemath_modules.py +62 -0
  71. sage/calculus/all__sagemath_modules.py +19 -0
  72. sage/calculus/expr.py +205 -0
  73. sage/calculus/integration.cpython-314-aarch64-linux-musl.so +0 -0
  74. sage/calculus/integration.pyx +698 -0
  75. sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
  76. sage/calculus/interpolation.pxd +13 -0
  77. sage/calculus/interpolation.pyx +387 -0
  78. sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
  79. sage/calculus/interpolators.pyx +326 -0
  80. sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
  81. sage/calculus/ode.pxd +5 -0
  82. sage/calculus/ode.pyx +610 -0
  83. sage/calculus/riemann.cpython-314-aarch64-linux-musl.so +0 -0
  84. sage/calculus/riemann.pyx +1521 -0
  85. sage/calculus/test_sympy.py +201 -0
  86. sage/calculus/transforms/all.py +7 -0
  87. sage/calculus/transforms/dft.py +844 -0
  88. sage/calculus/transforms/dwt.cpython-314-aarch64-linux-musl.so +0 -0
  89. sage/calculus/transforms/dwt.pxd +7 -0
  90. sage/calculus/transforms/dwt.pyx +160 -0
  91. sage/calculus/transforms/fft.cpython-314-aarch64-linux-musl.so +0 -0
  92. sage/calculus/transforms/fft.pxd +12 -0
  93. sage/calculus/transforms/fft.pyx +487 -0
  94. sage/calculus/wester.py +662 -0
  95. sage/coding/abstract_code.py +1108 -0
  96. sage/coding/ag_code.py +868 -0
  97. sage/coding/ag_code_decoders.cpython-314-aarch64-linux-musl.so +0 -0
  98. sage/coding/ag_code_decoders.pyx +2639 -0
  99. sage/coding/all.py +15 -0
  100. sage/coding/bch_code.py +494 -0
  101. sage/coding/binary_code.cpython-314-aarch64-linux-musl.so +0 -0
  102. sage/coding/binary_code.pxd +124 -0
  103. sage/coding/binary_code.pyx +4139 -0
  104. sage/coding/bounds_catalog.py +43 -0
  105. sage/coding/channel.py +819 -0
  106. sage/coding/channels_catalog.py +29 -0
  107. sage/coding/code_bounds.py +755 -0
  108. sage/coding/code_constructions.py +804 -0
  109. sage/coding/codes_catalog.py +111 -0
  110. sage/coding/cyclic_code.py +1329 -0
  111. sage/coding/databases.py +316 -0
  112. sage/coding/decoder.py +373 -0
  113. sage/coding/decoders_catalog.py +88 -0
  114. sage/coding/delsarte_bounds.py +709 -0
  115. sage/coding/encoder.py +390 -0
  116. sage/coding/encoders_catalog.py +64 -0
  117. sage/coding/extended_code.py +468 -0
  118. sage/coding/gabidulin_code.py +1058 -0
  119. sage/coding/golay_code.py +404 -0
  120. sage/coding/goppa_code.py +441 -0
  121. sage/coding/grs_code.py +2371 -0
  122. sage/coding/guava.py +107 -0
  123. sage/coding/guruswami_sudan/all.py +1 -0
  124. sage/coding/guruswami_sudan/gs_decoder.py +897 -0
  125. sage/coding/guruswami_sudan/interpolation.py +409 -0
  126. sage/coding/guruswami_sudan/utils.py +176 -0
  127. sage/coding/hamming_code.py +176 -0
  128. sage/coding/information_set_decoder.py +1032 -0
  129. sage/coding/kasami_codes.cpython-314-aarch64-linux-musl.so +0 -0
  130. sage/coding/kasami_codes.pyx +351 -0
  131. sage/coding/linear_code.py +3067 -0
  132. sage/coding/linear_code_no_metric.py +1354 -0
  133. sage/coding/linear_rank_metric.py +961 -0
  134. sage/coding/parity_check_code.py +353 -0
  135. sage/coding/punctured_code.py +719 -0
  136. sage/coding/reed_muller_code.py +999 -0
  137. sage/coding/self_dual_codes.py +942 -0
  138. sage/coding/source_coding/all.py +2 -0
  139. sage/coding/source_coding/huffman.py +553 -0
  140. sage/coding/subfield_subcode.py +423 -0
  141. sage/coding/two_weight_db.py +399 -0
  142. sage/combinat/all__sagemath_modules.py +7 -0
  143. sage/combinat/cartesian_product.py +347 -0
  144. sage/combinat/family.py +11 -0
  145. sage/combinat/free_module.py +1977 -0
  146. sage/combinat/root_system/all.py +147 -0
  147. sage/combinat/root_system/ambient_space.py +527 -0
  148. sage/combinat/root_system/associahedron.py +471 -0
  149. sage/combinat/root_system/braid_move_calculator.py +143 -0
  150. sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-musl.so +0 -0
  151. sage/combinat/root_system/braid_orbit.pyx +144 -0
  152. sage/combinat/root_system/branching_rules.py +2301 -0
  153. sage/combinat/root_system/cartan_matrix.py +1245 -0
  154. sage/combinat/root_system/cartan_type.py +3069 -0
  155. sage/combinat/root_system/coxeter_group.py +162 -0
  156. sage/combinat/root_system/coxeter_matrix.py +1261 -0
  157. sage/combinat/root_system/coxeter_type.py +681 -0
  158. sage/combinat/root_system/dynkin_diagram.py +900 -0
  159. sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
  160. sage/combinat/root_system/fundamental_group.py +795 -0
  161. sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
  162. sage/combinat/root_system/integrable_representations.py +1227 -0
  163. sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
  164. sage/combinat/root_system/pieri_factors.py +1147 -0
  165. sage/combinat/root_system/plot.py +1615 -0
  166. sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
  167. sage/combinat/root_system/root_lattice_realizations.py +4628 -0
  168. sage/combinat/root_system/root_space.py +487 -0
  169. sage/combinat/root_system/root_system.py +882 -0
  170. sage/combinat/root_system/type_A.py +348 -0
  171. sage/combinat/root_system/type_A_affine.py +227 -0
  172. sage/combinat/root_system/type_A_infinity.py +241 -0
  173. sage/combinat/root_system/type_B.py +347 -0
  174. sage/combinat/root_system/type_BC_affine.py +287 -0
  175. sage/combinat/root_system/type_B_affine.py +216 -0
  176. sage/combinat/root_system/type_C.py +317 -0
  177. sage/combinat/root_system/type_C_affine.py +188 -0
  178. sage/combinat/root_system/type_D.py +357 -0
  179. sage/combinat/root_system/type_D_affine.py +208 -0
  180. sage/combinat/root_system/type_E.py +641 -0
  181. sage/combinat/root_system/type_E_affine.py +231 -0
  182. sage/combinat/root_system/type_F.py +387 -0
  183. sage/combinat/root_system/type_F_affine.py +137 -0
  184. sage/combinat/root_system/type_G.py +293 -0
  185. sage/combinat/root_system/type_G_affine.py +132 -0
  186. sage/combinat/root_system/type_H.py +105 -0
  187. sage/combinat/root_system/type_I.py +110 -0
  188. sage/combinat/root_system/type_Q.py +150 -0
  189. sage/combinat/root_system/type_affine.py +509 -0
  190. sage/combinat/root_system/type_dual.py +704 -0
  191. sage/combinat/root_system/type_folded.py +301 -0
  192. sage/combinat/root_system/type_marked.py +748 -0
  193. sage/combinat/root_system/type_reducible.py +601 -0
  194. sage/combinat/root_system/type_relabel.py +730 -0
  195. sage/combinat/root_system/type_super_A.py +837 -0
  196. sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
  197. sage/combinat/root_system/weight_space.py +639 -0
  198. sage/combinat/root_system/weyl_characters.py +2238 -0
  199. sage/crypto/__init__.py +4 -0
  200. sage/crypto/all.py +28 -0
  201. sage/crypto/block_cipher/all.py +7 -0
  202. sage/crypto/block_cipher/des.py +1065 -0
  203. sage/crypto/block_cipher/miniaes.py +2171 -0
  204. sage/crypto/block_cipher/present.py +909 -0
  205. sage/crypto/block_cipher/sdes.py +1527 -0
  206. sage/crypto/boolean_function.cpython-314-aarch64-linux-musl.so +0 -0
  207. sage/crypto/boolean_function.pxd +10 -0
  208. sage/crypto/boolean_function.pyx +1487 -0
  209. sage/crypto/cipher.py +78 -0
  210. sage/crypto/classical.py +3668 -0
  211. sage/crypto/classical_cipher.py +569 -0
  212. sage/crypto/cryptosystem.py +387 -0
  213. sage/crypto/key_exchange/all.py +7 -0
  214. sage/crypto/key_exchange/catalog.py +24 -0
  215. sage/crypto/key_exchange/diffie_hellman.py +323 -0
  216. sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
  217. sage/crypto/lattice.py +312 -0
  218. sage/crypto/lfsr.py +295 -0
  219. sage/crypto/lwe.py +840 -0
  220. sage/crypto/mq/__init__.py +4 -0
  221. sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
  222. sage/crypto/mq/rijndael_gf.py +2345 -0
  223. sage/crypto/mq/sbox.py +7 -0
  224. sage/crypto/mq/sr.py +3344 -0
  225. sage/crypto/public_key/all.py +5 -0
  226. sage/crypto/public_key/blum_goldwasser.py +776 -0
  227. sage/crypto/sbox.cpython-314-aarch64-linux-musl.so +0 -0
  228. sage/crypto/sbox.pyx +2090 -0
  229. sage/crypto/sboxes.py +2090 -0
  230. sage/crypto/stream.py +390 -0
  231. sage/crypto/stream_cipher.py +297 -0
  232. sage/crypto/util.py +519 -0
  233. sage/ext/all__sagemath_modules.py +1 -0
  234. sage/ext/interpreters/__init__.py +1 -0
  235. sage/ext/interpreters/all__sagemath_modules.py +2 -0
  236. sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-musl.so +0 -0
  237. sage/ext/interpreters/wrapper_cc.pxd +30 -0
  238. sage/ext/interpreters/wrapper_cc.pyx +252 -0
  239. sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-musl.so +0 -0
  240. sage/ext/interpreters/wrapper_cdf.pxd +26 -0
  241. sage/ext/interpreters/wrapper_cdf.pyx +245 -0
  242. sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-musl.so +0 -0
  243. sage/ext/interpreters/wrapper_rdf.pxd +23 -0
  244. sage/ext/interpreters/wrapper_rdf.pyx +221 -0
  245. sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-musl.so +0 -0
  246. sage/ext/interpreters/wrapper_rr.pxd +28 -0
  247. sage/ext/interpreters/wrapper_rr.pyx +335 -0
  248. sage/geometry/all__sagemath_modules.py +5 -0
  249. sage/geometry/toric_lattice.py +1745 -0
  250. sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-musl.so +0 -0
  251. sage/geometry/toric_lattice_element.pyx +432 -0
  252. sage/groups/abelian_gps/abelian_group.py +1925 -0
  253. sage/groups/abelian_gps/abelian_group_element.py +164 -0
  254. sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
  255. sage/groups/abelian_gps/dual_abelian_group.py +421 -0
  256. sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
  257. sage/groups/abelian_gps/element_base.py +341 -0
  258. sage/groups/abelian_gps/values.py +488 -0
  259. sage/groups/additive_abelian/additive_abelian_group.py +476 -0
  260. sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
  261. sage/groups/additive_abelian/all.py +4 -0
  262. sage/groups/additive_abelian/qmodnz.py +231 -0
  263. sage/groups/additive_abelian/qmodnz_element.py +349 -0
  264. sage/groups/affine_gps/affine_group.py +535 -0
  265. sage/groups/affine_gps/all.py +1 -0
  266. sage/groups/affine_gps/catalog.py +17 -0
  267. sage/groups/affine_gps/euclidean_group.py +246 -0
  268. sage/groups/affine_gps/group_element.py +562 -0
  269. sage/groups/all__sagemath_modules.py +12 -0
  270. sage/groups/galois_group.py +479 -0
  271. sage/groups/matrix_gps/all.py +4 -0
  272. sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
  273. sage/groups/matrix_gps/catalog.py +26 -0
  274. sage/groups/matrix_gps/coxeter_group.py +927 -0
  275. sage/groups/matrix_gps/finitely_generated.py +487 -0
  276. sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-musl.so +0 -0
  277. sage/groups/matrix_gps/group_element.pxd +11 -0
  278. sage/groups/matrix_gps/group_element.pyx +431 -0
  279. sage/groups/matrix_gps/linear.py +440 -0
  280. sage/groups/matrix_gps/matrix_group.py +617 -0
  281. sage/groups/matrix_gps/named_group.py +296 -0
  282. sage/groups/matrix_gps/orthogonal.py +544 -0
  283. sage/groups/matrix_gps/symplectic.py +251 -0
  284. sage/groups/matrix_gps/unitary.py +436 -0
  285. sage/groups/misc_gps/all__sagemath_modules.py +1 -0
  286. sage/groups/misc_gps/argument_groups.py +1905 -0
  287. sage/groups/misc_gps/imaginary_groups.py +479 -0
  288. sage/groups/perm_gps/all__sagemath_modules.py +1 -0
  289. sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
  290. sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-musl.so +0 -0
  291. sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
  292. sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
  293. sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-musl.so +0 -0
  294. sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
  295. sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
  296. sage/homology/algebraic_topological_model.py +595 -0
  297. sage/homology/all.py +2 -0
  298. sage/homology/all__sagemath_modules.py +8 -0
  299. sage/homology/chain_complex.py +2148 -0
  300. sage/homology/chain_complex_homspace.py +165 -0
  301. sage/homology/chain_complex_morphism.py +629 -0
  302. sage/homology/chain_homotopy.py +604 -0
  303. sage/homology/chains.py +653 -0
  304. sage/homology/free_resolution.py +923 -0
  305. sage/homology/graded_resolution.py +567 -0
  306. sage/homology/hochschild_complex.py +756 -0
  307. sage/homology/homology_group.py +188 -0
  308. sage/homology/homology_morphism.py +422 -0
  309. sage/homology/homology_vector_space_with_basis.py +1454 -0
  310. sage/homology/koszul_complex.py +169 -0
  311. sage/homology/matrix_utils.py +205 -0
  312. sage/libs/all__sagemath_modules.py +1 -0
  313. sage/libs/gsl/__init__.py +1 -0
  314. sage/libs/gsl/airy.pxd +56 -0
  315. sage/libs/gsl/all.pxd +66 -0
  316. sage/libs/gsl/array.cpython-314-aarch64-linux-musl.so +0 -0
  317. sage/libs/gsl/array.pxd +5 -0
  318. sage/libs/gsl/array.pyx +102 -0
  319. sage/libs/gsl/bessel.pxd +208 -0
  320. sage/libs/gsl/blas.pxd +116 -0
  321. sage/libs/gsl/blas_types.pxd +34 -0
  322. sage/libs/gsl/block.pxd +52 -0
  323. sage/libs/gsl/chebyshev.pxd +37 -0
  324. sage/libs/gsl/clausen.pxd +12 -0
  325. sage/libs/gsl/combination.pxd +47 -0
  326. sage/libs/gsl/complex.pxd +151 -0
  327. sage/libs/gsl/coulomb.pxd +30 -0
  328. sage/libs/gsl/coupling.pxd +21 -0
  329. sage/libs/gsl/dawson.pxd +12 -0
  330. sage/libs/gsl/debye.pxd +24 -0
  331. sage/libs/gsl/dilog.pxd +14 -0
  332. sage/libs/gsl/eigen.pxd +46 -0
  333. sage/libs/gsl/elementary.pxd +12 -0
  334. sage/libs/gsl/ellint.pxd +48 -0
  335. sage/libs/gsl/elljac.pxd +8 -0
  336. sage/libs/gsl/erf.pxd +32 -0
  337. sage/libs/gsl/errno.pxd +26 -0
  338. sage/libs/gsl/exp.pxd +44 -0
  339. sage/libs/gsl/expint.pxd +44 -0
  340. sage/libs/gsl/fermi_dirac.pxd +44 -0
  341. sage/libs/gsl/fft.pxd +121 -0
  342. sage/libs/gsl/fit.pxd +50 -0
  343. sage/libs/gsl/gamma.pxd +94 -0
  344. sage/libs/gsl/gegenbauer.pxd +26 -0
  345. sage/libs/gsl/histogram.pxd +176 -0
  346. sage/libs/gsl/hyperg.pxd +52 -0
  347. sage/libs/gsl/integration.pxd +69 -0
  348. sage/libs/gsl/interp.pxd +109 -0
  349. sage/libs/gsl/laguerre.pxd +24 -0
  350. sage/libs/gsl/lambert.pxd +16 -0
  351. sage/libs/gsl/legendre.pxd +90 -0
  352. sage/libs/gsl/linalg.pxd +185 -0
  353. sage/libs/gsl/log.pxd +26 -0
  354. sage/libs/gsl/math.pxd +43 -0
  355. sage/libs/gsl/matrix.pxd +143 -0
  356. sage/libs/gsl/matrix_complex.pxd +130 -0
  357. sage/libs/gsl/min.pxd +67 -0
  358. sage/libs/gsl/monte.pxd +56 -0
  359. sage/libs/gsl/ntuple.pxd +32 -0
  360. sage/libs/gsl/odeiv.pxd +70 -0
  361. sage/libs/gsl/permutation.pxd +78 -0
  362. sage/libs/gsl/poly.pxd +40 -0
  363. sage/libs/gsl/pow_int.pxd +12 -0
  364. sage/libs/gsl/psi.pxd +28 -0
  365. sage/libs/gsl/qrng.pxd +29 -0
  366. sage/libs/gsl/random.pxd +257 -0
  367. sage/libs/gsl/rng.pxd +100 -0
  368. sage/libs/gsl/roots.pxd +72 -0
  369. sage/libs/gsl/sort.pxd +36 -0
  370. sage/libs/gsl/statistics.pxd +59 -0
  371. sage/libs/gsl/sum.pxd +55 -0
  372. sage/libs/gsl/synchrotron.pxd +16 -0
  373. sage/libs/gsl/transport.pxd +24 -0
  374. sage/libs/gsl/trig.pxd +58 -0
  375. sage/libs/gsl/types.pxd +137 -0
  376. sage/libs/gsl/vector.pxd +101 -0
  377. sage/libs/gsl/vector_complex.pxd +83 -0
  378. sage/libs/gsl/wavelet.pxd +49 -0
  379. sage/libs/gsl/zeta.pxd +28 -0
  380. sage/libs/mpc/__init__.pxd +114 -0
  381. sage/libs/mpc/types.pxd +28 -0
  382. sage/libs/mpfr/__init__.pxd +299 -0
  383. sage/libs/mpfr/types.pxd +26 -0
  384. sage/libs/mpmath/__init__.py +1 -0
  385. sage/libs/mpmath/all.py +27 -0
  386. sage/libs/mpmath/all__sagemath_modules.py +1 -0
  387. sage/libs/mpmath/utils.cpython-314-aarch64-linux-musl.so +0 -0
  388. sage/libs/mpmath/utils.pxd +4 -0
  389. sage/libs/mpmath/utils.pyx +319 -0
  390. sage/matrix/action.cpython-314-aarch64-linux-musl.so +0 -0
  391. sage/matrix/action.pxd +26 -0
  392. sage/matrix/action.pyx +596 -0
  393. sage/matrix/all.py +9 -0
  394. sage/matrix/args.cpython-314-aarch64-linux-musl.so +0 -0
  395. sage/matrix/args.pxd +144 -0
  396. sage/matrix/args.pyx +1668 -0
  397. sage/matrix/benchmark.py +1258 -0
  398. sage/matrix/berlekamp_massey.py +95 -0
  399. sage/matrix/compute_J_ideal.py +926 -0
  400. sage/matrix/constructor.cpython-314-aarch64-linux-musl.so +0 -0
  401. sage/matrix/constructor.pyx +750 -0
  402. sage/matrix/docs.py +430 -0
  403. sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
  404. sage/matrix/echelon_matrix.pyx +155 -0
  405. sage/matrix/matrix.pxd +2 -0
  406. sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
  407. sage/matrix/matrix0.pxd +68 -0
  408. sage/matrix/matrix0.pyx +6324 -0
  409. sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
  410. sage/matrix/matrix1.pxd +8 -0
  411. sage/matrix/matrix1.pyx +2851 -0
  412. sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
  413. sage/matrix/matrix2.pxd +25 -0
  414. sage/matrix/matrix2.pyx +20181 -0
  415. sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.so +0 -0
  416. sage/matrix/matrix_cdv.pxd +4 -0
  417. sage/matrix/matrix_cdv.pyx +93 -0
  418. sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  419. sage/matrix/matrix_complex_double_dense.pxd +5 -0
  420. sage/matrix/matrix_complex_double_dense.pyx +98 -0
  421. sage/matrix/matrix_dense.cpython-314-aarch64-linux-musl.so +0 -0
  422. sage/matrix/matrix_dense.pxd +5 -0
  423. sage/matrix/matrix_dense.pyx +343 -0
  424. sage/matrix/matrix_domain_dense.pxd +5 -0
  425. sage/matrix/matrix_domain_sparse.pxd +5 -0
  426. sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  427. sage/matrix/matrix_double_dense.pxd +7 -0
  428. sage/matrix/matrix_double_dense.pyx +3906 -0
  429. sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  430. sage/matrix/matrix_double_sparse.pxd +6 -0
  431. sage/matrix/matrix_double_sparse.pyx +248 -0
  432. sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-musl.so +0 -0
  433. sage/matrix/matrix_generic_dense.pxd +7 -0
  434. sage/matrix/matrix_generic_dense.pyx +354 -0
  435. sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  436. sage/matrix/matrix_generic_sparse.pxd +7 -0
  437. sage/matrix/matrix_generic_sparse.pyx +461 -0
  438. sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
  439. sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
  440. sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
  441. sage/matrix/matrix_misc.py +313 -0
  442. sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
  443. sage/matrix/matrix_numpy_dense.pxd +14 -0
  444. sage/matrix/matrix_numpy_dense.pyx +450 -0
  445. sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  446. sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
  447. sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
  448. sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
  449. sage/matrix/matrix_polynomial_dense.pxd +5 -0
  450. sage/matrix/matrix_polynomial_dense.pyx +5341 -0
  451. sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  452. sage/matrix/matrix_real_double_dense.pxd +7 -0
  453. sage/matrix/matrix_real_double_dense.pyx +122 -0
  454. sage/matrix/matrix_space.py +2848 -0
  455. sage/matrix/matrix_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  456. sage/matrix/matrix_sparse.pxd +5 -0
  457. sage/matrix/matrix_sparse.pyx +1222 -0
  458. sage/matrix/matrix_window.cpython-314-aarch64-linux-musl.so +0 -0
  459. sage/matrix/matrix_window.pxd +37 -0
  460. sage/matrix/matrix_window.pyx +242 -0
  461. sage/matrix/misc_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  462. sage/matrix/misc_mpfr.pyx +80 -0
  463. sage/matrix/operation_table.py +1182 -0
  464. sage/matrix/special.py +3666 -0
  465. sage/matrix/strassen.cpython-314-aarch64-linux-musl.so +0 -0
  466. sage/matrix/strassen.pyx +851 -0
  467. sage/matrix/symplectic_basis.py +541 -0
  468. sage/matrix/template.pxd +6 -0
  469. sage/matrix/tests.py +71 -0
  470. sage/matroids/advanced.py +77 -0
  471. sage/matroids/all.py +13 -0
  472. sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  473. sage/matroids/basis_exchange_matroid.pxd +96 -0
  474. sage/matroids/basis_exchange_matroid.pyx +2344 -0
  475. sage/matroids/basis_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  476. sage/matroids/basis_matroid.pxd +45 -0
  477. sage/matroids/basis_matroid.pyx +1217 -0
  478. sage/matroids/catalog.py +44 -0
  479. sage/matroids/chow_ring.py +473 -0
  480. sage/matroids/chow_ring_ideal.py +849 -0
  481. sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  482. sage/matroids/circuit_closures_matroid.pxd +16 -0
  483. sage/matroids/circuit_closures_matroid.pyx +559 -0
  484. sage/matroids/circuits_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  485. sage/matroids/circuits_matroid.pxd +38 -0
  486. sage/matroids/circuits_matroid.pyx +947 -0
  487. sage/matroids/constructor.py +1086 -0
  488. sage/matroids/database_collections.py +365 -0
  489. sage/matroids/database_matroids.py +5338 -0
  490. sage/matroids/dual_matroid.py +583 -0
  491. sage/matroids/extension.cpython-314-aarch64-linux-musl.so +0 -0
  492. sage/matroids/extension.pxd +34 -0
  493. sage/matroids/extension.pyx +519 -0
  494. sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  495. sage/matroids/flats_matroid.pxd +28 -0
  496. sage/matroids/flats_matroid.pyx +715 -0
  497. sage/matroids/gammoid.py +600 -0
  498. sage/matroids/graphic_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  499. sage/matroids/graphic_matroid.pxd +39 -0
  500. sage/matroids/graphic_matroid.pyx +2024 -0
  501. sage/matroids/lean_matrix.cpython-314-aarch64-linux-musl.so +0 -0
  502. sage/matroids/lean_matrix.pxd +126 -0
  503. sage/matroids/lean_matrix.pyx +3667 -0
  504. sage/matroids/linear_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  505. sage/matroids/linear_matroid.pxd +180 -0
  506. sage/matroids/linear_matroid.pyx +6649 -0
  507. sage/matroids/matroid.cpython-314-aarch64-linux-musl.so +0 -0
  508. sage/matroids/matroid.pxd +243 -0
  509. sage/matroids/matroid.pyx +8759 -0
  510. sage/matroids/matroids_catalog.py +190 -0
  511. sage/matroids/matroids_plot_helpers.py +890 -0
  512. sage/matroids/minor_matroid.py +480 -0
  513. sage/matroids/minorfix.h +9 -0
  514. sage/matroids/named_matroids.py +5 -0
  515. sage/matroids/rank_matroid.py +268 -0
  516. sage/matroids/set_system.cpython-314-aarch64-linux-musl.so +0 -0
  517. sage/matroids/set_system.pxd +38 -0
  518. sage/matroids/set_system.pyx +800 -0
  519. sage/matroids/transversal_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  520. sage/matroids/transversal_matroid.pxd +14 -0
  521. sage/matroids/transversal_matroid.pyx +893 -0
  522. sage/matroids/union_matroid.cpython-314-aarch64-linux-musl.so +0 -0
  523. sage/matroids/union_matroid.pxd +20 -0
  524. sage/matroids/union_matroid.pyx +331 -0
  525. sage/matroids/unpickling.cpython-314-aarch64-linux-musl.so +0 -0
  526. sage/matroids/unpickling.pyx +843 -0
  527. sage/matroids/utilities.py +809 -0
  528. sage/misc/all__sagemath_modules.py +20 -0
  529. sage/misc/c3.cpython-314-aarch64-linux-musl.so +0 -0
  530. sage/misc/c3.pyx +238 -0
  531. sage/misc/compat.py +87 -0
  532. sage/misc/element_with_label.py +173 -0
  533. sage/misc/func_persist.py +79 -0
  534. sage/misc/pickle_old.cpython-314-aarch64-linux-musl.so +0 -0
  535. sage/misc/pickle_old.pyx +19 -0
  536. sage/misc/proof.py +7 -0
  537. sage/misc/replace_dot_all.py +472 -0
  538. sage/misc/sagedoc_conf.py +168 -0
  539. sage/misc/sphinxify.py +167 -0
  540. sage/misc/test_class_pickling.py +85 -0
  541. sage/modules/all.py +42 -0
  542. sage/modules/complex_double_vector.py +25 -0
  543. sage/modules/diamond_cutting.py +380 -0
  544. sage/modules/fg_pid/all.py +1 -0
  545. sage/modules/fg_pid/fgp_element.py +456 -0
  546. sage/modules/fg_pid/fgp_module.py +2091 -0
  547. sage/modules/fg_pid/fgp_morphism.py +550 -0
  548. sage/modules/filtered_vector_space.py +1271 -0
  549. sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-musl.so +0 -0
  550. sage/modules/finite_submodule_iter.pxd +27 -0
  551. sage/modules/finite_submodule_iter.pyx +452 -0
  552. sage/modules/fp_graded/all.py +1 -0
  553. sage/modules/fp_graded/element.py +346 -0
  554. sage/modules/fp_graded/free_element.py +298 -0
  555. sage/modules/fp_graded/free_homspace.py +53 -0
  556. sage/modules/fp_graded/free_module.py +1060 -0
  557. sage/modules/fp_graded/free_morphism.py +217 -0
  558. sage/modules/fp_graded/homspace.py +563 -0
  559. sage/modules/fp_graded/module.py +1340 -0
  560. sage/modules/fp_graded/morphism.py +1990 -0
  561. sage/modules/fp_graded/steenrod/all.py +1 -0
  562. sage/modules/fp_graded/steenrod/homspace.py +65 -0
  563. sage/modules/fp_graded/steenrod/module.py +477 -0
  564. sage/modules/fp_graded/steenrod/morphism.py +404 -0
  565. sage/modules/fp_graded/steenrod/profile.py +241 -0
  566. sage/modules/free_module.py +8447 -0
  567. sage/modules/free_module_element.cpython-314-aarch64-linux-musl.so +0 -0
  568. sage/modules/free_module_element.pxd +22 -0
  569. sage/modules/free_module_element.pyx +5445 -0
  570. sage/modules/free_module_homspace.py +369 -0
  571. sage/modules/free_module_integer.py +896 -0
  572. sage/modules/free_module_morphism.py +823 -0
  573. sage/modules/free_module_pseudohomspace.py +352 -0
  574. sage/modules/free_module_pseudomorphism.py +578 -0
  575. sage/modules/free_quadratic_module.py +1706 -0
  576. sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
  577. sage/modules/matrix_morphism.py +1745 -0
  578. sage/modules/misc.py +103 -0
  579. sage/modules/module_functors.py +192 -0
  580. sage/modules/multi_filtered_vector_space.py +719 -0
  581. sage/modules/ore_module.py +2208 -0
  582. sage/modules/ore_module_element.py +178 -0
  583. sage/modules/ore_module_homspace.py +147 -0
  584. sage/modules/ore_module_morphism.py +968 -0
  585. sage/modules/quotient_module.py +699 -0
  586. sage/modules/real_double_vector.py +22 -0
  587. sage/modules/submodule.py +255 -0
  588. sage/modules/tensor_operations.py +567 -0
  589. sage/modules/torsion_quadratic_module.py +1352 -0
  590. sage/modules/tutorial_free_modules.py +248 -0
  591. sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  592. sage/modules/vector_complex_double_dense.pxd +6 -0
  593. sage/modules/vector_complex_double_dense.pyx +117 -0
  594. sage/modules/vector_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  595. sage/modules/vector_double_dense.pxd +6 -0
  596. sage/modules/vector_double_dense.pyx +604 -0
  597. sage/modules/vector_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  598. sage/modules/vector_integer_dense.pxd +15 -0
  599. sage/modules/vector_integer_dense.pyx +361 -0
  600. sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  601. sage/modules/vector_integer_sparse.pxd +29 -0
  602. sage/modules/vector_integer_sparse.pyx +406 -0
  603. sage/modules/vector_modn_dense.cpython-314-aarch64-linux-musl.so +0 -0
  604. sage/modules/vector_modn_dense.pxd +12 -0
  605. sage/modules/vector_modn_dense.pyx +394 -0
  606. sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  607. sage/modules/vector_modn_sparse.pxd +21 -0
  608. sage/modules/vector_modn_sparse.pyx +298 -0
  609. sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
  610. sage/modules/vector_numpy_dense.pxd +15 -0
  611. sage/modules/vector_numpy_dense.pyx +304 -0
  612. sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
  613. sage/modules/vector_numpy_integer_dense.pxd +7 -0
  614. sage/modules/vector_numpy_integer_dense.pyx +54 -0
  615. sage/modules/vector_rational_dense.cpython-314-aarch64-linux-musl.so +0 -0
  616. sage/modules/vector_rational_dense.pxd +15 -0
  617. sage/modules/vector_rational_dense.pyx +387 -0
  618. sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-musl.so +0 -0
  619. sage/modules/vector_rational_sparse.pxd +30 -0
  620. sage/modules/vector_rational_sparse.pyx +413 -0
  621. sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
  622. sage/modules/vector_real_double_dense.pxd +6 -0
  623. sage/modules/vector_real_double_dense.pyx +126 -0
  624. sage/modules/vector_space_homspace.py +430 -0
  625. sage/modules/vector_space_morphism.py +989 -0
  626. sage/modules/with_basis/all.py +15 -0
  627. sage/modules/with_basis/cell_module.py +494 -0
  628. sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-musl.so +0 -0
  629. sage/modules/with_basis/indexed_element.pxd +13 -0
  630. sage/modules/with_basis/indexed_element.pyx +1058 -0
  631. sage/modules/with_basis/invariant.py +1075 -0
  632. sage/modules/with_basis/morphism.py +1636 -0
  633. sage/modules/with_basis/representation.py +2939 -0
  634. sage/modules/with_basis/subquotient.py +685 -0
  635. sage/numerical/all__sagemath_modules.py +6 -0
  636. sage/numerical/gauss_legendre.cpython-314-aarch64-linux-musl.so +0 -0
  637. sage/numerical/gauss_legendre.pyx +381 -0
  638. sage/numerical/optimize.py +910 -0
  639. sage/probability/all.py +10 -0
  640. sage/probability/probability_distribution.cpython-314-aarch64-linux-musl.so +0 -0
  641. sage/probability/probability_distribution.pyx +1242 -0
  642. sage/probability/random_variable.py +411 -0
  643. sage/quadratic_forms/all.py +4 -0
  644. sage/quadratic_forms/all__sagemath_modules.py +15 -0
  645. sage/quadratic_forms/binary_qf.py +2042 -0
  646. sage/quadratic_forms/bqf_class_group.py +748 -0
  647. sage/quadratic_forms/constructions.py +93 -0
  648. sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-musl.so +0 -0
  649. sage/quadratic_forms/count_local_2.pyx +365 -0
  650. sage/quadratic_forms/extras.py +195 -0
  651. sage/quadratic_forms/quadratic_form.py +1753 -0
  652. sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
  653. sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
  654. sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-musl.so +0 -0
  655. sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
  656. sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
  657. sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
  658. sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
  659. sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
  660. sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
  661. sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
  662. sage/quadratic_forms/quadratic_form__theta.py +352 -0
  663. sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
  664. sage/quadratic_forms/random_quadraticform.py +209 -0
  665. sage/quadratic_forms/ternary.cpython-314-aarch64-linux-musl.so +0 -0
  666. sage/quadratic_forms/ternary.pyx +1154 -0
  667. sage/quadratic_forms/ternary_qf.py +2027 -0
  668. sage/rings/all__sagemath_modules.py +28 -0
  669. sage/rings/asymptotic/all__sagemath_modules.py +1 -0
  670. sage/rings/asymptotic/misc.py +1252 -0
  671. sage/rings/cc.py +4 -0
  672. sage/rings/cfinite_sequence.py +1306 -0
  673. sage/rings/complex_conversion.cpython-314-aarch64-linux-musl.so +0 -0
  674. sage/rings/complex_conversion.pxd +8 -0
  675. sage/rings/complex_conversion.pyx +23 -0
  676. sage/rings/complex_double.cpython-314-aarch64-linux-musl.so +0 -0
  677. sage/rings/complex_double.pxd +21 -0
  678. sage/rings/complex_double.pyx +2654 -0
  679. sage/rings/complex_mpc.cpython-314-aarch64-linux-musl.so +0 -0
  680. sage/rings/complex_mpc.pxd +21 -0
  681. sage/rings/complex_mpc.pyx +2576 -0
  682. sage/rings/complex_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  683. sage/rings/complex_mpfr.pxd +18 -0
  684. sage/rings/complex_mpfr.pyx +3602 -0
  685. sage/rings/derivation.py +2334 -0
  686. sage/rings/finite_rings/all__sagemath_modules.py +1 -0
  687. sage/rings/finite_rings/maps_finite_field.py +191 -0
  688. sage/rings/function_field/all__sagemath_modules.py +8 -0
  689. sage/rings/function_field/derivations.py +102 -0
  690. sage/rings/function_field/derivations_rational.py +132 -0
  691. sage/rings/function_field/differential.py +853 -0
  692. sage/rings/function_field/divisor.py +1107 -0
  693. sage/rings/function_field/drinfeld_modules/action.py +199 -0
  694. sage/rings/function_field/drinfeld_modules/all.py +1 -0
  695. sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
  696. sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
  697. sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
  698. sage/rings/function_field/drinfeld_modules/homset.py +420 -0
  699. sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
  700. sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-musl.so +0 -0
  701. sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
  702. sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.so +0 -0
  703. sage/rings/function_field/khuri_makdisi.pyx +935 -0
  704. sage/rings/invariants/all.py +4 -0
  705. sage/rings/invariants/invariant_theory.py +4597 -0
  706. sage/rings/invariants/reconstruction.py +395 -0
  707. sage/rings/polynomial/all__sagemath_modules.py +17 -0
  708. sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
  709. sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-musl.so +0 -0
  710. sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
  711. sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
  712. sage/rings/polynomial/ore_function_element.py +952 -0
  713. sage/rings/polynomial/ore_function_field.py +1028 -0
  714. sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
  715. sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
  716. sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
  717. sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
  718. sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-musl.so +0 -0
  719. sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
  720. sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
  721. sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
  722. sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
  723. sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
  724. sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-musl.so +0 -0
  725. sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
  726. sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
  727. sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-musl.so +0 -0
  728. sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
  729. sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
  730. sage/rings/polynomial/skew_polynomial_ring.py +908 -0
  731. sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-musl.so +0 -0
  732. sage/rings/real_double_element_gsl.pxd +8 -0
  733. sage/rings/real_double_element_gsl.pyx +794 -0
  734. sage/rings/real_field.py +58 -0
  735. sage/rings/real_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
  736. sage/rings/real_mpfr.pxd +29 -0
  737. sage/rings/real_mpfr.pyx +6122 -0
  738. sage/rings/ring_extension.cpython-314-aarch64-linux-musl.so +0 -0
  739. sage/rings/ring_extension.pxd +42 -0
  740. sage/rings/ring_extension.pyx +2779 -0
  741. sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-musl.so +0 -0
  742. sage/rings/ring_extension_conversion.pxd +16 -0
  743. sage/rings/ring_extension_conversion.pyx +462 -0
  744. sage/rings/ring_extension_element.cpython-314-aarch64-linux-musl.so +0 -0
  745. sage/rings/ring_extension_element.pxd +21 -0
  746. sage/rings/ring_extension_element.pyx +1635 -0
  747. sage/rings/ring_extension_homset.py +64 -0
  748. sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-musl.so +0 -0
  749. sage/rings/ring_extension_morphism.pxd +35 -0
  750. sage/rings/ring_extension_morphism.pyx +920 -0
  751. sage/schemes/all__sagemath_modules.py +1 -0
  752. sage/schemes/projective/all__sagemath_modules.py +1 -0
  753. sage/schemes/projective/coherent_sheaf.py +300 -0
  754. sage/schemes/projective/cohomology.py +510 -0
  755. sage/stats/all.py +15 -0
  756. sage/stats/basic_stats.py +489 -0
  757. sage/stats/distributions/all.py +7 -0
  758. sage/stats/distributions/catalog.py +34 -0
  759. sage/stats/distributions/dgs.h +50 -0
  760. sage/stats/distributions/dgs.pxd +111 -0
  761. sage/stats/distributions/dgs_bern.h +400 -0
  762. sage/stats/distributions/dgs_gauss.h +614 -0
  763. sage/stats/distributions/dgs_misc.h +104 -0
  764. sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-musl.so +0 -0
  765. sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
  766. sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
  767. sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
  768. sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
  769. sage/stats/hmm/all.py +15 -0
  770. sage/stats/hmm/chmm.cpython-314-aarch64-linux-musl.so +0 -0
  771. sage/stats/hmm/chmm.pyx +1595 -0
  772. sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.so +0 -0
  773. sage/stats/hmm/distributions.pxd +29 -0
  774. sage/stats/hmm/distributions.pyx +531 -0
  775. sage/stats/hmm/hmm.cpython-314-aarch64-linux-musl.so +0 -0
  776. sage/stats/hmm/hmm.pxd +17 -0
  777. sage/stats/hmm/hmm.pyx +1388 -0
  778. sage/stats/hmm/util.cpython-314-aarch64-linux-musl.so +0 -0
  779. sage/stats/hmm/util.pxd +7 -0
  780. sage/stats/hmm/util.pyx +165 -0
  781. sage/stats/intlist.cpython-314-aarch64-linux-musl.so +0 -0
  782. sage/stats/intlist.pxd +14 -0
  783. sage/stats/intlist.pyx +588 -0
  784. sage/stats/r.py +49 -0
  785. sage/stats/time_series.cpython-314-aarch64-linux-musl.so +0 -0
  786. sage/stats/time_series.pxd +6 -0
  787. sage/stats/time_series.pyx +2546 -0
  788. sage/tensor/all.py +2 -0
  789. sage/tensor/modules/all.py +8 -0
  790. sage/tensor/modules/alternating_contr_tensor.py +761 -0
  791. sage/tensor/modules/comp.py +5598 -0
  792. sage/tensor/modules/ext_pow_free_module.py +824 -0
  793. sage/tensor/modules/finite_rank_free_module.py +3589 -0
  794. sage/tensor/modules/format_utilities.py +333 -0
  795. sage/tensor/modules/free_module_alt_form.py +858 -0
  796. sage/tensor/modules/free_module_automorphism.py +1207 -0
  797. sage/tensor/modules/free_module_basis.py +1074 -0
  798. sage/tensor/modules/free_module_element.py +284 -0
  799. sage/tensor/modules/free_module_homset.py +652 -0
  800. sage/tensor/modules/free_module_linear_group.py +564 -0
  801. sage/tensor/modules/free_module_morphism.py +1581 -0
  802. sage/tensor/modules/free_module_tensor.py +3289 -0
  803. sage/tensor/modules/reflexive_module.py +386 -0
  804. sage/tensor/modules/tensor_free_module.py +780 -0
  805. sage/tensor/modules/tensor_free_submodule.py +538 -0
  806. sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
  807. sage/tensor/modules/tensor_with_indices.py +1043 -0
@@ -0,0 +1,4258 @@
1
+ # sage_setup: distribution = sagemath-modules
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ r"""
4
+ The Steenrod algebra
5
+
6
+ AUTHORS:
7
+
8
+ - John H. Palmieri (2008-07-30): version 0.9: Initial implementation.
9
+ - John H. Palmieri (2010-06-30): version 1.0: Implemented sub-Hopf
10
+ algebras and profile functions; direct multiplication of admissible
11
+ sequences (rather than conversion to the Milnor basis); implemented
12
+ the Steenrod algebra using CombinatorialFreeModule; improved the
13
+ test suite.
14
+
15
+ This module defines the mod `p` Steenrod algebra `\mathcal{A}_p`, some
16
+ of its properties, and ways to define elements of it.
17
+
18
+ From a topological point of view, `\mathcal{A}_p` is the algebra of
19
+ stable cohomology operations on mod `p` cohomology; thus for any
20
+ topological space `X`, its mod `p` cohomology algebra
21
+ `H^*(X,\mathbf{F}_p)` is a module over `\mathcal{A}_p`.
22
+
23
+ From an algebraic point of view, `\mathcal{A}_p` is an
24
+ `\mathbf{F}_p`-algebra; when `p=2`, it is generated by elements
25
+ `\text{Sq}^i` for `i\geq 0` (the *Steenrod squares*), and when `p` is
26
+ odd, it is generated by elements `\mathcal{P}^i` for `i \geq 0` (the
27
+ *Steenrod reduced `p`-th powers*) along with an element `\beta` (the *mod
28
+ p Bockstein*). The Steenrod algebra is graded: `\text{Sq}^i` is in
29
+ degree `i` for each `i`, `\beta` is in degree 1, and `\mathcal{P}^i`
30
+ is in degree `2(p-1)i`.
31
+
32
+ The unit element is `\text{Sq}^0` when `p=2` and
33
+ `\mathcal{P}^0` when `p` is odd. The generating
34
+ elements also satisfy the *Adem relations*. At the prime 2, these
35
+ have the form
36
+
37
+ .. MATH::
38
+
39
+ \text{Sq}^a \text{Sq}^b = \sum_{c=0}^{[a/2]} \binom{b-c-1}{a-2c} \text{Sq}^{a+b-c} \text{Sq}^c.
40
+
41
+ At odd primes, they are a bit more complicated; see Steenrod and
42
+ Epstein [SE1962]_ or :mod:`sage.algebras.steenrod.steenrod_algebra_bases`
43
+ for full details. These relations lead to the existence of the
44
+ *Serre-Cartan* basis for `\mathcal{A}_p`.
45
+
46
+ The mod `p` Steenrod algebra has the structure of a Hopf
47
+ algebra, and Milnor [Mil1958]_ has a beautiful description of the dual,
48
+ leading to a construction of the *Milnor basis* for
49
+ `\mathcal{A}_p`. In this module, elements in the Steenrod
50
+ algebra are represented, by default, using the Milnor basis.
51
+
52
+ .. rubric:: Bases for the Steenrod algebra
53
+
54
+ There are a handful of other bases studied in the literature; the
55
+ paper by Monks [Mon1998]_ is a good reference. Here is a quick summary:
56
+
57
+ - The *Milnor basis*. When `p=2`, the Milnor basis consists of symbols
58
+ of the form `\text{Sq}(m_1, m_2, ..., m_t)`, where each `m_i` is a
59
+ nonnegative integer and if `t>1`, then the last entry `m_t > 0`.
60
+ When `p` is odd, the Milnor basis consists of symbols of the form
61
+ `Q_{e_1} Q_{e_2} ... \mathcal{P}(m_1, m_2, ..., m_t)`, where `0 \leq
62
+ e_1 < e_2 < ...`, each `m_i` is a nonnegative integer, and if
63
+ `t>1`, then the last entry `m_t > 0`.
64
+
65
+ When `p=2`, it can be convenient to use the notation
66
+ `\mathcal{P}(-)` to mean `\text{Sq}(-)`, so that there is consistent
67
+ notation for all primes.
68
+
69
+ - The *Serre-Cartan basis*. This basis consists of 'admissible
70
+ monomials' in the Steenrod operations. Thus at the prime 2, it
71
+ consists of monomials `\text{Sq}^{m_1} \text{Sq}^{m_2}
72
+ ... \text{Sq}^{m_t}` with `m_i \geq 2m_{i+1}` for each `i`. At odd
73
+ primes, this basis consists of monomials `\beta^{\epsilon_0}
74
+ \mathcal{P}^{s_1} \beta^{\epsilon_1} \mathcal{P}^{s_2} ...
75
+ \mathcal{P}^{s_k} \beta^{\epsilon_k}` with each `\epsilon_i` either
76
+ 0 or 1, `s_i \geq p s_{i+1} + \epsilon_i`, and `s_k \geq 1`.
77
+
78
+ Most of the rest of the bases are only defined when `p=2`. The only
79
+ exceptions are the `P^s_t`-bases and the commutator bases, which are
80
+ defined at all primes.
81
+
82
+ - *Wood's Y basis*. For pairs of nonnegative integers `(m,k)`, let
83
+ `w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}`. Wood's `Y` basis consists of
84
+ monomials `w(m_0,k_0) ... w(m_t, k_t)` with `(m_i,k_i) >
85
+ (m_{i+1},k_{i+1})`, in left lex order.
86
+
87
+ - *Wood's Z basis*. For pairs of nonnegative integers `(m,k)`, let
88
+ `w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}`. Wood's `Z` basis consists of
89
+ monomials `w(m_0,k_0) ... w(m_t, k_t)` with `(m_i+k_i,m_i) >
90
+ (m_{i+1}+k_{i+1},m_{i+1})`, in left lex order.
91
+
92
+ - *Wall's basis*. For any pair of integers `(m,k)` with `m \geq k \geq
93
+ 0`, let `Q^m_k = \text{Sq}^{2^k} \text{Sq}^{2^{k+1}}
94
+ ... \text{Sq}^{2^m}`. The elements of Wall's basis are monomials
95
+ `Q^{m_0}_{k_0} ... Q^{m_t}_{k_t}` with `(m_i, k_i) > (m_{i+1},
96
+ k_{i+1})`, ordered left lexicographically.
97
+
98
+ (Note that `Q^m_k` is the reverse of the element `X^m_k` used in
99
+ defining Arnon's A basis.)
100
+
101
+ - *Arnon's A basis*. For any pair of integers `(m,k)` with `m \geq k
102
+ \geq 0`, let `X^m_k = \text{Sq}^{2^m} \text{Sq}^{2^{m-1}}
103
+ ... \text{Sq}^{2^k}`. The elements of Arnon's A basis are monomials
104
+ `X^{m_0}_{k_0} ... X^{m_t}_{k_t}` with `(m_i, k_i) < (m_{i+1},
105
+ k_{i+1})`, ordered left lexicographically.
106
+
107
+ (Note that `X^m_k` is the reverse of the element `Q^m_k` used in
108
+ defining Wall's basis.)
109
+
110
+ - *Arnon's C basis*. The elements of Arnon's C basis are monomials of
111
+ the form `\text{Sq}^{t_1} ... \text{Sq}^{t_m}` where for each `i`,
112
+ we have `t_i \leq 2t_{i+1}` and `2^i | t_{m-i}`.
113
+
114
+ - `P^s_t` *bases*. Let `p=2`. For integers `s \geq 0` and `t > 0`,
115
+ the element `P^s_t` is the Milnor basis element `\mathcal{P}(0, ...,
116
+ 0, p^s, 0, ...)`, with the nonzero entry in position `t`. To obtain
117
+ a `P^s_t`-basis, for each set `\{P^{s_1}_{t_1}, ...,
118
+ P^{s_k}_{t_k}\}` of (distinct) `P^s_t`'s, one chooses an ordering
119
+ and forms the monomials
120
+
121
+ .. MATH::
122
+
123
+ (P^{s_1}_{t_1})^{i_1} ... (P^{s_k}_{t_k})^{i_k}
124
+
125
+ for all exponents `i_j` with `0 < i_j < p`. When `p=2`, the set of
126
+ all such monomials then forms a basis, and when `p` is odd, if one
127
+ multiplies each such monomial on the left by products of the form
128
+ `Q_{e_1} Q_{e_2} ...` with `0 \leq e_1 < e_2 < ...`, one obtains a
129
+ basis.
130
+
131
+ Thus one gets a basis by choosing an ordering on each set of
132
+ `P^s_t`'s. There are infinitely many orderings possible, and we
133
+ have implemented four of them:
134
+
135
+ - 'rlex': right lexicographic ordering
136
+
137
+ - 'llex': left lexicographic ordering
138
+
139
+ - 'deg': ordered by degree, which is the same as left lexicographic
140
+ ordering on the pair `(s+t,t)`
141
+
142
+ - 'revz': left lexicographic ordering on the pair `(s+t,s)`, which
143
+ is the reverse of the ordering used (on elements in the same
144
+ degrees as the `P^s_t`'s) in Wood's Z basis: 'revz' stands for
145
+ 'reversed Z'. This is the default: 'pst' is the same as
146
+ 'pst_revz'.
147
+
148
+ - *Commutator bases*. Let `c_{i,1} = \mathcal{P}(p^i)`, let `c_{i,2}
149
+ = [c_{i+1,1}, c_{i,1}]`, and inductively define `c_{i,k} =
150
+ [c_{i+k-1,1}, c_{i,k-1}]`. Thus `c_{i,k}` is a `k`-fold iterated
151
+ commutator of the elements `\mathcal{P}(p^i)`, ...,
152
+ `\mathcal{P}(p^{i+k-1})`. Note that `\dim c_{i,k} = \dim P^i_k`.
153
+
154
+ Commutator bases are obtained in much the same way as `P^s_t`-bases:
155
+ for each set `\{c_{s_1,t_1}, ..., c_{s_k,t_k}\}` of (distinct)
156
+ `c_{s,t}`'s, one chooses an ordering and forms the resulting
157
+ monomials
158
+
159
+ .. MATH::
160
+
161
+ c_{s_1, t_1}^{i_1} ... c_{s_k,t_k}^{i_k}
162
+
163
+ for all exponents `i_j` with `0 < i_j < p`. When `p` is odd, one
164
+ also needs to left-multiply by products of the `Q_i`'s. As for
165
+ `P^s_t`-bases, every ordering on each set of iterated commutators
166
+ determines a basis, and the same four orderings have been defined
167
+ for these bases as for the `P^s_t` bases: 'rlex', 'llex', 'deg',
168
+ 'revz'.
169
+
170
+ .. rubric:: Sub-Hopf algebras of the Steenrod algebra
171
+
172
+ The sub-Hopf algebras of the Steenrod algebra have been
173
+ classified. Milnor proved that at the prime 2, the dual of the
174
+ Steenrod algebra `A_*` is isomorphic to a polynomial algebra
175
+
176
+ .. MATH::
177
+
178
+ A_* \cong \GF{2} [\xi_1, \xi_2, \xi_3, ...].
179
+
180
+ The Milnor basis is dual to the monomial basis. Furthermore, any sub-Hopf
181
+ algebra corresponds to a quotient of this of the form
182
+
183
+ .. MATH::
184
+
185
+ A_* /(\xi_1^{2^{e_1}}, \xi_2^{2^{e_2}}, \xi_3^{2^{e_3}}, ...).
186
+
187
+ The list of exponents `(e_1, e_2, ...)` may be considered a function
188
+ `e` from the positive integers to the extended nonnegative integers
189
+ (the nonnegative integers and `\infty`); this is called the *profile
190
+ function* for the sub-Hopf algebra. The profile function must satisfy
191
+ the condition
192
+
193
+ - `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`.
194
+
195
+ At odd primes, the situation is similar: the dual is isomorphic to the
196
+ tensor product of a polynomial algebra and an exterior algebra,
197
+
198
+ .. MATH::
199
+
200
+ A_* = \GF{p} [\xi_1, \xi_2, \xi_3, ...] \otimes \Lambda (\tau_0, \tau_1, ...),
201
+
202
+ and any sub-Hopf algebra corresponds to a quotient of this of the form
203
+
204
+ .. MATH::
205
+
206
+ A_* / (\xi_1^{p^{e_1}}, \xi_2^{p^{e_2}}, ...; \tau_0^{k_0}, \tau_1^{k_1}, ...).
207
+
208
+ Here the profile function has two pieces, `e` as at the prime 2, and
209
+ `k`, which maps the nonnegative integers to the set `\{1, 2\}`.
210
+ These must satisfy the following conditions:
211
+
212
+ - `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`.
213
+
214
+ - if `k(i+j) = 1`, then either `e(i) \leq j` or `k(j) = 1` for all `i
215
+ \geq 1`, `j \geq 0`.
216
+
217
+ (See Adams-Margolis [AM1974]_, for example, for these results on profile
218
+ functions.)
219
+
220
+ This module allows one to construct the Steenrod algebra or any of its
221
+ sub-Hopf algebras, at any prime. When defining a sub-Hopf algebra,
222
+ you must work with the Milnor basis or a `P^s_t`-basis.
223
+
224
+ .. rubric:: Elements of the Steenrod algebra
225
+
226
+ Basic arithmetic, `p=2`. To construct an element of the mod 2 Steenrod
227
+ algebra, use the function ``Sq``::
228
+
229
+ sage: a = Sq(1,2)
230
+ sage: b = Sq(4,1)
231
+ sage: z = a + b
232
+ sage: z
233
+ Sq(1,2) + Sq(4,1)
234
+ sage: Sq(4) * Sq(1,2)
235
+ Sq(1,1,1) + Sq(2,3) + Sq(5,2)
236
+ sage: z**2 # nonnegative exponents work as they should
237
+ Sq(1,2,1) + Sq(4,1,1)
238
+ sage: z**0
239
+ 1
240
+
241
+ Basic arithmetic, `p>2`. To construct an element of the mod `p`
242
+ Steenrod algebra when `p` is odd, you should first define a Steenrod
243
+ algebra, using the ``SteenrodAlgebra`` command::
244
+
245
+ sage: A3 = SteenrodAlgebra(3)
246
+
247
+ Having done this, the newly created algebra ``A3`` has methods ``Q``
248
+ and ``P`` which construct elements of ``A3``::
249
+
250
+ sage: c = A3.Q(1,3,6); c
251
+ Q_1 Q_3 Q_6
252
+ sage: d = A3.P(2,0,1); d
253
+ P(2,0,1)
254
+ sage: c * d
255
+ Q_1 Q_3 Q_6 P(2,0,1)
256
+ sage: e = A3.P(3)
257
+ sage: d * e
258
+ P(5,0,1)
259
+ sage: e * d
260
+ P(1,1,1) + P(5,0,1)
261
+ sage: c * c
262
+ 0
263
+ sage: e ** 3
264
+ 2 P(1,2)
265
+
266
+ Note that one can construct an element like ``c`` above in one step,
267
+ without first constructing the algebra::
268
+
269
+ sage: c = SteenrodAlgebra(3).Q(1,3,6)
270
+ sage: c
271
+ Q_1 Q_3 Q_6
272
+
273
+ And of course, you can do similar constructions with the mod 2
274
+ Steenrod algebra::
275
+
276
+ sage: A = SteenrodAlgebra(2); A
277
+ mod 2 Steenrod algebra, milnor basis
278
+ sage: A.Sq(2,3,5)
279
+ Sq(2,3,5)
280
+ sage: A.P(2,3,5) # when p=2, P = Sq
281
+ Sq(2,3,5)
282
+ sage: A.Q(1,4) # when p=2, this gives a product of Milnor primitives
283
+ Sq(0,1,0,0,1)
284
+
285
+ Associated to each element is its prime (the characteristic of the
286
+ underlying base field) and its basis (the basis for the Steenrod
287
+ algebra in which it lies)::
288
+
289
+ sage: a = SteenrodAlgebra(basis='milnor').Sq(1,2,1)
290
+ sage: a.prime()
291
+ 2
292
+ sage: a.basis_name()
293
+ 'milnor'
294
+ sage: a.degree()
295
+ 14
296
+
297
+ It can be viewed in other bases::
298
+
299
+ sage: a.milnor() # same as a
300
+ Sq(1,2,1)
301
+ sage: a.change_basis('adem')
302
+ Sq^9 Sq^4 Sq^1 + Sq^11 Sq^2 Sq^1 + Sq^13 Sq^1
303
+ sage: a.change_basis('adem').change_basis('milnor')
304
+ Sq(1,2,1)
305
+
306
+ Regardless of the prime, each element has an ``excess``, and if the
307
+ element is homogeneous, a ``degree``. The excess of
308
+ `\text{Sq}(i_1,i_2,i_3,...)` is `i_1 + i_2 + i_3 + ...`; when `p` is
309
+ odd, the excess of `Q_{0}^{e_0} Q_{1}^{e_1} ... \mathcal{P}(r_1, r_2,
310
+ ...)` is `\sum e_i + 2 \sum r_i`. The excess of a linear combination
311
+ of Milnor basis elements is the minimum of the excesses of those basis
312
+ elements.
313
+
314
+ The degree of `\text{Sq}(i_1,i_2,i_3,...)` is `\sum (2^n-1) i_n`, and
315
+ when `p` is odd, the degree of `Q_{0}^{\epsilon_0} Q_{1}^{\epsilon_1}
316
+ ... \mathcal{P}(r_1, r_2, ...)` is `\sum \epsilon_i (2p^i - 1) + \sum
317
+ r_j (2p^j - 2)`. The degree of a linear combination of such terms is
318
+ only defined if the terms all have the same degree.
319
+
320
+ Here are some simple examples::
321
+
322
+ sage: z = Sq(1,2) + Sq(4,1)
323
+ sage: z.degree()
324
+ 7
325
+ sage: (Sq(0,0,1) + Sq(5,3)).degree()
326
+ Traceback (most recent call last):
327
+ ...
328
+ ValueError: element is not homogeneous
329
+ sage: Sq(7,2,1).excess()
330
+ 10
331
+ sage: z.excess()
332
+ 3
333
+ sage: B = SteenrodAlgebra(3)
334
+ sage: x = B.Q(1,4)
335
+ sage: y = B.P(1,2,3)
336
+ sage: x.degree()
337
+ 166
338
+ sage: x.excess()
339
+ 2
340
+ sage: y.excess()
341
+ 12
342
+
343
+ Elements have a ``weight`` in the May filtration, which (when `p=2`)
344
+ is related to the ``height`` function defined by Wall::
345
+
346
+ sage: Sq(2,1,5).may_weight()
347
+ 9
348
+ sage: Sq(2,1,5).wall_height()
349
+ [2, 3, 2, 1, 1]
350
+ sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
351
+ sage: b.may_weight()
352
+ 2
353
+ sage: b.wall_height()
354
+ [0, 0, 1, 1]
355
+
356
+ Odd primary May weights::
357
+
358
+ sage: A5 = SteenrodAlgebra(5)
359
+ sage: a = A5.Q(1,2,4)
360
+ sage: b = A5.P(1,2,1)
361
+ sage: a.may_weight()
362
+ 10
363
+ sage: b.may_weight()
364
+ 8
365
+ sage: (a * b).may_weight()
366
+ 18
367
+ sage: A5.P(0,0,1).may_weight()
368
+ 3
369
+
370
+ Since the Steenrod algebra is a Hopf algebra, every element has a
371
+ coproduct and an antipode::
372
+
373
+ sage: Sq(5).coproduct()
374
+ 1 # Sq(5) + Sq(1) # Sq(4) + Sq(2) # Sq(3) + Sq(3) # Sq(2) + Sq(4) # Sq(1) + Sq(5) # 1
375
+ sage: Sq(5).antipode()
376
+ Sq(2,1) + Sq(5)
377
+ sage: d = Sq(0,0,1); d
378
+ Sq(0,0,1)
379
+ sage: d.antipode()
380
+ Sq(0,0,1)
381
+ sage: Sq(4).antipode()
382
+ Sq(1,1) + Sq(4)
383
+ sage: (Sq(4) * Sq(2)).antipode()
384
+ Sq(6)
385
+ sage: SteenrodAlgebra(7).P(3,1).antipode()
386
+ P(3,1)
387
+
388
+ Applying the antipode twice returns the original element::
389
+
390
+ sage: y = Sq(8)*Sq(4)
391
+ sage: y == (y.antipode()).antipode()
392
+ True
393
+
394
+ Internal representation: you can use any element as an iterator (``for
395
+ x in a: ...``), and the method :meth:`monomial_coefficients` returns a
396
+ dictionary with keys tuples representing basis elements and with
397
+ corresponding value representing the coefficient of that term::
398
+
399
+ sage: c = Sq(5).antipode(); c
400
+ Sq(2,1) + Sq(5)
401
+ sage: for mono, coeff in c: print((coeff, mono))
402
+ (1, (5,))
403
+ (1, (2, 1))
404
+ sage: c.monomial_coefficients() == {(2, 1): 1, (5,): 1}
405
+ True
406
+ sage: sorted(c.monomials(), key=lambda x: tuple(x.support()))
407
+ [Sq(2,1), Sq(5)]
408
+ sage: sorted(c.support())
409
+ [(2, 1), (5,)]
410
+ sage: Adem = SteenrodAlgebra(basis='adem')
411
+ sage: elt = Adem.Sq(10) + Adem.Sq(9) * Adem.Sq(1)
412
+ sage: sorted(elt.monomials(), key=lambda x: tuple(x.support()))
413
+ [Sq^9 Sq^1, Sq^10]
414
+
415
+ sage: A7 = SteenrodAlgebra(p=7)
416
+ sage: a = A7.P(1) * A7.P(1); a
417
+ 2 P(2)
418
+ sage: a.leading_coefficient()
419
+ 2
420
+ sage: a.leading_monomial()
421
+ P(2)
422
+ sage: a.leading_term()
423
+ 2 P(2)
424
+ sage: a.change_basis('adem').monomial_coefficients()
425
+ {(0, 2, 0): 2}
426
+
427
+ The tuple in the previous output stands for the element `\beta^0
428
+ P^2 \beta^0`, i.e., `P^2`. Going in the other direction, if you
429
+ want to specify a basis element by giving the corresponding tuple,
430
+ you can use the :meth:`monomial` method on the algebra::
431
+
432
+ sage: SteenrodAlgebra(p=7, basis='adem').monomial((0, 2, 0))
433
+ P^2
434
+ sage: 10 * SteenrodAlgebra(p=7, basis='adem').monomial((0, 2, 0))
435
+ 3 P^2
436
+
437
+ In the following example, elements in Wood's Z basis are certain
438
+ products of the elements `w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}`.
439
+ Internally, each `w(m,k)` is represented by the pair `(m,k)`, and
440
+ products of them are represented by tuples of such pairs. ::
441
+
442
+ sage: A = SteenrodAlgebra(basis='wood_z')
443
+ sage: t = ((2, 0), (0, 0))
444
+ sage: A.monomial(t)
445
+ Sq^4 Sq^1
446
+
447
+ See the documentation for :func:`SteenrodAlgebra` for more details and
448
+ examples.
449
+ """
450
+
451
+ # ****************************************************************************
452
+ # Copyright (C) 2008-2010 John H. Palmieri <palmieri@math.washington.edu>
453
+ # Distributed under the terms of the GNU General Public License (GPL)
454
+ # ****************************************************************************
455
+
456
+ from sage.categories.homset import Hom
457
+ from sage.categories.modules_with_basis import ModulesWithBasis
458
+ from sage.categories.tensor import tensor
459
+ from sage.combinat.free_module import CombinatorialFreeModule
460
+ from sage.misc.cachefunc import cached_method
461
+ from sage.misc.lazy_attribute import lazy_attribute
462
+ from sage.sets.family import Family
463
+
464
+ ######################################################
465
+ # the main class
466
+ ######################################################
467
+
468
+
469
+ class SteenrodAlgebra_generic(CombinatorialFreeModule):
470
+ r"""
471
+ The mod `p` Steenrod algebra.
472
+
473
+ Users should not call this, but use the function
474
+ :func:`SteenrodAlgebra` instead. See that function for
475
+ extensive documentation.
476
+
477
+ EXAMPLES::
478
+
479
+ sage: sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra_generic()
480
+ mod 2 Steenrod algebra, milnor basis
481
+ sage: sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra_generic(5)
482
+ mod 5 Steenrod algebra, milnor basis
483
+ sage: sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra_generic(5, 'adem')
484
+ mod 5 Steenrod algebra, serre-cartan basis
485
+ """
486
+ @staticmethod
487
+ def __classcall__(self, p=2, basis='milnor', **kwds):
488
+ """
489
+ This normalizes the basis name and the profile, to make unique
490
+ representation work properly.
491
+
492
+ EXAMPLES::
493
+
494
+ sage: SteenrodAlgebra(basis='adem') is SteenrodAlgebra(basis='serre-cartan')
495
+ True
496
+ sage: SteenrodAlgebra(profile=[3,2,1,0]) is SteenrodAlgebra(profile=lambda n: max(4-n,0), truncation_type=0)
497
+ True
498
+ sage: SteenrodAlgebra(p=5) is SteenrodAlgebra(p=5, generic=True)
499
+ True
500
+ """
501
+ from .steenrod_algebra_misc import get_basis_name, normalize_profile
502
+ profile = kwds.get('profile', None)
503
+ precision = kwds.get('precision', None)
504
+ truncation_type = kwds.get('truncation_type', 'auto')
505
+ generic = kwds.get('generic', 'auto')
506
+ if generic == 'auto':
507
+ std_generic = p != 2
508
+ else:
509
+ std_generic = generic
510
+ if p != 2:
511
+ std_generic = True
512
+ if not (std_generic is True or std_generic is False):
513
+ raise ValueError("option 'generic' is not a boolean")
514
+
515
+ std_basis = get_basis_name(basis, p, generic=std_generic)
516
+ std_profile, std_type = normalize_profile(profile, precision=precision,
517
+ truncation_type=truncation_type, p=p, generic=std_generic)
518
+ return super().__classcall__(self, p=p, basis=std_basis, profile=std_profile,
519
+ truncation_type=std_type, generic=std_generic)
520
+
521
+ def __init__(self, p=2, basis='milnor', **kwds):
522
+ r"""
523
+ INPUT:
524
+
525
+ - ``p`` -- positive prime integer (default: 2)
526
+ - ``basis`` -- string (default: ``'milnor'``)
527
+ - ``profile`` -- profile function (default: ``None``)
528
+ - ``truncation_type`` -- (default: ``'auto'``)
529
+ - ``precision`` -- (default: ``None``)
530
+ - ``generic`` -- (default: ``'auto'``)
531
+
532
+ OUTPUT:
533
+
534
+ mod `p` Steenrod algebra with basis, or a sub-Hopf
535
+ algebra of the mod `p` Steenrod algebra defined by the given
536
+ profile function.
537
+
538
+ See :func:`SteenrodAlgebra` for full documentation.
539
+
540
+ EXAMPLES::
541
+
542
+ sage: SteenrodAlgebra() # 2 is the default prime
543
+ mod 2 Steenrod algebra, milnor basis
544
+ sage: SteenrodAlgebra(5)
545
+ mod 5 Steenrod algebra, milnor basis
546
+ sage: SteenrodAlgebra(2, 'milnor').Sq(0,1)
547
+ Sq(0,1)
548
+ sage: SteenrodAlgebra(2, 'adem').Sq(0,1)
549
+ Sq^2 Sq^1 + Sq^3
550
+
551
+ TESTS::
552
+
553
+ sage: TestSuite(SteenrodAlgebra()).run()
554
+ sage: TestSuite(SteenrodAlgebra(profile=[4,3,2,2,1])).run()
555
+ sage: TestSuite(SteenrodAlgebra(basis='adem')).run()
556
+ sage: TestSuite(SteenrodAlgebra(basis='wall')).run()
557
+ sage: TestSuite(SteenrodAlgebra(basis='arnonc')).run() # long time
558
+ sage: TestSuite(SteenrodAlgebra(basis='woody')).run() # long time
559
+ sage: A3 = SteenrodAlgebra(3)
560
+ sage: A3.category()
561
+ Category of supercocommutative super Hopf algebras
562
+ with basis over Finite Field of size 3
563
+ sage: TestSuite(A3).run() # long time
564
+ sage: TestSuite(SteenrodAlgebra(basis='adem', p=3)).run()
565
+ sage: TestSuite(SteenrodAlgebra(basis='pst_llex', p=7)).run() # long time
566
+ sage: TestSuite(SteenrodAlgebra(basis='comm_deg', p=5)).run() # long time
567
+ sage: TestSuite(SteenrodAlgebra(p=2, generic=True)).run() # long time
568
+
569
+ Two Steenrod algebras are equal iff their associated primes,
570
+ bases, and profile functions (if present) are equal. Because
571
+ this class inherits from :class:`UniqueRepresentation`, this
572
+ means that they are equal if and only they are identical: ``A
573
+ == B`` is True if and only if ``A is B`` is ``True``::
574
+
575
+ sage: A = SteenrodAlgebra(2)
576
+ sage: B = SteenrodAlgebra(2, 'adem')
577
+ sage: A == B
578
+ False
579
+ sage: C = SteenrodAlgebra(17)
580
+ sage: A == C
581
+ False
582
+
583
+ sage: A1 = SteenrodAlgebra(2, profile=[2,1])
584
+ sage: A1 == A
585
+ False
586
+ sage: A1 == SteenrodAlgebra(2, profile=[2,1,0])
587
+ True
588
+ sage: A1 == SteenrodAlgebra(2, profile=[2,1], basis='pst')
589
+ False
590
+ """
591
+ from sage.arith.misc import is_prime
592
+ from sage.categories.super_hopf_algebras_with_basis import SuperHopfAlgebrasWithBasis
593
+ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
594
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
595
+ from sage.rings.infinity import Infinity
596
+ from sage.sets.set_from_iterator import EnumeratedSetFromIterator
597
+ from functools import partial
598
+ from .steenrod_algebra_bases import steenrod_algebra_basis
599
+ from sage.rings.finite_rings.finite_field_constructor import GF
600
+ profile = kwds.get('profile', None)
601
+ truncation_type = kwds.get('truncation_type', 'auto')
602
+ self._generic = kwds.get('generic')
603
+ assert (self._generic is True or (p == 2 and self._generic is False))
604
+
605
+ if not is_prime(p):
606
+ raise ValueError("%s is not prime" % p)
607
+ self._prime = p
608
+ base_ring = GF(p)
609
+ self._profile = profile
610
+ self._truncation_type = truncation_type
611
+ if ((not self._generic and profile and profile[0] < Infinity)
612
+ or (self._generic and profile != ((), ()) and profile[0]
613
+ and profile[0][0] < Infinity)
614
+ or (truncation_type < Infinity)):
615
+ if basis != 'milnor' and basis.find('pst') == -1:
616
+ raise NotImplementedError("for sub-Hopf algebras of the Steenrod algebra, only the Milnor basis and the pst bases are implemented")
617
+ self._basis_name = basis
618
+ basis_category = FiniteEnumeratedSets() if self.is_finite() else InfiniteEnumeratedSets()
619
+ basis_set = EnumeratedSetFromIterator(self._basis_key_iterator,
620
+ category=basis_category,
621
+ name="basis key family of %s" % self,
622
+ cache=False)
623
+
624
+ self._basis_fcn = partial(steenrod_algebra_basis,
625
+ p=p,
626
+ basis=basis,
627
+ profile=profile,
628
+ truncation_type=truncation_type,
629
+ generic=self._generic)
630
+
631
+ cat = SuperHopfAlgebrasWithBasis(base_ring).Supercocommutative()
632
+ CombinatorialFreeModule.__init__(self,
633
+ base_ring,
634
+ basis_set,
635
+ prefix=self._basis_name,
636
+ element_class=self.Element,
637
+ category=cat,
638
+ scalar_mult=' ')
639
+
640
+ # For the graded modules
641
+ from sage.modules.fp_graded.steenrod.module import SteenrodFPModule, SteenrodFreeModule
642
+ self._fp_graded_module_class = SteenrodFPModule
643
+ self._free_graded_module_class = SteenrodFreeModule
644
+
645
+ def _basis_key_iterator(self):
646
+ """
647
+ An iterator for the basis keys of the Steenrod algebra.
648
+
649
+ EXAMPLES::
650
+
651
+ sage: A = SteenrodAlgebra(3,basis='adem')
652
+ sage: for (idx,key) in zip((1,..,10),A._basis_key_iterator()):
653
+ ....: print("> %2d %-20s %s" % (idx,key,A.monomial(key)))
654
+ > 1 () 1
655
+ > 2 (1,) beta
656
+ > 3 (0, 1, 0) P^1
657
+ > 4 (1, 1, 0) beta P^1
658
+ > 5 (0, 1, 1) P^1 beta
659
+ > 6 (1, 1, 1) beta P^1 beta
660
+ > 7 (0, 2, 0) P^2
661
+ > 8 (1, 2, 0) beta P^2
662
+ > 9 (0, 2, 1) P^2 beta
663
+ > 10 (1, 2, 1) beta P^2 beta
664
+ """
665
+ from .steenrod_algebra_bases import steenrod_algebra_basis
666
+ from sage.sets.integer_range import IntegerRange
667
+ from sage.rings.integer import Integer
668
+ from sage.rings.infinity import Infinity
669
+ from functools import partial
670
+ import itertools
671
+ if self.is_finite():
672
+ maxdim = self.top_class().degree()
673
+ Ir = IntegerRange(Integer(0), Integer(maxdim + 1))
674
+ else:
675
+ Ir = IntegerRange(Integer(0), Infinity)
676
+ basfnc = partial(steenrod_algebra_basis,
677
+ p=self.prime(),
678
+ basis=self._basis_name,
679
+ profile=self._profile,
680
+ truncation_type=self._truncation_type)
681
+ return itertools.chain.from_iterable(basfnc(dim) for dim in Ir)
682
+
683
+ def prime(self):
684
+ r"""
685
+ The prime associated to ``self``.
686
+
687
+ EXAMPLES::
688
+
689
+ sage: SteenrodAlgebra(p=2, profile=[1,1]).prime()
690
+ 2
691
+ sage: SteenrodAlgebra(p=7).prime()
692
+ 7
693
+ """
694
+ return self._prime
695
+
696
+ def basis_name(self):
697
+ r"""
698
+ The basis name associated to ``self``.
699
+
700
+ EXAMPLES::
701
+
702
+ sage: SteenrodAlgebra(p=2, profile=[1,1]).basis_name()
703
+ 'milnor'
704
+ sage: SteenrodAlgebra(basis='serre-cartan').basis_name()
705
+ 'serre-cartan'
706
+ sage: SteenrodAlgebra(basis='adem').basis_name()
707
+ 'serre-cartan'
708
+ """
709
+ return self.prefix()
710
+
711
+ def _has_nontrivial_profile(self):
712
+ r"""
713
+ Return ``True`` if the profile function for this algebra seems to be that
714
+ for a proper sub-Hopf algebra of the Steenrod algebra.
715
+
716
+ EXAMPLES::
717
+
718
+ sage: SteenrodAlgebra()._has_nontrivial_profile()
719
+ False
720
+ sage: SteenrodAlgebra(p=3)._has_nontrivial_profile()
721
+ False
722
+ sage: SteenrodAlgebra(profile=[3,2,1])._has_nontrivial_profile()
723
+ True
724
+ sage: SteenrodAlgebra(profile=([1], [2, 2]), p=3)._has_nontrivial_profile()
725
+ True
726
+ sage: SteenrodAlgebra(generic=True)._has_nontrivial_profile()
727
+ False
728
+ sage: SteenrodAlgebra(generic=True, profile=[[3,2,1], []])._has_nontrivial_profile()
729
+ True
730
+
731
+ Check that a bug in :issue:`11832` has been fixed::
732
+
733
+ sage: P3 = SteenrodAlgebra(p=3, profile=(lambda n: Infinity, lambda n: 1))
734
+ sage: P3._has_nontrivial_profile()
735
+ True
736
+ """
737
+ from sage.rings.infinity import Infinity
738
+ profile = self._profile
739
+ trunc = self._truncation_type
740
+ if not self._generic:
741
+ return ((profile and profile[0] < Infinity)
742
+ or (trunc < Infinity))
743
+ return ((profile != ((), ()) and
744
+ ((profile[0] and profile[0][0] < Infinity)
745
+ or (profile[1] and min(profile[1]) == 1)))
746
+ or (trunc < Infinity))
747
+
748
+ def _repr_(self):
749
+ r"""
750
+ Printed representation of the Steenrod algebra.
751
+
752
+ EXAMPLES::
753
+
754
+ sage: SteenrodAlgebra(3)
755
+ mod 3 Steenrod algebra, milnor basis
756
+ sage: SteenrodAlgebra(2, basis='adem')
757
+ mod 2 Steenrod algebra, serre-cartan basis
758
+ sage: B = SteenrodAlgebra(2003) # needs sage.rings.finite_rings
759
+ sage: B._repr_() # needs sage.rings.finite_rings
760
+ 'mod 2003 Steenrod algebra, milnor basis'
761
+ sage: SteenrodAlgebra(generic=True, basis='adem')
762
+ generic mod 2 Steenrod algebra, serre-cartan basis
763
+
764
+ sage: SteenrodAlgebra(profile=(3,2,1,0))
765
+ sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
766
+ sage: SteenrodAlgebra(profile=lambda n: 4)
767
+ sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [4, 4, 4, ..., 4, 4, +Infinity, +Infinity, +Infinity, ...]
768
+ sage: SteenrodAlgebra(p=5, profile=(lambda n: 4, lambda n: 1))
769
+ sub-Hopf algebra of mod 5 Steenrod algebra, milnor basis, profile function ([4, 4, 4, ..., 4, 4, +Infinity, +Infinity, +Infinity, ...], [1, 1, 1, ..., 1, 1, 2, 2, ...])
770
+ """
771
+ def abridge_list(l):
772
+ """
773
+ String rep for list ``l`` if ``l`` is short enough;
774
+ otherwise print the first few terms and the last few
775
+ terms, with an ellipsis in between.
776
+ """
777
+ if len(l) < 8:
778
+ l_str = str(l)
779
+ else:
780
+ l_str = str(l[:3]).rstrip("]") + ", ..., " + str(l[-2:]).lstrip("[")
781
+ return l_str
782
+
783
+ from sage.rings.infinity import Infinity
784
+ profile = self._profile
785
+ trunc = self._truncation_type
786
+ p = self.prime()
787
+ genprefix = "generic " if p == 2 and self._generic else ""
788
+ if self._has_nontrivial_profile():
789
+ if not self._generic:
790
+ pro_str = abridge_list(list(profile))
791
+ if trunc != 0:
792
+ pro_str = pro_str.rstrip("]") + ", " + str([Infinity] * 3).strip("[]") + ", ...]"
793
+ else:
794
+ e_str = abridge_list(list(profile[0]))
795
+ k_str = abridge_list(list(profile[1]))
796
+ if trunc != 0:
797
+ e_str = e_str.rstrip("]") + ", " + str([Infinity] * 3).strip("[]") + ", ...]"
798
+ k_str = k_str.rstrip("]") + ", " + str([2] * 2).strip("[]") + ", ...]"
799
+ pro_str = "(%s, %s)" % (e_str, k_str)
800
+ return "sub-Hopf algebra of %smod %d Steenrod algebra, %s basis, profile function %s" % (genprefix, self.prime(), self._basis_name, pro_str)
801
+ return "%smod %d Steenrod algebra, %s basis" % (genprefix, self.prime(), self._basis_name)
802
+
803
+ def _latex_(self):
804
+ r"""
805
+ LaTeX representation of the Steenrod algebra.
806
+
807
+ EXAMPLES::
808
+
809
+ sage: C = SteenrodAlgebra(3)
810
+ sage: C
811
+ mod 3 Steenrod algebra, milnor basis
812
+ sage: C._latex_()
813
+ '\\mathcal{A}_{3}'
814
+ """
815
+ return "\\mathcal{A}_{%s}" % self.prime()
816
+
817
+ def _repr_term(self, t):
818
+ r"""
819
+ String representation of the monomial specified by the tuple ``t``.
820
+
821
+ INPUT:
822
+
823
+ - ``t`` -- tuple, representing basis element in the current basis
824
+
825
+ OUTPUT: string
826
+
827
+ This is tested in many places: any place elements are printed
828
+ is essentially a doctest for this method. Also, each basis
829
+ has its own method for printing monomials, and those are
830
+ doctested individually. We give a few doctests here, in
831
+ addition.
832
+
833
+ EXAMPLES::
834
+
835
+ sage: SteenrodAlgebra()._repr_term((3,2))
836
+ 'Sq(3,2)'
837
+ sage: SteenrodAlgebra(p=7)._repr_term(((0,2), (3,2)))
838
+ 'Q_0 Q_2 P(3,2)'
839
+ sage: SteenrodAlgebra(basis='adem')._repr_term((14,2))
840
+ 'Sq^14 Sq^2'
841
+ sage: SteenrodAlgebra(basis='adem', p=3)._repr_term((1,3,0))
842
+ 'beta P^3'
843
+ sage: SteenrodAlgebra(basis='pst')._repr_term(((0,2), (1,3)))
844
+ 'P^0_2 P^1_3'
845
+ sage: SteenrodAlgebra(basis='arnon_a')._repr_term(((0,2), (1,3)))
846
+ 'X^0_2 X^1_3'
847
+
848
+ sage: A7 = SteenrodAlgebra(7)
849
+ sage: x = A7.Q(0,3) * A7.P(2,2)
850
+ sage: x._repr_()
851
+ 'Q_0 Q_3 P(2,2)'
852
+ sage: x
853
+ Q_0 Q_3 P(2,2)
854
+ sage: a = SteenrodAlgebra().Sq(0,0,2)
855
+ sage: a
856
+ Sq(0,0,2)
857
+ sage: A2_adem = SteenrodAlgebra(2,'admissible')
858
+ sage: A2_adem(a)
859
+ Sq^8 Sq^4 Sq^2 + Sq^9 Sq^4 Sq^1 + Sq^10 Sq^3 Sq^1 +
860
+ Sq^10 Sq^4 + Sq^11 Sq^2 Sq^1 + Sq^12 Sq^2 + Sq^13 Sq^1
861
+ + Sq^14
862
+ sage: SteenrodAlgebra(2, 'woodz')(a)
863
+ Sq^6 Sq^7 Sq^1 + Sq^14 + Sq^4 Sq^7 Sq^3 + Sq^4 Sq^7
864
+ Sq^2 Sq^1 + Sq^12 Sq^2 + Sq^8 Sq^6 + Sq^8 Sq^4 Sq^2
865
+ sage: SteenrodAlgebra(2, 'arnonc')(a)
866
+ Sq^4 Sq^2 Sq^8 + Sq^4 Sq^4 Sq^6 + Sq^4 Sq^6 Sq^4 +
867
+ Sq^6 Sq^8 + Sq^8 Sq^4 Sq^2 + Sq^8 Sq^6
868
+ sage: SteenrodAlgebra(2, 'pst_llex')(a)
869
+ P^1_3
870
+ sage: SteenrodAlgebra(2, 'comm_revz')(a)
871
+ c_0,1 c_1,1 c_0,3 c_2,1 + c_0,2 c_0,3 c_2,1 + c_1,3
872
+ sage: SteenrodAlgebra(2, generic=True, basis='pst').P(0,0,2)
873
+ P^1_3
874
+ """
875
+ from .steenrod_algebra_misc import milnor_mono_to_string, \
876
+ serre_cartan_mono_to_string, wood_mono_to_string, \
877
+ wall_mono_to_string, wall_long_mono_to_string, \
878
+ arnonA_mono_to_string, arnonA_long_mono_to_string, \
879
+ pst_mono_to_string, \
880
+ comm_long_mono_to_string, comm_mono_to_string
881
+ p = self.prime()
882
+ basis = self.basis_name()
883
+ if basis == 'milnor':
884
+ s = milnor_mono_to_string(t, generic=self._generic)
885
+ elif basis == 'serre-cartan':
886
+ s = serre_cartan_mono_to_string(t, generic=self._generic)
887
+ elif basis.find('wood') >= 0:
888
+ s = wood_mono_to_string(t)
889
+ elif basis == 'wall':
890
+ s = wall_mono_to_string(t)
891
+ elif basis == 'wall_long':
892
+ s = wall_long_mono_to_string(t)
893
+ elif basis == 'arnona':
894
+ s = arnonA_mono_to_string(t)
895
+ elif basis == 'arnona_long':
896
+ s = arnonA_long_mono_to_string(t)
897
+ elif basis == 'arnonc':
898
+ s = serre_cartan_mono_to_string(t, generic=self._generic)
899
+ elif basis.find('pst') >= 0:
900
+ s = pst_mono_to_string(t, generic=self._generic)
901
+ elif basis.find('comm') >= 0 and basis.find('long') >= 0:
902
+ s = comm_long_mono_to_string(t, p, generic=self._generic)
903
+ elif basis.find('comm') >= 0:
904
+ s = comm_mono_to_string(t, generic=self._generic)
905
+ s = s.replace('{', '').replace('}', '')
906
+ return s
907
+
908
+ def _latex_term(self, t):
909
+ r"""
910
+ LaTeX representation of the monomial specified by the tuple ``t``.
911
+
912
+ INPUT:
913
+
914
+ - ``t`` -- tuple, representing basis element in the current basis
915
+
916
+ OUTPUT: string
917
+
918
+ The string depends on the basis over which the element is defined.
919
+
920
+ EXAMPLES::
921
+
922
+ sage: A7 = SteenrodAlgebra(7)
923
+ sage: A7._latex_term(((0, 3), (2,2)))
924
+ 'Q_{0} Q_{3} \\mathcal{P}(2,2)'
925
+ sage: x = A7.Q(0,3) * A7.P(2,2)
926
+ sage: x._latex_() # indirect doctest
927
+ 'Q_{0} Q_{3} \\mathcal{P}(2,2)'
928
+ sage: latex(x)
929
+ Q_{0} Q_{3} \mathcal{P}(2,2)
930
+ sage: b = Sq(0,2)
931
+ sage: b.change_basis('adem')._latex_()
932
+ '\\text{Sq}^{4} \\text{Sq}^{2} + \\text{Sq}^{5} \\text{Sq}^{1} +
933
+ \\text{Sq}^{6}'
934
+ sage: b.change_basis('woody')._latex_()
935
+ '\\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{1} + \\text{Sq}^{6} +
936
+ \\text{Sq}^{4} \\text{Sq}^{2}'
937
+ sage: SteenrodAlgebra(2, 'arnona')(b)._latex_()
938
+ 'X^{1}_{1} X^{2}_{2} + X^{2}_{1}'
939
+ sage: SteenrodAlgebra(p=3, basis='serre-cartan').Q(0)._latex_()
940
+ '\\beta'
941
+ sage: latex(Sq(2).change_basis('adem').coproduct())
942
+ 1 \otimes \text{Sq}^{2} + \text{Sq}^{1} \otimes \text{Sq}^{1} + \text{Sq}^{2} \otimes 1
943
+ sage: latex(SteenrodAlgebra(basis='pst').P(0,0,2))
944
+ P^{1}_{3}
945
+ """
946
+ import re
947
+ s = self._repr_term(t)
948
+ s = re.sub(r"\^([0-9]*)", r"^{\1}", s)
949
+ s = re.sub("_([0-9,]*)", r"_{\1}", s)
950
+ s = s.replace("Sq", "\\text{Sq}")
951
+ if not self.basis_name().find('pst') >= 0:
952
+ s = s.replace("P", "\\mathcal{P}")
953
+ s = s.replace("beta", "\\beta")
954
+ return s
955
+
956
+ def profile(self, i, component=0):
957
+ r"""
958
+ Profile function for this algebra.
959
+
960
+ INPUT:
961
+
962
+ - ``i`` -- integer
963
+ - ``component`` -- either 0 or 1 (default: 0)
964
+
965
+ OUTPUT: integer or `\infty`
966
+
967
+ See the documentation for
968
+ :mod:`sage.algebras.steenrod.steenrod_algebra` and
969
+ :func:`SteenrodAlgebra` for information on profile functions.
970
+
971
+ This applies the profile function to the integer `i`. Thus
972
+ when `p=2`, `i` must be a positive integer. When `p` is odd,
973
+ there are two profile functions, `e` and `k` (in the notation
974
+ of the aforementioned documentation), corresponding,
975
+ respectively to ``component=0`` and ``component=1``. So when
976
+ `p` is odd and ``component`` is 0, `i` must be positive, while
977
+ when ``component`` is 1, `i` must be nonnegative.
978
+
979
+ EXAMPLES::
980
+
981
+ sage: SteenrodAlgebra().profile(3)
982
+ +Infinity
983
+ sage: SteenrodAlgebra(profile=[3,2,1]).profile(1)
984
+ 3
985
+ sage: SteenrodAlgebra(profile=[3,2,1]).profile(2)
986
+ 2
987
+
988
+ When the profile is specified by a list, the default behavior
989
+ is to return zero values outside the range of the list. This
990
+ can be overridden if the algebra is created with an infinite
991
+ ``truncation_type``::
992
+
993
+ sage: SteenrodAlgebra(profile=[3,2,1]).profile(9)
994
+ 0
995
+ sage: SteenrodAlgebra(profile=[3,2,1], truncation_type=Infinity).profile(9)
996
+ +Infinity
997
+
998
+ sage: B = SteenrodAlgebra(p=3, profile=(lambda n: n, lambda n: 1))
999
+ sage: B.profile(3)
1000
+ 3
1001
+ sage: B.profile(3, component=1)
1002
+ 1
1003
+
1004
+ sage: EA = SteenrodAlgebra(generic=True, profile=(lambda n: n, lambda n: 1))
1005
+ sage: EA.profile(4)
1006
+ 4
1007
+ sage: EA.profile(2, component=1)
1008
+ 1
1009
+ """
1010
+ # determine the tuple t to use
1011
+ if not self._generic:
1012
+ t = self._profile
1013
+ elif component == 0:
1014
+ t = self._profile[0]
1015
+ else:
1016
+ t = self._profile[1]
1017
+ # case 1: exponents of the xi's
1018
+ if not self._generic or component == 0:
1019
+ if i <= 0:
1020
+ return 0
1021
+ try:
1022
+ return t[i-1]
1023
+ except IndexError:
1024
+ return self._truncation_type
1025
+ else:
1026
+ # case 2: exponents of the tau's
1027
+ if i < 0:
1028
+ return 1
1029
+ try:
1030
+ return t[i]
1031
+ except IndexError:
1032
+ if self._truncation_type > 0:
1033
+ return 2
1034
+ else:
1035
+ return 1
1036
+
1037
+ def homogeneous_component(self, n):
1038
+ """
1039
+ Return the `n`-th homogeneous piece of the Steenrod algebra.
1040
+
1041
+ INPUT:
1042
+
1043
+ - ``n`` -- integer
1044
+
1045
+ OUTPUT: a vector space spanned by the basis for this algebra in dimension `n`
1046
+
1047
+ EXAMPLES::
1048
+
1049
+ sage: A = SteenrodAlgebra()
1050
+ sage: A.homogeneous_component(4)
1051
+ Vector space spanned by (Sq(1,1), Sq(4)) over Finite Field of size 2
1052
+ sage: SteenrodAlgebra(profile=[2,1,0]).homogeneous_component(4)
1053
+ Vector space spanned by (Sq(1,1),) over Finite Field of size 2
1054
+
1055
+ The notation A[n] may also be used::
1056
+
1057
+ sage: A[5]
1058
+ Vector space spanned by (Sq(2,1), Sq(5)) over Finite Field of size 2
1059
+ sage: SteenrodAlgebra(basis='wall')[4]
1060
+ Vector space spanned by (Q^1_0 Q^0_0, Q^2_2) over Finite Field of size 2
1061
+ sage: SteenrodAlgebra(p=5)[17]
1062
+ Vector space spanned by (Q_1 P(1), Q_0 P(2)) over Finite Field of size 5
1063
+
1064
+ Note that A[n] is just a vector space, not a Hopf algebra, so
1065
+ its elements don't have products, coproducts, or antipodes
1066
+ defined on them. If you want to use operations like this on
1067
+ elements of some A[n], then convert them back to elements of A::
1068
+
1069
+ sage: sorted(A[5].basis())
1070
+ [milnor[(2, 1)], milnor[(5,)]]
1071
+ sage: a = list(A[5].basis())[1]
1072
+ sage: a # not in A, doesn't print like an element of A
1073
+ milnor[(5,)]
1074
+ sage: A(a) # in A
1075
+ Sq(5)
1076
+ sage: A(a) * A(a)
1077
+ Sq(7,1)
1078
+ sage: a * A(a) # only need to convert one factor
1079
+ Sq(7,1)
1080
+ sage: a.antipode() # not defined
1081
+ Traceback (most recent call last):
1082
+ ...
1083
+ AttributeError: 'CombinatorialFreeModule_with_category.element_class' object has no attribute 'antipode'...
1084
+ sage: A(a).antipode() # convert to elt of A, then compute antipode
1085
+ Sq(2,1) + Sq(5)
1086
+
1087
+ sage: G = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]], basis='pst')
1088
+
1089
+ TESTS:
1090
+
1091
+ The following sort of thing is also tested by the function
1092
+ :func:`steenrod_basis_error_check
1093
+ <sage.algebras.steenrod.steenrod_algebra_bases.steenrod_basis_error_check>`::
1094
+
1095
+ sage: H = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]])
1096
+ sage: G = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]], basis='pst')
1097
+ sage: max([H[n].dimension() - G[n].dimension() for n in range(100)])
1098
+ 0
1099
+ """
1100
+ from sage.rings.finite_rings.finite_field_constructor import GF
1101
+ basis = self._basis_fcn(n)
1102
+ M = CombinatorialFreeModule(GF(self.prime()), basis,
1103
+ element_class=self.Element,
1104
+ prefix=self._basis_name)
1105
+ M._name = "Vector space spanned by %s" % (tuple(self.monomial(a) for a in basis),)
1106
+ return M
1107
+
1108
+ __getitem__ = homogeneous_component
1109
+
1110
+ def one_basis(self):
1111
+ """
1112
+ The index of the element 1 in the basis for the Steenrod algebra.
1113
+
1114
+ EXAMPLES::
1115
+
1116
+ sage: SteenrodAlgebra(p=2).one_basis()
1117
+ ()
1118
+ sage: SteenrodAlgebra(p=7).one_basis()
1119
+ ((), ())
1120
+ """
1121
+ basis = self.basis_name()
1122
+ if basis == 'serre-cartan' or basis == 'arnonc':
1123
+ return (0,)
1124
+ if not self._generic:
1125
+ return ()
1126
+ return ((), ())
1127
+
1128
+ def product_on_basis(self, t1, t2):
1129
+ """
1130
+ The product of two basis elements of this algebra.
1131
+
1132
+ INPUT:
1133
+
1134
+ - ``t1``, ``t2`` -- tuples, the indices of two basis elements of self
1135
+
1136
+ OUTPUT:
1137
+
1138
+ the product of the two corresponding basis elements,
1139
+ as an element of self
1140
+
1141
+ ALGORITHM: If the two elements are represented in the Milnor
1142
+ basis, use Milnor multiplication as implemented in
1143
+ :mod:`sage.algebras.steenrod.steenrod_algebra_mult`. If the two
1144
+ elements are represented in the Serre-Cartan basis, then
1145
+ multiply them using Adem relations (also implemented in
1146
+ :mod:`sage.algebras.steenrod.steenrod_algebra_mult`). This
1147
+ provides a good way of checking work -- multiply Milnor
1148
+ elements, then convert them to Adem elements and multiply
1149
+ those, and see if the answers correspond.
1150
+
1151
+ If the two elements are represented in some other basis, then
1152
+ convert them both to the Milnor basis and multiply.
1153
+
1154
+ EXAMPLES::
1155
+
1156
+ sage: Milnor = SteenrodAlgebra()
1157
+ sage: Milnor.product_on_basis((2,), (2,))
1158
+ Sq(1,1)
1159
+ sage: Adem = SteenrodAlgebra(basis='adem')
1160
+ sage: Adem.Sq(2) * Adem.Sq(2) # indirect doctest
1161
+ Sq^3 Sq^1
1162
+
1163
+ When multiplying elements from different bases, the left-hand
1164
+ factor determines the form of the output::
1165
+
1166
+ sage: Adem.Sq(2) * Milnor.Sq(2)
1167
+ Sq^3 Sq^1
1168
+ sage: Milnor.Sq(2) * Adem.Sq(2)
1169
+ Sq(1,1)
1170
+
1171
+ TESTS::
1172
+
1173
+ sage: all(Adem(Milnor.Sq(n) ** 3)._repr_() == (Adem.Sq(n) ** 3)._repr_() for n in range(10))
1174
+ True
1175
+ sage: Wall = SteenrodAlgebra(basis='wall')
1176
+ sage: Wall(Adem.Sq(4,4) * Milnor.Sq(4)) == Adem(Wall.Sq(4,4) * Milnor.Sq(4))
1177
+ True
1178
+
1179
+ sage: A3 = SteenrodAlgebra(p=3, basis='adem')
1180
+ sage: M3 = SteenrodAlgebra(p=3, basis='milnor')
1181
+ sage: all(A3(M3.P(n) * M3.Q(0) * M3.P(n))._repr_() == (A3.P(n) * A3.Q(0) * A3.P(n))._repr_() for n in range(5))
1182
+ True
1183
+
1184
+ sage: EA = SteenrodAlgebra(generic=True)
1185
+ sage: EA.product_on_basis(((1, 3), (2, 1)), ((2, ), (0, 0, 1)))
1186
+ Q_1 Q_2 Q_3 P(2,1,1)
1187
+
1188
+ sage: EA2 = SteenrodAlgebra(basis='serre-cartan', generic=True)
1189
+ sage: EA2.product_on_basis((1, 2, 0, 1, 0), (1, 2, 0, 1, 0))
1190
+ beta P^4 P^2 beta + beta P^5 beta P^1
1191
+ """
1192
+ p = self.prime()
1193
+ basis = self.basis_name()
1194
+ if basis == 'milnor':
1195
+ if not self._generic:
1196
+ from .steenrod_algebra_mult import milnor_multiplication
1197
+ d = milnor_multiplication(t1, t2)
1198
+ else:
1199
+ from .steenrod_algebra_mult import milnor_multiplication_odd
1200
+ d = milnor_multiplication_odd(t1, t2, p)
1201
+ return self._from_dict(d, coerce=True)
1202
+ elif basis == 'serre-cartan':
1203
+ from .steenrod_algebra_mult import make_mono_admissible
1204
+ if self._generic:
1205
+ # make sure output has an odd number of terms. if both t1
1206
+ # and t2 have an odd number, concatenate them, adding the
1207
+ # middle term...
1208
+ #
1209
+ # if either t1 or t2 has an even number of terms, append a
1210
+ # 0.
1211
+ if (len(t1) % 2) == 0:
1212
+ t1 = t1 + (0,)
1213
+ if (len(t2) % 2) == 0:
1214
+ t2 = t2 + (0,)
1215
+ if t1[-1] + t2[0] == 2:
1216
+ return self.zero()
1217
+ mono = t1[:-1] + (t1[-1] + t2[0],) + t2[1:]
1218
+ d = make_mono_admissible(mono, p, generic=self._generic)
1219
+ else: # p=2
1220
+ mono = t1 + t2
1221
+ while len(mono) > 1 and mono[-1] == 0:
1222
+ mono = mono[:-1]
1223
+ d = make_mono_admissible(mono, generic=self._generic)
1224
+ return self._from_dict(d, coerce=True)
1225
+ else:
1226
+ x = self({t1: 1})
1227
+ y = self({t2: 1})
1228
+ A = SteenrodAlgebra(basis='milnor', p=p, generic=self._generic)
1229
+ return self(A(x) * A(y))
1230
+
1231
+ def coproduct_on_basis(self, t, algorithm=None):
1232
+ r"""
1233
+ The coproduct of a basis element of this algebra.
1234
+
1235
+ INPUT:
1236
+
1237
+ - ``t`` -- tuple, the index of a basis element of self
1238
+
1239
+ - ``algorithm`` -- ``None`` or a string, either 'milnor' or
1240
+ 'serre-cartan' (or anything which will be converted to one
1241
+ of these by the function :func:`get_basis_name
1242
+ <sage.algebras.steenrod.steenrod_algebra_misc.get_basis_name>`.
1243
+ If ``None``, default to 'milnor' unless current basis is
1244
+ 'serre-cartan', in which case use 'serre-cartan'.
1245
+
1246
+ ALGORITHM: The coproduct on a Milnor basis element `P(n_1,
1247
+ n_2, ...)` is `\sum P(i_1, i_2, ...) \otimes P(j_1, j_2,
1248
+ ...)`, summed over all `i_k + j_k = n_k` for each `k`. At odd
1249
+ primes, each element `Q_n` is primitive: its coproduct is `Q_n
1250
+ \otimes 1 + 1 \otimes Q_n`.
1251
+
1252
+ One can deduce a coproduct formula for the Serre-Cartan basis
1253
+ from this: the coproduct on each `P^n` is `\sum P^i \otimes
1254
+ P^{n-i}` and at odd primes `\beta` is primitive. Since the
1255
+ coproduct is an algebra map, one can then compute the
1256
+ coproduct on any Serre-Cartan basis element.
1257
+
1258
+ Which of these methods is used is controlled by whether
1259
+ ``algorithm`` is 'milnor' or 'serre-cartan'.
1260
+
1261
+ OUTPUT:
1262
+
1263
+ the coproduct of the corresponding basis element,
1264
+ as an element of ``self`` tensor ``self``.
1265
+
1266
+ EXAMPLES::
1267
+
1268
+ sage: A = SteenrodAlgebra()
1269
+ sage: A.coproduct_on_basis((3,))
1270
+ 1 # Sq(3) + Sq(1) # Sq(2) + Sq(2) # Sq(1) + Sq(3) # 1
1271
+
1272
+ TESTS::
1273
+
1274
+ sage: all(A.coproduct_on_basis((n,1), algorithm='milnor') == A.coproduct_on_basis((n,1), algorithm='adem') for n in range(9)) # long time
1275
+ True
1276
+ sage: A7 = SteenrodAlgebra(p=7, basis='adem')
1277
+ sage: all(A7.coproduct_on_basis((0,n,1), algorithm='milnor') == A7.coproduct_on_basis((0,n,1), algorithm='adem') for n in range(9)) # long time
1278
+ True
1279
+ """
1280
+ def coprod_list(t):
1281
+ """
1282
+ If t = (n0, n1, ...), then return list of terms (i0, i1,
1283
+ ...) where ik <= nk for each k. From each such term, can
1284
+ recover the second factor in the coproduct.
1285
+ """
1286
+ if len(t) == 0:
1287
+ return [()]
1288
+ if len(t) == 1:
1289
+ return [[a] for a in range(t[0] + 1)]
1290
+ ans = []
1291
+ for i in range(t[0] + 1):
1292
+ ans.extend([[i] + x for x in coprod_list(t[1:])])
1293
+ return ans
1294
+
1295
+ from .steenrod_algebra_misc import get_basis_name
1296
+ p = self.prime()
1297
+ basis = self.basis_name()
1298
+ if algorithm is None:
1299
+ if basis == 'serre-cartan':
1300
+ algorithm = 'serre-cartan'
1301
+ else:
1302
+ algorithm = 'milnor'
1303
+ else:
1304
+ algorithm = get_basis_name(algorithm, p, generic=self._generic)
1305
+ if basis == algorithm:
1306
+ if basis == 'milnor':
1307
+ if not self._generic:
1308
+ left = coprod_list(t)
1309
+ right = [[x - y for x, y in zip(t, m)] for m in left]
1310
+ old = list(left)
1311
+ left = []
1312
+ # trim trailing zeros:
1313
+ for a in old:
1314
+ while a and a[-1] == 0:
1315
+ a = a[:-1]
1316
+ left.append(tuple(a))
1317
+ old = list(right)
1318
+ right = []
1319
+ for a in old:
1320
+ while a and a[-1] == 0:
1321
+ a = a[:-1]
1322
+ right.append(tuple(a))
1323
+ tens = dict.fromkeys(zip(left, right), 1)
1324
+ return self.tensor_square()._from_dict(tens, coerce=True)
1325
+ else: # p odd
1326
+ from sage.combinat.permutation import Permutation
1327
+ from .steenrod_algebra_misc import convert_perm
1328
+ from sage.sets.set import Set
1329
+ left_p = coprod_list(t[1])
1330
+ right_p = [[x - y for x, y in zip(t[1], m)] for m in left_p]
1331
+ old = list(left_p)
1332
+ left_p = []
1333
+ # trim trailing zeros:
1334
+ for a in old:
1335
+ while a and a[-1] == 0:
1336
+ a = a[:-1]
1337
+ left_p.append(tuple(a))
1338
+ old = list(right_p)
1339
+ right_p = []
1340
+ for a in old:
1341
+ while a and a[-1] == 0:
1342
+ a = a[:-1]
1343
+ right_p.append(tuple(a))
1344
+ all_q = Set(t[0])
1345
+ tens_q = {}
1346
+ for a in all_q.subsets():
1347
+ left_q = sorted(a)
1348
+ right_q = sorted(all_q - a)
1349
+ sign = Permutation(convert_perm(left_q + right_q)).signature()
1350
+ tens_q[(tuple(left_q), tuple(right_q))] = sign
1351
+ tens = {((q[0], l), (q[1], r)): tq
1352
+ for l, r in zip(left_p, right_p)
1353
+ for q, tq in tens_q.items()}
1354
+ return self.tensor_square()._from_dict(tens, coerce=True)
1355
+ elif basis == 'serre-cartan':
1356
+ result = self.tensor_square().one()
1357
+ if not self._generic:
1358
+ for n in t:
1359
+ s = self.tensor_square().zero()
1360
+ for i in range(n + 1):
1361
+ s += tensor((self.Sq(i), self.Sq(n-i)))
1362
+ result = result * s
1363
+ return result
1364
+ else:
1365
+ bockstein = True
1366
+ for n in t:
1367
+ if bockstein:
1368
+ if n != 0:
1369
+ s = tensor((self.Q(0), self.one())) + tensor((self.one(), self.Q(0)))
1370
+ else:
1371
+ s = self.tensor_square().one()
1372
+ bockstein = False
1373
+ else:
1374
+ s = self.tensor_square().zero()
1375
+ for i in range(n + 1):
1376
+ s += tensor((self.P(i), self.P(n-i)))
1377
+ bockstein = True
1378
+ result = result * s
1379
+ return result
1380
+ else:
1381
+ A = SteenrodAlgebra(p=p, basis=algorithm, generic=self._generic)
1382
+ x = A(self._change_basis_on_basis(t, algorithm)).coproduct(algorithm=algorithm)
1383
+ result = []
1384
+ for (a, b), coeff in x:
1385
+ result.append((tensor((A._change_basis_on_basis(a, basis),
1386
+ A._change_basis_on_basis(b, basis))),
1387
+ coeff))
1388
+ return self.tensor_square().linear_combination(result)
1389
+
1390
+ def coproduct(self, x, algorithm='milnor'):
1391
+ r"""
1392
+ Return the coproduct of an element ``x`` of this algebra.
1393
+
1394
+ INPUT:
1395
+
1396
+ - ``x`` -- element of ``self``
1397
+
1398
+ - ``algorithm`` -- ``None`` or a string, either ``'milnor'`` or
1399
+ ``'serre-cartan'`` (or anything which will be converted to one
1400
+ of these by the function :func:`get_basis_name
1401
+ <sage.algebras.steenrod.steenrod_algebra_misc.get_basis_name>`.
1402
+ If ``None``, default to ``'serre-cartan'`` if current basis is
1403
+ ``'serre-cartan'``; otherwise use ``'milnor'``.
1404
+
1405
+ This calls :meth:`coproduct_on_basis` on the summands of ``x``
1406
+ and extends linearly.
1407
+
1408
+ EXAMPLES::
1409
+
1410
+ sage: SteenrodAlgebra().Sq(3).coproduct()
1411
+ 1 # Sq(3) + Sq(1) # Sq(2) + Sq(2) # Sq(1) + Sq(3) # 1
1412
+
1413
+ The element `\text{Sq}(0,1)` is primitive::
1414
+
1415
+ sage: SteenrodAlgebra(basis='adem').Sq(0,1).coproduct()
1416
+ 1 # Sq^2 Sq^1 + 1 # Sq^3 + Sq^2 Sq^1 # 1 + Sq^3 # 1
1417
+ sage: SteenrodAlgebra(basis='pst').Sq(0,1).coproduct()
1418
+ 1 # P^0_2 + P^0_2 # 1
1419
+
1420
+ sage: SteenrodAlgebra(p=3).P(4).coproduct()
1421
+ 1 # P(4) + P(1) # P(3) + P(2) # P(2) + P(3) # P(1) + P(4) # 1
1422
+ sage: SteenrodAlgebra(p=3).P(4).coproduct(algorithm='serre-cartan')
1423
+ 1 # P(4) + P(1) # P(3) + P(2) # P(2) + P(3) # P(1) + P(4) # 1
1424
+ sage: SteenrodAlgebra(p=3, basis='serre-cartan').P(4).coproduct()
1425
+ 1 # P^4 + P^1 # P^3 + P^2 # P^2 + P^3 # P^1 + P^4 # 1
1426
+ sage: SteenrodAlgebra(p=11, profile=((), (2,1,2))).Q(0,2).coproduct()
1427
+ 1 # Q_0 Q_2 + Q_0 # Q_2 + Q_0 Q_2 # 1 + 10*Q_2 # Q_0
1428
+ """
1429
+ # taken from categories.coalgebras_with_basis, then modified
1430
+ # to allow the use of the "algorithm" keyword
1431
+
1432
+ def coprod(x):
1433
+ return self.coproduct_on_basis(x, algorithm)
1434
+ return Hom(self, tensor([self, self]),
1435
+ ModulesWithBasis(self.base_ring()))(on_basis=coprod)(x)
1436
+
1437
+ def antipode_on_basis(self, t):
1438
+ r"""
1439
+ The antipode of a basis element of this algebra.
1440
+
1441
+ INPUT:
1442
+
1443
+ - ``t`` -- tuple, the index of a basis element of ``self``
1444
+
1445
+ OUTPUT:
1446
+
1447
+ the antipode of the corresponding basis element,
1448
+ as an element of ``self``.
1449
+
1450
+ ALGORITHM: according to a result of Milnor's, the antipode of
1451
+ `\text{Sq}(n)` is the sum of all of the Milnor basis elements
1452
+ in dimension `n`. So: convert the element to the Serre-Cartan
1453
+ basis, thus writing it as a sum of products of elements
1454
+ `\text{Sq}(n)`, and use Milnor's formula for the antipode of
1455
+ `\text{Sq}(n)`, together with the fact that the antipode is an
1456
+ antihomomorphism: if we call the antipode `c`, then `c(ab) =
1457
+ c(b) c(a)`.
1458
+
1459
+ At odd primes, a similar method is used: the antipode of
1460
+ `P(n)` is the sum of the Milnor P basis elements in dimension
1461
+ `n*2(p-1)`, multiplied by `(-1)^n`, and the antipode of `\beta
1462
+ = Q_0` is `-Q_0`. So convert to the Serre-Cartan basis, as in
1463
+ the `p = 2` case. Note that in the odd prime case, there is a
1464
+ sign in the antihomomorphism formula:
1465
+ `c(ab) = (-1)^{\deg a \deg b} c(b) c(a)`.
1466
+
1467
+ EXAMPLES::
1468
+
1469
+ sage: A = SteenrodAlgebra()
1470
+ sage: A.antipode_on_basis((4,))
1471
+ Sq(1,1) + Sq(4)
1472
+ sage: A.Sq(4).antipode()
1473
+ Sq(1,1) + Sq(4)
1474
+ sage: Adem = SteenrodAlgebra(basis='adem')
1475
+ sage: Adem.Sq(4).antipode()
1476
+ Sq^3 Sq^1 + Sq^4
1477
+ sage: SteenrodAlgebra(basis='pst').Sq(3).antipode()
1478
+ P^0_1 P^1_1 + P^0_2
1479
+ sage: a = SteenrodAlgebra(basis='wall_long').Sq(10)
1480
+ sage: a.antipode()
1481
+ Sq^1 Sq^2 Sq^4 Sq^1 Sq^2 + Sq^2 Sq^4 Sq^1 Sq^2 Sq^1 + Sq^8 Sq^2
1482
+ sage: a.antipode().antipode() == a
1483
+ True
1484
+
1485
+ sage: SteenrodAlgebra(p=3).P(6).antipode()
1486
+ P(2,1) + P(6)
1487
+ sage: SteenrodAlgebra(p=3).P(6).antipode().antipode()
1488
+ P(6)
1489
+
1490
+ TESTS::
1491
+
1492
+ sage: Milnor = SteenrodAlgebra()
1493
+ sage: all(x.antipode().antipode() == x for x in Milnor.basis(11)) # long time
1494
+ True
1495
+ sage: A5 = SteenrodAlgebra(p=5, basis='adem')
1496
+ sage: all(x.antipode().antipode() == x for x in A5.basis(25))
1497
+ True
1498
+ sage: H = SteenrodAlgebra(profile=[2,2,1])
1499
+ sage: H.Sq(1,2).antipode() in H
1500
+ True
1501
+
1502
+ sage: Q = A5.Q
1503
+ sage: (Q(0) * Q(1)).antipode() == - Q(1).antipode() * Q(0).antipode()
1504
+ True
1505
+ """
1506
+ p = self.prime()
1507
+ if self.basis_name() == 'serre-cartan':
1508
+ antipode = self.one()
1509
+ if not self._generic:
1510
+ for n in t:
1511
+ antipode = self(sum(SteenrodAlgebra().basis(n))) * antipode
1512
+ else:
1513
+ from sage.misc.functional import is_even
1514
+ for index, n in enumerate(t):
1515
+ if is_even(index):
1516
+ if n != 0:
1517
+ antipode = -self.Q(0) * antipode * (-1)**antipode.degree()
1518
+ else:
1519
+ B = SteenrodAlgebra(p=p, generic=self._generic).basis(n * 2 * (p-1))
1520
+ s = self(0)
1521
+ for b in B:
1522
+ if len(b.leading_support()[0]) == 0:
1523
+ s += self(b)
1524
+ antipode = (-1)**n * s * antipode
1525
+ return antipode
1526
+ return self(self._change_basis_on_basis(t, 'serre-cartan').antipode())
1527
+
1528
+ def counit_on_basis(self, t):
1529
+ """
1530
+ The counit sends all elements of positive degree to zero.
1531
+
1532
+ INPUT:
1533
+
1534
+ - ``t`` -- tuple, the index of a basis element of ``self``
1535
+
1536
+ EXAMPLES::
1537
+
1538
+ sage: A2 = SteenrodAlgebra(p=2)
1539
+ sage: A2.counit_on_basis(())
1540
+ 1
1541
+ sage: A2.counit_on_basis((0,0,1))
1542
+ 0
1543
+ sage: parent(A2.counit_on_basis((0,0,1)))
1544
+ Finite Field of size 2
1545
+ sage: A3 = SteenrodAlgebra(p=3)
1546
+ sage: A3.counit_on_basis(((1,2,3), (1,1,1)))
1547
+ 0
1548
+ sage: A3.counit_on_basis(((), ()))
1549
+ 1
1550
+ sage: A3.counit(A3.P(10,5))
1551
+ 0
1552
+ sage: A3.counit(A3.P(0))
1553
+ 1
1554
+ """
1555
+ if t != () and t != ((), ()):
1556
+ return self.base_ring().zero()
1557
+ else:
1558
+ return self.base_ring().one()
1559
+
1560
+ def _milnor_on_basis(self, t):
1561
+ r"""
1562
+ Convert the tuple ``t`` in the current basis to an element in the
1563
+ Milnor basis.
1564
+
1565
+ INPUT:
1566
+
1567
+ - ``t`` -- tuple, representing basis element in the current basis
1568
+
1569
+ OUTPUT: element of the Steenrod algebra with the Milnor basis
1570
+
1571
+ ALGORITHM: there is a simple conversion from each basis to the
1572
+ Milnor basis, so use that. In more detail:
1573
+
1574
+ - If the current basis is the Milnor basis, just return the
1575
+ corresponding element.
1576
+
1577
+ - If the current basis is the Serre-Cartan basis: when `p=2`,
1578
+ the element `\text{Sq}^a` equals the Milnor element
1579
+ `\text{Sq}(a)`; when `p` is odd, `\mathcal{P}^a =
1580
+ \mathcal{P}(a)` and `\beta = Q_0`. Hence for any
1581
+ Serre-Cartan basis element, represent it in the
1582
+ Milnor basis by computing an appropriate product using
1583
+ Milnor multiplication.
1584
+
1585
+ - The same goes for Arnon's C basis, since the elements are
1586
+ monomials in the Steenrod squares.
1587
+
1588
+ - If the current basis is Wood's Y or Z bases, then each basis
1589
+ element is a monomial in the classes `w(m,k) =
1590
+ \text{Sq}^{2^m (2^{k+1}-1)}`. So again, multiply the
1591
+ corresponding Milnor elements together.
1592
+
1593
+ - The Wall basis: each basis element is a monomial in the
1594
+ elements `Q^m_k = Sq(2^k) Sq(2^{k+1}) ... Sq(2^m)`.
1595
+
1596
+ - Arnon's A basis: each basis element is a monomial in the
1597
+ elements `X^m_k = Sq(2^m) ... Sq(2^{k+1}) Sq(2^k)`.
1598
+
1599
+ - The `P^s_t` bases: when `p=2`, each basis element is a
1600
+ monomial in the elements `P^s_t`. When `p` is odd, each
1601
+ basis element is a product of elements `Q_i` and a monomial
1602
+ in the elements `(P^s_t)^n` where `0 < n < p`.
1603
+
1604
+ - The commutator bases: when `p=2`, each basis element is a
1605
+ monomial in the iterated commutators `c_{i,j}`, defined by
1606
+ `c_{i,1} = \text{Sq}(2^i)` and `c_{i,j} = [c_{i,j-1},
1607
+ \text{Sq}(2^{i+j-1})]`. When `p` is odd, each basis element
1608
+ is a product of elements `Q_i` and a monomial in the
1609
+ elements `c_{i,j}^n` where `0 < n < p`, `c_{i,1} =
1610
+ P(p^i)` and `c_{i,j} = [P(p^{i+j-1}), c_{i,j-1}]`.
1611
+
1612
+ EXAMPLES::
1613
+
1614
+ sage: Adem = SteenrodAlgebra(basis='serre-cartan')
1615
+ sage: Adem._milnor_on_basis((2,1)) # Sq^2 Sq^1
1616
+ Sq(0,1) + Sq(3)
1617
+ sage: Pst = SteenrodAlgebra(basis='pst')
1618
+ sage: Pst._milnor_on_basis(((0,1), (1,1), (2,1)))
1619
+ Sq(7)
1620
+ """
1621
+ basis = self.basis_name()
1622
+ p = self.prime()
1623
+ A = SteenrodAlgebra(p=p, generic=self._generic)
1624
+ # milnor
1625
+ if basis == 'milnor':
1626
+ return A({t: 1})
1627
+
1628
+ ans = A(1)
1629
+ # serre-cartan, arnonc
1630
+ if not self._generic and (basis == 'serre-cartan' or basis == 'arnonc'):
1631
+ for j in t:
1632
+ ans = ans * A.Sq(j)
1633
+
1634
+ elif self._generic and basis == 'serre-cartan':
1635
+ bockstein = True
1636
+ for j in t:
1637
+ if bockstein:
1638
+ if j != 0:
1639
+ ans = ans * A.Q(0)
1640
+ bockstein = False
1641
+ else:
1642
+ ans = ans * A.P(j)
1643
+ bockstein = True
1644
+ # wood_y:
1645
+ elif basis == 'woody' or basis == 'woodz':
1646
+ # each entry in t is a pair (m,k), corresponding to w(m,k), defined by
1647
+ # `w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}`.
1648
+ for (m, k) in t:
1649
+ ans = ans * A.Sq(2**m * (2**(k+1) - 1))
1650
+
1651
+ # wall[_long]
1652
+ elif basis.find('wall') >= 0:
1653
+ # each entry in t is a pair (m,k), corresponding to Q^m_k, defined by
1654
+ # `Q^m_k = Sq(2^k) Sq(2^{k+1}) ... Sq(2^m)`.
1655
+ for (m, k) in t:
1656
+ exponent = 2**k
1657
+ ans = ans * A.Sq(exponent)
1658
+ for i in range(m-k):
1659
+ exponent = exponent * 2
1660
+ ans = ans * A.Sq(exponent)
1661
+
1662
+ # pst...
1663
+ elif basis.find('pst') >= 0:
1664
+ if not self._generic:
1665
+ # each entry in t is a pair (i,j), corresponding to P^i_j
1666
+ for (i, j) in t:
1667
+ ans = ans * A.pst(i, j)
1668
+ else:
1669
+ # t = (Q, P) where Q is the tuple of Q_i's, and P is a
1670
+ # tuple with entries of the form ((i,j), n),
1671
+ # corresponding to (P^i_j)^n
1672
+ if t[0]:
1673
+ ans = ans * A.Q(*t[0])
1674
+ for ((i, j), n) in t[1]:
1675
+ ans = ans * (A.pst(i, j))**n
1676
+
1677
+ # arnona[_long]
1678
+ elif basis.find('arnona') >= 0:
1679
+ # each entry in t is a pair (m,k), corresponding to X^m_k, defined by
1680
+ # `X^m_k = Sq(2^m) ... Sq(2^{k+1}) Sq(2^k)`
1681
+ for (m, k) in t:
1682
+ exponent = 2**k
1683
+ X = A.Sq(exponent)
1684
+ for i in range(m-k):
1685
+ exponent = exponent * 2
1686
+ X = A.Sq(exponent) * X
1687
+ ans = ans * X
1688
+
1689
+ # comm...[_long]
1690
+ elif basis.find('comm') >= 0:
1691
+ if not self._generic:
1692
+ # each entry in t is a pair (i,j), corresponding to
1693
+ # c_{i,j}, the iterated commutator defined by c_{i,1}
1694
+ # = Sq(2^i) and c_{i,j} = [c_{i,j-1}, Sq(2^{i+j-1})].
1695
+ for (i, j) in t:
1696
+ comm = A.Sq(2**i)
1697
+ for k in range(2, j+1):
1698
+ y = A.Sq(2**(i+k-1))
1699
+ comm = comm * y + y * comm
1700
+ ans = ans * comm
1701
+ else:
1702
+ # t = (Q, P) where Q is the tuple of Q_i's, and P is a
1703
+ # tuple with entries of the form ((i,j), n),
1704
+ # corresponding to (c_{i,j})^n. Here c_{i,j} is the
1705
+ # iterated commutator defined by c_{i,1} = P(p^i) and
1706
+ # c_{i,j} = [P(p^{i+j-1}), c_{i,j-1}].
1707
+ if t[0]:
1708
+ ans = ans * A.Q(*t[0])
1709
+ for ((i, j), n) in t[1]:
1710
+ comm = A.P(p**i)
1711
+ for k in range(2, j+1):
1712
+ y = A.P(p**(i+k-1))
1713
+ comm = y * comm - comm * y
1714
+ ans = ans * comm**n
1715
+ return ans
1716
+
1717
+ @lazy_attribute
1718
+ def milnor(self):
1719
+ """
1720
+ Convert an element of this algebra to the Milnor basis.
1721
+
1722
+ INPUT:
1723
+
1724
+ - ``x`` -- an element of this algebra
1725
+
1726
+ OUTPUT: x converted to the Milnor basis
1727
+
1728
+ ALGORITHM: use the method ``_milnor_on_basis`` and linearity.
1729
+
1730
+ EXAMPLES::
1731
+
1732
+ sage: Adem = SteenrodAlgebra(basis='adem')
1733
+ sage: a = Adem.Sq(2) * Adem.Sq(1)
1734
+ sage: Adem.milnor(a)
1735
+ Sq(0,1) + Sq(3)
1736
+ """
1737
+ A = SteenrodAlgebra(p=self.prime(), basis='milnor', generic=self._generic)
1738
+ return self._module_morphism(self._milnor_on_basis, codomain=A)
1739
+
1740
+ def _change_basis_on_basis(self, t, basis='milnor'):
1741
+ """
1742
+ Convert the tuple t to the named basis.
1743
+
1744
+ INPUT:
1745
+
1746
+ - ``t`` -- tuple, representing basis element in the current basis
1747
+
1748
+ - ``basis`` -- string, the basis to which to convert, optional
1749
+ (default: ``'milnor'``)
1750
+
1751
+ OUTPUT: an element of the Steenrod algebra with basis ``basis``
1752
+
1753
+ ALGORITHM: it's straightforward to convert to the Milnor basis
1754
+ (using :meth:`milnor` or :meth:`_milnor_on_basis`), so it's
1755
+ straightforward to produce a matrix representing this
1756
+ conversion in any degree. The function
1757
+ :func:`convert_from_milnor_matrix
1758
+ <steenrod_algebra_bases.convert_from_milnor_matrix>` provides
1759
+ the inverse operation.
1760
+
1761
+ So: convert from the current basis to the Milnor basis, then
1762
+ from the Milnor basis to the new basis.
1763
+
1764
+ EXAMPLES::
1765
+
1766
+ sage: Adem = SteenrodAlgebra(basis='adem')
1767
+ sage: a = Adem({(2,1): 1}); a
1768
+ Sq^2 Sq^1
1769
+ sage: a.change_basis('adem') # indirect doctest
1770
+ Sq^2 Sq^1
1771
+ sage: a.change_basis('milnor')
1772
+ Sq(0,1) + Sq(3)
1773
+ sage: a.change_basis('pst')
1774
+ P^0_1 P^1_1 + P^0_2
1775
+ sage: a.change_basis('milnor').change_basis('adem').change_basis('adem')
1776
+ Sq^2 Sq^1
1777
+ sage: a.change_basis('wall') == a.change_basis('woody')
1778
+ True
1779
+
1780
+ TESTS::
1781
+
1782
+ sage: a = sum(SteenrodAlgebra(basis='comm').basis(10))
1783
+ sage: a.change_basis('adem').change_basis('wall').change_basis('comm')._repr_() == a._repr_()
1784
+ True
1785
+ sage: a.change_basis('pst').change_basis('milnor').change_basis('comm')._repr_() == a._repr_()
1786
+ True
1787
+ sage: a.change_basis('woody').change_basis('arnona').change_basis('comm')._repr_() == a._repr_()
1788
+ True
1789
+
1790
+ sage: b = sum(SteenrodAlgebra(p=3).basis(41))
1791
+ sage: b.change_basis('adem').change_basis('adem').change_basis('milnor')._repr_() == b._repr_()
1792
+ True
1793
+
1794
+ sage: SteenrodAlgebra(generic=True).P(0,2).change_basis('serre-cartan')
1795
+ P^4 P^2 + P^5 P^1 + P^6
1796
+ """
1797
+ from sage.matrix.constructor import matrix
1798
+ from sage.rings.finite_rings.finite_field_constructor import GF
1799
+ from .steenrod_algebra_bases import steenrod_algebra_basis, \
1800
+ convert_from_milnor_matrix
1801
+ from .steenrod_algebra_misc import get_basis_name
1802
+ basis = get_basis_name(basis, self.prime(), generic=self._generic)
1803
+ if basis == self.basis_name():
1804
+ return self({t: 1})
1805
+ a = self._milnor_on_basis(t)
1806
+ if basis == 'milnor':
1807
+ return a
1808
+ d = a.monomial_coefficients()
1809
+ p = self.prime()
1810
+ deg = a.degree()
1811
+ A = SteenrodAlgebra(basis=basis, p=p, generic=self._generic)
1812
+ if deg == 0:
1813
+ return A(a.leading_coefficient())
1814
+ Bnew = steenrod_algebra_basis(deg, basis, p, generic=self._generic)
1815
+ Bmil = steenrod_algebra_basis(deg, 'milnor', p, generic=self._generic)
1816
+ v = [d.get(a, 0) for a in Bmil]
1817
+ out = (matrix(GF(p), 1, len(v), v) *
1818
+ convert_from_milnor_matrix(deg, basis, p, generic=self._generic))
1819
+ new_d = dict(zip(Bnew, out[0]))
1820
+ return A(new_d)
1821
+
1822
+ def _change_basis(self, x, basis='milnor'):
1823
+ """
1824
+ Convert an element of this algebra to the specified basis.
1825
+
1826
+ INPUT:
1827
+
1828
+ - ``x`` -- an element of this algebra
1829
+
1830
+ - ``basis`` -- string, the basis to which to convert, optional
1831
+ (default: ``'milnor'``)
1832
+
1833
+ OUTPUT: an element of the Steenrod algebra with basis ``basis``
1834
+
1835
+ ALGORITHM: use :meth:`_change_basis_on_basis` and linearity
1836
+
1837
+ EXAMPLES::
1838
+
1839
+ sage: Adem = SteenrodAlgebra(basis='adem')
1840
+ sage: a = Adem({(2,1): 1}); a
1841
+ Sq^2 Sq^1
1842
+ sage: a.change_basis('adem') # indirect doctest
1843
+ Sq^2 Sq^1
1844
+ sage: a.change_basis('milnor')
1845
+ Sq(0,1) + Sq(3)
1846
+ sage: a.change_basis('pst')
1847
+ P^0_1 P^1_1 + P^0_2
1848
+ """
1849
+ if basis == 'milnor':
1850
+ return x.milnor()
1851
+ A = SteenrodAlgebra(p=self.prime(), basis=basis, generic=self._generic)
1852
+
1853
+ def change(y):
1854
+ return self._change_basis_on_basis(y, basis)
1855
+ f = self._module_morphism(change, codomain=A)
1856
+ return f(x)
1857
+
1858
+ def degree_on_basis(self, t):
1859
+ r"""
1860
+ The degree of the monomial specified by the tuple ``t``.
1861
+
1862
+ INPUT:
1863
+
1864
+ - ``t`` -- tuple, representing basis element in the current basis
1865
+
1866
+ OUTPUT: integer, the degree of the corresponding element
1867
+
1868
+ The degree of `\text{Sq}(i_1,i_2,i_3,...)` is
1869
+
1870
+ .. MATH::
1871
+
1872
+ i_1 + 3i_2 + 7i_3 + ... + (2^k - 1) i_k + ....
1873
+
1874
+ At an odd prime `p`, the degree of `Q_k` is `2p^k - 1` and the
1875
+ degree of `\mathcal{P}(i_1, i_2, ...)` is
1876
+
1877
+ .. MATH::
1878
+
1879
+ \sum_{k \geq 0} 2(p^k - 1) i_k.
1880
+
1881
+ ALGORITHM: Each basis element is represented in terms relevant
1882
+ to the particular basis: 'milnor' basis elements (at the prime
1883
+ 2) are given by tuples ``(a,b,c,...)`` corresponding to the
1884
+ element `\text{Sq}(a,b,c,...)`, while 'pst' basis elements are
1885
+ given by tuples of pairs ``((a, b), (c, d), ...)``,
1886
+ corresponding to the product `P^a_b P^c_d ...`. The other
1887
+ bases have similar descriptions. The degree of each basis
1888
+ element is computed from this data, rather than converting the
1889
+ element to the Milnor basis, for example, and then computing
1890
+ the degree.
1891
+
1892
+ EXAMPLES::
1893
+
1894
+ sage: SteenrodAlgebra().degree_on_basis((0,0,1))
1895
+ 7
1896
+ sage: Sq(7).degree()
1897
+ 7
1898
+
1899
+ sage: A11 = SteenrodAlgebra(p=11)
1900
+ sage: A11.degree_on_basis(((), (1,1)))
1901
+ 260
1902
+ sage: A11.degree_on_basis(((2,), ()))
1903
+ 241
1904
+ """
1905
+ def p_degree(m, mult=1, prime=2):
1906
+ """
1907
+ For m=(n_1, n_2, n_3, ...), Sum_i (mult) * n_i * (p^i - 1)
1908
+ """
1909
+ i = 0
1910
+ deg = 0
1911
+ for n in m:
1912
+ i += 1
1913
+ deg += n*mult*(prime**i - 1)
1914
+ return deg
1915
+
1916
+ def q_degree(m, prime=3):
1917
+ """
1918
+ For m=(n_0, n_1, n_2, ...), Sum_i 2*p^(n_i) - 1
1919
+ """
1920
+ deg = 0
1921
+ for n in m:
1922
+ deg += 2*prime**n - 1
1923
+ return deg
1924
+
1925
+ p = self.prime()
1926
+ basis = self.basis_name()
1927
+ # milnor
1928
+ if basis == 'milnor':
1929
+ if not self._generic:
1930
+ return p_degree(t)
1931
+ else:
1932
+ return q_degree(t[0], prime=p) + p_degree(t[1], prime=p, mult=2)
1933
+ # serre-cartan, arnonc
1934
+ if not self._generic and (basis == 'serre-cartan' or basis == 'arnonc'):
1935
+ return sum(t)
1936
+ if self._generic and basis == 'serre-cartan':
1937
+ bockstein = True
1938
+ n = 0
1939
+ for j in t:
1940
+ if bockstein:
1941
+ if j != 0:
1942
+ n += 1
1943
+ bockstein = False
1944
+ else:
1945
+ n += 2 * j * (p - 1)
1946
+ bockstein = True
1947
+ return n
1948
+
1949
+ # wood_y:
1950
+ if basis == 'woody' or basis == 'woodz':
1951
+ # each entry in t is a pair (m,k), corresponding to w(m,k), defined by
1952
+ # `w(m,k) = \text{Sq}^{2^m (2^{k+1}-1)}`.
1953
+ return sum(2**m * (2**(k+1)-1) for (m, k) in t)
1954
+
1955
+ # wall, arnon_a
1956
+ if basis.find('wall') >= 0 or basis.find('arnona') >= 0:
1957
+ # Wall: each entry in t is a pair (m,k), corresponding to
1958
+ # Q^m_k, defined by `Q^m_k = Sq(2^k) Sq(2^{k+1})
1959
+ # ... Sq(2^m)`.
1960
+ #
1961
+ # Arnon A: each entry in t is a pair (m,k), corresponding
1962
+ # to X^m_k, defined by `X^m_k = Sq(2^m) ... Sq(2^{k+1})
1963
+ # Sq(2^k)`
1964
+ return sum(2**k * (2**(m-k+1)-1) for (m, k) in t)
1965
+
1966
+ # pst, comm
1967
+ if basis.find('pst') >= 0 or basis.find('comm') >= 0:
1968
+ if not self._generic:
1969
+ # Pst: each entry in t is a pair (i,j), corresponding to P^i_j
1970
+ #
1971
+ # Comm: each entry in t is a pair (i,j), corresponding
1972
+ # to c_{i,j}, the iterated commutator defined by
1973
+ # c_{i,1} = Sq(2^i) and c_{i,j} = [c_{i,j-1},
1974
+ # Sq(2^{i+j-1})].
1975
+ return sum(2**m * (2**k - 1) for (m, k) in t)
1976
+ # p odd:
1977
+ #
1978
+ # Pst: have pair (Q, P) where Q is a tuple of Q's, as in
1979
+ # the Milnor basis, and P is a tuple of terms of the form
1980
+ # ((i,j), n), corresponding to (P^i_j)^n.
1981
+ #
1982
+ # Comm: similarly (Q, C) with Q as above and C a tuple
1983
+ # with each entry in t is of the form ((s,t), n),
1984
+ # corresponding to c_{s,t}^n. here c_{s,t} is the
1985
+ # iterated commutator defined by c_{s,1} = P(p^s) and
1986
+ # c_{s,t} = [P(p^{s+t-1}), c_{s,t-1}].
1987
+ q_deg = q_degree(t[0], prime=p)
1988
+ p_deg = sum(2 * n * p**s * (p**t - 1) for ((s, t), n) in t[1])
1989
+ return q_deg + p_deg
1990
+
1991
+ # coercion methods:
1992
+
1993
+ def _coerce_map_from_(self, S):
1994
+ r"""
1995
+ Return ``True`` if there is a coercion from ``S`` to ``self``, ``False``
1996
+ otherwise.
1997
+
1998
+ INPUT:
1999
+
2000
+ - ``S`` -- a Sage object
2001
+
2002
+ The algebras that coerce into the mod p Steenrod algebra are:
2003
+
2004
+ - the mod p Steenrod algebra `A`
2005
+ - its sub-Hopf algebras
2006
+ - its homogeneous components
2007
+ - its base field `GF(p)`
2008
+ - `ZZ`
2009
+
2010
+ Similarly, a sub-Hopf algebra `B` of `A` coerces into another
2011
+ sub-Hopf algebra `C` if and only if the profile function for
2012
+ `B` is less than or equal to that of `C`, pointwise.
2013
+
2014
+ EXAMPLES::
2015
+
2016
+ sage: A = SteenrodAlgebra()
2017
+ sage: A1 = SteenrodAlgebra(profile=[2,1])
2018
+ sage: A2 = SteenrodAlgebra(profile=[3,2,1])
2019
+ sage: B = SteenrodAlgebra(profile=[1,2,1])
2020
+ sage: A._coerce_map_from_(A1)
2021
+ True
2022
+ sage: A2._coerce_map_from_(A1)
2023
+ True
2024
+ sage: A1._coerce_map_from_(A)
2025
+ False
2026
+ sage: A1._coerce_map_from_(B)
2027
+ False
2028
+ sage: B._coerce_map_from_(A1)
2029
+ False
2030
+
2031
+ sage: A._coerce_map_from_(A[12])
2032
+ True
2033
+
2034
+ sage: EA = SteenrodAlgebra(generic=True)
2035
+ sage: A._coerce_map_from_(EA)
2036
+ False
2037
+ sage: EA._coerce_map_from_(A)
2038
+ False
2039
+ sage: EA._coerce_map_from_(EA)
2040
+ True
2041
+
2042
+ sage: A3 = SteenrodAlgebra(p=3)
2043
+ sage: A31 = SteenrodAlgebra(p=3, profile=([1], [2, 2]))
2044
+ sage: B3 = SteenrodAlgebra(p=3, profile=([1, 2, 1], [1]))
2045
+ sage: A3._coerce_map_from_(A31)
2046
+ True
2047
+ sage: A31._coerce_map_from_(A3)
2048
+ False
2049
+ sage: A31._coerce_map_from_(B3)
2050
+ False
2051
+ sage: B3._coerce_map_from_(A31)
2052
+ False
2053
+ """
2054
+ from sage.rings.integer_ring import ZZ
2055
+ from sage.rings.finite_rings.finite_field_constructor import GF
2056
+ from sage.rings.infinity import Infinity
2057
+ p = self.prime()
2058
+ if S == ZZ or S == GF(p):
2059
+ return True
2060
+ if (isinstance(S, SteenrodAlgebra_generic) and p == S.prime() and self._generic == S._generic):
2061
+ # deal with profiles.
2062
+ if not self._generic:
2063
+ self_prec = len(self._profile)
2064
+ S_prec = len(S._profile)
2065
+ return all(self.profile(i) >= S.profile(i)
2066
+ for i in range(1, max(self_prec, S_prec)+1))
2067
+ self_prec = len(self._profile[0])
2068
+ S_prec = len(S._profile[0])
2069
+ return (all(self.profile(i) >= S.profile(i)
2070
+ for i in range(1, max(self_prec, S_prec)+1))
2071
+ and all(self.profile(i, 1) >= S.profile(i, 1)
2072
+ for i in range(1, max(self_prec, S_prec)+1)))
2073
+ if (isinstance(S, CombinatorialFreeModule)
2074
+ and S.dimension() < Infinity and p == S.base_ring().characteristic()):
2075
+ from .steenrod_algebra_misc import get_basis_name
2076
+ try:
2077
+ get_basis_name(S.prefix(), S.base_ring().characteristic())
2078
+ # return all(a in self for a in S.basis())
2079
+ return True
2080
+ except ValueError:
2081
+ return False
2082
+ return False
2083
+
2084
+ def _element_constructor_(self, x):
2085
+ r"""
2086
+ Try to turn ``x`` into an element of ``self``.
2087
+
2088
+ INPUT:
2089
+
2090
+ - ``x`` -- an element of some Steenrod algebra or an element of
2091
+ `\ZZ` or `\GF{p}` or a dict
2092
+
2093
+ OUTPUT: ``x`` as a member of ``self``
2094
+
2095
+ If ``x`` is a dict, then call :meth:`_from_dict` on it,
2096
+ coercing the coefficients into the base field. That is, treat
2097
+ it as having entries of the form ``tuple: coeff``, where
2098
+ ``tuple`` is a tuple representing a basis element and
2099
+ ``coeff`` is the coefficient of that element.
2100
+
2101
+ EXAMPLES::
2102
+
2103
+ sage: A1 = SteenrodAlgebra(profile=[2,1])
2104
+ sage: A1(Sq(2)) # indirect doctest
2105
+ Sq(2)
2106
+ sage: A1._element_constructor_(Sq(2))
2107
+ Sq(2)
2108
+ sage: A1(3) # map integer into A1
2109
+ 1
2110
+ sage: A1._element_constructor_(Sq(4)) # Sq(4) not in A1
2111
+ Traceback (most recent call last):
2112
+ ...
2113
+ ValueError: element does not lie in this Steenrod algebra
2114
+ sage: A1({(2,): 1, (1,): 13})
2115
+ Sq(1) + Sq(2)
2116
+ """
2117
+ from sage.rings.integer_ring import ZZ
2118
+ from sage.rings.finite_rings.finite_field_constructor import GF
2119
+ if x in GF(self.prime()) or x in ZZ:
2120
+ return self.from_base_ring_from_one_basis(x)
2121
+
2122
+ if isinstance(x, dict):
2123
+ A = SteenrodAlgebra(p=self.prime(), basis=self.basis_name(), generic=self._generic)
2124
+ x = A._from_dict(x, coerce=True)
2125
+ if x in self:
2126
+ if x.basis_name() == self.basis_name():
2127
+ if x.parent() is self:
2128
+ return x
2129
+ return self._from_dict(x.monomial_coefficients(), coerce=True)
2130
+ else:
2131
+ a = x.milnor()
2132
+ if self.basis_name() == 'milnor':
2133
+ return a
2134
+ return a.change_basis(self.basis_name())
2135
+ raise ValueError("element does not lie in this Steenrod algebra")
2136
+
2137
+ def __contains__(self, x):
2138
+ r"""
2139
+ Return ``True`` if ``self`` contains `x`.
2140
+
2141
+ EXAMPLES::
2142
+
2143
+ sage: Sq(3,1,1) in SteenrodAlgebra()
2144
+ True
2145
+ sage: Sq(3,1,1) in SteenrodAlgebra(p=5)
2146
+ False
2147
+
2148
+ sage: A1 = SteenrodAlgebra(profile=[2,1])
2149
+ sage: Sq(3) in A1
2150
+ True
2151
+ sage: Sq(4) in A1
2152
+ False
2153
+ sage: Sq(0,2) in A1
2154
+ False
2155
+
2156
+ sage: Sq(3) in SteenrodAlgebra(generic=True)
2157
+ False
2158
+
2159
+ sage: A_3 = SteenrodAlgebra(p=3)
2160
+ sage: B_3 = SteenrodAlgebra(p=3, profile=([1], [2,2,1,1]))
2161
+ sage: A_3.P(2) in B_3
2162
+ True
2163
+ sage: A_3.P(3) in B_3
2164
+ False
2165
+ sage: A_3.Q(1) in B_3
2166
+ True
2167
+ sage: A_3.P(1) * A_3.Q(2) in B_3
2168
+ False
2169
+ """
2170
+ from sage.rings.finite_rings.finite_field_constructor import GF
2171
+ p = self.prime()
2172
+ if x in GF(p):
2173
+ return True
2174
+ if (isinstance(x, self.Element) and x.prime() == p):
2175
+ try:
2176
+ if x.parent()._generic != self._generic:
2177
+ return False
2178
+ except AttributeError:
2179
+ pass
2180
+ A = SteenrodAlgebra(p=p, basis=self.basis_name(),
2181
+ generic=self._generic)
2182
+ if self._has_nontrivial_profile():
2183
+ return all(self._check_profile_on_basis(mono)
2184
+ for mono in A(x).support())
2185
+ return True # trivial profile, so True
2186
+ return False
2187
+
2188
+ def basis(self, d=None):
2189
+ """
2190
+ Return basis for ``self``, either the whole basis or the basis in
2191
+ degree `d`.
2192
+
2193
+ INPUT:
2194
+
2195
+ - ``d`` -- integer or ``None`` (default: ``None``)
2196
+
2197
+ OUTPUT:
2198
+
2199
+ If `d` is ``None``, then return a basis of the algebra.
2200
+ Otherwise, return the basis in degree `d`.
2201
+
2202
+ EXAMPLES::
2203
+
2204
+ sage: A3 = SteenrodAlgebra(3)
2205
+ sage: A3.basis(13)
2206
+ Family (Q_1 P(2), Q_0 P(3))
2207
+ sage: SteenrodAlgebra(2, 'adem').basis(12)
2208
+ Family (Sq^12, Sq^11 Sq^1, Sq^9 Sq^2 Sq^1, Sq^8 Sq^3 Sq^1, Sq^10 Sq^2, Sq^9 Sq^3, Sq^8 Sq^4)
2209
+
2210
+ sage: A = SteenrodAlgebra(profile=[1,2,1])
2211
+ sage: A.basis(2)
2212
+ Family ()
2213
+ sage: A.basis(3)
2214
+ Family (Sq(0,1),)
2215
+ sage: SteenrodAlgebra().basis(3)
2216
+ Family (Sq(0,1), Sq(3))
2217
+ sage: A_pst = SteenrodAlgebra(profile=[1,2,1], basis='pst')
2218
+ sage: A_pst.basis(3)
2219
+ Family (P^0_2,)
2220
+
2221
+ sage: A7 = SteenrodAlgebra(p=7)
2222
+ sage: B = SteenrodAlgebra(p=7, profile=([1,2,1], [1]))
2223
+ sage: A7.basis(84)
2224
+ Family (P(7),)
2225
+ sage: B.basis(84)
2226
+ Family ()
2227
+ sage: C = SteenrodAlgebra(p=7, profile=([1], [2,2]))
2228
+ sage: A7.Q(0,1) in C.basis(14)
2229
+ True
2230
+ sage: A7.Q(2) in A7.basis(97)
2231
+ True
2232
+ sage: A7.Q(2) in C.basis(97)
2233
+ False
2234
+
2235
+ With no arguments, return the basis of the whole algebra.
2236
+ This does not print in a very helpful way, unfortunately::
2237
+
2238
+ sage: A7.basis()
2239
+ Lazy family (Term map from basis key family of mod 7 Steenrod algebra, milnor basis
2240
+ to mod 7 Steenrod algebra, milnor basis(i))_{i in basis key family
2241
+ of mod 7 Steenrod algebra, milnor basis}
2242
+ sage: for (idx,a) in zip((1,..,9),A7.basis()):
2243
+ ....: print("{} {}".format(idx, a))
2244
+ 1 1
2245
+ 2 Q_0
2246
+ 3 P(1)
2247
+ 4 Q_1
2248
+ 5 Q_0 P(1)
2249
+ 6 Q_0 Q_1
2250
+ 7 P(2)
2251
+ 8 Q_1 P(1)
2252
+ 9 Q_0 P(2)
2253
+ sage: D = SteenrodAlgebra(p=3, profile=([1], [2,2]))
2254
+ sage: sorted(D.basis())
2255
+ [1, P(1), P(2), Q_0, Q_0 P(1), Q_0 P(2), Q_0 Q_1,
2256
+ Q_0 Q_1 P(1), Q_0 Q_1 P(2), Q_1, Q_1 P(1), Q_1 P(2)]
2257
+ """
2258
+ from sage.sets.family import Family
2259
+ if d is None:
2260
+ return Family(self._indices, self.monomial)
2261
+ else:
2262
+ return Family([self.monomial(tuple(a)) for a in self._basis_fcn(d)])
2263
+
2264
+ def _check_profile_on_basis(self, t):
2265
+ """
2266
+ Return ``True`` if the element specified by the tuple ``t`` is in this
2267
+ algebra.
2268
+
2269
+ INPUT:
2270
+
2271
+ - ``t`` -- tuple
2272
+
2273
+ EXAMPLES::
2274
+
2275
+ sage: A = SteenrodAlgebra(profile=[1,2,1])
2276
+ sage: A._check_profile_on_basis((0,0,1))
2277
+ True
2278
+ sage: A._check_profile_on_basis((0,0,2))
2279
+ False
2280
+ sage: A5 = SteenrodAlgebra(p=5, profile=([3,2,1], [2,2,2,2,2]))
2281
+ sage: A5._check_profile_on_basis(((), (1,5)))
2282
+ True
2283
+ sage: A5._check_profile_on_basis(((1,1,1), (1,5)))
2284
+ True
2285
+ sage: A5._check_profile_on_basis(((1,1,1), (1,5,5)))
2286
+ False
2287
+ """
2288
+ if self.basis_name() != 'milnor':
2289
+ A = SteenrodAlgebra(p=self.prime(),
2290
+ profile=self._profile,
2291
+ truncation_type=self._truncation_type,
2292
+ generic=self._generic)
2293
+ return all(A._check_profile_on_basis(a[0])
2294
+ for a in self._milnor_on_basis(t))
2295
+
2296
+ from sage.rings.infinity import Infinity
2297
+ p = self.prime()
2298
+ if not self._has_nontrivial_profile():
2299
+ return True
2300
+ if not self._generic:
2301
+ return all(self.profile(i+1) == Infinity
2302
+ or t[i] < 2**self.profile(i+1)
2303
+ for i in range(len(t)))
2304
+ # p odd:
2305
+ if any(self.profile(i, 1) != 2 for i in t[0]):
2306
+ return False
2307
+ return all(self.profile(i + 1, 0) == Infinity
2308
+ or t[1][i] < p**self.profile(i + 1, 0)
2309
+ for i in range(len(t[1])))
2310
+
2311
+ def P(self, *nums):
2312
+ r"""
2313
+ The element `P(a, b, c, \ldots)`.
2314
+
2315
+ INPUT:
2316
+
2317
+ - ``a``, ``b``, ``c``, ... -- nonnegative integers
2318
+
2319
+ OUTPUT:
2320
+
2321
+ element of the Steenrod algebra given by the Milnor
2322
+ single basis element `P(a, b, c, ...)`
2323
+
2324
+ Note that at the prime 2, this is the same element as
2325
+ `\text{Sq}(a, b, c, ...)`.
2326
+
2327
+ EXAMPLES::
2328
+
2329
+ sage: A = SteenrodAlgebra(2)
2330
+ sage: A.P(5)
2331
+ Sq(5)
2332
+ sage: B = SteenrodAlgebra(3)
2333
+ sage: B.P(5,1,1)
2334
+ P(5,1,1)
2335
+ sage: B.P(1,1,-12,1)
2336
+ Traceback (most recent call last):
2337
+ ...
2338
+ TypeError: entries must be nonnegative integers
2339
+
2340
+ sage: SteenrodAlgebra(basis='serre-cartan').P(0,1)
2341
+ Sq^2 Sq^1 + Sq^3
2342
+ sage: SteenrodAlgebra(generic=True).P(2,0,1)
2343
+ P(2,0,1)
2344
+ """
2345
+ from sage.rings.integer import Integer
2346
+ if self.basis_name() != 'milnor':
2347
+ return self(SteenrodAlgebra(p=self.prime(),
2348
+ generic=self._generic).P(*nums))
2349
+ while nums and nums[-1] == 0:
2350
+ nums = nums[:-1]
2351
+ if len(nums) == 0 or (len(nums) == 1 and nums[0] == 0):
2352
+ return self.one()
2353
+ for i in nums:
2354
+ try:
2355
+ assert Integer(i) >= 0
2356
+ except (TypeError, AssertionError):
2357
+ raise TypeError("entries must be nonnegative integers")
2358
+
2359
+ if not self._generic:
2360
+ t = nums
2361
+ else:
2362
+ t = ((), nums)
2363
+ if self._check_profile_on_basis(t):
2364
+ A = SteenrodAlgebra_generic(p=self.prime(),
2365
+ generic=self._generic)
2366
+ a = A.monomial(t)
2367
+ return self(a)
2368
+ raise ValueError("element not in this algebra")
2369
+
2370
+ def Q_exp(self, *nums):
2371
+ r"""
2372
+ The element `Q_0^{e_0} Q_1^{e_1} ...` , given by
2373
+ specifying the exponents.
2374
+
2375
+ INPUT:
2376
+
2377
+ - ``e0``, ``e1``, ... -- sequence of 0s and 1s
2378
+
2379
+ OUTPUT: the element `Q_0^{e_0} Q_1^{e_1} ...`
2380
+
2381
+ Note that at the prime 2, `Q_n` is the element
2382
+ `\text{Sq}(0,0,...,1)` , where the 1 is in the
2383
+ `(n+1)^{st}` position.
2384
+
2385
+ Compare this to the method :meth:`Q`, which defines a similar
2386
+ element, but by specifying the tuple of subscripts of terms
2387
+ with exponent 1.
2388
+
2389
+ EXAMPLES::
2390
+
2391
+ sage: A2 = SteenrodAlgebra(2)
2392
+ sage: A5 = SteenrodAlgebra(5)
2393
+ sage: A2.Q_exp(0,0,1,1,0)
2394
+ Sq(0,0,1,1)
2395
+ sage: A5.Q_exp(0,0,1,1,0)
2396
+ Q_2 Q_3
2397
+ sage: A5.Q(2,3)
2398
+ Q_2 Q_3
2399
+ sage: A5.Q_exp(0,0,1,1,0) == A5.Q(2,3)
2400
+ True
2401
+ sage: SteenrodAlgebra(2,generic=True).Q_exp(1,0,1)
2402
+ Q_0 Q_2
2403
+ """
2404
+ if not all(x in (0, 1) for x in nums):
2405
+ raise ValueError("the tuple %s should consist " % (nums,) +
2406
+ "only of 0s and 1s")
2407
+ else:
2408
+ if self.basis_name() != 'milnor':
2409
+ return self(SteenrodAlgebra(p=self.prime(),
2410
+ generic=self._generic).Q_exp(*nums))
2411
+ while nums[-1] == 0:
2412
+ nums = nums[:-1]
2413
+ if not self._generic:
2414
+ return self.P(*nums)
2415
+ else:
2416
+ mono = ()
2417
+ index = 0
2418
+ for e in nums:
2419
+ if e == 1:
2420
+ mono = mono + (index,)
2421
+ index += 1
2422
+ return self.Q(*mono)
2423
+
2424
+ def Q(self, *nums):
2425
+ r"""
2426
+ The element `Q_{n0} Q_{n1} ...` , given by specifying the
2427
+ subscripts.
2428
+
2429
+ INPUT:
2430
+
2431
+ - ``n0``, ``n1``, ... -- nonnegative integers
2432
+
2433
+ OUTPUT: the element `Q_{n0} Q_{n1} ...`
2434
+
2435
+ Note that at the prime 2, `Q_n` is the element
2436
+ `\text{Sq}(0,0,...,1)` , where the 1 is in the
2437
+ `(n+1)^{st}` position.
2438
+
2439
+ Compare this to the method :meth:`Q_exp`, which defines a
2440
+ similar element, but by specifying the tuple of exponents.
2441
+
2442
+ EXAMPLES::
2443
+
2444
+ sage: A2 = SteenrodAlgebra(2)
2445
+ sage: A2.Q(2,3)
2446
+ Sq(0,0,1,1)
2447
+ sage: A5 = SteenrodAlgebra(5)
2448
+ sage: A5.Q(1,4)
2449
+ Q_1 Q_4
2450
+ sage: A5.Q(1,4) == A5.Q_exp(0,1,0,0,1)
2451
+ True
2452
+ sage: H = SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]])
2453
+ sage: H.Q(2)
2454
+ Q_2
2455
+ sage: H.Q(4)
2456
+ Traceback (most recent call last):
2457
+ ...
2458
+ ValueError: element not in this algebra
2459
+ """
2460
+ if len(nums) != len(set(nums)):
2461
+ return self(0)
2462
+ else:
2463
+ if self.basis_name() != 'milnor':
2464
+ return self(SteenrodAlgebra(p=self.prime(),
2465
+ generic=self._generic).Q(*nums))
2466
+ if not self._generic:
2467
+ if len(nums) == 0:
2468
+ return self.one()
2469
+ else:
2470
+ list = (1+max(nums)) * [0]
2471
+ for i in nums:
2472
+ list[i] = 1
2473
+ return self.Sq(*tuple(list))
2474
+ else:
2475
+ answer = self.one()
2476
+ for i in nums:
2477
+ answer = answer * self.monomial(((i,), ()))
2478
+ t = answer.leading_support()
2479
+ if self._check_profile_on_basis(t):
2480
+ return answer
2481
+ raise ValueError("element not in this algebra")
2482
+
2483
+ def _an_element_(self):
2484
+ """
2485
+ An element of this Steenrod algebra.
2486
+
2487
+ The element depends on
2488
+ the basis and whether there is a nontrivial profile function.
2489
+ (This is used by the automatic test suite, so having different
2490
+ elements in different bases may help in discovering bugs.)
2491
+
2492
+ EXAMPLES::
2493
+
2494
+ sage: SteenrodAlgebra().an_element()
2495
+ Sq(2,1)
2496
+ sage: SteenrodAlgebra(basis='adem').an_element()
2497
+ Sq^4 Sq^2 Sq^1
2498
+ sage: SteenrodAlgebra(p=5).an_element()
2499
+ 4 Q_1 Q_3 P(2,1)
2500
+ sage: SteenrodAlgebra(basis='pst').an_element()
2501
+ P^3_1
2502
+ sage: SteenrodAlgebra(basis='pst', profile=[3,2,1]).an_element()
2503
+ P^0_1
2504
+ """
2505
+ from sage.rings.finite_rings.finite_field_constructor import GF
2506
+ basis = self.basis_name()
2507
+ p = self.prime()
2508
+
2509
+ if self._has_nontrivial_profile():
2510
+ if self.ngens():
2511
+ return self.gen(0)
2512
+ else:
2513
+ return self.one()
2514
+
2515
+ if basis == 'milnor' and not self._generic:
2516
+ return self.monomial((2, 1))
2517
+ if basis == 'milnor' and self._generic:
2518
+ return self.term(((1, 3), (2, 1)), GF(p)(p - 1))
2519
+ if basis == 'serre-cartan' and not self._generic:
2520
+ return self.monomial((4, 2, 1))
2521
+ if basis == 'serre-cartan' and self._generic:
2522
+ return self.term((1, p, 0, 1, 0), GF(p)(p - 1))
2523
+ if basis == 'woody' or basis == 'woodz':
2524
+ return self._from_dict({((3, 0),): 1,
2525
+ ((1, 1), (1, 0)): 1}, coerce=True)
2526
+ if basis.find('wall') >= 0:
2527
+ return self._from_dict({((1, 1), (1, 0)): 1,
2528
+ ((2, 2), (0, 0)): 1}, coerce=True)
2529
+ if basis.find('arnona') >= 0:
2530
+ return self._from_dict({((3, 3),): 1,
2531
+ ((1, 1), (2, 1)): 1}, coerce=True)
2532
+ if basis == 'arnonc':
2533
+ return self._from_dict({(8,): 1, (4, 4): 1}, coerce=True)
2534
+ if basis.find('pst') >= 0:
2535
+ if not self._generic:
2536
+ return self.monomial(((3, 1),))
2537
+ return self.term(((1,), (((1, 1), 2),)), GF(p)(p - 1))
2538
+ if basis.find('comm') >= 0:
2539
+ if not self._generic:
2540
+ return self.monomial(((1, 2),))
2541
+ return self.term(((), (((1, 2), 1),)), GF(p)(p - 1))
2542
+
2543
+ def pst(self, s, t):
2544
+ r"""
2545
+ The Margolis element `P^s_t`.
2546
+
2547
+ INPUT:
2548
+
2549
+ - ``s`` -- nonnegative integer
2550
+
2551
+ - ``t`` -- positive integer
2552
+
2553
+ - ``p`` -- positive prime number
2554
+
2555
+ OUTPUT: element of the Steenrod algebra
2556
+
2557
+ This returns the Margolis element `P^s_t` of the mod
2558
+ `p` Steenrod algebra: the element equal to
2559
+ `P(0,0,...,0,p^s)`, where the `p^s` is in position
2560
+ `t`.
2561
+
2562
+ EXAMPLES::
2563
+
2564
+ sage: A2 = SteenrodAlgebra(2)
2565
+ sage: A2.pst(3,5)
2566
+ Sq(0,0,0,0,8)
2567
+ sage: A2.pst(1,2) == Sq(4)*Sq(2) + Sq(2)*Sq(4)
2568
+ True
2569
+ sage: SteenrodAlgebra(5).pst(3,5)
2570
+ P(0,0,0,0,125)
2571
+ """
2572
+ from sage.rings.integer import Integer
2573
+ if self.basis_name() != 'milnor':
2574
+ return self(SteenrodAlgebra(p=self.prime(),
2575
+ generic=self._generic).pst(s, t))
2576
+ if not isinstance(s, (Integer, int)) and s >= 0:
2577
+ raise ValueError("%s is not a nonnegative integer" % s)
2578
+ if not isinstance(t, (Integer, int)) and t > 0:
2579
+ raise ValueError("%s is not a positive integer" % t)
2580
+ nums = (0,)*(t-1) + (self.prime()**s,)
2581
+ return self.P(*nums)
2582
+
2583
+ def ngens(self):
2584
+ r"""
2585
+ Number of generators of ``self``.
2586
+
2587
+ OUTPUT: number or Infinity
2588
+
2589
+ The Steenrod algebra is infinitely generated. A sub-Hopf
2590
+ algebra may be finitely or infinitely generated; in general,
2591
+ it is not clear what a minimal generating set is, nor the
2592
+ cardinality of that set. So: if the algebra is
2593
+ infinite-dimensional, this returns Infinity. If the algebra
2594
+ is finite-dimensional and is equal to one of the sub-Hopf
2595
+ algebras `A(n)`, then their minimal generating set is known,
2596
+ and this returns the cardinality of that set. Otherwise, any
2597
+ sub-Hopf algebra is (not necessarily minimally) generated by
2598
+ the `P^s_t`'s that it contains (along with the `Q_n`'s it
2599
+ contains, at odd primes), so this returns the number of
2600
+ `P^s_t`'s and `Q_n`'s in the algebra.
2601
+
2602
+ EXAMPLES::
2603
+
2604
+ sage: A = SteenrodAlgebra(3)
2605
+ sage: A.ngens()
2606
+ +Infinity
2607
+ sage: SteenrodAlgebra(profile=lambda n: n).ngens()
2608
+ +Infinity
2609
+ sage: SteenrodAlgebra(profile=[3,2,1]).ngens() # A(2)
2610
+ 3
2611
+ sage: SteenrodAlgebra(profile=[3,2,1], basis='pst').ngens()
2612
+ 3
2613
+ sage: SteenrodAlgebra(p=3, profile=[[3,2,1], [2,2,2,2]]).ngens() # A(3) at p=3
2614
+ 4
2615
+ sage: SteenrodAlgebra(profile=[1,2,1,1]).ngens()
2616
+ 5
2617
+ """
2618
+ from sage.rings.infinity import Infinity
2619
+ if self._truncation_type == Infinity:
2620
+ return Infinity
2621
+ n = self.profile(1)
2622
+ p = self.prime()
2623
+ if not self._generic and self._profile == AA(n-1, p=p)._profile:
2624
+ return n
2625
+ if self._generic and self._profile == AA(n, p=p)._profile:
2626
+ return n+1
2627
+ if not self._generic:
2628
+ return sum(self._profile)
2629
+ return sum(self._profile[0]) + len([a for a in self._profile[1] if a == 2])
2630
+
2631
+ def gens(self) -> Family:
2632
+ r"""
2633
+ Family of generators for this algebra.
2634
+
2635
+ OUTPUT: family of elements of this algebra
2636
+
2637
+ At the prime 2, the Steenrod algebra is generated by the
2638
+ elements `\text{Sq}^{2^i}` for `i \geq 0`. At odd primes, it
2639
+ is generated by the elements `Q_0` and `\mathcal{P}^{p^i}` for
2640
+ `i \geq 0`. So if this algebra is the entire Steenrod
2641
+ algebra, return an infinite family made up of these elements.
2642
+
2643
+ For sub-Hopf algebras of the Steenrod algebra, it is not
2644
+ always clear what a minimal generating set is. The sub-Hopf
2645
+ algebra `A(n)` is minimally generated by the elements
2646
+ `\text{Sq}^{2^i}` for `0 \leq i \leq n` at the prime 2. At
2647
+ odd primes, `A(n)` is minimally generated by `Q_0` along with
2648
+ `\mathcal{P}^{p^i}` for `0 \leq i \leq n-1`. So if this
2649
+ algebra is `A(n)`, return the appropriate list of generators.
2650
+
2651
+ For other sub-Hopf algebras: return a non-minimal generating
2652
+ set: the family of `P^s_t`'s and `Q_n`'s contained in the
2653
+ algebra.
2654
+
2655
+ EXAMPLES::
2656
+
2657
+ sage: A3 = SteenrodAlgebra(3, 'adem')
2658
+ sage: A3.gens()
2659
+ Lazy family (<bound method SteenrodAlgebra_generic.gen of mod 3 Steenrod algebra,
2660
+ serre-cartan basis>(i))_{i in Non negative integers}
2661
+ sage: A3.gens()[0]
2662
+ beta
2663
+ sage: A3.gens()[1]
2664
+ P^1
2665
+ sage: A3.gens()[2]
2666
+ P^3
2667
+ sage: SteenrodAlgebra(profile=[3,2,1]).gens()
2668
+ Family (Sq(1), Sq(2), Sq(4))
2669
+
2670
+ In the following case, return a non-minimal generating set.
2671
+ (It is not minimal because `\text{Sq}(0,0,1)` is the
2672
+ commutator of `\text{Sq}(1)` and `\text{Sq}(0,2)`.) ::
2673
+
2674
+ sage: SteenrodAlgebra(profile=[1,2,1]).gens()
2675
+ Family (Sq(1), Sq(0,1), Sq(0,2), Sq(0,0,1))
2676
+ sage: SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]]).gens()
2677
+ Family (Q_0, P(1), P(5))
2678
+ sage: SteenrodAlgebra(profile=lambda n: n).gens()
2679
+ Lazy family (<bound method SteenrodAlgebra_generic.gen of sub-Hopf algebra
2680
+ of mod 2 Steenrod algebra, milnor basis, profile function [1, 2, 3, ...,
2681
+ 98, 99, +Infinity, +Infinity, +Infinity, ...]>(i))_{i in Non negative integers}
2682
+
2683
+ You may also use ``algebra_generators`` instead of ``gens``::
2684
+
2685
+ sage: SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]]).algebra_generators()
2686
+ Family (Q_0, P(1), P(5))
2687
+ """
2688
+ from sage.sets.non_negative_integers import NonNegativeIntegers
2689
+ from sage.rings.infinity import Infinity
2690
+ n = self.ngens()
2691
+ if n < Infinity:
2692
+ return Family([self.gen(i) for i in range(n)])
2693
+ return Family(NonNegativeIntegers(), self.gen)
2694
+
2695
+ algebra_generators = gens
2696
+
2697
+ def gen(self, i=0):
2698
+ r"""
2699
+ The `i`-th generator of this algebra.
2700
+
2701
+ INPUT:
2702
+
2703
+ - ``i`` -- nonnegative integer
2704
+
2705
+ OUTPUT: the `i`-th generator of this algebra
2706
+
2707
+ For the full Steenrod algebra, the `i`-th generator is
2708
+ `\text{Sq}(2^i)` at the prime 2; when `p` is odd, the `0`-th generator
2709
+ is `\beta = Q(0)`, and for `i>0`, the `i`-th generator is
2710
+ `P(p^{i-1})`.
2711
+
2712
+ For sub-Hopf algebras of the Steenrod algebra, it is not
2713
+ always clear what a minimal generating set is. The sub-Hopf
2714
+ algebra `A(n)` is minimally generated by the elements
2715
+ `\text{Sq}^{2^i}` for `0 \leq i \leq n` at the prime 2. At
2716
+ odd primes, `A(n)` is minimally generated by `Q_0` along with
2717
+ `\mathcal{P}^{p^i}` for `0 \leq i \leq n-1`. So if this
2718
+ algebra is `A(n)`, return the appropriate generator.
2719
+
2720
+ For other sub-Hopf algebras: they are generated (but not
2721
+ necessarily minimally) by the `P^s_t`'s (and `Q_n`'s, if `p`
2722
+ is odd) that they contain. So order the `P^s_t`'s (and
2723
+ `Q_n`'s) in the algebra by degree and return the `i`-th one.
2724
+
2725
+ EXAMPLES::
2726
+
2727
+ sage: A = SteenrodAlgebra(2)
2728
+ sage: A.gen(4)
2729
+ Sq(16)
2730
+ sage: A.gen(200)
2731
+ Sq(1606938044258990275541962092341162602522202993782792835301376)
2732
+ sage: SteenrodAlgebra(2, basis='adem').gen(2)
2733
+ Sq^4
2734
+ sage: SteenrodAlgebra(2, basis='pst').gen(2)
2735
+ P^2_1
2736
+ sage: B = SteenrodAlgebra(5)
2737
+ sage: B.gen(0)
2738
+ Q_0
2739
+ sage: B.gen(2)
2740
+ P(5)
2741
+
2742
+ sage: SteenrodAlgebra(profile=[2,1]).gen(1)
2743
+ Sq(2)
2744
+ sage: SteenrodAlgebra(profile=[1,2,1]).gen(1)
2745
+ Sq(0,1)
2746
+ sage: SteenrodAlgebra(profile=[1,2,1]).gen(5)
2747
+ Traceback (most recent call last):
2748
+ ...
2749
+ ValueError: this algebra only has 4 generators, so call gen(i) with 0 <= i < 4
2750
+
2751
+ sage: D = SteenrodAlgebra(profile=lambda n: n)
2752
+ sage: [D.gen(n) for n in range(5)]
2753
+ [Sq(1), Sq(0,1), Sq(0,2), Sq(0,0,1), Sq(0,0,2)]
2754
+ sage: D3 = SteenrodAlgebra(p=3, profile=(lambda n: n, lambda n: 2))
2755
+ sage: [D3.gen(n) for n in range(9)]
2756
+ [Q_0, P(1), Q_1, P(0,1), Q_2, P(0,3), P(0,0,1), Q_3, P(0,0,3)]
2757
+ sage: D3 = SteenrodAlgebra(p=3, profile=(lambda n: n, lambda n: 1 if n<1 else 2))
2758
+ sage: [D3.gen(n) for n in range(9)]
2759
+ [P(1), Q_1, P(0,1), Q_2, P(0,3), P(0,0,1), Q_3, P(0,0,3), P(0,0,0,1)]
2760
+ sage: SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]], basis='pst').gen(2)
2761
+ P^1_1
2762
+ """
2763
+ from sage.rings.infinity import Infinity
2764
+ from sage.rings.integer import Integer
2765
+ p = self.prime()
2766
+ if not isinstance(i, (Integer, int)) and i >= 0:
2767
+ raise ValueError("%s is not a nonnegative integer" % i)
2768
+ num = self.ngens()
2769
+ if num < Infinity:
2770
+ if i >= num:
2771
+ raise ValueError("this algebra only has %s generators, so call gen(i) with 0 <= i < %s" % (num, num))
2772
+ # check to see if equal to A(n) for some n.
2773
+ n = self.profile(1)
2774
+ if not self._generic and self._profile == AA(n-1, p=p)._profile:
2775
+ return self.pst(i, 1)
2776
+ if self._generic and self._profile == AA(n, p=p)._profile:
2777
+ if i == 0:
2778
+ return self.Q(0)
2779
+ return self.pst(i-1, 1)
2780
+ # if not A(n), return list of P^s_t's in algebra, along with Q's if p is odd
2781
+ idx = -1
2782
+ if not self._generic:
2783
+ last_t = len(self._profile)
2784
+ else:
2785
+ last_t = max(len(self._profile[0]), len(self._profile[1]))
2786
+ last_s = self.profile(last_t)
2787
+ for j in range(1, last_s + last_t + 1):
2788
+ if self._generic and self.profile(j-1, 1) == 2:
2789
+ guess = self.Q(j-1)
2790
+ idx += 1
2791
+ if idx == i:
2792
+ elt = guess
2793
+ break
2794
+ for t in range(1, min(j, last_t) + 1):
2795
+ s = j - t
2796
+ if self.profile(t) > s:
2797
+ guess = self.pst(s, t)
2798
+ idx += 1
2799
+ if idx == i:
2800
+ elt = guess
2801
+ break
2802
+ return elt
2803
+
2804
+ # entire Steenrod algebra:
2805
+ if self.profile(1) == Infinity:
2806
+ if not self._generic:
2807
+ return self.Sq(p**i)
2808
+ elif self.profile(0, 1) == 2:
2809
+ if i == 0:
2810
+ return self.Q(0)
2811
+ else:
2812
+ return self.P(p**(i-1))
2813
+
2814
+ # infinite-dimensional sub-Hopf algebra
2815
+ idx = -1
2816
+ tot = 1
2817
+ found = False
2818
+ A = SteenrodAlgebra(p=p, generic=self._generic)
2819
+ while not found:
2820
+ if self._generic:
2821
+ test = A.Q(tot-1)
2822
+ if test in self:
2823
+ idx += 1
2824
+ if idx == i:
2825
+ break
2826
+ for t in range(1, tot+1):
2827
+ s = tot - t
2828
+ test = A.pst(s, t)
2829
+ if test in self:
2830
+ idx += 1
2831
+ if idx == i:
2832
+ found = True
2833
+ break
2834
+ tot += 1
2835
+ return test
2836
+
2837
+ def is_commutative(self) -> bool:
2838
+ r"""
2839
+ Return ``True`` if ``self`` is graded commutative, as determined by the
2840
+ profile function.
2841
+
2842
+ In particular, a sub-Hopf algebra of the
2843
+ mod 2 Steenrod algebra is commutative if and only if there is
2844
+ an integer `n>0` so that its profile function `e` satisfies
2845
+
2846
+ - `e(i) = 0` for `i < n`,
2847
+ - `e(i) \leq n` for `i \geq n`.
2848
+
2849
+ When `p` is odd, there must be an integer `n \geq 0` so that
2850
+ the profile functions `e` and `k` satisfy
2851
+
2852
+ - `e(i) = 0` for `i < n`,
2853
+ - `e(i) \leq n` for `i \geq n`.
2854
+ - `k(i) = 1` for `i < n`.
2855
+
2856
+ EXAMPLES::
2857
+
2858
+ sage: A = SteenrodAlgebra(p=3)
2859
+ sage: A.is_commutative()
2860
+ False
2861
+ sage: SteenrodAlgebra(profile=[2,1]).is_commutative()
2862
+ False
2863
+ sage: SteenrodAlgebra(profile=[0,2,2,1]).is_commutative()
2864
+ True
2865
+
2866
+ Note that if the profile function is specified by a function,
2867
+ then by default it has infinite truncation type: the profile
2868
+ function is assumed to be infinite after the 100th term. ::
2869
+
2870
+ sage: SteenrodAlgebra(profile=lambda n: 1).is_commutative()
2871
+ False
2872
+ sage: SteenrodAlgebra(profile=lambda n: 1, truncation_type=0).is_commutative()
2873
+ True
2874
+
2875
+ sage: SteenrodAlgebra(p=5, profile=([0,2,2,1], [])).is_commutative()
2876
+ True
2877
+ sage: SteenrodAlgebra(p=5, profile=([0,2,2,1], [1,1,2])).is_commutative()
2878
+ True
2879
+ sage: SteenrodAlgebra(p=5, profile=([0,2,1], [1,2,2,2])).is_commutative()
2880
+ False
2881
+ """
2882
+ if not self._has_nontrivial_profile() or self._truncation_type > 0:
2883
+ return False
2884
+ if not self._generic:
2885
+ n = max(self._profile)
2886
+ return all(self.profile(i) == 0 for i in range(1, n))
2887
+ n = max(self._profile[0])
2888
+ return (all(self.profile(i, 0) == 0 for i in range(1, n))
2889
+ and all(self.profile(i, 1) == 1 for i in range(n)))
2890
+
2891
+ def is_finite(self):
2892
+ r"""
2893
+ Return ``True`` if this algebra is finite-dimensional.
2894
+
2895
+ Therefore true if the profile function is finite, and in
2896
+ particular the ``truncation_type`` must be finite.
2897
+
2898
+ EXAMPLES::
2899
+
2900
+ sage: A = SteenrodAlgebra(p=3)
2901
+ sage: A.is_finite()
2902
+ False
2903
+ sage: SteenrodAlgebra(profile=[3,2,1]).is_finite()
2904
+ True
2905
+ sage: SteenrodAlgebra(profile=lambda n: n).is_finite()
2906
+ False
2907
+ """
2908
+ return self._has_nontrivial_profile() and self._truncation_type == 0
2909
+
2910
+ def dimension(self):
2911
+ r"""
2912
+ The dimension of this algebra as a vector space over `\GF{p}`.
2913
+
2914
+ If the algebra is infinite, return ``+Infinity``. Otherwise,
2915
+ the profile function must be finite. In this case, at the
2916
+ prime 2, its dimension is `2^s`, where `s` is the sum of the
2917
+ entries in the profile function. At odd primes, the dimension
2918
+ is `p^s * 2^t` where `s` is the sum of the `e` component of
2919
+ the profile function and `t` is the number of 2's in the `k`
2920
+ component of the profile function.
2921
+
2922
+ EXAMPLES::
2923
+
2924
+ sage: SteenrodAlgebra(p=7).dimension()
2925
+ +Infinity
2926
+ sage: SteenrodAlgebra(profile=[3,2,1]).dimension()
2927
+ 64
2928
+ sage: SteenrodAlgebra(p=3, profile=([1,1], [])).dimension()
2929
+ 9
2930
+ sage: SteenrodAlgebra(p=5, profile=([1], [2,2])).dimension()
2931
+ 20
2932
+ """
2933
+ from sage.rings.infinity import Infinity
2934
+ if not self.is_finite():
2935
+ return Infinity
2936
+ p = self.prime()
2937
+ if not self._generic:
2938
+ return 2**sum(self._profile)
2939
+ return p**sum(self._profile[0]) * 2**len([a for a in self._profile[1] if a == 2])
2940
+
2941
+ @cached_method
2942
+ def top_class(self):
2943
+ r"""
2944
+ Highest dimensional basis element. This is only defined if the algebra is finite.
2945
+
2946
+ EXAMPLES::
2947
+
2948
+ sage: SteenrodAlgebra(2, profile=(3,2,1)).top_class()
2949
+ Sq(7,3,1)
2950
+ sage: SteenrodAlgebra(3, profile=((2,2,1),(1,2,2,2,2))).top_class()
2951
+ Q_1 Q_2 Q_3 Q_4 P(8,8,2)
2952
+
2953
+ TESTS::
2954
+
2955
+ sage: SteenrodAlgebra(2, profile=(3,2,1), basis='pst').top_class()
2956
+ P^0_1 P^0_2 P^1_1 P^0_3 P^1_2 P^2_1
2957
+ sage: SteenrodAlgebra(5, profile=((0,),(2,1,2,2))).top_class()
2958
+ Q_0 Q_2 Q_3
2959
+ sage: SteenrodAlgebra(5).top_class()
2960
+ Traceback (most recent call last):
2961
+ ...
2962
+ ValueError: the algebra is not finite dimensional
2963
+
2964
+ Currently, we create the top class in the Milnor basis version and transform
2965
+ this result back into the requested basis. This approach is easy to implement
2966
+ but far from optimal for the 'pst' basis. Occasionally, it also gives an awkward
2967
+ leading coefficient::
2968
+
2969
+ sage: SteenrodAlgebra(3, profile=((2,1),(1,2,2)), basis='pst').top_class()
2970
+ 2 Q_1 Q_2 (P^0_1)^2 (P^0_2)^2 (P^1_1)^2
2971
+
2972
+ TESTS::
2973
+
2974
+ sage: A=SteenrodAlgebra(2, profile=(3,2,1), basis='pst')
2975
+ sage: A.top_class().parent() is A
2976
+ True
2977
+ """
2978
+ if not self.is_finite():
2979
+ raise ValueError("the algebra is not finite dimensional")
2980
+ p = self.prime()
2981
+ # we create the top class in the Milnor basis version
2982
+ AM = SteenrodAlgebra(basis='milnor', p=p, generic=self._generic)
2983
+ if not self._generic:
2984
+ ans = AM.monomial(tuple((1 << k) - 1 for k in self._profile))
2985
+ else:
2986
+ rp, ep = self._profile
2987
+ e = [kk for kk in range(len(ep)) if ep[kk] == 2]
2988
+ r = [p**kk-1 for kk in rp]
2989
+ ans = AM.monomial((tuple(e), tuple(r)))
2990
+ return self(ans.change_basis(self.basis_name()))
2991
+
2992
+ def order(self):
2993
+ r"""
2994
+ The order of this algebra.
2995
+
2996
+ This is computed by computing its vector space dimension `d`
2997
+ and then returning `p^d`.
2998
+
2999
+ EXAMPLES::
3000
+
3001
+ sage: SteenrodAlgebra(p=7).order()
3002
+ +Infinity
3003
+ sage: SteenrodAlgebra(profile=[2,1]).dimension()
3004
+ 8
3005
+ sage: SteenrodAlgebra(profile=[2,1]).order()
3006
+ 256
3007
+ sage: SteenrodAlgebra(p=3, profile=([1], [])).dimension()
3008
+ 3
3009
+ sage: SteenrodAlgebra(p=3, profile=([1], [])).order()
3010
+ 27
3011
+ sage: SteenrodAlgebra(p=5, profile=([], [2, 2])).dimension()
3012
+ 4
3013
+ sage: SteenrodAlgebra(p=5, profile=([], [2, 2])).order() == 5**4
3014
+ True
3015
+ """
3016
+ from sage.rings.infinity import Infinity
3017
+ if not self.is_finite():
3018
+ return Infinity
3019
+ return self.prime() ** self.dimension()
3020
+
3021
+ def is_division_algebra(self):
3022
+ r"""
3023
+ The only way this algebra can be a division algebra is if it
3024
+ is the ground field `\GF{p}`.
3025
+
3026
+ EXAMPLES::
3027
+
3028
+ sage: SteenrodAlgebra(11).is_division_algebra()
3029
+ False
3030
+ sage: SteenrodAlgebra(profile=lambda n: 0, truncation_type=0).is_division_algebra()
3031
+ True
3032
+ """
3033
+ return self.is_field()
3034
+
3035
+ def is_field(self, proof=True):
3036
+ r"""
3037
+ The only way this algebra can be a field is if it is the
3038
+ ground field `\GF{p}`.
3039
+
3040
+ EXAMPLES::
3041
+
3042
+ sage: SteenrodAlgebra(11).is_field()
3043
+ False
3044
+ sage: SteenrodAlgebra(profile=lambda n: 0, truncation_type=0).is_field()
3045
+ True
3046
+ """
3047
+ return self.dimension() == 1
3048
+
3049
+ def is_integral_domain(self, proof=True):
3050
+ r"""
3051
+ The only way this algebra can be an integral domain is if it
3052
+ is the ground field `\GF{p}`.
3053
+
3054
+ EXAMPLES::
3055
+
3056
+ sage: SteenrodAlgebra(11).is_integral_domain()
3057
+ False
3058
+ sage: SteenrodAlgebra(profile=lambda n: 0, truncation_type=0).is_integral_domain()
3059
+ True
3060
+ """
3061
+ return self.is_field()
3062
+
3063
+ def is_noetherian(self) -> bool:
3064
+ """
3065
+ This algebra is Noetherian if and only if it is finite.
3066
+
3067
+ EXAMPLES::
3068
+
3069
+ sage: SteenrodAlgebra(3).is_noetherian()
3070
+ False
3071
+ sage: SteenrodAlgebra(profile=[1,2,1]).is_noetherian()
3072
+ True
3073
+ sage: SteenrodAlgebra(profile=lambda n: n+2).is_noetherian()
3074
+ False
3075
+ """
3076
+ return self.is_finite()
3077
+
3078
+ def is_generic(self):
3079
+ r"""
3080
+ The algebra is generic if it is based on the odd-primary relations,
3081
+ i.e. if its dual is a quotient of
3082
+
3083
+ .. MATH::
3084
+
3085
+ A_* = \GF{p} [\xi_1, \xi_2, \xi_3, ...] \otimes \Lambda (\tau_0, \tau_1, ...)
3086
+
3087
+ Sage also allows this for `p=2`. Only the usual Steenrod algebra at the prime `2` and
3088
+ its sub algebras are non-generic.
3089
+
3090
+ EXAMPLES::
3091
+
3092
+ sage: SteenrodAlgebra(3).is_generic()
3093
+ True
3094
+ sage: SteenrodAlgebra(2).is_generic()
3095
+ False
3096
+ sage: SteenrodAlgebra(2, generic=True).is_generic()
3097
+ True
3098
+ """
3099
+ return self._generic
3100
+
3101
+ ######################################################
3102
+ # element class
3103
+ ######################################################
3104
+
3105
+ class Element(CombinatorialFreeModule.Element):
3106
+ r"""
3107
+ Class for elements of the Steenrod algebra. Since the
3108
+ Steenrod algebra class is based on
3109
+ :class:`CombinatorialFreeModule
3110
+ <sage.combinat.free_module.CombinatorialFreeModule>`, this is
3111
+ based on :class:`IndexedFreeModuleElement
3112
+ <sage.modules.with_basis.indexed_element.IndexedFreeModuleElement>`.
3113
+ It has new methods reflecting its role, like :meth:`degree`
3114
+ for computing the degree of an element.
3115
+
3116
+ EXAMPLES:
3117
+
3118
+ Since this class inherits from
3119
+ :class:`IndexedFreeModuleElement
3120
+ <sage.modules.with_basis.indexed_element.IndexedFreeModuleElement>`,
3121
+ elements can be used as iterators, and there are other useful
3122
+ methods::
3123
+
3124
+ sage: c = Sq(5).antipode(); c
3125
+ Sq(2,1) + Sq(5)
3126
+ sage: for mono, coeff in c: print((coeff, mono))
3127
+ (1, (5,))
3128
+ (1, (2, 1))
3129
+ sage: c.monomial_coefficients() == {(2, 1): 1, (5,): 1}
3130
+ True
3131
+ sage: sorted(c.monomials(), key=lambda x: tuple(x.support()))
3132
+ [Sq(2,1), Sq(5)]
3133
+ sage: sorted(c.support())
3134
+ [(2, 1), (5,)]
3135
+
3136
+ See the documentation for this module (type
3137
+ ``sage.algebras.steenrod.steenrod_algebra?``) for more
3138
+ information about elements of the Steenrod algebra.
3139
+ """
3140
+ def prime(self):
3141
+ """
3142
+ The prime associated to ``self``.
3143
+
3144
+ EXAMPLES::
3145
+
3146
+ sage: a = SteenrodAlgebra().Sq(3,2,1)
3147
+ sage: a.prime()
3148
+ 2
3149
+ sage: a.change_basis('adem').prime()
3150
+ 2
3151
+ sage: b = SteenrodAlgebra(p=7).basis(36)[0]
3152
+ sage: b.prime()
3153
+ 7
3154
+ sage: SteenrodAlgebra(p=3, basis='adem').one().prime()
3155
+ 3
3156
+ """
3157
+ return self.base_ring().characteristic()
3158
+
3159
+ def basis_name(self):
3160
+ """
3161
+ The basis name associated to ``self``.
3162
+
3163
+ EXAMPLES::
3164
+
3165
+ sage: a = SteenrodAlgebra().Sq(3,2,1)
3166
+ sage: a.basis_name()
3167
+ 'milnor'
3168
+ sage: a.change_basis('adem').basis_name()
3169
+ 'serre-cartan'
3170
+ sage: a.change_basis('wood____y').basis_name()
3171
+ 'woody'
3172
+ sage: b = SteenrodAlgebra(p=7).basis(36)[0]
3173
+ sage: b.basis_name()
3174
+ 'milnor'
3175
+ sage: a.change_basis('adem').basis_name()
3176
+ 'serre-cartan'
3177
+ """
3178
+ return self.parent().prefix()
3179
+
3180
+ def is_homogeneous(self):
3181
+ """
3182
+ Return ``True`` iff this element is homogeneous.
3183
+
3184
+ EXAMPLES::
3185
+
3186
+ sage: (Sq(0,0,1) + Sq(7)).is_homogeneous()
3187
+ True
3188
+ sage: (Sq(0,0,1) + Sq(2)).is_homogeneous()
3189
+ False
3190
+ """
3191
+ monos = self.support()
3192
+ if len(monos) <= 1:
3193
+ return True
3194
+ degree = None
3195
+ deg = self.parent().degree_on_basis
3196
+ for mono in monos:
3197
+ if degree is None:
3198
+ degree = deg(mono)
3199
+ elif deg(mono) != degree:
3200
+ return False
3201
+ return True
3202
+
3203
+ def degree(self):
3204
+ r"""
3205
+ The degree of ``self``.
3206
+
3207
+ The degree of `\text{Sq}(i_1,i_2,i_3,...)` is
3208
+
3209
+ .. MATH::
3210
+
3211
+ i_1 + 3i_2 + 7i_3 + ... + (2^k - 1) i_k + ....
3212
+
3213
+ At an odd prime `p`, the degree of `Q_k` is `2p^k - 1` and the
3214
+ degree of `\mathcal{P}(i_1, i_2, ...)` is
3215
+
3216
+ .. MATH::
3217
+
3218
+ \sum_{k \geq 0} 2(p^k - 1) i_k.
3219
+
3220
+ ALGORITHM: If :meth:`is_homogeneous` returns True, call
3221
+ :meth:`SteenrodAlgebra_generic.degree_on_basis` on the leading
3222
+ summand.
3223
+
3224
+ EXAMPLES::
3225
+
3226
+ sage: Sq(0,0,1).degree()
3227
+ 7
3228
+ sage: (Sq(0,0,1) + Sq(7)).degree()
3229
+ 7
3230
+ sage: (Sq(0,0,1) + Sq(2)).degree()
3231
+ Traceback (most recent call last):
3232
+ ...
3233
+ ValueError: element is not homogeneous
3234
+
3235
+ sage: A11 = SteenrodAlgebra(p=11)
3236
+ sage: A11.P(1).degree()
3237
+ 20
3238
+ sage: A11.P(1,1).degree()
3239
+ 260
3240
+ sage: A11.Q(2).degree()
3241
+ 241
3242
+
3243
+ TESTS::
3244
+
3245
+ sage: all(x.degree() == 10 for x in SteenrodAlgebra(basis='woody').basis(10))
3246
+ True
3247
+ sage: all(x.degree() == 11 for x in SteenrodAlgebra(basis='woodz').basis(11))
3248
+ True
3249
+ sage: all(x.degree() == x.milnor().degree() for x in SteenrodAlgebra(basis='wall').basis(11))
3250
+ True
3251
+ sage: a = SteenrodAlgebra(basis='pst').basis(10)[0]
3252
+ sage: a.degree() == a.change_basis('arnonc').degree()
3253
+ True
3254
+ sage: b = SteenrodAlgebra(basis='comm').basis(12)[1]
3255
+ sage: b.degree() == b.change_basis('adem').change_basis('arnona').degree()
3256
+ True
3257
+ sage: all(x.degree() == 9 for x in SteenrodAlgebra(basis='comm').basis(9))
3258
+ True
3259
+ sage: all(x.degree() == 8 for x in SteenrodAlgebra(basis='adem').basis(8))
3260
+ True
3261
+ sage: all(x.degree() == 7 for x in SteenrodAlgebra(basis='milnor').basis(7))
3262
+ True
3263
+ sage: all(x.degree() == 24 for x in SteenrodAlgebra(p=3).basis(24))
3264
+ True
3265
+ sage: all(x.degree() == 40 for x in SteenrodAlgebra(p=5, basis='serre-cartan').basis(40))
3266
+ True
3267
+ """
3268
+ if len(self.support()) == 0:
3269
+ raise ValueError("the zero element does not have a well-defined degree")
3270
+ if not self.is_homogeneous():
3271
+ raise ValueError("element is not homogeneous")
3272
+ return self.parent().degree_on_basis(self.leading_support())
3273
+
3274
+ def milnor(self):
3275
+ """
3276
+ Return this element in the Milnor basis; that is, as an
3277
+ element of the appropriate Steenrod algebra.
3278
+
3279
+ This just calls the method
3280
+ :meth:`SteenrodAlgebra_generic.milnor`.
3281
+
3282
+ EXAMPLES::
3283
+
3284
+ sage: Adem = SteenrodAlgebra(basis='adem')
3285
+ sage: a = Adem.basis(4)[1]; a
3286
+ Sq^3 Sq^1
3287
+ sage: a.milnor()
3288
+ Sq(1,1)
3289
+ """
3290
+ A = self.parent()
3291
+ return A.milnor(self)
3292
+
3293
+ def change_basis(self, basis='milnor'):
3294
+ r"""
3295
+ Representation of element with respect to basis.
3296
+
3297
+ INPUT:
3298
+
3299
+ - ``basis`` -- string; basis in which to work
3300
+
3301
+ OUTPUT: representation of ``self`` in given basis
3302
+
3303
+ The choices for ``basis`` are:
3304
+
3305
+ - 'milnor' for the Milnor basis.
3306
+ - 'serre-cartan', 'serre_cartan', 'sc', 'adem', 'admissible'
3307
+ for the Serre-Cartan basis.
3308
+ - 'wood_y' for Wood's Y basis.
3309
+ - 'wood_z' for Wood's Z basis.
3310
+ - 'wall' for Wall's basis.
3311
+ - 'wall_long' for Wall's basis, alternate representation
3312
+ - 'arnon_a' for Arnon's A basis.
3313
+ - 'arnon_a_long' for Arnon's A basis, alternate representation.
3314
+ - 'arnon_c' for Arnon's C basis.
3315
+ - 'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz' for
3316
+ various `P^s_t`-bases.
3317
+ - 'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz'
3318
+ for various commutator bases.
3319
+ - 'comm_long', 'comm_rlex_long', etc., for commutator bases,
3320
+ alternate representations.
3321
+
3322
+ See documentation for this module (by browsing the
3323
+ reference manual or by typing
3324
+ ``sage.algebras.steenrod.steenrod_algebra?``) for
3325
+ descriptions of the different bases.
3326
+
3327
+ EXAMPLES::
3328
+
3329
+ sage: c = Sq(2) * Sq(1)
3330
+ sage: c.change_basis('milnor')
3331
+ Sq(0,1) + Sq(3)
3332
+ sage: c.change_basis('serre-cartan')
3333
+ Sq^2 Sq^1
3334
+ sage: d = Sq(0,0,1)
3335
+ sage: d.change_basis('arnonc')
3336
+ Sq^2 Sq^5 + Sq^4 Sq^2 Sq^1 + Sq^4 Sq^3 + Sq^7
3337
+ """
3338
+ A = self.parent()
3339
+ return A._change_basis(self, basis)
3340
+
3341
+ def _basis_dictionary(self, basis):
3342
+ r"""
3343
+ Convert ``self`` to ``basis``, returning a dictionary of terms of
3344
+ the form (mono: coeff), where mono is a monomial in the given
3345
+ basis.
3346
+
3347
+ INPUT:
3348
+
3349
+ - ``basis`` -- string, basis in which to work
3350
+
3351
+ OUTPUT: dictionary
3352
+
3353
+ This just calls :meth:`change_basis` to get an element of the
3354
+ Steenrod algebra with the new basis, and then calls
3355
+ :meth:`monomial_coefficients` on this element to produce its
3356
+ dictionary representation.
3357
+
3358
+ EXAMPLES::
3359
+
3360
+ sage: c = Sq(2) * Sq(1)
3361
+ sage: c._basis_dictionary('milnor') == {(0, 1): 1, (3,): 1}
3362
+ True
3363
+ sage: c
3364
+ Sq(0,1) + Sq(3)
3365
+ sage: c._basis_dictionary('serre-cartan')
3366
+ {(2, 1): 1}
3367
+ sage: c.change_basis('serre-cartan')
3368
+ Sq^2 Sq^1
3369
+ sage: d = Sq(0,0,1)
3370
+ sage: sorted(d._basis_dictionary('arnonc').items())
3371
+ [((2, 5), 1), ((4, 2, 1), 1), ((4, 3), 1), ((7,), 1)]
3372
+ sage: d.change_basis('arnonc')
3373
+ Sq^2 Sq^5 + Sq^4 Sq^2 Sq^1 + Sq^4 Sq^3 + Sq^7
3374
+
3375
+ At odd primes::
3376
+
3377
+ sage: e = 2 * SteenrodAlgebra(3).P(1,2)
3378
+ sage: e._basis_dictionary('milnor')
3379
+ {((), (1, 2)): 2}
3380
+ sage: e
3381
+ 2 P(1,2)
3382
+ sage: sorted(e._basis_dictionary('serre-cartan').items())
3383
+ [((0, 7, 0, 2, 0), 2), ((0, 8, 0, 1, 0), 2)]
3384
+ sage: e.change_basis('adem')
3385
+ 2 P^7 P^2 + 2 P^8 P^1
3386
+ """
3387
+ a = self.change_basis(basis)
3388
+ return a.monomial_coefficients()
3389
+
3390
+ def coproduct(self, algorithm='milnor'):
3391
+ """
3392
+ The coproduct of this element.
3393
+
3394
+ INPUT:
3395
+
3396
+ - ``algorithm`` -- ``None`` or a string, either 'milnor' or
3397
+ 'serre-cartan' (or anything which will be converted to
3398
+ one of these by the function :func:`get_basis_name
3399
+ <sage.algebras.steenrod.steenrod_algebra_misc.get_basis_name>`).
3400
+ If ``None``, default to 'serre-cartan' if current basis is
3401
+ 'serre-cartan'; otherwise use 'milnor'.
3402
+
3403
+ See :meth:`SteenrodAlgebra_generic.coproduct_on_basis` for
3404
+ more information on computing the coproduct.
3405
+
3406
+ EXAMPLES::
3407
+
3408
+ sage: a = Sq(2)
3409
+ sage: a.coproduct()
3410
+ 1 # Sq(2) + Sq(1) # Sq(1) + Sq(2) # 1
3411
+ sage: b = Sq(4)
3412
+ sage: (a*b).coproduct() == (a.coproduct()) * (b.coproduct())
3413
+ True
3414
+
3415
+ sage: c = a.change_basis('adem'); c.coproduct(algorithm='milnor')
3416
+ 1 # Sq^2 + Sq^1 # Sq^1 + Sq^2 # 1
3417
+ sage: c = a.change_basis('adem'); c.coproduct(algorithm='adem')
3418
+ 1 # Sq^2 + Sq^1 # Sq^1 + Sq^2 # 1
3419
+
3420
+ sage: d = a.change_basis('comm_long'); d.coproduct()
3421
+ 1 # s_2 + s_1 # s_1 + s_2 # 1
3422
+
3423
+ sage: A7 = SteenrodAlgebra(p=7)
3424
+ sage: a = A7.Q(1) * A7.P(1); a
3425
+ Q_1 P(1)
3426
+ sage: a.coproduct()
3427
+ 1 # Q_1 P(1) + P(1) # Q_1 + Q_1 # P(1) + Q_1 P(1) # 1
3428
+ sage: a.coproduct(algorithm='adem')
3429
+ 1 # Q_1 P(1) + P(1) # Q_1 + Q_1 # P(1) + Q_1 P(1) # 1
3430
+
3431
+ Once you have an element of the tensor product, you may
3432
+ want to extract the tensor factors of its summands. ::
3433
+
3434
+ sage: b = Sq(2).coproduct()
3435
+ sage: b
3436
+ 1 # Sq(2) + Sq(1) # Sq(1) + Sq(2) # 1
3437
+ sage: supp = sorted(b.support()); supp
3438
+ [((), (2,)), ((1,), (1,)), ((2,), ())]
3439
+ sage: Sq(*supp[0][0])
3440
+ 1
3441
+ sage: Sq(*supp[0][1])
3442
+ Sq(2)
3443
+ sage: [(Sq(*x), Sq(*y)) for (x,y) in supp]
3444
+ [(1, Sq(2)), (Sq(1), Sq(1)), (Sq(2), 1)]
3445
+
3446
+ The ``support`` of an element does not include the
3447
+ coefficients, so at odd primes it may be better to use
3448
+ ``monomial_coefficients``::
3449
+
3450
+ sage: A3 = SteenrodAlgebra(p=3)
3451
+ sage: b = (A3.P(1)**2).coproduct()
3452
+ sage: b
3453
+ 2*1 # P(2) + 2*P(1) # P(1) + 2*P(2) # 1
3454
+ sage: sorted(b.support())
3455
+ [(((), ()), ((), (2,))), (((), (1,)), ((), (1,))), (((), (2,)), ((), ()))]
3456
+ sage: b.monomial_coefficients()
3457
+ {(((), ()), ((), (2,))): 2,
3458
+ (((), (1,)), ((), (1,))): 2,
3459
+ (((), (2,)), ((), ())): 2}
3460
+ sage: mc = b.monomial_coefficients()
3461
+ sage: sorted([(A3.monomial(x), A3.monomial(y), mc[x,y]) for (x,y) in mc])
3462
+ [(1, P(2), 2), (P(1), P(1), 2), (P(2), 1, 2)]
3463
+ """
3464
+ A = self.parent()
3465
+ return A.coproduct(self, algorithm=algorithm)
3466
+
3467
+ def excess(self):
3468
+ r"""
3469
+ Excess of element.
3470
+
3471
+ OUTPUT: ``excess`` -- nonnegative integer
3472
+
3473
+ The excess of a Milnor basis element `\text{Sq}(a,b,c,...)` is
3474
+ `a + b + c + \cdots`. When `p` is odd, the excess of `Q_{0}^{e_0}
3475
+ Q_{1}^{e_1} \cdots P(r_1, r_2, ...)` is `\sum e_i + 2 \sum r_i`.
3476
+ The excess of a linear combination of Milnor basis elements is
3477
+ the minimum of the excesses of those basis elements.
3478
+
3479
+ See [Kr1971]_ for the proofs of these assertions.
3480
+
3481
+ EXAMPLES::
3482
+
3483
+ sage: a = Sq(1,2,3)
3484
+ sage: a.excess()
3485
+ 6
3486
+ sage: (Sq(0,0,1) + Sq(4,1) + Sq(7)).excess()
3487
+ 1
3488
+ sage: elt = Sq(0,0,1) + Sq(4,1) + Sq(7)
3489
+ sage: M = sorted(elt.monomials(), key=lambda x: tuple(x.support()))
3490
+ sage: [m.excess() for m in M]
3491
+ [1, 5, 7]
3492
+ sage: [m for m in M]
3493
+ [Sq(0,0,1), Sq(4,1), Sq(7)]
3494
+ sage: B = SteenrodAlgebra(7)
3495
+ sage: a = B.Q(1,2,5)
3496
+ sage: b = B.P(2,2,3)
3497
+ sage: a.excess()
3498
+ 3
3499
+ sage: b.excess()
3500
+ 14
3501
+ sage: (a + b).excess()
3502
+ 3
3503
+ sage: (a * b).excess()
3504
+ 17
3505
+ """
3506
+ def excess_odd(mono):
3507
+ """
3508
+ Excess of mono, where mono has the form
3509
+ ((s0, s1, ...), (r1, r2, ...)).
3510
+
3511
+ Return the length of the first component, since that
3512
+ is the number of factors, plus twice the sum of the
3513
+ terms in the second component.
3514
+ """
3515
+ if not mono:
3516
+ return 0
3517
+ else:
3518
+ return len(mono[0]) + 2 * sum(mono[1])
3519
+
3520
+ a = self.milnor()
3521
+ if not self.parent()._generic:
3522
+ excesses = [sum(mono) for mono in a.support()]
3523
+ else:
3524
+ excesses = [excess_odd(mono) for mono in a.support()]
3525
+ return min(excesses)
3526
+
3527
+ def is_unit(self):
3528
+ r"""
3529
+ Return ``True`` if element has a nonzero scalar multiple of
3530
+ `P(0)` as a summand, ``False`` otherwise.
3531
+
3532
+ EXAMPLES::
3533
+
3534
+ sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
3535
+ sage: z.is_unit()
3536
+ False
3537
+ sage: u = Sq(0) + Sq(3,1)
3538
+ sage: u == 1 + Sq(3,1)
3539
+ True
3540
+ sage: u.is_unit()
3541
+ True
3542
+ sage: A5 = SteenrodAlgebra(5)
3543
+ sage: v = A5.P(0)
3544
+ sage: (v + v + v).is_unit()
3545
+ True
3546
+ """
3547
+ return self.parent().one() in self.monomials()
3548
+
3549
+ def is_nilpotent(self):
3550
+ """
3551
+ Return ``True`` if element is not a unit, ``False`` otherwise.
3552
+
3553
+ EXAMPLES::
3554
+
3555
+ sage: z = Sq(4,2) + Sq(7,1) + Sq(3,0,1)
3556
+ sage: z.is_nilpotent()
3557
+ True
3558
+ sage: u = 1 + Sq(3,1)
3559
+ sage: u == 1 + Sq(3,1)
3560
+ True
3561
+ sage: u.is_nilpotent()
3562
+ False
3563
+ """
3564
+ return not self.is_unit()
3565
+
3566
+ def may_weight(self):
3567
+ r"""
3568
+ May's 'weight' of element.
3569
+
3570
+ OUTPUT: ``weight`` -- nonnegative integer
3571
+
3572
+ If we let `F_* (A)` be the May filtration of the Steenrod
3573
+ algebra, the weight of an element `x` is the integer `k` so
3574
+ that `x` is in `F_k(A)` and not in `F_{k+1}(A)`. According to
3575
+ Theorem 2.6 in May's thesis [May1964]_, the weight of a Milnor
3576
+ basis element is computed as follows: first, to compute the
3577
+ weight of `P(r_1,r_2, ...)`, write each `r_i` in base `p` as
3578
+ `r_i = \sum_j p^j r_{ij}`. Then each nonzero binary digit
3579
+ `r_{ij}` contributes `i` to the weight: the weight is
3580
+ `\sum_{i,j} i r_{ij}`. When `p` is odd, the weight of `Q_i` is
3581
+ `i+1`, so the weight of a product `Q_{i_1} Q_{i_2} ...` equals
3582
+ `(i_1+1) + (i_2+1) + ...`. Then the weight of `Q_{i_1} Q_{i_2}
3583
+ ...P(r_1,r_2, ...)` is the sum of `(i_1+1) + (i_2+1) + ...`
3584
+ and `\sum_{i,j} i r_{ij}`.
3585
+
3586
+ The weight of a sum of Milnor basis elements is the minimum of
3587
+ the weights of the summands.
3588
+
3589
+ When `p=2`, we compute the weight on Milnor basis elements by
3590
+ adding up the terms in their 'height' - see
3591
+ :meth:`wall_height` for documentation. (When `p` is odd, the
3592
+ height of an element is not defined.)
3593
+
3594
+ EXAMPLES::
3595
+
3596
+ sage: Sq(0).may_weight()
3597
+ 0
3598
+ sage: a = Sq(4)
3599
+ sage: a.may_weight()
3600
+ 1
3601
+ sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
3602
+ sage: b.may_weight()
3603
+ 2
3604
+ sage: Sq(2,1,5).wall_height()
3605
+ [2, 3, 2, 1, 1]
3606
+ sage: Sq(2,1,5).may_weight()
3607
+ 9
3608
+ sage: A5 = SteenrodAlgebra(5)
3609
+ sage: a = A5.Q(1,2,4)
3610
+ sage: b = A5.P(1,2,1)
3611
+ sage: a.may_weight()
3612
+ 10
3613
+ sage: b.may_weight()
3614
+ 8
3615
+ sage: (a * b).may_weight()
3616
+ 18
3617
+ sage: A5.P(0,0,1).may_weight()
3618
+ 3
3619
+ """
3620
+ from sage.rings.infinity import Infinity
3621
+ from sage.rings.integer import Integer
3622
+ p = self.prime()
3623
+ generic = self.parent()._generic
3624
+ if self == 0:
3625
+ return Infinity
3626
+ elif self.is_unit():
3627
+ return 0
3628
+ elif not generic:
3629
+ wt = Infinity
3630
+ for mono in self.milnor().monomials():
3631
+ wt = min(wt, sum(mono.wall_height()))
3632
+ return wt
3633
+ else: # p odd
3634
+ wt = Infinity
3635
+ for (mono1, mono2) in self.milnor().support():
3636
+ P_wt = 0
3637
+ index = 1
3638
+ for n in mono2:
3639
+ P_wt += index * sum(Integer(n).digits(p))
3640
+ index += 1
3641
+ wt = min(wt, sum(mono1) + len(mono1) + P_wt)
3642
+ return wt
3643
+
3644
+ def is_decomposable(self):
3645
+ r"""
3646
+ Return ``True`` if element is decomposable, ``False`` otherwise.
3647
+
3648
+ That is, if element is in the square of the augmentation ideal,
3649
+ return ``True``; otherwise, return ``False``.
3650
+
3651
+ OUTPUT: boolean
3652
+
3653
+ EXAMPLES::
3654
+
3655
+ sage: a = Sq(6)
3656
+ sage: a.is_decomposable()
3657
+ True
3658
+ sage: for i in range(9):
3659
+ ....: if not Sq(i).is_decomposable():
3660
+ ....: print(Sq(i))
3661
+ 1
3662
+ Sq(1)
3663
+ Sq(2)
3664
+ Sq(4)
3665
+ Sq(8)
3666
+ sage: A3 = SteenrodAlgebra(p=3, basis='adem')
3667
+ sage: [A3.P(n) for n in range(30) if not A3.P(n).is_decomposable()]
3668
+ [1, P^1, P^3, P^9, P^27]
3669
+
3670
+ TESTS:
3671
+
3672
+ These all test changing bases and printing in various bases::
3673
+
3674
+ sage: A = SteenrodAlgebra(basis='milnor')
3675
+ sage: [A.Sq(n) for n in range(9) if not A.Sq(n).is_decomposable()]
3676
+ [1, Sq(1), Sq(2), Sq(4), Sq(8)]
3677
+ sage: A = SteenrodAlgebra(basis='wall_long')
3678
+ sage: [A.Sq(n) for n in range(9) if not A.Sq(n).is_decomposable()]
3679
+ [1, Sq^1, Sq^2, Sq^4, Sq^8]
3680
+ sage: A = SteenrodAlgebra(basis='arnona_long')
3681
+ sage: [A.Sq(n) for n in range(9) if not A.Sq(n).is_decomposable()]
3682
+ [1, Sq^1, Sq^2, Sq^4, Sq^8]
3683
+ sage: A = SteenrodAlgebra(basis='woodz')
3684
+ sage: [A.Sq(n) for n in range(20) if not A.Sq(n).is_decomposable()] # long time
3685
+ [1, Sq^1, Sq^2, Sq^4, Sq^8, Sq^16]
3686
+ sage: A = SteenrodAlgebra(basis='comm_long')
3687
+ sage: [A.Sq(n) for n in range(25) if not A.Sq(n).is_decomposable()] # long time
3688
+ [1, s_1, s_2, s_4, s_8, s_16]
3689
+ """
3690
+ return self.may_weight() > 1
3691
+
3692
+ def wall_height(self):
3693
+ r"""
3694
+ Wall's 'height' of element.
3695
+
3696
+ OUTPUT: list of nonnegative integers
3697
+
3698
+ The height of an element of the mod 2 Steenrod algebra is a
3699
+ list of nonnegative integers, defined as follows: if the
3700
+ element is a monomial in the generators `\text{Sq}(2^i)`, then
3701
+ the `i`-th entry in the list is the number of times
3702
+ `\text{Sq}(2^i)` appears. For an arbitrary element, write it
3703
+ as a sum of such monomials; then its height is the maximum,
3704
+ ordered right-lexicographically, of the heights of those
3705
+ monomials.
3706
+
3707
+ When `p` is odd, the height of an element is not defined.
3708
+
3709
+ According to Theorem 3 in [Wal1960]_, the height of the Milnor
3710
+ basis element `\text{Sq}(r_1, r_2, ...)` is obtained as
3711
+ follows: write each `r_i` in binary as `r_i = \sum_j 2^j
3712
+ r_{ij}`. Then each nonzero binary digit `r_{ij}` contributes 1
3713
+ to the `k`-th entry in the height, for `j \leq k \leq
3714
+ i+j-1`.
3715
+
3716
+ EXAMPLES::
3717
+
3718
+ sage: Sq(0).wall_height()
3719
+ []
3720
+ sage: a = Sq(4)
3721
+ sage: a.wall_height()
3722
+ [0, 0, 1]
3723
+ sage: b = Sq(4)*Sq(8) + Sq(8)*Sq(4)
3724
+ sage: b.wall_height()
3725
+ [0, 0, 1, 1]
3726
+ sage: Sq(0,0,3).wall_height()
3727
+ [1, 2, 2, 1]
3728
+ """
3729
+ from sage.rings.integer import Integer
3730
+ if self.parent()._generic:
3731
+ raise NotImplementedError("Wall height is not defined at odd primes")
3732
+ if self == 0 or self == 1:
3733
+ return []
3734
+ result = []
3735
+ deg = self.parent().degree_on_basis
3736
+ for r in self.milnor().support():
3737
+ h = [0]*(1 + deg(r))
3738
+ i = 1
3739
+ for x in r:
3740
+ if x > 0:
3741
+ for j in range(1+Integer(x).exact_log(2)):
3742
+ if (2**j & x) != 0:
3743
+ for k in range(j, i+j):
3744
+ h[k] += 1
3745
+ i += 1
3746
+ h.reverse()
3747
+ result = max(h, result)
3748
+ result.reverse()
3749
+ while result and result[-1] == 0:
3750
+ result = result[:-1]
3751
+ return result
3752
+
3753
+ def additive_order(self):
3754
+ """
3755
+ The additive order of any nonzero element of the mod p
3756
+ Steenrod algebra is p.
3757
+
3758
+ OUTPUT: 1 (for the zero element) or p (for anything else)
3759
+
3760
+ EXAMPLES::
3761
+
3762
+ sage: z = Sq(4) + Sq(6) + 1
3763
+ sage: z.additive_order()
3764
+ 2
3765
+ sage: (Sq(3) + Sq(3)).additive_order()
3766
+ 1
3767
+ """
3768
+ if self == 0:
3769
+ return 1
3770
+ return self.prime()
3771
+
3772
+
3773
+ class SteenrodAlgebra_mod_two(SteenrodAlgebra_generic):
3774
+ """
3775
+ The mod 2 Steenrod algebra.
3776
+
3777
+ Users should not call this, but use the function
3778
+ :func:`SteenrodAlgebra` instead. See that function for extensive
3779
+ documentation. (This differs from :class:`SteenrodAlgebra_generic`
3780
+ only in that it has a method :meth:`Sq` for defining elements.)
3781
+ """
3782
+ def Sq(self, *nums):
3783
+ r"""
3784
+ Milnor element `\text{Sq}(a,b,c,...)`.
3785
+
3786
+ INPUT:
3787
+
3788
+ - ``a``, ``b``, ``c``, ... -- nonnegative integers
3789
+
3790
+ OUTPUT: element of the Steenrod algebra
3791
+
3792
+ This returns the Milnor basis element
3793
+ `\text{Sq}(a, b, c, ...)`.
3794
+
3795
+ EXAMPLES::
3796
+
3797
+ sage: A = SteenrodAlgebra(2)
3798
+ sage: A.Sq(5)
3799
+ Sq(5)
3800
+ sage: A.Sq(5,0,2)
3801
+ Sq(5,0,2)
3802
+
3803
+ Entries must be nonnegative integers; otherwise, an error
3804
+ results.
3805
+ """
3806
+ if self.prime() == 2:
3807
+ return self.P(*nums)
3808
+ else:
3809
+ raise ValueError("Sq is only defined at the prime 2")
3810
+
3811
+
3812
+ def SteenrodAlgebra(p=2, basis='milnor', generic='auto', **kwds):
3813
+ r"""
3814
+ The mod `p` Steenrod algebra.
3815
+
3816
+ INPUT:
3817
+
3818
+ - ``p`` -- positive prime integer (default: 2)
3819
+ - ``basis`` -- string (default: ``'milnor'``)
3820
+ - ``profile`` -- a profile function in form specified below (default: ``None``)
3821
+ - ``truncation_type`` -- 0 or `\infty` or 'auto' (default: ``'auto'``)
3822
+ - ``precision`` -- integer or ``None`` (default: ``None``)
3823
+ - ``generic`` -- (default: ``'auto'``)
3824
+
3825
+ OUTPUT:
3826
+
3827
+ mod `p` Steenrod algebra or one of its sub-Hopf algebras,
3828
+ elements of which are printed using ``basis``
3829
+
3830
+ See below for information about ``basis``, ``profile``, etc.
3831
+
3832
+ EXAMPLES:
3833
+
3834
+ Some properties of the Steenrod algebra are available::
3835
+
3836
+ sage: A = SteenrodAlgebra(2)
3837
+ sage: A.order()
3838
+ +Infinity
3839
+ sage: A.is_finite()
3840
+ False
3841
+ sage: A.is_commutative()
3842
+ False
3843
+ sage: A.is_noetherian()
3844
+ False
3845
+ sage: A.is_integral_domain()
3846
+ False
3847
+ sage: A.is_field()
3848
+ False
3849
+ sage: A.is_division_algebra()
3850
+ False
3851
+ sage: A.category()
3852
+ Category of supercocommutative super Hopf algebras
3853
+ with basis over Finite Field of size 2
3854
+
3855
+ There are methods for constructing elements of the Steenrod
3856
+ algebra::
3857
+
3858
+ sage: A2 = SteenrodAlgebra(2); A2
3859
+ mod 2 Steenrod algebra, milnor basis
3860
+ sage: A2.Sq(1,2,6)
3861
+ Sq(1,2,6)
3862
+ sage: A2.Q(3,4) # product of Milnor primitives Q_3 and Q_4
3863
+ Sq(0,0,0,1,1)
3864
+ sage: A2.pst(2,3) # Margolis pst element
3865
+ Sq(0,0,4)
3866
+ sage: A5 = SteenrodAlgebra(5); A5
3867
+ mod 5 Steenrod algebra, milnor basis
3868
+ sage: A5.P(1,2,6)
3869
+ P(1,2,6)
3870
+ sage: A5.Q(3,4)
3871
+ Q_3 Q_4
3872
+ sage: A5.Q(3,4) * A5.P(1,2,6)
3873
+ Q_3 Q_4 P(1,2,6)
3874
+ sage: A5.pst(2,3)
3875
+ P(0,0,25)
3876
+
3877
+ You can test whether elements are contained in the Steenrod
3878
+ algebra::
3879
+
3880
+ sage: w = Sq(2) * Sq(4)
3881
+ sage: w in SteenrodAlgebra(2)
3882
+ True
3883
+ sage: w in SteenrodAlgebra(17)
3884
+ False
3885
+
3886
+ .. rubric:: Different bases for the Steenrod algebra:
3887
+
3888
+ There are two standard vector space bases for the mod `p` Steenrod
3889
+ algebra: the Milnor basis and the Serre-Cartan basis. When `p=2`,
3890
+ there are also several other, less well-known, bases. See the
3891
+ documentation for this module (type
3892
+ ``sage.algebras.steenrod.steenrod_algebra?``) and the function
3893
+ :func:`steenrod_algebra_basis
3894
+ <sage.algebras.steenrod.steenrod_algebra_bases.steenrod_algebra_basis_>`
3895
+ for full descriptions of each of the implemented bases.
3896
+
3897
+ This module implements the following bases at all primes:
3898
+
3899
+ - 'milnor': Milnor basis.
3900
+
3901
+ - 'serre-cartan' or 'adem' or 'admissible': Serre-Cartan basis.
3902
+
3903
+ - 'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz': various
3904
+ `P^s_t`-bases.
3905
+
3906
+ - 'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz', or
3907
+ these with '_long' appended: various commutator bases.
3908
+
3909
+ It implements the following bases when `p=2`:
3910
+
3911
+ - 'wood_y': Wood's Y basis.
3912
+
3913
+ - 'wood_z': Wood's Z basis.
3914
+
3915
+ - 'wall', 'wall_long': Wall's basis.
3916
+
3917
+ - 'arnon_a', 'arnon_a_long': Arnon's A basis.
3918
+
3919
+ - 'arnon_c': Arnon's C basis.
3920
+
3921
+ When defining a Steenrod algebra, you can specify a basis. Then
3922
+ elements of that Steenrod algebra are printed in that basis::
3923
+
3924
+ sage: adem = SteenrodAlgebra(2, 'adem')
3925
+ sage: x = adem.Sq(2,1) # Sq(-) always means a Milnor basis element
3926
+ sage: x
3927
+ Sq^4 Sq^1 + Sq^5
3928
+ sage: y = Sq(0,1) # unadorned Sq defines elements w.r.t. Milnor basis
3929
+ sage: y
3930
+ Sq(0,1)
3931
+ sage: adem(y)
3932
+ Sq^2 Sq^1 + Sq^3
3933
+ sage: adem5 = SteenrodAlgebra(5, 'serre-cartan')
3934
+ sage: adem5.P(0,2)
3935
+ P^10 P^2 + 4 P^11 P^1 + P^12
3936
+
3937
+ If you add or multiply elements defined using different bases, the
3938
+ left-hand factor determines the form of the output::
3939
+
3940
+ sage: SteenrodAlgebra(basis='adem').Sq(3) + SteenrodAlgebra(basis='pst').Sq(0,1)
3941
+ Sq^2 Sq^1
3942
+ sage: SteenrodAlgebra(basis='pst').Sq(3) + SteenrodAlgebra(basis='milnor').Sq(0,1)
3943
+ P^0_1 P^1_1 + P^0_2
3944
+ sage: SteenrodAlgebra(basis='milnor').Sq(2) * SteenrodAlgebra(basis='arnonc').Sq(2)
3945
+ Sq(1,1)
3946
+
3947
+ You can get a list of basis elements in a given dimension::
3948
+
3949
+ sage: A3 = SteenrodAlgebra(3, 'milnor')
3950
+ sage: A3.basis(13)
3951
+ Family (Q_1 P(2), Q_0 P(3))
3952
+
3953
+ Algebras defined over different bases are not equal::
3954
+
3955
+ sage: SteenrodAlgebra(basis='milnor') == SteenrodAlgebra(basis='pst')
3956
+ False
3957
+
3958
+ Bases have various synonyms, and in general Sage tries to figure
3959
+ out what basis you meant::
3960
+
3961
+ sage: SteenrodAlgebra(basis='MiLNOr')
3962
+ mod 2 Steenrod algebra, milnor basis
3963
+ sage: SteenrodAlgebra(basis='MiLNOr') == SteenrodAlgebra(basis='milnor')
3964
+ True
3965
+ sage: SteenrodAlgebra(basis='adem')
3966
+ mod 2 Steenrod algebra, serre-cartan basis
3967
+ sage: SteenrodAlgebra(basis='adem').basis_name()
3968
+ 'serre-cartan'
3969
+ sage: SteenrodAlgebra(basis='wood---z---').basis_name()
3970
+ 'woodz'
3971
+
3972
+ As noted above, several of the bases ('arnon_a', 'wall', 'comm')
3973
+ have alternate, sometimes longer, representations. These provide
3974
+ ways of expressing elements of the Steenrod algebra in terms of
3975
+ the `\text{Sq}^{2^n}`.
3976
+
3977
+ ::
3978
+
3979
+ sage: A_long = SteenrodAlgebra(2, 'arnon_a_long')
3980
+ sage: A_long(Sq(6))
3981
+ Sq^1 Sq^2 Sq^1 Sq^2 + Sq^2 Sq^4
3982
+ sage: SteenrodAlgebra(2, 'wall_long')(Sq(6))
3983
+ Sq^2 Sq^1 Sq^2 Sq^1 + Sq^2 Sq^4
3984
+ sage: SteenrodAlgebra(2, 'comm_deg_long')(Sq(6))
3985
+ s_1 s_2 s_12 + s_2 s_4
3986
+
3987
+ .. rubric:: Sub-Hopf algebras of the Steenrod algebra:
3988
+
3989
+ These are specified using the argument ``profile``, along with,
3990
+ optionally, ``truncation_type`` and ``precision``. The
3991
+ ``profile`` argument specifies the profile function for this
3992
+ algebra. Any sub-Hopf algebra of the Steenrod algebra is
3993
+ determined by its *profile function*. When `p=2`, this is a map `e`
3994
+ from the positive integers to the set of nonnegative integers,
3995
+ plus `\infty`, corresponding to the sub-Hopf algebra dual to this
3996
+ quotient of the dual Steenrod algebra:
3997
+
3998
+ .. MATH::
3999
+
4000
+ \GF{2} [\xi_1, \xi_2, \xi_3, ...] / (\xi_1^{2^{e(1)}}, \xi_2^{2^{e(2)}}, \xi_3^{2^{e(3)}}, ...).
4001
+
4002
+ The profile function `e` must satisfy the condition
4003
+
4004
+ - `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`.
4005
+
4006
+ This is specified via ``profile``, and optionally ``precision``
4007
+ and ``truncation_type``. First, ``profile`` must have one of the
4008
+ following forms:
4009
+
4010
+ - a list or tuple, e.g., ``[3,2,1]``, corresponding to the
4011
+ function sending 1 to 3, 2 to 2, 3 to 1, and all other integers
4012
+ to the value of ``truncation_type``.
4013
+ - a function from positive integers to nonnegative integers (and
4014
+ `\infty`), e.g., ``lambda n: n+2``.
4015
+ - ``None`` or ``Infinity`` -- use this for the profile function for
4016
+ the whole Steenrod algebra
4017
+
4018
+ In the first and third cases, ``precision`` is ignored. In the
4019
+ second case, this function is converted to a tuple of length one
4020
+ less than ``precision``, which has default value 100. The
4021
+ function is truncated at this point, and all remaining values are
4022
+ set to the value of ``truncation_type``.
4023
+
4024
+ ``truncation_type`` may be 0, `\infty`, or 'auto'. If it's
4025
+ 'auto', then it gets converted to 0 in the first case above (when
4026
+ ``profile`` is a list), and otherwise (when ``profile`` is a
4027
+ function, ``None``, or ``Infinity``) it gets converted to `\infty`.
4028
+
4029
+ For example, the sub-Hopf algebra `A(2)` has profile function
4030
+ ``[3,2,1,0,0,0,...]``, so it can be defined by any of the
4031
+ following::
4032
+
4033
+ sage: A2 = SteenrodAlgebra(profile=[3,2,1])
4034
+ sage: B2 = SteenrodAlgebra(profile=[3,2,1,0,0]) # trailing 0s ignored
4035
+ sage: A2 == B2
4036
+ True
4037
+ sage: C2 = SteenrodAlgebra(profile=lambda n: max(4-n, 0), truncation_type=0)
4038
+ sage: A2 == C2
4039
+ True
4040
+
4041
+ In the following case, the profile function is specified by a
4042
+ function and ``truncation_type`` isn't specified, so it defaults
4043
+ to `\infty`; therefore this gives a different sub-Hopf algebra::
4044
+
4045
+ sage: D2 = SteenrodAlgebra(profile=lambda n: max(4-n, 0))
4046
+ sage: A2 == D2
4047
+ False
4048
+ sage: D2.is_finite()
4049
+ False
4050
+ sage: E2 = SteenrodAlgebra(profile=lambda n: max(4-n, 0), truncation_type=Infinity)
4051
+ sage: D2 == E2
4052
+ True
4053
+
4054
+ The argument ``precision`` only needs to be specified if the
4055
+ profile function is defined by a function and you want to control
4056
+ when the profile switches from the given function to the
4057
+ truncation type. For example::
4058
+
4059
+ sage: D3 = SteenrodAlgebra(profile=lambda n: n, precision=3)
4060
+ sage: D3
4061
+ sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [1, 2, +Infinity, +Infinity, +Infinity, ...]
4062
+ sage: D4 = SteenrodAlgebra(profile=lambda n: n, precision=4); D4
4063
+ sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [1, 2, 3, +Infinity, +Infinity, +Infinity, ...]
4064
+ sage: D3 == D4
4065
+ False
4066
+
4067
+ When `p` is odd, ``profile`` is a pair of functions `e` and `k`,
4068
+ corresponding to the quotient
4069
+
4070
+ .. MATH::
4071
+
4072
+ \GF{p} [\xi_1, \xi_2, \xi_3, ...] \otimes \Lambda (\tau_0,
4073
+ \tau_1, ...) / (\xi_1^{p^{e_1}}, \xi_2^{p^{e_2}}, ...;
4074
+ \tau_0^{k_0}, \tau_1^{k_1}, ...).
4075
+
4076
+ Together, the functions `e` and `k` must satisfy the conditions
4077
+
4078
+ - `e(r) \geq \min( e(r-i) - i, e(i))` for all `0 < i < r`,
4079
+
4080
+ - if `k(i+j) = 1`, then either `e(i) \leq j` or `k(j) = 1` for all `i
4081
+ \geq 1`, `j \geq 0`.
4082
+
4083
+ Therefore ``profile`` must have one of the following forms:
4084
+
4085
+ - a pair of lists or tuples, the second of which takes values in
4086
+ the set `\{1,2\}`, e.g., ``([3,2,1,1], [1,1,2,2,1])``.
4087
+
4088
+ - a pair of functions, one from the positive integers to
4089
+ nonnegative integers (and `\infty`), one from the nonnegative
4090
+ integers to the set `\{1,2\}`, e.g., ``(lambda n: n+2, lambda n:
4091
+ 1 if n<3 else 2)``.
4092
+
4093
+ - ``None`` or ``Infinity`` -- use this for the profile function for
4094
+ the whole Steenrod algebra
4095
+
4096
+ You can also mix and match the first two, passing a pair with
4097
+ first entry a list and second entry a function, for instance. The
4098
+ values of ``precision`` and ``truncation_type`` are determined by
4099
+ the first entry.
4100
+
4101
+ More examples::
4102
+
4103
+ sage: E = SteenrodAlgebra(profile=lambda n: 0 if n<3 else 3, truncation_type=0)
4104
+ sage: E.is_commutative()
4105
+ True
4106
+
4107
+ sage: A2 = SteenrodAlgebra(profile=[3,2,1]) # the algebra A(2)
4108
+ sage: Sq(7,3,1) in A2
4109
+ True
4110
+ sage: Sq(8) in A2
4111
+ False
4112
+ sage: Sq(8) in SteenrodAlgebra().basis(8)
4113
+ True
4114
+ sage: Sq(8) in A2.basis(8)
4115
+ False
4116
+ sage: A2.basis(8)
4117
+ Family (Sq(1,0,1), Sq(2,2), Sq(5,1))
4118
+
4119
+ sage: A5 = SteenrodAlgebra(p=5)
4120
+ sage: A51 = SteenrodAlgebra(p=5, profile=([1], [2,2]))
4121
+ sage: A5.Q(0,1) * A5.P(4) in A51
4122
+ True
4123
+ sage: A5.Q(2) in A51
4124
+ False
4125
+ sage: A5.P(5) in A51
4126
+ False
4127
+
4128
+ For sub-Hopf algebras of the Steenrod algebra, only the Milnor
4129
+ basis or the various `P^s_t`-bases may be used. ::
4130
+
4131
+ sage: SteenrodAlgebra(profile=[1,2,1,1], basis='adem')
4132
+ Traceback (most recent call last):
4133
+ ...
4134
+ NotImplementedError: for sub-Hopf algebras of the Steenrod algebra, only the Milnor basis and the pst bases are implemented
4135
+
4136
+ .. rubric:: The generic Steenrod algebra at the prime `2`:
4137
+
4138
+ The structure formulas for the Steenrod algebra at odd primes `p` also make sense
4139
+ when `p` is set to `2`. We refer to the resulting algebra as the "generic Steenrod algebra" for
4140
+ the prime `2`. The dual Hopf algebra is given by
4141
+
4142
+ .. MATH::
4143
+
4144
+ A_* = \GF{2} [\xi_1, \xi_2, \xi_3, ...] \otimes \Lambda (\tau_0, \tau_1, ...)
4145
+
4146
+ The degree of `\xi_k` is `2^{k+1}-2` and the degree of `\tau_k` is `2^{k+1}-1`.
4147
+
4148
+ The generic Steenrod algebra is an associated graded algebra of the usual Steenrod algebra
4149
+ that is occasionally useful. Its cohomology, for example, is the `E_2`-term of a spectral sequence
4150
+ that computes the `E_2`-term of the Novikov spectral sequence. It can also be obtained as a
4151
+ specialisation of Voevodsky's "motivic Steenrod algebra": in the notation of [Voe2003]_, Remark 12.12,
4152
+ it corresponds to setting `\rho = \tau = 0`. The usual Steenrod algebra is given by `\rho = 0`
4153
+ and `\tau = 1`.
4154
+
4155
+ In Sage this algebra is constructed using the 'generic' keyword.
4156
+
4157
+ Example::
4158
+
4159
+ sage: EA = SteenrodAlgebra(p=2,generic=True) ; EA
4160
+ generic mod 2 Steenrod algebra, milnor basis
4161
+ sage: EA[8]
4162
+ Vector space spanned by (Q_0 Q_2, Q_0 Q_1 P(2), P(1,1), P(4))
4163
+ over Finite Field of size 2
4164
+
4165
+ TESTS:
4166
+
4167
+ Testing unique parents::
4168
+
4169
+ sage: S0 = SteenrodAlgebra(2)
4170
+ sage: S1 = SteenrodAlgebra(2)
4171
+ sage: S0 is S1
4172
+ True
4173
+ sage: S2 = SteenrodAlgebra(2, basis='adem')
4174
+ sage: S0 is S2
4175
+ False
4176
+ sage: S0 == S2
4177
+ False
4178
+ sage: A1 = SteenrodAlgebra(profile=[2,1])
4179
+ sage: B1 = SteenrodAlgebra(profile=[2,1,0,0])
4180
+ sage: A1 is B1
4181
+ True
4182
+ """
4183
+ if generic == 'auto':
4184
+ generic = p != 2
4185
+ if not generic:
4186
+ return SteenrodAlgebra_mod_two(p=2, basis=basis, **kwds)
4187
+ else:
4188
+ return SteenrodAlgebra_generic(p=p, basis=basis, generic=True, **kwds)
4189
+
4190
+
4191
+ def AA(n=None, p=2):
4192
+ r"""
4193
+ This returns the Steenrod algebra `A` or its sub-Hopf algebra `A(n)`.
4194
+
4195
+ INPUT:
4196
+
4197
+ - ``n`` -- nonnegative integer (default: ``None``)
4198
+ - ``p`` -- prime number (default: 2)
4199
+
4200
+ OUTPUT:
4201
+
4202
+ If `n` is ``None``, then return the full Steenrod algebra.
4203
+ Otherwise, return `A(n)`.
4204
+
4205
+ When `p=2`, `A(n)` is the sub-Hopf algebra generated by the
4206
+ elements `\text{Sq}^i` for `i \leq 2^n`. Its profile function is
4207
+ `(n+1, n, n-1, ...)`. When `p` is odd, `A(n)` is the sub-Hopf
4208
+ algebra generated by the elements `Q_0` and `\mathcal{P}^i` for `i
4209
+ \leq p^{n-1}`. Its profile function is `e=(n, n-1, n-2, ...)`
4210
+ and `k=(2, 2, ..., 2)` (length `n+1`).
4211
+
4212
+ EXAMPLES::
4213
+
4214
+ sage: from sage.algebras.steenrod.steenrod_algebra import AA as A
4215
+ sage: A()
4216
+ mod 2 Steenrod algebra, milnor basis
4217
+ sage: A(2)
4218
+ sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis,
4219
+ profile function [3, 2, 1]
4220
+ sage: A(2, p=5)
4221
+ sub-Hopf algebra of mod 5 Steenrod algebra, milnor basis,
4222
+ profile function ([2, 1], [2, 2, 2])
4223
+ """
4224
+ if n is None:
4225
+ return SteenrodAlgebra(p=p)
4226
+ if p == 2:
4227
+ return SteenrodAlgebra(p=p, profile=list(range(n + 1, 0, -1)))
4228
+ return SteenrodAlgebra(p=p, profile=(list(range(n, 0, -1)), [2]*(n+1)))
4229
+
4230
+
4231
+ def Sq(*nums):
4232
+ r"""
4233
+ Milnor element Sq(a,b,c,...).
4234
+
4235
+ INPUT:
4236
+
4237
+ - ``a``, ``b``, ``c``, ... -- nonnegative integers
4238
+
4239
+ OUTPUT: element of the Steenrod algebra
4240
+
4241
+ This returns the Milnor basis element `\text{Sq}(a, b, c, ...)`.
4242
+
4243
+ EXAMPLES::
4244
+
4245
+ sage: Sq(5)
4246
+ Sq(5)
4247
+ sage: Sq(5) + Sq(2,1) + Sq(5) # addition is mod 2:
4248
+ Sq(2,1)
4249
+ sage: (Sq(4,3) + Sq(7,2)).degree()
4250
+ 13
4251
+
4252
+ Entries must be nonnegative integers; otherwise, an error
4253
+ results.
4254
+
4255
+ This function is a good way to define elements of the Steenrod
4256
+ algebra.
4257
+ """
4258
+ return SteenrodAlgebra(p=2).Sq(*nums)