passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. passagemath_combinat/__init__.py +3 -0
  2. passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
  3. passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
  4. passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
  5. passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
  6. passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  7. passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
  8. sage/algebras/affine_nil_temperley_lieb.py +263 -0
  9. sage/algebras/all.py +24 -0
  10. sage/algebras/all__sagemath_combinat.py +35 -0
  11. sage/algebras/askey_wilson.py +935 -0
  12. sage/algebras/associated_graded.py +345 -0
  13. sage/algebras/cellular_basis.py +350 -0
  14. sage/algebras/cluster_algebra.py +2766 -0
  15. sage/algebras/down_up_algebra.py +860 -0
  16. sage/algebras/free_algebra.py +1698 -0
  17. sage/algebras/free_algebra_element.py +345 -0
  18. sage/algebras/free_algebra_quotient.py +405 -0
  19. sage/algebras/free_algebra_quotient_element.py +295 -0
  20. sage/algebras/free_zinbiel_algebra.py +885 -0
  21. sage/algebras/hall_algebra.py +783 -0
  22. sage/algebras/hecke_algebras/all.py +4 -0
  23. sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
  24. sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
  25. sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
  26. sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
  27. sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
  28. sage/algebras/iwahori_hecke_algebra.py +3095 -0
  29. sage/algebras/jordan_algebra.py +1773 -0
  30. sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
  31. sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
  32. sage/algebras/lie_conformal_algebras/all.py +18 -0
  33. sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
  34. sage/algebras/lie_conformal_algebras/examples.py +43 -0
  35. sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
  36. sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
  37. sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
  38. sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
  39. sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
  40. sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
  41. sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
  42. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
  43. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
  44. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
  45. sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
  46. sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
  47. sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
  48. sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
  49. sage/algebras/nil_coxeter_algebra.py +191 -0
  50. sage/algebras/q_commuting_polynomials.py +673 -0
  51. sage/algebras/q_system.py +608 -0
  52. sage/algebras/quantum_clifford.py +959 -0
  53. sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
  54. sage/algebras/quantum_groups/all.py +9 -0
  55. sage/algebras/quantum_groups/fock_space.py +2219 -0
  56. sage/algebras/quantum_groups/q_numbers.py +207 -0
  57. sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
  58. sage/algebras/quantum_groups/representations.py +591 -0
  59. sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
  60. sage/algebras/quantum_oscillator.py +623 -0
  61. sage/algebras/quaternion_algebra.py +20 -0
  62. sage/algebras/quaternion_algebra_element.py +55 -0
  63. sage/algebras/rational_cherednik_algebra.py +525 -0
  64. sage/algebras/schur_algebra.py +670 -0
  65. sage/algebras/shuffle_algebra.py +1011 -0
  66. sage/algebras/splitting_algebra.py +779 -0
  67. sage/algebras/tensor_algebra.py +709 -0
  68. sage/algebras/yangian.py +1082 -0
  69. sage/algebras/yokonuma_hecke_algebra.py +1018 -0
  70. sage/all__sagemath_combinat.py +35 -0
  71. sage/combinat/SJT.py +255 -0
  72. sage/combinat/affine_permutation.py +2405 -0
  73. sage/combinat/algebraic_combinatorics.py +55 -0
  74. sage/combinat/all.py +53 -0
  75. sage/combinat/all__sagemath_combinat.py +195 -0
  76. sage/combinat/alternating_sign_matrix.py +2063 -0
  77. sage/combinat/baxter_permutations.py +346 -0
  78. sage/combinat/bijectionist.py +3220 -0
  79. sage/combinat/binary_recurrence_sequences.py +1180 -0
  80. sage/combinat/blob_algebra.py +685 -0
  81. sage/combinat/catalog_partitions.py +27 -0
  82. sage/combinat/chas/all.py +23 -0
  83. sage/combinat/chas/fsym.py +1180 -0
  84. sage/combinat/chas/wqsym.py +2601 -0
  85. sage/combinat/cluster_complex.py +326 -0
  86. sage/combinat/colored_permutations.py +2039 -0
  87. sage/combinat/colored_permutations_representations.py +964 -0
  88. sage/combinat/composition_signed.py +142 -0
  89. sage/combinat/composition_tableau.py +855 -0
  90. sage/combinat/constellation.py +1729 -0
  91. sage/combinat/core.py +751 -0
  92. sage/combinat/counting.py +12 -0
  93. sage/combinat/crystals/affine.py +742 -0
  94. sage/combinat/crystals/affine_factorization.py +518 -0
  95. sage/combinat/crystals/affinization.py +331 -0
  96. sage/combinat/crystals/alcove_path.py +2013 -0
  97. sage/combinat/crystals/all.py +22 -0
  98. sage/combinat/crystals/bkk_crystals.py +141 -0
  99. sage/combinat/crystals/catalog.py +115 -0
  100. sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
  101. sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
  102. sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
  103. sage/combinat/crystals/crystals.py +257 -0
  104. sage/combinat/crystals/direct_sum.py +260 -0
  105. sage/combinat/crystals/elementary_crystals.py +1251 -0
  106. sage/combinat/crystals/fast_crystals.py +441 -0
  107. sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
  108. sage/combinat/crystals/generalized_young_walls.py +1076 -0
  109. sage/combinat/crystals/highest_weight_crystals.py +436 -0
  110. sage/combinat/crystals/induced_structure.py +695 -0
  111. sage/combinat/crystals/infinity_crystals.py +730 -0
  112. sage/combinat/crystals/kac_modules.py +863 -0
  113. sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
  114. sage/combinat/crystals/kyoto_path_model.py +497 -0
  115. sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
  116. sage/combinat/crystals/letters.pxd +79 -0
  117. sage/combinat/crystals/letters.pyx +3056 -0
  118. sage/combinat/crystals/littelmann_path.py +1518 -0
  119. sage/combinat/crystals/monomial_crystals.py +1262 -0
  120. sage/combinat/crystals/multisegments.py +462 -0
  121. sage/combinat/crystals/mv_polytopes.py +467 -0
  122. sage/combinat/crystals/pbw_crystal.py +511 -0
  123. sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
  124. sage/combinat/crystals/pbw_datum.pxd +4 -0
  125. sage/combinat/crystals/pbw_datum.pyx +487 -0
  126. sage/combinat/crystals/polyhedral_realization.py +372 -0
  127. sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/combinat/crystals/spins.pxd +21 -0
  129. sage/combinat/crystals/spins.pyx +756 -0
  130. sage/combinat/crystals/star_crystal.py +290 -0
  131. sage/combinat/crystals/subcrystal.py +464 -0
  132. sage/combinat/crystals/tensor_product.py +1177 -0
  133. sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
  134. sage/combinat/crystals/tensor_product_element.pxd +35 -0
  135. sage/combinat/crystals/tensor_product_element.pyx +1870 -0
  136. sage/combinat/crystals/virtual_crystal.py +420 -0
  137. sage/combinat/cyclic_sieving_phenomenon.py +204 -0
  138. sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/combinat/debruijn_sequence.pyx +355 -0
  140. sage/combinat/decorated_permutation.py +270 -0
  141. sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
  142. sage/combinat/degree_sequences.pyx +588 -0
  143. sage/combinat/derangements.py +527 -0
  144. sage/combinat/descent_algebra.py +1008 -0
  145. sage/combinat/diagram.py +1551 -0
  146. sage/combinat/diagram_algebras.py +5886 -0
  147. sage/combinat/dyck_word.py +4349 -0
  148. sage/combinat/e_one_star.py +1623 -0
  149. sage/combinat/enumerated_sets.py +123 -0
  150. sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
  151. sage/combinat/expnums.pyx +148 -0
  152. sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
  153. sage/combinat/fast_vector_partitions.pyx +346 -0
  154. sage/combinat/fqsym.py +1977 -0
  155. sage/combinat/free_dendriform_algebra.py +954 -0
  156. sage/combinat/free_prelie_algebra.py +1141 -0
  157. sage/combinat/fully_commutative_elements.py +1077 -0
  158. sage/combinat/fully_packed_loop.py +1523 -0
  159. sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
  160. sage/combinat/gray_codes.py +311 -0
  161. sage/combinat/grossman_larson_algebras.py +667 -0
  162. sage/combinat/growth.py +4352 -0
  163. sage/combinat/hall_polynomial.py +188 -0
  164. sage/combinat/hillman_grassl.py +866 -0
  165. sage/combinat/integer_matrices.py +329 -0
  166. sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
  167. sage/combinat/k_tableau.py +4564 -0
  168. sage/combinat/kazhdan_lusztig.py +215 -0
  169. sage/combinat/key_polynomial.py +885 -0
  170. sage/combinat/knutson_tao_puzzles.py +2286 -0
  171. sage/combinat/lr_tableau.py +311 -0
  172. sage/combinat/matrices/all.py +24 -0
  173. sage/combinat/matrices/hadamard_matrix.py +3790 -0
  174. sage/combinat/matrices/latin.py +2912 -0
  175. sage/combinat/misc.py +401 -0
  176. sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
  177. sage/combinat/ncsf_qsym/all.py +21 -0
  178. sage/combinat/ncsf_qsym/combinatorics.py +317 -0
  179. sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
  180. sage/combinat/ncsf_qsym/ncsf.py +5637 -0
  181. sage/combinat/ncsf_qsym/qsym.py +4053 -0
  182. sage/combinat/ncsf_qsym/tutorial.py +447 -0
  183. sage/combinat/ncsym/all.py +21 -0
  184. sage/combinat/ncsym/bases.py +855 -0
  185. sage/combinat/ncsym/dual.py +593 -0
  186. sage/combinat/ncsym/ncsym.py +2076 -0
  187. sage/combinat/necklace.py +551 -0
  188. sage/combinat/non_decreasing_parking_function.py +634 -0
  189. sage/combinat/nu_dyck_word.py +1474 -0
  190. sage/combinat/output.py +861 -0
  191. sage/combinat/parallelogram_polyomino.py +4326 -0
  192. sage/combinat/parking_functions.py +1602 -0
  193. sage/combinat/partition_algebra.py +1998 -0
  194. sage/combinat/partition_kleshchev.py +1982 -0
  195. sage/combinat/partition_shifting_algebras.py +584 -0
  196. sage/combinat/partition_tuple.py +3114 -0
  197. sage/combinat/path_tableaux/all.py +13 -0
  198. sage/combinat/path_tableaux/catalog.py +29 -0
  199. sage/combinat/path_tableaux/dyck_path.py +380 -0
  200. sage/combinat/path_tableaux/frieze.py +476 -0
  201. sage/combinat/path_tableaux/path_tableau.py +728 -0
  202. sage/combinat/path_tableaux/semistandard.py +510 -0
  203. sage/combinat/perfect_matching.py +779 -0
  204. sage/combinat/plane_partition.py +3300 -0
  205. sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
  206. sage/combinat/q_bernoulli.pyx +128 -0
  207. sage/combinat/quickref.py +81 -0
  208. sage/combinat/recognizable_series.py +2051 -0
  209. sage/combinat/regular_sequence.py +4316 -0
  210. sage/combinat/regular_sequence_bounded.py +543 -0
  211. sage/combinat/restricted_growth.py +81 -0
  212. sage/combinat/ribbon.py +20 -0
  213. sage/combinat/ribbon_shaped_tableau.py +489 -0
  214. sage/combinat/ribbon_tableau.py +1180 -0
  215. sage/combinat/rigged_configurations/all.py +46 -0
  216. sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
  217. sage/combinat/rigged_configurations/bij_infinity.py +370 -0
  218. sage/combinat/rigged_configurations/bij_type_A.py +163 -0
  219. sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
  220. sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
  221. sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
  222. sage/combinat/rigged_configurations/bij_type_B.py +900 -0
  223. sage/combinat/rigged_configurations/bij_type_C.py +267 -0
  224. sage/combinat/rigged_configurations/bij_type_D.py +771 -0
  225. sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
  226. sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
  227. sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
  228. sage/combinat/rigged_configurations/bijection.py +143 -0
  229. sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
  230. sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
  231. sage/combinat/rigged_configurations/rc_crystal.py +461 -0
  232. sage/combinat/rigged_configurations/rc_infinity.py +540 -0
  233. sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
  234. sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
  235. sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
  236. sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
  237. sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
  238. sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
  239. sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
  240. sage/combinat/rsk.py +3438 -0
  241. sage/combinat/schubert_polynomial.py +508 -0
  242. sage/combinat/set_partition.py +3318 -0
  243. sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/combinat/set_partition_iterator.pyx +136 -0
  245. sage/combinat/set_partition_ordered.py +1590 -0
  246. sage/combinat/sf/abreu_nigro.py +346 -0
  247. sage/combinat/sf/all.py +52 -0
  248. sage/combinat/sf/character.py +576 -0
  249. sage/combinat/sf/classical.py +319 -0
  250. sage/combinat/sf/dual.py +996 -0
  251. sage/combinat/sf/elementary.py +549 -0
  252. sage/combinat/sf/hall_littlewood.py +1028 -0
  253. sage/combinat/sf/hecke.py +336 -0
  254. sage/combinat/sf/homogeneous.py +464 -0
  255. sage/combinat/sf/jack.py +1428 -0
  256. sage/combinat/sf/k_dual.py +1458 -0
  257. sage/combinat/sf/kfpoly.py +447 -0
  258. sage/combinat/sf/llt.py +789 -0
  259. sage/combinat/sf/macdonald.py +2019 -0
  260. sage/combinat/sf/monomial.py +525 -0
  261. sage/combinat/sf/multiplicative.py +113 -0
  262. sage/combinat/sf/new_kschur.py +1786 -0
  263. sage/combinat/sf/ns_macdonald.py +964 -0
  264. sage/combinat/sf/orthogonal.py +246 -0
  265. sage/combinat/sf/orthotriang.py +355 -0
  266. sage/combinat/sf/powersum.py +963 -0
  267. sage/combinat/sf/schur.py +880 -0
  268. sage/combinat/sf/sf.py +1653 -0
  269. sage/combinat/sf/sfa.py +7053 -0
  270. sage/combinat/sf/symplectic.py +253 -0
  271. sage/combinat/sf/witt.py +721 -0
  272. sage/combinat/shifted_primed_tableau.py +2735 -0
  273. sage/combinat/shuffle.py +830 -0
  274. sage/combinat/sidon_sets.py +146 -0
  275. sage/combinat/similarity_class_type.py +1721 -0
  276. sage/combinat/sine_gordon.py +618 -0
  277. sage/combinat/six_vertex_model.py +784 -0
  278. sage/combinat/skew_partition.py +2053 -0
  279. sage/combinat/skew_tableau.py +2989 -0
  280. sage/combinat/sloane_functions.py +8935 -0
  281. sage/combinat/specht_module.py +1403 -0
  282. sage/combinat/species/all.py +48 -0
  283. sage/combinat/species/characteristic_species.py +321 -0
  284. sage/combinat/species/composition_species.py +273 -0
  285. sage/combinat/species/cycle_species.py +284 -0
  286. sage/combinat/species/empty_species.py +155 -0
  287. sage/combinat/species/functorial_composition_species.py +148 -0
  288. sage/combinat/species/generating_series.py +673 -0
  289. sage/combinat/species/library.py +148 -0
  290. sage/combinat/species/linear_order_species.py +169 -0
  291. sage/combinat/species/misc.py +83 -0
  292. sage/combinat/species/partition_species.py +290 -0
  293. sage/combinat/species/permutation_species.py +268 -0
  294. sage/combinat/species/product_species.py +423 -0
  295. sage/combinat/species/recursive_species.py +476 -0
  296. sage/combinat/species/set_species.py +192 -0
  297. sage/combinat/species/species.py +820 -0
  298. sage/combinat/species/structure.py +539 -0
  299. sage/combinat/species/subset_species.py +243 -0
  300. sage/combinat/species/sum_species.py +225 -0
  301. sage/combinat/subword.py +564 -0
  302. sage/combinat/subword_complex.py +2122 -0
  303. sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
  304. sage/combinat/subword_complex_c.pyx +119 -0
  305. sage/combinat/super_tableau.py +821 -0
  306. sage/combinat/superpartition.py +1154 -0
  307. sage/combinat/symmetric_group_algebra.py +3774 -0
  308. sage/combinat/symmetric_group_representations.py +1830 -0
  309. sage/combinat/t_sequences.py +877 -0
  310. sage/combinat/tableau.py +9506 -0
  311. sage/combinat/tableau_residues.py +860 -0
  312. sage/combinat/tableau_tuple.py +5353 -0
  313. sage/combinat/tiling.py +2432 -0
  314. sage/combinat/triangles_FHM.py +777 -0
  315. sage/combinat/tutorial.py +1857 -0
  316. sage/combinat/vector_partition.py +337 -0
  317. sage/combinat/words/abstract_word.py +1722 -0
  318. sage/combinat/words/all.py +59 -0
  319. sage/combinat/words/alphabet.py +268 -0
  320. sage/combinat/words/finite_word.py +7201 -0
  321. sage/combinat/words/infinite_word.py +113 -0
  322. sage/combinat/words/lyndon_word.py +652 -0
  323. sage/combinat/words/morphic.py +351 -0
  324. sage/combinat/words/morphism.py +3878 -0
  325. sage/combinat/words/paths.py +2932 -0
  326. sage/combinat/words/shuffle_product.py +278 -0
  327. sage/combinat/words/suffix_trees.py +1873 -0
  328. sage/combinat/words/word.py +769 -0
  329. sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
  330. sage/combinat/words/word_char.pyx +847 -0
  331. sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
  332. sage/combinat/words/word_datatypes.pxd +4 -0
  333. sage/combinat/words/word_datatypes.pyx +1067 -0
  334. sage/combinat/words/word_generators.py +2026 -0
  335. sage/combinat/words/word_infinite_datatypes.py +1218 -0
  336. sage/combinat/words/word_options.py +99 -0
  337. sage/combinat/words/words.py +2396 -0
  338. sage/data_structures/all__sagemath_combinat.py +1 -0
  339. sage/databases/all__sagemath_combinat.py +13 -0
  340. sage/databases/findstat.py +4897 -0
  341. sage/databases/oeis.py +2058 -0
  342. sage/databases/sloane.py +393 -0
  343. sage/dynamics/all__sagemath_combinat.py +14 -0
  344. sage/dynamics/cellular_automata/all.py +7 -0
  345. sage/dynamics/cellular_automata/catalog.py +34 -0
  346. sage/dynamics/cellular_automata/elementary.py +612 -0
  347. sage/dynamics/cellular_automata/glca.py +477 -0
  348. sage/dynamics/cellular_automata/solitons.py +1463 -0
  349. sage/dynamics/finite_dynamical_system.py +1249 -0
  350. sage/dynamics/finite_dynamical_system_catalog.py +382 -0
  351. sage/games/all.py +7 -0
  352. sage/games/hexad.py +704 -0
  353. sage/games/quantumino.py +591 -0
  354. sage/games/sudoku.py +889 -0
  355. sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
  356. sage/games/sudoku_backtrack.pyx +189 -0
  357. sage/groups/all__sagemath_combinat.py +1 -0
  358. sage/groups/indexed_free_group.py +489 -0
  359. sage/libs/all__sagemath_combinat.py +6 -0
  360. sage/libs/lrcalc/__init__.py +1 -0
  361. sage/libs/lrcalc/lrcalc.py +525 -0
  362. sage/libs/symmetrica/__init__.py +7 -0
  363. sage/libs/symmetrica/all.py +101 -0
  364. sage/libs/symmetrica/kostka.pxi +168 -0
  365. sage/libs/symmetrica/part.pxi +193 -0
  366. sage/libs/symmetrica/plet.pxi +42 -0
  367. sage/libs/symmetrica/sab.pxi +196 -0
  368. sage/libs/symmetrica/sb.pxi +332 -0
  369. sage/libs/symmetrica/sc.pxi +192 -0
  370. sage/libs/symmetrica/schur.pxi +956 -0
  371. sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
  372. sage/libs/symmetrica/symmetrica.pxi +1172 -0
  373. sage/libs/symmetrica/symmetrica.pyx +39 -0
  374. sage/monoids/all.py +13 -0
  375. sage/monoids/automatic_semigroup.py +1054 -0
  376. sage/monoids/free_abelian_monoid.py +315 -0
  377. sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
  378. sage/monoids/free_abelian_monoid_element.pxd +16 -0
  379. sage/monoids/free_abelian_monoid_element.pyx +397 -0
  380. sage/monoids/free_monoid.py +335 -0
  381. sage/monoids/free_monoid_element.py +431 -0
  382. sage/monoids/hecke_monoid.py +65 -0
  383. sage/monoids/string_monoid.py +817 -0
  384. sage/monoids/string_monoid_element.py +547 -0
  385. sage/monoids/string_ops.py +143 -0
  386. sage/monoids/trace_monoid.py +972 -0
  387. sage/rings/all__sagemath_combinat.py +2 -0
  388. sage/sat/all.py +4 -0
  389. sage/sat/boolean_polynomials.py +405 -0
  390. sage/sat/converters/__init__.py +6 -0
  391. sage/sat/converters/anf2cnf.py +14 -0
  392. sage/sat/converters/polybori.py +611 -0
  393. sage/sat/solvers/__init__.py +5 -0
  394. sage/sat/solvers/cryptominisat.py +287 -0
  395. sage/sat/solvers/dimacs.py +783 -0
  396. sage/sat/solvers/picosat.py +228 -0
  397. sage/sat/solvers/sat_lp.py +156 -0
  398. sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
  399. sage/sat/solvers/satsolver.pxd +3 -0
  400. sage/sat/solvers/satsolver.pyx +405 -0
@@ -0,0 +1,3520 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.groups sage.modules
3
+ r"""
4
+ Cubic Hecke Algebras
5
+
6
+ We consider the factors of the group algebra of the Artin braid groups
7
+ such that the images `s_i` of the braid generators satisfy a cubic equation:
8
+
9
+ .. MATH::
10
+
11
+ s_i^3 = u s_i^2 - v s_i + w.
12
+
13
+ Here `u, v, w` are elements in an arbitrary integral domain and `i` is a
14
+ positive integer less than `n`, the number of the braid group's strands.
15
+ By the analogue to the *Iwahori Hecke algebras* (see
16
+ :class:`~sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra`), in which the
17
+ braid generators satisfy a quadratic relation these algebras have been called
18
+ *cubic Hecke algebras*. The relations inherited from the braid group are:
19
+
20
+ .. MATH::
21
+
22
+ s_i s_{i+1} s_i = s_{i+1} s_i s_{i+1} \text{ for } 1 \leq i < n - 1
23
+ \mbox{ and } s_i s_j = s_j s_i \text{ for } 1 \leq i < j - 1 < n - 1.
24
+
25
+ The algebra epimorphism from the braid group algebra over the same base ring is
26
+ realized inside the element constructor of the present class, for example in the
27
+ case of the 3 strand cubic Hecke algebra::
28
+
29
+ sage: CHA3 = algebras.CubicHecke(3)
30
+ sage: BG3 = CHA3.braid_group()
31
+ sage: braid = BG3((1,2,-1,2,2,-1)); braid
32
+ c0*c1*c0^-1*c1^2*c0^-1
33
+ sage: braid_image = CHA3(braid); braid_image
34
+ u*c1*c0^-1*c1 + u*v*c0*c1^-1*c0^-1 - u^2*c0^-1*c1
35
+ + ((u^2*v-v^2)/w)*c0*c1*c0^-1 + ((u^2-v)/w)*c0*c1*c0
36
+ - ((u^3-u*v)/w)*c0*c1 - (u*v-w)*c1^-1
37
+
38
+ If the ring elements `u, v, w` (which will be called the *cubic equation
39
+ parameters* in the sequel) are taken to be `u = v = 0, w = 1` the cubic Hecke
40
+ algebra specializes to the group algebra of the *cubic braid group*, which is
41
+ the factor group of the Artin braid group under setting the generators order
42
+ to be three. These groups can be obtained by
43
+ :meth:`CubicHeckeAlgebra.cubic_braid_group`.
44
+
45
+ It is well known, that these algebras are free of finite rank as long as the
46
+ number of braid generators is less than six and infinite dimensional else wise.
47
+ In the former (non trivial) cases they are also known as *cyclotomic Hecke
48
+ algebras* corresponding to the complex reflection groups having Shepard-Todd
49
+ number `4`, `25` and `32`.
50
+
51
+ Since the *Broué, Malle, Rouquiere* conjecture has been proved (for references
52
+ of these cases see [Mar2012]_) there exists a finite free basis of the cubic
53
+ Hecke algebra which is in bijection to the cubic braid group and compatible
54
+ with the specialization to the cubic braid group algebra as explained above.
55
+
56
+ For the algebras corresponding to braid groups of less than five strands such
57
+ a basis has been calculated by Ivan Marin. This one is used here. In the case
58
+ of 5 strands such a basis is not available, right now. Instead the elements
59
+ of the cubic braid group class themselves are used as basis elements. This
60
+ is also the case when the cubic braid group is infinite, even though it is
61
+ not known if these elements span all of the cubic Hecke algebra.
62
+
63
+ Accordingly, be aware that the module embedding of the group algebra of the
64
+ cubicbraid groups is known to be an isomorphism of free modules only in the
65
+ cases of less than five strands.
66
+
67
+ EXAMPLES:
68
+
69
+ Consider the obstruction ``b`` of the *triple quadratic algebra* from Section 2.6
70
+ of [Mar2018]_. We verify that the third power of it is a scalar multiple
71
+ of itself (explicitly ``2*w^2`` times the *Schur element* of the three
72
+ dimensional irreducible representation)::
73
+
74
+ sage: CHA3 = algebras.CubicHecke(3)
75
+ sage: c1, c2 = CHA3.gens()
76
+ sage: b = c1^2*c2 - c2*c1^2 - c1*c2^2 + c2^2*c1; b
77
+ w*c0^-1*c1 - w*c0*c1^-1 - w*c1*c0^-1 + w*c1^-1*c0
78
+ sage: b2 = b*b
79
+ sage: b3 = b2*b
80
+ sage: BR = CHA3.base_ring()
81
+ sage: ER = CHA3.extension_ring()
82
+ sage: u, v, w = BR.gens()
83
+ sage: f = BR(b3.coefficients()[0]/w)
84
+ sage: try:
85
+ ....: sh = CHA3.schur_element(CHA3.irred_repr.W3_111)
86
+ ....: except NotImplementedError: # for the case GAP3 / CHEVIE not available
87
+ ....: sh = ER(f/(2*w^2))
88
+ sage: ER(f/(2*w^2)) == sh
89
+ True
90
+ sage: b3 == f*b
91
+ True
92
+
93
+ Defining the cubic Hecke algebra on 6 strands will need some seconds for
94
+ initializing. However, you can do calculations inside the infinite
95
+ algebra as well::
96
+
97
+ sage: # optional - database_cubic_hecke
98
+ sage: CHA6 = algebras.CubicHecke(6)
99
+ sage: CHA6.inject_variables()
100
+ Defining c0, c1, c2, c3, c4
101
+ sage: s = c0*c1*c2*c3*c4; s
102
+ c0*c1*c2*c3*c4
103
+ sage: s^2
104
+ (c0*c1*c2*c3*c4)^2
105
+ sage: t = CHA6.an_element() * c4; t
106
+ (-w)*c0*c1^-1*c4 + v*c0*c2^-1*c4 + u*c2*c1*c4 + ((-v*w+u)/w)*c4
107
+
108
+ REFERENCES:
109
+
110
+ - [Mar2012]_
111
+ - [Mar2018]_
112
+ - [CM2012]_
113
+
114
+ AUTHORS:
115
+
116
+ - Sebastian Oehms May 2020: initial version
117
+ """
118
+ # ###########################################################################
119
+ # Copyright (C) 2020 Sebastian Oehms <seb.oehms@gmail.com>
120
+ #
121
+ # This program is free software: you can redistribute it and/or modify
122
+ # it under the terms of the GNU General Public License as published by
123
+ # the Free Software Foundation, either version 2 of the License, or
124
+ # (at your option) any later version.
125
+ # https://www.gnu.org/licenses/
126
+ # ###########################################################################
127
+ from warnings import warn
128
+
129
+ from sage.combinat.free_module import CombinatorialFreeModule
130
+ from sage.misc.cachefunc import cached_method
131
+ from sage.misc.verbose import verbose
132
+ from sage.groups.cubic_braid import CubicBraidGroup
133
+ from sage.rings.integer_ring import ZZ
134
+ from sage.algebras.splitting_algebra import solve_with_extension
135
+ from sage.modules.free_module_element import vector
136
+ from sage.matrix.matrix_space import MatrixSpace
137
+ from sage.algebras.hecke_algebras.cubic_hecke_base_ring import CubicHeckeRingOfDefinition
138
+ from sage.algebras.hecke_algebras.cubic_hecke_matrix_rep import CubicHeckeMatrixSpace, AbsIrreducibeRep, RepresentationType
139
+
140
+
141
+ ##############################################################################
142
+ #
143
+ # Class CubicHeckeElement (for elements)
144
+ #
145
+ ##############################################################################
146
+ class CubicHeckeElement(CombinatorialFreeModule.Element):
147
+ r"""
148
+ An element of a :class:`CubicHeckeAlgebra`.
149
+
150
+ For more information see :class:`CubicHeckeAlgebra`.
151
+
152
+ EXAMPLES::
153
+
154
+ sage: CHA3s = algebras.CubicHecke('s1, s2'); CHA3s.an_element()
155
+ -w*s1*s2^-1 + v*s1 + u*s2 - ((v*w-u)/w)
156
+ sage: CHA3.<c1, c2> = algebras.CubicHecke(3)
157
+ sage: c1**3*~c2
158
+ u*w*c1^-1*c2^-1 + (u^2-v)*c1*c2^-1 - (u*v-w)*c2^-1
159
+ """
160
+ # --------------------------------------------------------------------------
161
+ # Overloading inherited methods
162
+ # --------------------------------------------------------------------------
163
+ def __invert__(self):
164
+ r"""
165
+ Return inverse of ``self`` (if possible).
166
+
167
+ EXAMPLES::
168
+
169
+ sage: CHA3 = algebras.CubicHecke(3)
170
+ sage: ele1 = CHA3((1,-2,1)); ele1
171
+ c0*c1^-1*c0
172
+ sage: ~ele1 # indirect doctest
173
+ c0^-1*c1*c0^-1
174
+
175
+ sage: CHA2 = algebras.CubicHecke(2)
176
+ sage: x = CHA2.an_element(); x
177
+ v*c - ((v*w-u)/w)
178
+ sage: ~x
179
+ Traceback (most recent call last):
180
+ ...
181
+ ValueError: cannot invert self (= v*c - ((v*w-u)/w))
182
+ """
183
+ self_Tietze = self.Tietze()
184
+
185
+ if self_Tietze is None:
186
+ return super().__invert__()
187
+
188
+ inverse_Tietze = ()
189
+ len_self = len(self_Tietze)
190
+
191
+ inverse_Tietze = tuple([-1 * self_Tietze[len_self - i - 1]
192
+ for i in range(len_self)])
193
+ P = self.parent()
194
+ return P(inverse_Tietze)
195
+
196
+ def Tietze(self):
197
+ r"""
198
+ Return the Tietze presentation of ``self`` if ``self`` belongs to the
199
+ basis of its parent and ``None`` otherwise.
200
+
201
+ OUTPUT:
202
+
203
+ A tuple representing the pre image braid of ``self`` if ``self`` is a
204
+ monomial from the basis ``None`` else-wise
205
+
206
+ EXAMPLES::
207
+
208
+ sage: CHA3 = algebras.CubicHecke(3)
209
+ sage: ele = CHA3.an_element(); ele
210
+ -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
211
+ sage: ele.Tietze() is None
212
+ True
213
+ sage: [CHA3(sp).Tietze() for sp in ele.support()]
214
+ [(), (1,), (1, -2), (2,)]
215
+ """
216
+ vecd = self._monomial_coefficients
217
+ if len(vecd) != 1:
218
+ return None
219
+ ind, coeff = next(iter(vecd.items()))
220
+ if coeff.is_one():
221
+ return ind.Tietze()
222
+
223
+ def max_len(self):
224
+ r"""
225
+ Return the maximum of the length of Tietze expressions among the
226
+ support of ``self``.
227
+
228
+ EXAMPLES::
229
+
230
+ sage: CHA3 = algebras.CubicHecke(3)
231
+ sage: ele = CHA3.an_element(); ele
232
+ -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
233
+ sage: ele.max_len()
234
+ 2
235
+ """
236
+ return max(len(bas_ele.Tietze()) for bas_ele in self.support())
237
+
238
+ def braid_group_algebra_pre_image(self):
239
+ r"""
240
+ Return a pre image of ``self`` in the group algebra of the braid group
241
+ (with respect to the basis given by Ivan Marin).
242
+
243
+ OUTPUT:
244
+
245
+ The pre image of ``self`` as instance of the element class of the group
246
+ algebra of the BraidGroup
247
+
248
+ EXAMPLES::
249
+
250
+ sage: CHA3 = algebras.CubicHecke(3)
251
+ sage: ele = CHA3.an_element(); ele
252
+ -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
253
+ sage: b_ele = ele.braid_group_algebra_pre_image(); b_ele
254
+ -((v*w-u)/w) + v*c0 + u*c1 - w*c0*c1^-1
255
+ sage: ele in CHA3
256
+ True
257
+ sage: b_ele in CHA3
258
+ False
259
+ sage: b_ele in CHA3.braid_group_algebra()
260
+ True
261
+ """
262
+ ch_algebra = self.parent()
263
+ braid_group_algebra = ch_algebra.braid_group_algebra()
264
+ braid_group = ch_algebra.braid_group()
265
+
266
+ def phi(bas_ele):
267
+ return braid_group_algebra(braid_group(bas_ele))
268
+ return ch_algebra._apply_module_morphism(self, phi,
269
+ codomain=braid_group_algebra)
270
+
271
+ def cubic_braid_group_algebra_pre_image(self):
272
+ r"""
273
+ Return a pre image of ``self`` in the group algebra of the cubic braid
274
+ group.
275
+
276
+ OUTPUT:
277
+
278
+ The pre image of ``self`` as instance of the element class of the group
279
+ algebra of the :class:`CubicBraidGroup`.
280
+
281
+ EXAMPLES::
282
+
283
+ sage: CHA3 = algebras.CubicHecke(3)
284
+ sage: ele = CHA3.an_element(); ele
285
+ -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
286
+ sage: cb_ele = ele.cubic_braid_group_algebra_pre_image(); cb_ele
287
+ -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w)
288
+ sage: ele in CHA3
289
+ True
290
+ sage: cb_ele in CHA3
291
+ False
292
+ sage: cb_ele in CHA3.cubic_braid_group_algebra()
293
+ True
294
+ """
295
+ ch_algebra = self.parent()
296
+ cbraid_group_algebra = ch_algebra.cubic_braid_group_algebra()
297
+ cbraid_group = ch_algebra.cubic_braid_group()
298
+
299
+ def phi(bas_ele):
300
+ return cbraid_group_algebra(cbraid_group(bas_ele))
301
+ return ch_algebra._apply_module_morphism(self, phi,
302
+ codomain=cbraid_group_algebra)
303
+
304
+ @cached_method
305
+ def matrix(self, subdivide=False, representation_type=None, original=False):
306
+ r"""
307
+ Return certain types of matrix representations of ``self``.
308
+
309
+ The absolutely irreducible representations of the cubic Hecke algebra
310
+ are constructed using the ``GAP3`` interface and the ``CHEVIE`` package
311
+ if ``GAP3`` and ``CHEVIE`` are installed on the system. Furthermore,
312
+ the representations given on `Ivan Marin's homepage
313
+ <http://www.lamfa.u-picardie.fr/marin/representationH4-en.html>`__
314
+ are used:
315
+
316
+ INPUT:
317
+
318
+ - ``subdivide`` -- boolean (default: ``False``); this boolean is passed
319
+ to the block_matrix function
320
+ - ``representation_type`` -- instance of enum :class:`RepresentationType`;
321
+ this can be obtained by the attribute :attr:`CubicHeckeAlgebra.repr_type`
322
+ of ``self``; the following values are possible:
323
+
324
+ - ``RegularLeft`` -- (regular left repr. from the above URL)
325
+ - ``RegularRight`` -- (regular right repr. from the above URL)
326
+ - ``SplitIrredChevie`` -- (split irred. repr. via CHEVIE)
327
+ - ``SplitIrredMarin`` -- (split irred. repr. from the above URL)
328
+ - default: ``SplitIrredChevie`` taken if GAP3 and CHEVIE are installed
329
+ on the system, otherwise the default will be ``SplitIrredMarin``
330
+
331
+ - ``original`` -- boolean (default: ``False``); if set to ``True`` the base
332
+ ring of the matrix will be the generic base_ring resp. generic extension
333
+ ring (for the split versions) of the parent of ``self``
334
+
335
+ OUTPUT:
336
+
337
+ An instance of :class:`~sage.algebras.hecke_algebras.cubic_hecke_matrix_rep.CubicHeckeMatrixRep`,
338
+ which is inherited from :class:`~sage.matrix.matrix_generic_dense.Matrix_generic_dense`.
339
+ In the case of the irreducible representations the matrix is given as a
340
+ block matrix. Each single irreducible can be obtained as item indexed by
341
+ the members of the enum :class:`AbsIrreducibeRep` available via
342
+ :attr:`CubicHeckeAlgebra.irred_repr`.
343
+ For details type: ``CubicHeckeAlgebra.irred_repr?``.
344
+
345
+ EXAMPLES::
346
+
347
+ sage: CHA3 = algebras.CubicHecke(3)
348
+ sage: CHA3.inject_variables()
349
+ Defining c0, c1
350
+ sage: c0m = c0.matrix()
351
+ sage: c0m[CHA3.irred_repr.W3_111]
352
+ [ -b - a + u 0 0]
353
+ [(-2*a + u)*b - 2*a^2 + 2*u*a - v b 0]
354
+ [ b 1 a]
355
+
356
+ using the ``representation_type`` option::
357
+
358
+ sage: CHA3.<c0, c1> = algebras.CubicHecke(3) # optional gap3
359
+ sage: chevie = CHA3.repr_type.SplitIrredChevie # optional gap3
360
+ sage: c0m_ch = c0.matrix(representation_type=chevie) # optional gap3
361
+ sage: c0m_ch[CHA3.irred_repr.W3_011] # optional gap3
362
+ [ b 0]
363
+ [ -b -b - a + u]
364
+ sage: c0m[CHA3.irred_repr.W3_011]
365
+ [ b 0]
366
+ [a^2 - u*a + v -b - a + u]
367
+
368
+ using the ``original`` option::
369
+
370
+ sage: c0mo = c0.matrix(original=True)
371
+ sage: c0mo_ch = c0.matrix(representation_type=chevie, original=True) # optional gap3
372
+ sage: c0mo[CHA3.irred_repr.W3_011]
373
+ [ b 0]
374
+ [b*c c]
375
+ sage: c0mo_ch[CHA3.irred_repr.W3_011] # optional gap3
376
+ [ b 0]
377
+ [-b c]
378
+
379
+ specialized matrices::
380
+
381
+ sage: t = (3,7,11)
382
+ sage: CHA4 = algebras.CubicHecke(4, cubic_equation_roots=t) # optional database_cubic_hecke
383
+ sage: e = CHA4.an_element(); e # optional database_cubic_hecke
384
+ -231*c0*c1^-1 + 131*c0*c2^-1 + 21*c2*c1 - 1440/11
385
+ sage: em = e.matrix() # optional database_cubic_hecke
386
+ sage: em.base_ring() # optional database_cubic_hecke
387
+ Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
388
+ over Integer Ring localized at (3, 7, 11)
389
+ sage: em.dimensions() # optional database_cubic_hecke
390
+ (108, 108)
391
+ sage: em_irr24 = em[23] # optional database_cubic_hecke
392
+ sage: em_irr24.dimensions() # optional database_cubic_hecke
393
+ (9, 9)
394
+ sage: em_irr24[3,2] # optional database_cubic_hecke
395
+ -131*E3 - 393/7
396
+ sage: emg = e.matrix(representation_type=chevie) # optional gap3 database_cubic_hecke
397
+ sage: emg_irr24 = emg[23] # optional gap3 database_cubic_hecke
398
+ sage: emg_irr24[3,2] # optional gap3 database_cubic_hecke
399
+ -131*E3 - 393/7
400
+ """
401
+ parent = self.parent()
402
+ MS = CubicHeckeMatrixSpace(parent, representation_type=representation_type, subdivide=subdivide, original=original)
403
+ return MS(self)
404
+
405
+ def revert_garside(self):
406
+ r"""
407
+ Return the image of ``self`` under the Garside involution.
408
+
409
+ .. SEEALSO::
410
+
411
+ :meth:`CubicHeckeAlgebra.garside_involution`
412
+
413
+ EXAMPLES::
414
+
415
+ sage: roots = (E(3), ~E(3), 1)
416
+ sage: CHA3.<c1, c2> = algebras.CubicHecke(3, cubic_equation_roots=roots)
417
+ sage: e = CHA3.an_element(); e
418
+ -c1*c2^-1
419
+ sage: _.revert_garside()
420
+ -c2*c1^-1
421
+ sage: _.revert_garside()
422
+ -c1*c2^-1
423
+ """
424
+ return self.parent().garside_involution(self)
425
+
426
+ def revert_mirror(self):
427
+ r"""
428
+ Return the image of ``self`` under the mirror isomorphism.
429
+
430
+ .. SEEALSO::
431
+
432
+ :meth:`CubicHeckeAlgebra.mirror_isomorphism`
433
+
434
+ EXAMPLES::
435
+
436
+ sage: CHA3.<c1, c2> = algebras.CubicHecke(3)
437
+ sage: e = CHA3.an_element()
438
+ sage: e.revert_mirror()
439
+ -1/w*c0^-1*c1 + u/w*c0^-1 + v/w*c1^-1 + ((v*w-u)/w)
440
+ sage: _.revert_mirror() == e
441
+ True
442
+ """
443
+ return self.parent().mirror_isomorphism(self)
444
+
445
+ def revert_orientation(self):
446
+ r"""
447
+ Return the image of ``self`` under the anti involution reverting the
448
+ orientation of braids.
449
+
450
+ .. SEEALSO::
451
+
452
+ :meth:`CubicHeckeAlgebra.orientation_antiinvolution`
453
+
454
+ EXAMPLES::
455
+
456
+ sage: CHA3.<c1, c2> = algebras.CubicHecke(3)
457
+ sage: e = CHA3.an_element()
458
+ sage: e.revert_orientation()
459
+ -w*c2^-1*c1 + v*c1 + u*c2 - ((v*w-u)/w)
460
+ sage: _.revert_orientation() == e
461
+ True
462
+ """
463
+ return self.parent().orientation_antiinvolution(self)
464
+
465
+ def formal_markov_trace(self, extended=False, field_embedding=False):
466
+ r"""
467
+ Return a formal expression which can be specialized to Markov traces
468
+ which factor through the cubic Hecke algebra.
469
+
470
+ This covers Markov traces corresponding to the
471
+
472
+ - HOMFLY-PT polynomial,
473
+ - Kauffman polynomial,
474
+ - Links-Gould polynomial.
475
+
476
+ These expressions are elements of a sub-module of the module of linear
477
+ forms on ``self`` the base ring of which is an extension of the
478
+ generic base ring of ``self`` by an additional variable ``s``
479
+ representing the writhe factor. All variables of this base ring
480
+ extension are invertible.
481
+
482
+ A Markov trace is a family of class functions `tr_n` on the family
483
+ of braid groups `B_n` into some commutative ring `R` depending on
484
+ a unit `s \in R` such that for all `b \in B_n` the following two
485
+ conditions are satisfied (see [Kau1991]_, section 7):
486
+
487
+ .. MATH::
488
+
489
+ \begin{array}{lll}
490
+ tr_{n+1}(b g_n) & = & s tr_n(b), \\
491
+ tr_{n+1}(b g^{-1}_n) & = & s^{-1} tr_n(b).
492
+ \end{array}
493
+
494
+ The unit `s` is often called the writhe factor and corresponds to the
495
+ additional variable mentioned above.
496
+
497
+ .. NOTE::
498
+
499
+ Currently it is not known if all linear forms of this sub-module
500
+ belong to a Markov trace, i.e. can be extended to the full tower
501
+ of cubic Hecke algebras. Anyway, at least the four basis elements
502
+ (``U1``, ``U2``, ``U3`` and ``K4``) can be reconstructed form
503
+ the HOMFLY-PT and Kauffman polynomial.
504
+
505
+ INPUT:
506
+
507
+ - ``extended`` -- boolean (default: ``False``); if set to ``True`` the
508
+ base ring of the Markov trace module is constructed as an extension
509
+ of generic extension ring of ``self``; per default it is constructed
510
+ upon the generic base ring
511
+ - ``field_embedding`` -- boolean (default: ``False``); if set to ``True``
512
+ the base ring of the module is the smallest field containing the
513
+ generic extension ring of ``self``; ignored if ``extended=False``
514
+
515
+ EXAMPLES::
516
+
517
+ sage: from sage.knots.knotinfo import KnotInfo
518
+ sage: CHA2 = algebras.CubicHecke(2)
519
+ sage: K3_1 = KnotInfo.K3_1
520
+ sage: b3_1 = CHA2(K3_1.braid())
521
+ sage: mt3_1 = b3_1.formal_markov_trace(); mt3_1
522
+ ((u^2*s^2-v*s^2+u*w)/s)*B[U1] - (u*v-w)*B[U2]
523
+ sage: mt3_1.parent()
524
+ Free module generated by {U1, U2}
525
+ over Multivariate Polynomial Ring in u, v, w, s
526
+ over Integer Ring localized at (s, w, v, u)
527
+
528
+ sage: f = b3_1.formal_markov_trace(extended=True); f
529
+ (a^2*b*c*s^-1+a*b^2*c*s^-1+a*b*c^2*s^-1+a^2*s+a*b*s+b^2*s+a*c*s+b*c*s+c^2*s)*B[U1]
530
+ + (-a^2*b-a*b^2-a^2*c+(-2)*a*b*c-b^2*c-a*c^2-b*c^2)*B[U2]
531
+ sage: f.parent().base_ring()
532
+ Multivariate Laurent Polynomial Ring in a, b, c, s
533
+ over Splitting Algebra of x^2 + x + 1 with roots [e3, -e3 - 1]
534
+ over Integer Ring
535
+
536
+ sage: f = b3_1.formal_markov_trace(extended=True, field_embedding=True); f
537
+ ((a^2*b*c+a*b^2*c+a*b*c^2+a^2*s^2+a*b*s^2+b^2*s^2+a*c*s^2+b*c*s^2+c^2*s^2)/s)*B[U1]
538
+ - (a^2*b+a*b^2+a^2*c+2*a*b*c+b^2*c+a*c^2+b*c^2)*B[U2]
539
+ sage: f.parent().base_ring()
540
+ Fraction Field of Multivariate Polynomial Ring in a, b, c, s
541
+ over Cyclotomic Field of order 3 and degree 2
542
+
543
+ Obtaining the well known link invariants from it::
544
+
545
+ sage: MT = mt3_1.base_ring()
546
+ sage: sup = mt3_1.support()
547
+ sage: u, v, w, s = mt3_1.base_ring().gens()
548
+ sage: LK3_1 = mt3_1*s**-3 # since the writhe of K3_1 is 3
549
+ sage: f = MT.specialize_homfly()
550
+ sage: g = sum(f(LK3_1.coefficient(b)) * b.regular_homfly_polynomial() for b in sup); g
551
+ L^-2*M^2 - 2*L^-2 - L^-4
552
+ sage: g == K3_1.link().homfly_polynomial()
553
+ True
554
+
555
+ sage: f = MT.specialize_kauffman()
556
+ sage: g = sum(f(LK3_1.coefficient(b)) * b.regular_kauffman_polynomial() for b in sup); g
557
+ a^-2*z^2 - 2*a^-2 + a^-3*z + a^-4*z^2 - a^-4 + a^-5*z
558
+ sage: g == K3_1.kauffman_polynomial()
559
+ True
560
+
561
+ sage: f = MT.specialize_links_gould()
562
+ sage: g = sum(f(LK3_1.coefficient(b)) * b.links_gould_polynomial() for b in sup); g
563
+ -t0^2*t1 - t0*t1^2 + t0^2 + 2*t0*t1 + t1^2 - t0 - t1 + 1
564
+ sage: g == K3_1.link().links_gould_polynomial()
565
+ True
566
+ """
567
+ cha = self.parent()
568
+ vs = self.to_vector()
569
+ mtcf = cha._markov_trace_coeffs()
570
+ M = cha._markov_trace_module(extended=extended, field_embedding=field_embedding)
571
+ if M != mtcf[0].parent():
572
+ if field_embedding:
573
+ # intermediate step needed since internal coercion to the field
574
+ # maps (u, v, w ) -> (a, b, c)
575
+ MI = cha._markov_trace_module(extended=extended, field_embedding=False)
576
+ RI = MI.base_ring()
577
+ mtcf = [MI.from_vector(cf.to_vector()) for cf in mtcf]
578
+ vs = vs.change_ring(RI)
579
+ mtcf = [M.from_vector(cf.to_vector()) for cf in mtcf]
580
+
581
+ R = M.base_ring()
582
+ return M.linear_combination((mtcf[i], R(val)) for i, val in vs.iteritems())
583
+
584
+
585
+ class CubicHeckeAlgebra(CombinatorialFreeModule):
586
+ r"""
587
+ Return the Cubic-Hecke algebra with respect to the Artin braid group on
588
+ `n` strands.
589
+
590
+ This is a quotient of the group algebra of the Artin braid group, such that
591
+ the images `s_i` (`1 \leq i < n`) of the braid generators satisfy a cubic
592
+ equation (see :mod:`~sage.algebras.hecke_algebras.cubic_hecke_algebra`
593
+ for more information, in a session type
594
+ ``sage.algebras.hecke_algebras.cubic_hecke_algebra?``):
595
+
596
+ .. MATH::
597
+
598
+ s_i^3 = u s_i^2 - v s_i + w.
599
+
600
+ The base ring of this algebra can be specified by giving optional keywords
601
+ described below. If no keywords are given, the base ring will be a
602
+ :class:`CubicHeckeRingOfDefinition`, which is constructed as the
603
+ polynomial ring in `u, v, w` over the integers localized at `w`.
604
+ This ring will be called the *ring of definition* or sometimes for short
605
+ *generic base ring*. However note, that in this context the word *generic*
606
+ should not remind in a generic point of the corresponding scheme.
607
+
608
+ In addition to the base ring, another ring containing the roots (`a`, `b`
609
+ and `c`) of the cubic equation will be needed to handle the split
610
+ irreducible representations. This ring will be called the *extension ring*.
611
+ Generically, the extension ring will be a
612
+ :class:`~sage.algebras.hecke_algebras.cubic_hecke_base_ring.CubicHeckeExtensionRing`,
613
+ which is constructed as the Laurent polynomial ring in `a, b` and `c` over
614
+ the integers adjoined with a primitive third root of unity. A special form
615
+ of this *generic extension ring* is constructed as a
616
+ :class:`~sage.algebras.splitting_algebra.SplittingAlgebra` for the roots of
617
+ the cubic equation and a primitive third root of unity over the ring of
618
+ definition. This ring will be called the *default extension ring*.
619
+
620
+ This class uses a static and a dynamic data library. The first one is defined
621
+ as instance of :class:`~sage.databases.cubic_hecke_db.CubicHeckeDataBase`
622
+ and contains the complete basis for the algebras with less than 5 strands
623
+ and various types of representation matrices of the generators. These data
624
+ have been calculated by `Ivan Marin <http://www.lamfa.u-picardie.fr/marin/anglais.html>`__
625
+ and have been imported from his corresponding
626
+ `web page <http://www.lamfa.u-picardie.fr/marin/representationH4-en.html>`__.
627
+
628
+ Note that just the data for the cubic Hecke algebras on less than four
629
+ strands is available in Sage by default. To deal with four strands and
630
+ more you need to install the optional package
631
+ `database_cubic_hecke <https://pypi.org/project/database-cubic-hecke/>`__
632
+ by typing
633
+
634
+ - ``sage -i database_cubic_hecke`` (first time installation) or
635
+ - ``sage -f database_cubic_hecke`` (reinstallation) respective
636
+ - ``sage -i -c database_cubic_hecke`` (for running all test in concern)
637
+ - ``sage -f -c database_cubic_hecke``
638
+
639
+ This will add a `Python wrapper <https://github.com/soehms/database_cubic_hecke#readme>`__
640
+ around Ivan Marin's data to the Sage library. For more installation hints
641
+ see the documentation of this wrapper.
642
+
643
+ Furthermore, representation matrices can be obtained from the ``CHEVIE``
644
+ package of ``GAP3`` via the ``GAP3`` interface if ``GAP3`` is installed
645
+ inside Sage. For more information on how to obtain representation matrices
646
+ to elements of this class, see the documentation of the element class
647
+ :class:`~sage.algebras.hecke_algebras.cubic_hecke_algebra.CubicHeckeElement`
648
+ or its method
649
+ :meth:`~sage.algebras.hecke_algebras.cubic_hecke_algebra.CubicHeckeElement.matrix`:
650
+
651
+ ``algebras.CubicHecke.Element?`` or ``algebras.CubicHecke.Element.matrix?``
652
+
653
+ The second library is created as instance of
654
+ :class:`~sage.databases.cubic_hecke_db.CubicHeckeFileCache` and used while
655
+ working with the class to achieve a better performance. This file cache
656
+ contains images of braids and representation matrices of basis elements
657
+ from former calculations. A refresh of the file cache can be done using
658
+ the :meth:`reset_filecache`.
659
+
660
+ INPUT:
661
+
662
+ - ``names`` -- string containing the names of the generators as images of
663
+ the braid group generators
664
+ - ``cubic_equation_parameters`` -- tuple ``(u, v, w)`` of three elements
665
+ in an integral domain used as coefficients in the cubic equation. If this
666
+ argument is given the base ring will be set to the common parent of
667
+ ``u, v, w``. In addition a conversion map from the generic base ring is
668
+ supplied. This keyword can also be used to change the variable names of
669
+ the generic base ring (see example 3 below)
670
+ - ``cubic_equation_roots`` -- tuple ``(a, b, c)`` of three elements in an
671
+ integral domain which stand for the roots of the cubic equation. If this
672
+ argument is given the extension ring will be set to the common parent of
673
+ ``a, b, c``. In addition a conversion map from the generic extension ring
674
+ and the generic base ring is supplied. This keyword can also be used to
675
+ change the variable names of the generic extension ring (see example 3
676
+ below)
677
+
678
+ EXAMPLES:
679
+
680
+ Cubic Hecke algebra over the ring of definition::
681
+
682
+ sage: CHA3 = algebras.CubicHecke('s1, s2'); CHA3
683
+ Cubic Hecke algebra on 3 strands over Multivariate Polynomial Ring
684
+ in u, v, w
685
+ over Integer Ring localized at (w,)
686
+ with cubic equation: h^3 - u*h^2 + v*h - w = 0
687
+ sage: CHA3.gens()
688
+ (s1, s2)
689
+ sage: GER = CHA3.extension_ring(generic=True); GER
690
+ Multivariate Laurent Polynomial Ring in a, b, c
691
+ over Splitting Algebra of x^2 + x + 1
692
+ with roots [e3, -e3 - 1] over Integer Ring
693
+ sage: ER = CHA3.extension_ring(); ER
694
+ Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
695
+ over Splitting Algebra of h^3 - u*h^2 + v*h - w
696
+ with roots [a, b, -b - a + u]
697
+ over Multivariate Polynomial Ring in u, v, w
698
+ over Integer Ring localized at (w,)
699
+
700
+ Element construction::
701
+
702
+ sage: ele = CHA3.an_element(); ele
703
+ -w*s1*s2^-1 + v*s1 + u*s2 - ((v*w-u)/w)
704
+ sage: ele2 = ele**2; ele2
705
+ w^2*(s1^-1*s2)^2 - u*w^2*s1^-1*s2*s1^-1 - v*w*s2*s1^-1*s2
706
+ - v*w^2*s1^-1*s2^-1 + u*w*s1*s2*s1^-1*s2 - u*w*s1^-1*s2*s1
707
+ - (u*v*w-2*v*w+2*u)*s1*s2^-1 + u*v*w*s2*s1^-1 + u*v*s2*s1 + v^2*w*s1^-1
708
+ - u^2*w*s1*s2*s1^-1 + ((u*v^2*w-2*v^2*w-u*w^2+2*u*v)/w)*s1 + u*v*s1*s2
709
+ + (u^2*w+v^2*w)*s2^-1 + ((u^3*w-2*u*v*w+2*u^2)/w)*s2
710
+ - ((u^2*v*w^2+v^3*w^2-v^2*w^2+2*u*v*w-u^2)/w^2)
711
+ sage: B3 = CHA3.braid_group()
712
+ sage: braid = B3((2,-1, 2, 1)); braid
713
+ s2*s1^-1*s2*s1
714
+ sage: ele3 = CHA3(braid); ele3
715
+ s1*s2*s1^-1*s2 + u*s1^-1*s2*s1 - v*s1*s2^-1 + v*s2^-1*s1 - u*s1*s2*s1^-1
716
+ sage: ele3t = CHA3((2,-1, 2, 1))
717
+ sage: ele3 == ele3t
718
+ True
719
+ sage: CHA4 = algebras.CubicHecke(4) # optional database_cubic_hecke
720
+ sage: ele4 = CHA4(ele3); ele4 # optional database_cubic_hecke
721
+ c0*c1*c0^-1*c1 + u*c0^-1*c1*c0 + (-v)*c0*c1^-1 + v*c1^-1*c0 + (-u)*c0*c1*c0^-1
722
+
723
+ Cubic Hecke algebra over the ring of definition using different variable
724
+ names::
725
+
726
+ sage: algebras.CubicHecke(3, cubic_equation_parameters='u, v, w', cubic_equation_roots='p, q, r')
727
+ Cubic Hecke algebra on 3 strands over Multivariate Polynomial Ring
728
+ in u, v, w
729
+ over Integer Ring localized at (w,)
730
+ with cubic equation: h^3 - u*h^2 + v*h - w = 0
731
+ sage: _.extension_ring()
732
+ Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
733
+ over Splitting Algebra of h^3 - u*h^2 + v*h - w
734
+ with roots [p, q, -q - p + u]
735
+ over Multivariate Polynomial Ring in u, v, w
736
+ over Integer Ring localized at (w,)
737
+
738
+ Cubic Hecke algebra over a special base ring with respect to a special
739
+ cubic equation::
740
+
741
+ sage: algebras.CubicHecke('s1, s2', cubic_equation_parameters=(QQ(1),3,1))
742
+ Cubic Hecke algebra on 3 strands over Rational Field
743
+ with cubic equation: h^3 - h^2 + 3*h - 1 = 0
744
+ sage: CHA3 = _
745
+ sage: ER = CHA3.extension_ring(); ER
746
+ Number Field in T with defining polynomial T^12 + 4*T^11 + 51*T^10
747
+ + 154*T^9 + 855*T^8 + 1880*T^7 + 5805*T^6 + 8798*T^5 + 15312*T^4
748
+ + 14212*T^3 + 13224*T^2 + 5776*T + 1444
749
+ sage: CHA3.cubic_equation_roots()[0]
750
+ -4321/1337904*T^11 - 4181/445968*T^10 - 4064/27873*T^9 - 51725/167238*T^8
751
+ - 2693189/1337904*T^7 - 1272907/445968*T^6 - 704251/74328*T^5
752
+ - 591488/83619*T^4 - 642145/83619*T^3 + 252521/111492*T^2 + 45685/5868*T
753
+ + 55187/17604
754
+
755
+ sage: F = GF(25,'u')
756
+ sage: algebras.CubicHecke('s1, s2', cubic_equation_parameters=(F(1), F.gen(), F(3)))
757
+ Cubic Hecke algebra on 3 strands over Finite Field in u of size 5^2
758
+ with cubic equation: h^3 + 4*h^2 + u*h + 2 = 0
759
+ sage: CHA3 = _
760
+ sage: ER = CHA3.extension_ring(); ER
761
+ Finite Field in S of size 5^4
762
+ sage: CHA3.cubic_equation_roots()
763
+ [2*S^3 + 2*S^2 + 2*S + 1, 2*S^3 + 3*S^2 + 3*S + 2, S^3 + 3]
764
+
765
+
766
+ Cubic Hecke algebra over a special extension ring with respect to special
767
+ roots of the cubic equation::
768
+
769
+ sage: UCF = UniversalCyclotomicField()
770
+ sage: e3=UCF.gen(3); e5=UCF.gen(5)
771
+ sage: algebras.CubicHecke('s1, s2', cubic_equation_roots=(1, e5, e3))
772
+ Cubic Hecke algebra on 3 strands over Universal Cyclotomic Field
773
+ with cubic equation:
774
+ h^3 + (-E(15) - E(15)^4 - E(15)^7 + E(15)^8)*h^2 + (-E(15)^2 - E(15)^8
775
+ - E(15)^11 - E(15)^13 - E(15)^14)*h - E(15)^8 = 0
776
+
777
+ TESTS::
778
+
779
+ sage: CHA3 = algebras.CubicHecke(3)
780
+ sage: TestSuite(CHA3).run()
781
+
782
+ Note, that the ``TestSuite`` run on the cubic Hecke algebra on four strands
783
+ would take up to half an hour if the file cache is empty. A repetition takes
784
+ less than half a minute.
785
+ """
786
+ Element = CubicHeckeElement
787
+ repr_type = RepresentationType
788
+ irred_repr = AbsIrreducibeRep
789
+
790
+ ############################################################################
791
+ # private methods
792
+ ############################################################################
793
+ @staticmethod
794
+ def __classcall_private__(cls, n=None, names='c', cubic_equation_parameters=None, cubic_equation_roots=None):
795
+ r"""
796
+ Normalize input to ensure a unique representation.
797
+
798
+ EXAMPLES::
799
+
800
+ sage: CHA2 = algebras.CubicHecke(2, 'd', cubic_equation_roots=(3,5,7)); CHA2
801
+ Cubic Hecke algebra on 2 strands
802
+ over Integer Ring localized at (3, 5, 7)
803
+ with cubic equation:
804
+ h^3 - 15*h^2 + 71*h - 105 = 0
805
+ sage: CHA2.inject_variables()
806
+ Defining d
807
+ sage: CHA3 = algebras.CubicHecke(3, cubic_equation_parameters=(3,5,7)); CHA3
808
+ Cubic Hecke algebra on 3 strands
809
+ over Integer Ring localized at (7,)
810
+ with cubic equation:
811
+ h^3 - 3*h^2 + 5*h - 7 = 0
812
+ sage: CHA3.cubic_equation_roots()
813
+ [a, b, -b - a + 3]
814
+ """
815
+ # Support Freegroup('a,b') syntax
816
+ if n is not None:
817
+ try:
818
+ n = ZZ(n) - 1
819
+ except TypeError:
820
+ names = n
821
+ n = None
822
+
823
+ # derive n from counting names
824
+ if n is None:
825
+ if type(names) is str:
826
+ n = len(names.split(','))
827
+ else:
828
+ names = list(names)
829
+ n = len(names)
830
+
831
+ from sage.structure.category_object import normalize_names
832
+ names = tuple(normalize_names(n, names))
833
+ return super().__classcall__(cls, names,
834
+ cubic_equation_parameters=cubic_equation_parameters,
835
+ cubic_equation_roots=cubic_equation_roots)
836
+
837
+ def __init__(self, names, cubic_equation_parameters=None, cubic_equation_roots=None):
838
+ r"""
839
+ Initialize ``self``.
840
+
841
+ TESTS::
842
+
843
+ sage: CHA2 = algebras.CubicHecke(2, 'd', cubic_equation_roots=(3,5,7))
844
+ sage: TestSuite(CHA2).run()
845
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_parameters=(3,5,7))
846
+ sage: TestSuite(CHA2).run()
847
+ """
848
+ # ----------------------------------------------------------------------
849
+ # Define underlying group
850
+ # ----------------------------------------------------------------------
851
+ self._cubic_braid_group = CubicBraidGroup(names)
852
+ self._braid_group = self._cubic_braid_group.braid_group()
853
+ n = len(self._cubic_braid_group.gens())
854
+ self._nstrands = n + 1
855
+ self._dim_irr_rep = sum([irr.dimension() for irr in AbsIrreducibeRep if irr.number_gens() == n])
856
+
857
+ # ----------------------------------------------------------------------
858
+ # preparing use of data base anf file cache
859
+ # ----------------------------------------------------------------------
860
+ from sage.databases.cubic_hecke_db import CubicHeckeDataBase, CubicHeckeFileCache
861
+ self._database = CubicHeckeDataBase()
862
+ self._filecache = CubicHeckeFileCache(self._nstrands)
863
+
864
+ # ----------------------------------------------------------------------
865
+ # interpretation of keywords and type verifications
866
+ # ----------------------------------------------------------------------
867
+ # cubic_equation_parameters
868
+ # ----------------------------------------------------------------------
869
+ ring_of_definition_names = ('u', 'v', 'w')
870
+ if cubic_equation_parameters is not None:
871
+ if isinstance(cubic_equation_parameters, str):
872
+ # --------------------------------------------------------------
873
+ # Input specifies names for the generic base ring
874
+ # --------------------------------------------------------------
875
+ ring_of_definition_names = tuple(cubic_equation_parameters.split(','))
876
+ if len(ring_of_definition_names) != 3:
877
+ raise ValueError('cubic_equation_parameters must consist of exactly 3 elements')
878
+ cubic_equation_parameters = None
879
+ else:
880
+ # --------------------------------------------------------------
881
+ # Input specifies a specialized base ring
882
+ # --------------------------------------------------------------
883
+ if isinstance(cubic_equation_parameters, list):
884
+ cubic_equation_parameters = tuple(cubic_equation_parameters)
885
+ if not isinstance(cubic_equation_parameters, tuple):
886
+ raise TypeError('cubic_equation_parameters must be a tuple or list')
887
+ if len(cubic_equation_parameters) != 3:
888
+ raise ValueError('cubic_equation_parameters must consist of exactly 3 elements')
889
+
890
+ # ----------------------------------------------------------------------
891
+ # cubic_equation_roots
892
+ # ----------------------------------------------------------------------
893
+ generic_extension_ring_names = ('a', 'b', 'c')
894
+ if cubic_equation_roots is not None:
895
+ if isinstance(cubic_equation_roots, str):
896
+ # --------------------------------------------------------------
897
+ # Input specifies names for the generic extension ring
898
+ # --------------------------------------------------------------
899
+ generic_extension_ring_names = tuple(cubic_equation_roots.split(','))
900
+ if len(generic_extension_ring_names) != 3:
901
+ raise ValueError('cubic_equation_roots must consist of exactly 3 elements')
902
+ cubic_equation_roots = None
903
+ else:
904
+ # --------------------------------------------------------------
905
+ # Input specifies a specialized base ring
906
+ # --------------------------------------------------------------
907
+ if isinstance(cubic_equation_roots, list):
908
+ cubic_equation_roots = tuple(cubic_equation_roots)
909
+ if not isinstance(cubic_equation_roots, tuple):
910
+ raise TypeError('cubic_equation_roots must be a tuple or list')
911
+ if len(cubic_equation_roots) != 3:
912
+ raise ValueError('cubic_equation_roots must consist of exactly 3 elements')
913
+
914
+ if len(set(ring_of_definition_names + generic_extension_ring_names)) < 6:
915
+ raise ValueError('there is an overlap of names between cubic equation '
916
+ 'parameters (%s) and cubic equation roots (%s)'
917
+ % (ring_of_definition_names, generic_extension_ring_names))
918
+
919
+ # ----------------------------------------------------------------------
920
+ # setting the generic rings
921
+ # ----------------------------------------------------------------------
922
+ ring_of_definition = CubicHeckeRingOfDefinition(names=ring_of_definition_names)
923
+ u, v, w = ring_of_definition.gens()
924
+
925
+ generic_extension_ring = ring_of_definition.extension_ring(names=generic_extension_ring_names)
926
+ a, b, c = generic_extension_ring.gens()
927
+
928
+ # ----------------------------------------------------------------------
929
+ # registering generic items as variables
930
+ # ----------------------------------------------------------------------
931
+ self._ring_of_definition = ring_of_definition
932
+ self._generic_extension_ring = generic_extension_ring
933
+ self._generic_cubic_equation_parameters = [u, v, w]
934
+ self._generic_cubic_equation_roots = [a, b, c]
935
+
936
+ # ----------------------------------------------------------------------
937
+ # interpreting user given cubic equation parameters to define the
938
+ # corresponding specialized base ring
939
+ # ----------------------------------------------------------------------
940
+ if cubic_equation_parameters is None and cubic_equation_roots is not None:
941
+ pa, pb, pc = cubic_equation_roots
942
+ cubic_equation_parameters = [pa+pb+pc, pa*pb+pb*pc+pa*pc, pa*pb*pc]
943
+ verbose('cubic_equation_parameters %s set according to '
944
+ 'cubic_equation_roots %s' % (cubic_equation_parameters,
945
+ cubic_equation_roots), level=2)
946
+
947
+ if cubic_equation_parameters is not None:
948
+ base_ring = ring_of_definition.create_specialization(cubic_equation_parameters)
949
+ cubic_equation_parameters = [base_ring(para) for para in cubic_equation_parameters]
950
+ verbose('base_ring %s set according to cubic_equation_parameters %s'
951
+ % (base_ring, cubic_equation_parameters), level=2)
952
+ else:
953
+ base_ring = self._ring_of_definition
954
+ cubic_equation_parameters = self._generic_cubic_equation_parameters
955
+
956
+ verbose('base_ring %s and cubic_equation_parameters %s defined'
957
+ % (base_ring, cubic_equation_parameters), level=2)
958
+
959
+ # ----------------------------------------------------------------------
960
+ # defining the cubic equation
961
+ # ----------------------------------------------------------------------
962
+ pu, pv, pw = cubic_equation_parameters
963
+ pol_bas_ring = base_ring['h']
964
+ cubic_equation = pol_bas_ring([-pw, pv, -pu, 1])
965
+
966
+ verbose('cubic_equation %s defined' % cubic_equation, level=2)
967
+
968
+ # ----------------------------------------------------------------------
969
+ # defining cubic_equation_roots if not given using the cubic_equation
970
+ # ----------------------------------------------------------------------
971
+ if base_ring != ring_of_definition:
972
+ if cubic_equation_roots is None:
973
+ # --------------------------------------------------------------
974
+ # No roots given
975
+ # --------------------------------------------------------------
976
+ ext_ring_names = list(generic_extension_ring_names)
977
+ cubic_equation_roots = solve_with_extension(cubic_equation,
978
+ ext_ring_names,
979
+ var='S', flatten=True)
980
+
981
+ # ----------------------------------------------------------------------
982
+ # interpreting user given cubic equation roots to define the
983
+ # corresponding specialized extension ring
984
+ # ----------------------------------------------------------------------
985
+ if cubic_equation_roots is not None:
986
+ extension_ring = generic_extension_ring.create_specialization(cubic_equation_roots)
987
+ cubic_equation_roots = [extension_ring(root) for root in cubic_equation_roots]
988
+ verbose('extension_ring %s set according to cubic_equation_roots %s'
989
+ % (base_ring, cubic_equation_roots), level=2)
990
+
991
+ else:
992
+ extension_ring = generic_extension_ring.as_splitting_algebra()
993
+ cubic_equation_roots = [extension_ring(a), extension_ring(b), extension_ring(c)]
994
+
995
+ verbose('cubic roots %s and extension ring %s defined'
996
+ % (cubic_equation_roots, extension_ring), level=2)
997
+ pa, pb, pc = cubic_equation_roots
998
+
999
+ # ----------------------------------------------------------------------
1000
+ # check keywords plausibility
1001
+ # ----------------------------------------------------------------------
1002
+ if base_ring == extension_ring:
1003
+ val_a = cubic_equation.substitute(h=pa)
1004
+ val_b = cubic_equation.substitute(h=pb)
1005
+ val_c = cubic_equation.substitute(h=pc)
1006
+ if val_a != 0 or val_b != 0 or val_c != 0:
1007
+ raise ValueError('cubic equation does not vanish on cubic equation roots')
1008
+
1009
+ # ----------------------------------------------------------------------
1010
+ # defining the base ring embedding into the extension ring
1011
+ # ----------------------------------------------------------------------
1012
+ im_base_gens = [pa+pb+pc, pa*pb+pa*pc+pb*pc, pa*pb*pc]
1013
+ base_ring_embedding = extension_ring.coerce_map_from(base_ring)
1014
+
1015
+ def check_base_ring_embedding(base_ring_embedding):
1016
+ if base_ring_embedding is None:
1017
+ return False
1018
+ try:
1019
+ ipu = base_ring_embedding(pu)
1020
+ ipv = base_ring_embedding(pv)
1021
+ ipw = base_ring_embedding(pw)
1022
+ if [ipu, ipv, ipw] != im_base_gens:
1023
+ return False
1024
+ except (TypeError, ValueError):
1025
+ return False
1026
+ return True
1027
+
1028
+ if check_base_ring_embedding(base_ring_embedding):
1029
+ verbose('base_ring_embedding defined via coercion', level=2)
1030
+ else:
1031
+ base_ring_embedding = extension_ring.convert_map_from(base_ring)
1032
+ if check_base_ring_embedding(base_ring_embedding):
1033
+ verbose('base_ring_embedding defined via conversion', level=2)
1034
+ else:
1035
+ try:
1036
+ if base_ring.gens() == cubic_equation_parameters:
1037
+ base_ring_embedding = base_ring.hom(im_base_gens, codomain=extension_ring)
1038
+ except (TypeError, ValueError):
1039
+ base_ring_embedding = None
1040
+
1041
+ if base_ring_embedding is None:
1042
+ warn('Warning: no base_ring_embedding found')
1043
+
1044
+ # ----------------------------------------------------------------------
1045
+ # registering variables
1046
+ # ----------------------------------------------------------------------
1047
+ self._extension_ring = extension_ring
1048
+ self._base_ring_embedding = base_ring_embedding
1049
+ self._ring_of_definition_map = base_ring.convert_map_from(ring_of_definition)
1050
+ self._generic_extension_ring_map = extension_ring.convert_map_from(generic_extension_ring)
1051
+ self._cubic_equation_parameters = cubic_equation_parameters
1052
+ self._cubic_equation_roots = cubic_equation_roots
1053
+
1054
+ # ----------------------------------------------------------------------
1055
+ # defining the associated group algebras
1056
+ # ----------------------------------------------------------------------
1057
+ from sage.algebras.group_algebra import GroupAlgebra
1058
+ self._cubic_braid_group_algebra = GroupAlgebra(self._cubic_braid_group, R=base_ring)
1059
+ self._braid_group_algebra = GroupAlgebra(self._braid_group, R=base_ring)
1060
+
1061
+ # ----------------------------------------------------------------------
1062
+ # Setup of Basis
1063
+ # ----------------------------------------------------------------------
1064
+ # Fetch Ivan Marin's basis for the algebras on at most 4 strands.
1065
+ # An explicit list of basis element which represents a flat deformation
1066
+ # of the cubic braid group is only available in the cases where the
1067
+ # number of strands is less than 5. In the case of exactly 5 strands
1068
+ # it is known that such a basis exist by work of Ivan Marin in
1069
+ # [Marin2012] but it can not be calculated, right now. In the (infinite
1070
+ # dimensional) cases of more than 5 strands it is even an open problem
1071
+ # if the cubic Hecke algebra is a flat deformation of the group algebra
1072
+ # of the corresponding cubic braid group.
1073
+ #
1074
+ # But anyway, we will take the elements of the cubic braid group as a
1075
+ # basis of the cubic Hecke algebra in all cases. Beware that this might
1076
+ # not cover the whole cubic Hecke algebra if the number of strands is
1077
+ # larger than 4
1078
+ #
1079
+ # Internally the basis is implemented using two lists one of which
1080
+ # consists of fixed braid pre images of the basis elements and the other
1081
+ # (redundant) of the corresponding Tietze expressions.
1082
+ #
1083
+ # In the case of less than 5 strands these lists are directly obtained
1084
+ # from the list calculated by Ivan Marin available at
1085
+ #
1086
+ # In the other cases these lists are implemented as growing list which
1087
+ # is initialized with Marin's list and is extended on demand.
1088
+ # ----------------------------------------------------------------------
1089
+ db = self._database
1090
+ ns = min(self._nstrands, 4)
1091
+ self._basis_static = db.read(db.section.basis, nstrands=ns)
1092
+
1093
+ # ----------------------------------------------------------------------
1094
+ # defining the algebra itself
1095
+ # ----------------------------------------------------------------------
1096
+ if self._cubic_braid_group.is_finite():
1097
+ from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis
1098
+ category = FiniteDimensionalAlgebrasWithBasis(base_ring)
1099
+ else:
1100
+ from sage.categories.algebras_with_basis import AlgebrasWithBasis
1101
+ category = AlgebrasWithBasis(base_ring)
1102
+
1103
+ CombinatorialFreeModule.__init__(self, base_ring, self._cubic_braid_group,
1104
+ prefix='', names=names, bracket=False,
1105
+ category=category)
1106
+
1107
+ # ----------------------------------------------------------------------
1108
+ # init the attributes being set on demand
1109
+ # ----------------------------------------------------------------------
1110
+ self._cubic_hecke_subalgebra = None
1111
+ self._mirror_image = None
1112
+ self._is_mirror = False
1113
+ self._base_ring_mirror = None
1114
+ self._gens_reg_repres_matrix = {}
1115
+
1116
+ # ----------------------------------------------------------------------
1117
+ # initializing the basis extension (in case of more than 4 strands)
1118
+ # ----------------------------------------------------------------------
1119
+ self._init_basis_extension()
1120
+
1121
+ ############################################################################
1122
+ # --------------------------------------------------------------------------
1123
+ # overloaded inherited methods
1124
+ # --------------------------------------------------------------------------
1125
+ ############################################################################
1126
+ def _repr_(self):
1127
+ r"""
1128
+ Return a string representation.
1129
+
1130
+ OUTPUT: string describing ``self``
1131
+
1132
+ TESTS::
1133
+
1134
+ sage: CHA3 = algebras.CubicHecke(3)
1135
+ sage: CHA3 # indirect doctest
1136
+ Cubic Hecke algebra on 3 strands
1137
+ over Multivariate Polynomial Ring in u, v, w
1138
+ over Integer Ring localized at (w,)
1139
+ with cubic equation: h^3 - u*h^2 + v*h - w = 0
1140
+ """
1141
+ s = 'Cubic Hecke algebra on %s strands over %s with cubic equation: %s = 0'
1142
+ return s % (self._nstrands, self.base_ring(), self.cubic_equation())
1143
+
1144
+ def _element_constructor_(self, x):
1145
+ r"""
1146
+ Extensions to the element constructor of class :class:`CombinatorialFreeModule`.
1147
+
1148
+ New functionalities are:
1149
+
1150
+ - constructing element from a braid (group homomorphism)
1151
+ - constructing element from a braid giving in Tietze form
1152
+ - constructing element from an element of the braid group algebra
1153
+ (algebra homomorphism)
1154
+ - constructing element from an element of the cubic braid group
1155
+ algebra (module homomorphism)
1156
+ - constructing element from an element of an other cubic Hecke
1157
+ algebra over an other base ring or with less strands
1158
+ - constructing element from an element of the mirror image of
1159
+ ``self`` (see method mirror_image)
1160
+
1161
+ INPUT:
1162
+
1163
+ - ``x`` -- can be one of the following:
1164
+
1165
+ * an instance of the element class of ``self`` (but possible
1166
+ to a different parent)
1167
+ * an instance of the element class of the braid group
1168
+ * an instance of the element class of the braid group algebra
1169
+ over the base ring of ``self``
1170
+ * an instance of the element class of the cubic braid group
1171
+ * an instance of the element class of the cubic braid group
1172
+ algebra over the base ring of ``self``
1173
+ * an instance of the element class of the mirror image of
1174
+ ``self``
1175
+ * a tuple representing a braid in Tietze form
1176
+ * any other object which works for the element constructor
1177
+ of :class:`CombinatorialFreeModule`
1178
+
1179
+ EXAMPLES::
1180
+
1181
+ sage: B2 = BraidGroup(2)
1182
+ sage: b, = B2.gens()
1183
+ sage: b2 = b**2
1184
+ sage: CB2 = CubicBraidGroup(2)
1185
+ sage: cb, = CB2.gens()
1186
+ sage: cb2 = cb**2
1187
+ sage: CHA2 = algebras.CubicHecke(2)
1188
+ sage: CHA2(b2)
1189
+ w*c^-1 + u*c - v
1190
+ sage: CHA2(cb2)
1191
+ c^-1
1192
+ sage: CHA3 = algebras.CubicHecke(3)
1193
+ sage: B3 = CHA3.braid_group()
1194
+ sage: CB3 = CHA3.cubic_braid_group()
1195
+ sage: CB3GA = CHA3.cubic_braid_group_algebra()
1196
+ sage: braid = B3((1,2,2,-1,2,1,1,-1)); braid
1197
+ c0*c1^2*c0^-1*c1*c0
1198
+ sage: img_braid = CHA3(braid); img_braid
1199
+ u*w*(c0^-1*c1)^2 + u*v*c0*c1^-1*c0 - u^2*w*c0^-1*c1*c0^-1
1200
+ - u*v*c1*c0^-1*c1 - (u*v*w-w^2)*c0^-1*c1^-1 + u^2*c0*c1*c0^-1*c1
1201
+ - (u^2*v-u*w)*c0*c1^-1 + u^2*v*c1*c0^-1 + (u^2-v)*c1*c0
1202
+ - u^3*c0*c1*c0^-1 + (u*v^2-v*w)*c1^-1
1203
+ sage: cbraid = CB3(braid); cbraid
1204
+ c0*c1^2*c0^-1*c1*c0
1205
+ sage: img_cbraid = CHA3(cbraid); img_cbraid
1206
+ c0^-1*c1^-1
1207
+ sage: img_cbraid_back = img_cbraid.cubic_braid_group_algebra_pre_image()
1208
+ sage: img_cbraid_back in CB3GA
1209
+ True
1210
+ sage: img_cbraid_back == CB3GA(cbraid)
1211
+ True
1212
+ """
1213
+ braid_grp = self.braid_group()
1214
+ braid_grp_alg = self.braid_group_algebra()
1215
+ braid_img = self._braid_image
1216
+
1217
+ cbraid_grp = self.cubic_braid_group()
1218
+ cbraid_grp_alg = self.cubic_braid_group_algebra()
1219
+ cbraid_img = self._cubic_braid_image
1220
+
1221
+ base_ring = self.base_ring()
1222
+ ngens = self.ngens()
1223
+ params = self.cubic_equation_parameters()
1224
+
1225
+ # ----------------------------------------------------------------------
1226
+ # if x is a tuple we may interpret it as a braid in Tietze form
1227
+ # ----------------------------------------------------------------------
1228
+ xb = x
1229
+ if type(x) in (tuple, list):
1230
+ x = tuple(x)
1231
+ result = self._tietze_to_finite_sub_basis_monomial(x)
1232
+ if result is not None:
1233
+ # x represents a monomial
1234
+ verbose('end from tuple %s: %s' % (x, result), level=2)
1235
+ return result
1236
+
1237
+ try:
1238
+ xb = braid_grp(x)
1239
+ except (TypeError, ValueError, NotImplementedError):
1240
+ pass
1241
+
1242
+ # ----------------------------------------------------------------------
1243
+ # embedding of an element of an other cubic Hecke algebra with lower
1244
+ # number of strands but same base ring
1245
+ # ----------------------------------------------------------------------
1246
+ if isinstance(xb, CubicHeckeElement):
1247
+ other_cha = xb.parent()
1248
+ other_base_ring = other_cha.base_ring()
1249
+ other_ngens = other_cha.ngens()
1250
+ other_params = other_cha.cubic_equation_parameters()
1251
+ if other_base_ring != base_ring:
1252
+ if other_ngens == ngens:
1253
+ xbv = xb.to_vector()
1254
+ img_xbv = vector([self.base_ring()(cf) for cf in xbv])
1255
+ return self.from_vector(img_xbv)
1256
+ elif other_ngens < ngens:
1257
+ sub_alg = self.cubic_hecke_subalgebra(other_ngens+1)
1258
+ return self(sub_alg(xb))
1259
+
1260
+ elif other_ngens < ngens and other_params == params:
1261
+ cbraid_preimg = xb.cubic_braid_group_algebra_pre_image()
1262
+ other_cbga = other_cha.cubic_braid_group_algebra()
1263
+
1264
+ def fc(ele):
1265
+ return cbraid_img(cbraid_grp(ele))
1266
+ result = other_cbga._apply_module_morphism(cbraid_preimg, fc, codomain=self)
1267
+ verbose('end from smaller cubic Hecke algebra %s: %s' % (xb, result), level=2)
1268
+ return result
1269
+
1270
+ elif other_cha == self._mirror_image:
1271
+ result = other_cha.mirror_isomorphism(xb)
1272
+ verbose('end from mirror image %s: %s' % (xb, result), level=2)
1273
+ return result
1274
+
1275
+ # ----------------------------------------------------------------------
1276
+ # if xb is an element of the braid group or its group algebra over the
1277
+ # same base ring the algebra morphism self._braid_image is applied
1278
+ # ----------------------------------------------------------------------
1279
+ if isinstance(xb, braid_grp_alg.element_class) and xb in braid_grp_alg:
1280
+
1281
+ def fb(ele):
1282
+ return braid_img(ele)
1283
+ result = braid_grp_alg._apply_module_morphism(xb, fb, codomain=self)
1284
+ verbose('end from braid_group algebra %s: %s' % (xb, result), level=2)
1285
+ return result
1286
+
1287
+ from sage.groups.braid import Braid
1288
+ if isinstance(xb, Braid) and xb.strands() == self._nstrands:
1289
+ result = braid_img(xb)
1290
+ verbose('end from braid_group %s: %s' % (xb, result), level=2)
1291
+ return result
1292
+
1293
+ # ----------------------------------------------------------------------
1294
+ # if xb is an element of the cubic_braid group or its group algebra over
1295
+ # the same base ring xb the module morphism self._braid_image is applied
1296
+ # ----------------------------------------------------------------------
1297
+ if isinstance(xb, cbraid_grp_alg.element_class) and xb in cbraid_grp_alg:
1298
+ result = cbraid_grp_alg._apply_module_morphism(xb, cbraid_img, codomain=self)
1299
+ verbose('end from cubic braid_group algebra %s: %s' % (xb, result), level=2)
1300
+ return result
1301
+
1302
+ from sage.groups.cubic_braid import CubicBraidElement
1303
+ if isinstance(xb, CubicBraidElement) and xb.parent().strands() == self._nstrands:
1304
+ result = cbraid_img(xb)
1305
+ verbose('end from cubic braid_group %s: %s' % (xb, result), level=2)
1306
+ return result
1307
+
1308
+ # ----------------------------------------------------------------------
1309
+ # doing the default construction by inheritance
1310
+ # ----------------------------------------------------------------------
1311
+ result = CombinatorialFreeModule._element_constructor_(self, x)
1312
+ verbose('end (default) %s: %s' % (xb, result), level=2)
1313
+ return result
1314
+
1315
+ def get_order(self):
1316
+ r"""
1317
+ Return an ordering of the basis of ``self``.
1318
+
1319
+ EXAMPLES::
1320
+
1321
+ sage: CHA3 = algebras.CubicHecke(3)
1322
+ sage: len(CHA3.get_order())
1323
+ 24
1324
+ """
1325
+ # The reason we have overridden this is that we have to care about
1326
+ # the dynamical growth of thefinite sub basis used for the
1327
+ # calculation in case of more than 4 strands.
1328
+
1329
+ if self._nstrands < 5:
1330
+ return self._order
1331
+
1332
+ # detect change of _order of sub algebra
1333
+ sub_alg = self.cubic_hecke_subalgebra()
1334
+ former_len_sub = len(sub_alg._order)
1335
+ sub_order = sub_alg.get_order()
1336
+ if former_len_sub == len(sub_order):
1337
+ if len(self._order) == former_len_sub + len(self._basis_extension):
1338
+ return self._order
1339
+ # _order has changed! re-calculation necessary:
1340
+ cbg = self.cubic_braid_group()
1341
+ sub_order = [cbg(cb) for cb in sub_order]
1342
+ self._order = sub_order + [cbg(tup) for tup in self._basis_extension]
1343
+ return self._order
1344
+
1345
+ def _order_key(self, x):
1346
+ """
1347
+ Return a key for `x` compatible with the term order.
1348
+
1349
+ INPUT:
1350
+
1351
+ - ``x`` -- indices of the basis of ``self``
1352
+
1353
+ EXAMPLES::
1354
+
1355
+ sage: A = CombinatorialFreeModule(QQ, ['x','y','a','b'])
1356
+ sage: A.set_order(['x', 'y', 'a', 'b'])
1357
+ sage: A._order_key('x')
1358
+ 0
1359
+ sage: A._order_key('y')
1360
+ 1
1361
+ sage: A._order_key('a')
1362
+ 2
1363
+ """
1364
+ try:
1365
+ return self._rank_basis(x)
1366
+ except AttributeError:
1367
+ from sage.combinat.ranker import rank_from_list
1368
+ self._rank_basis = rank_from_list(self._order)
1369
+ return self._rank_basis(x)
1370
+
1371
+ def _dense_free_module(self, base_ring=None):
1372
+ r"""
1373
+ Return a dense free module with the same dimension as ``self``.
1374
+
1375
+ This overwrites the corresponding method of :class:`CombinatorialFreeModule`.
1376
+ The only difference is, that the dimension is not the dimension of
1377
+ ``self`` but the dimension of the sub-module generated by the dynamically
1378
+ growing basis given by the :meth:`get_order`. In particular there is
1379
+ no difference if the number of strands is less than 5.
1380
+
1381
+ EXAMPLES::
1382
+
1383
+ sage: CHA2 = algebras.CubicHecke(2)
1384
+ sage: CHA2._dense_free_module()
1385
+ Ambient free module of rank 3
1386
+ over the integral domain Multivariate Polynomial Ring in u, v, w
1387
+ over Integer Ring localized at (w,)
1388
+ """
1389
+ if base_ring is None:
1390
+ base_ring = self.base_ring()
1391
+ from sage.modules.free_module import FreeModule
1392
+ return FreeModule(base_ring, len(self.get_order()))
1393
+
1394
+ def ngens(self):
1395
+ r"""
1396
+ The number of generators of the algebra.
1397
+
1398
+ EXAMPLES::
1399
+
1400
+ sage: CHA2 = algebras.CubicHecke(2)
1401
+ sage: CHA2.ngens()
1402
+ 1
1403
+ """
1404
+ return self._nstrands - 1
1405
+
1406
+ def algebra_generators(self):
1407
+ r"""
1408
+ Return the algebra generators of ``self``.
1409
+
1410
+ EXAMPLES::
1411
+
1412
+ sage: CHA2 = algebras.CubicHecke(2)
1413
+ sage: CHA2.algebra_generators()
1414
+ Finite family {c: c}
1415
+ """
1416
+ from sage.sets.family import Family
1417
+ return Family(self._cubic_braid_group.gens(), self.monomial)
1418
+
1419
+ def gens(self) -> tuple:
1420
+ r"""
1421
+ Return the generators of ``self``.
1422
+
1423
+ EXAMPLES::
1424
+
1425
+ sage: CHA2 = algebras.CubicHecke(2)
1426
+ sage: CHA2.gens()
1427
+ (c,)
1428
+ """
1429
+ return tuple(self.algebra_generators())
1430
+
1431
+ def gen(self, i):
1432
+ r"""
1433
+ The ``i``-th generator of the algebra.
1434
+
1435
+ EXAMPLES::
1436
+
1437
+ sage: CHA2 = algebras.CubicHecke(2)
1438
+ sage: CHA2.gen(0)
1439
+ c
1440
+ """
1441
+ return self.gens()[i]
1442
+
1443
+ def one_basis(self):
1444
+ r"""
1445
+ Return the index of the basis element for the identity element
1446
+ in the cubic braid group.
1447
+
1448
+ EXAMPLES::
1449
+
1450
+ sage: CHA2 = algebras.CubicHecke(2)
1451
+ sage: CHA2.one_basis()
1452
+ 1
1453
+ """
1454
+ return self.cubic_braid_group().one()
1455
+
1456
+ def _an_element_(self):
1457
+ r"""
1458
+ Overwrite the original method from :mod:`~sage.combinat.free_module`
1459
+ to obtain a more interesting element for ``TestSuite``.
1460
+
1461
+ EXAMPLES::
1462
+
1463
+ sage: CHA2 = algebras.CubicHecke(2)
1464
+ sage: CHA2.an_element() # indirect doctest
1465
+ v*c - ((v*w-u)/w)
1466
+ """
1467
+ n = self.ngens() + 1
1468
+ base_ring = self.base_ring()
1469
+ u, v, w = (base_ring(para) for para in self._cubic_equation_parameters)
1470
+ const = (u*~w - v) * self.one()
1471
+
1472
+ gens = self.gens()
1473
+ first_gens = [gen for gen in gens if gens.index(gen) < 3]
1474
+ if n == 2:
1475
+ c1, = first_gens
1476
+ return const + v*c1
1477
+ elif n == 3:
1478
+ c1, c2 = first_gens
1479
+ return const + v*c1 - w*c1*~c2 + u*c2
1480
+ else:
1481
+ c1, c2, c3 = first_gens
1482
+ return const + v*c1*~c3 - w*c1*~c2 + u*c3*c2
1483
+
1484
+ @cached_method
1485
+ def chevie(self):
1486
+ r"""
1487
+ Return the ``GAP3``-``CHEVIE`` realization of the corresponding
1488
+ cyclotomic Hecke algebra in the finite-dimensional case.
1489
+
1490
+ EXAMPLES::
1491
+
1492
+ sage: CHA3 = algebras.CubicHecke(3) # optional gap3
1493
+ sage: CHA3.chevie() # optional gap3
1494
+ Hecke(G4,[[a,b,c]])
1495
+ """
1496
+ from sage.combinat.root_system.reflection_group_real import is_chevie_available
1497
+ if not is_chevie_available():
1498
+ raise NotImplementedError('this functionality needs GAP3 with package CHEVIE')
1499
+
1500
+ n = self._nstrands
1501
+ if n == 3:
1502
+ st_number = 4
1503
+ elif n == 4:
1504
+ st_number = 25
1505
+ elif n == 5:
1506
+ st_number = 32
1507
+ else:
1508
+ raise NotImplementedError('CHEVIE version doesn\'t exist for this cubic Hecke algebra')
1509
+
1510
+ gap3_function_str = """function(st_number, na, nb,nc)
1511
+ local a, b, c, # embedded Indeterminates
1512
+ ReflGroup, # Reflection group
1513
+ HeckeAlg; # Hecke algebra
1514
+
1515
+ a := Mvp(na); b := Mvp(nb); c := Mvp(nc);
1516
+ ReflGroup := ComplexReflectionGroup(st_number);
1517
+ HeckeAlg := Hecke(ReflGroup, [[a, b, c]] );
1518
+ return HeckeAlg;
1519
+ end;"""
1520
+
1521
+ from sage.interfaces.gap3 import gap3
1522
+ gap3_function = gap3(gap3_function_str)
1523
+ na, nb, nc = ('\"%s\"' % indet for indet in self.extension_ring(generic=True).variable_names())
1524
+ return gap3_function(st_number, na, nb, nc)
1525
+
1526
+ @cached_method
1527
+ def product_on_basis(self, g1, g2):
1528
+ r"""
1529
+ Return product on basis elements indexed by ``g1`` and ``g2``.
1530
+
1531
+ EXAMPLES::
1532
+
1533
+ sage: CHA3 = algebras.CubicHecke(3)
1534
+ sage: g = CHA3.basis().keys().an_element(); g
1535
+ c0*c1
1536
+ sage: CHA3.product_on_basis(g, ~g)
1537
+ 1
1538
+ sage: CHA3.product_on_basis(g, g)
1539
+ w*c0^-1*c1*c0 - v*c1*c0 + u*c0*c1*c0
1540
+ """
1541
+ # ----------------------------------------------------------------------
1542
+ # short way for multiplications with one
1543
+ # ----------------------------------------------------------------------
1544
+ if g1 == g1.parent().one():
1545
+ return self.monomial(g2)
1546
+
1547
+ if g2 == g2.parent().one():
1548
+ return self.monomial(g1)
1549
+
1550
+ # ----------------------------------------------------------------------
1551
+ # convert to monomials
1552
+ # ----------------------------------------------------------------------
1553
+ g1 = self.monomial(g1)
1554
+ g2 = self.monomial(g2)
1555
+
1556
+ result = None
1557
+
1558
+ g1_Tietze = g1.Tietze()
1559
+ g2_Tietze = g2.Tietze()
1560
+
1561
+ verbose('Tietze established (%s, %s)' % (g1_Tietze, g2_Tietze), level=2)
1562
+
1563
+ # ----------------------------------------------------------------------
1564
+ # The product is calculated from the corresponding product of the braids
1565
+ # ----------------------------------------------------------------------
1566
+ braid_group = self.braid_group()
1567
+ braid_product = braid_group(g1_Tietze+g2_Tietze)
1568
+ result = self._braid_image(braid_product)
1569
+ return result
1570
+
1571
+ ############################################################################
1572
+ # --------------------------------------------------------------------------
1573
+ # local methods
1574
+ # --------------------------------------------------------------------------
1575
+ ############################################################################
1576
+ def _basis_tietze(self):
1577
+ r"""
1578
+ Return the complete finite sub basis as list of Tietze tuples.
1579
+
1580
+ EXAMPLES::
1581
+
1582
+ sage: CHA2 = algebras.CubicHecke(2)
1583
+ sage: CHA2._basis_tietze()
1584
+ [[], [1], [-1]]
1585
+ """
1586
+ if self._nstrands > 4:
1587
+ self_sub = self.cubic_hecke_subalgebra()
1588
+ result_list = self_sub._basis_tietze() + self._basis_extension
1589
+ else:
1590
+ result_list = self._basis_static
1591
+ return result_list
1592
+
1593
+ def _tietze_to_finite_sub_basis_monomial(self, tietze_tup):
1594
+ r"""
1595
+ Return the monomial corresponding to a Tietze tuple
1596
+ if it is in the finite sub basis, otherwise return ``None``.
1597
+
1598
+ EXAMPLES::
1599
+
1600
+ sage: CHA2 = algebras.CubicHecke(2)
1601
+ sage: CHA2._tietze_to_finite_sub_basis_monomial([-1])
1602
+ c^-1
1603
+ sage: CHA2._tietze_to_finite_sub_basis_monomial([-2]) is None
1604
+ True
1605
+ """
1606
+ tietze_list = list(tietze_tup)
1607
+ in_basis = False
1608
+ if tietze_list in self._basis_tietze():
1609
+ in_basis = True
1610
+ elif self._nstrands > 4:
1611
+ fsb_dict = self._finite_sub_basis_tuples
1612
+ if tietze_list in list(fsb_dict.values()):
1613
+ in_basis = True
1614
+ elif self.cubic_hecke_subalgebra()._tietze_to_finite_sub_basis_monomial(tietze_tup) is not None:
1615
+ in_basis = True
1616
+
1617
+ if in_basis:
1618
+ # tietze_tup represents a monomial
1619
+ B = self.basis()
1620
+ cb = self.cubic_braid_group()(tietze_tup)
1621
+ return B[cb]
1622
+
1623
+ return None
1624
+
1625
+ @cached_method
1626
+ def _create_matrix_list_for_one(self, representation_type):
1627
+ r"""
1628
+ Return the matrix list for the given representation type
1629
+ for ``self.one()``.
1630
+
1631
+ EXAMPLES::
1632
+
1633
+ sage: CHA2 = algebras.CubicHecke(2)
1634
+ sage: CHA2._create_matrix_list_for_one(CHA2.repr_type.SplitIrredMarin)
1635
+ [[1], [1], [1]]
1636
+ sage: CHA2._create_matrix_list_for_one(CHA2.repr_type.RegularLeft)
1637
+ [
1638
+ [1 0 0]
1639
+ [0 1 0]
1640
+ [0 0 1]
1641
+ ]
1642
+ """
1643
+ n = self._nstrands
1644
+ if representation_type.is_split():
1645
+ gen_base_ring = self.extension_ring(generic=True)
1646
+ rep_ind = [rep.internal_index() for rep in AbsIrreducibeRep if rep.number_gens() == n - 1]
1647
+ rep_dim = [rep.dimension() for rep in AbsIrreducibeRep if rep.number_gens() == n - 1]
1648
+ dim_sort = [rep_dim[rep_ind.index(i)] for i in range(len(rep_ind))]
1649
+ matrix_list = [MatrixSpace(gen_base_ring, dim_sort[i]).one() for i in range(len(rep_ind))]
1650
+ else:
1651
+ gen_base_ring = self.base_ring(generic=True)
1652
+ matrix_list = [MatrixSpace(gen_base_ring, self.dimension()).one()]
1653
+ return matrix_list
1654
+
1655
+ @cached_method
1656
+ def _fetch_matrix_list_from_chevie(self, number):
1657
+ r"""
1658
+ This method reads irreducible representation of the cubic Hecke algebra
1659
+ via the *GAP3* interface from *CHEVIE*.
1660
+
1661
+ INPUT:
1662
+
1663
+ - ``number`` -- integer; number of the representation according to
1664
+ *CHEVIE*
1665
+
1666
+ OUTPUT:
1667
+
1668
+ A list of representing matrices over the generic extension ring, one
1669
+ matrix for each generators.
1670
+
1671
+ EXAMPLES::
1672
+
1673
+ sage: CHA3 = algebras.CubicHecke(3) # optional gap3
1674
+ sage: CHA3._fetch_matrix_list_from_chevie(5) # optional gap3
1675
+ [
1676
+ [ a 0] [c c]
1677
+ [-a c], [0 a]
1678
+ ]
1679
+ """
1680
+ GER = self.extension_ring(generic=True)
1681
+ gap3_result = self.chevie().Representations(number)
1682
+ from sage.matrix.constructor import matrix
1683
+ matrix_list_gens = [matrix(GER, mat_gap) for mat_gap in gap3_result]
1684
+ for m in matrix_list_gens:
1685
+ m.set_immutable()
1686
+ return matrix_list_gens
1687
+
1688
+ # --------------------------------------------------------------------------
1689
+ # Methods for test_suite
1690
+ # --------------------------------------------------------------------------
1691
+ # _test_ring_constructions
1692
+ # --------------------------------------------------------------------------
1693
+ def _test_ring_constructions(self, **options):
1694
+ r"""
1695
+ Method called by :class:`TestSuite`.
1696
+
1697
+ The following is checked:
1698
+
1699
+ - construction of base_ring and extension ring
1700
+ - construction of maps between generic base and extension ring and
1701
+ the user defined rings
1702
+ - application of the ring homomorphisms
1703
+
1704
+ EXAMPLES::
1705
+
1706
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3,7,11))
1707
+ sage: CHA2._test_ring_constructions()
1708
+ """
1709
+ # ------------------------------------------------------------------------
1710
+ # testing ring constructions
1711
+ # ------------------------------------------------------------------------
1712
+ br = self.base_ring()
1713
+ er = self.extension_ring()
1714
+ A, B, C = self.cubic_equation_roots()
1715
+ a, b, c = self.cubic_equation_roots(generic=True)
1716
+ U, V, W = self.cubic_equation_parameters()
1717
+ u, v, w = self.cubic_equation_parameters(generic=True)
1718
+ eleB = U*V - W**2
1719
+ eleBgen = u*v - w**2
1720
+ eleE = A*B - C**2
1721
+ eleEgen = a*b - c**2
1722
+
1723
+ mbr = self._ring_of_definition_map
1724
+ mer = self._generic_extension_ring_map
1725
+ bri = self._base_ring_embedding
1726
+
1727
+ eleBgenEmb = 0
1728
+ eleEgenEmb = 0
1729
+ eleBembE = 0
1730
+
1731
+ try:
1732
+ eleBgenEmb = br(eleBgen)
1733
+ except (TypeError, ValueError, NotImplementedError):
1734
+ verbose('generic base ring map not registered')
1735
+ try:
1736
+ eleBgenEmb = mbr(eleBgen)
1737
+ except (TypeError, ValueError, NotImplementedError):
1738
+ raise RuntimeError('fatal: generic base ring map %s does not work' % mbr)
1739
+ try:
1740
+ eleEgenEmb = er(eleEgen)
1741
+ except (TypeError, ValueError, NotImplementedError):
1742
+ verbose('generic extension ring map not registered')
1743
+ try:
1744
+ eleEgenEmb = mer(eleEgen)
1745
+ except (TypeError, ValueError, NotImplementedError):
1746
+ raise RuntimeError('fatal: generic extension ring map %s does not work' % mer)
1747
+
1748
+ try:
1749
+ eleBembE = er(eleB)
1750
+ except (TypeError, ValueError, NotImplementedError):
1751
+ verbose('base ring embedding map not registered')
1752
+ try:
1753
+ eleBembE = bri(eleB)
1754
+ except (TypeError, ValueError, NotImplementedError):
1755
+ raise RuntimeError('fatal: base ring embedding %s does not work' % bri)
1756
+
1757
+ test_eleBgenEmb = self._tester(**options)
1758
+ test_eleBgenEmb.assertEqual(eleBgenEmb, eleB)
1759
+ test_eleEgenEmb = self._tester(**options)
1760
+ test_eleEgenEmb.assertEqual(eleEgenEmb, eleE)
1761
+ test_eleBembE = self._tester(**options)
1762
+ test_eleBembE.assertEqual(eleBembE, eleB)
1763
+
1764
+ # --------------------------------------------------------------------------
1765
+ # _test_matrix_constructions
1766
+ # --------------------------------------------------------------------------
1767
+ def _test_matrix_constructions(self, **options):
1768
+ r"""
1769
+ Test that the matrix constructions are valid.
1770
+
1771
+ The following is checked:
1772
+
1773
+ - construction of matrices of the following types:
1774
+
1775
+ * ``RepresentationType.SplitIrredChevie``
1776
+ * ``RepresentationType.SplitIrredMarin``
1777
+ * ``RepresentationType.RegularLeft``
1778
+
1779
+ - multiplication of matrices and compare with the matrix of the
1780
+ corresponding product of elements
1781
+ - construction of maps between generic base and extension ring and
1782
+ the user defined rings
1783
+
1784
+ EXAMPLES::
1785
+
1786
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3,7,11))
1787
+ sage: CHA2._test_matrix_constructions()
1788
+ """
1789
+ # ----------------------------------------------------------------------
1790
+ # testing matrix constructions
1791
+ # ----------------------------------------------------------------------
1792
+ if self.ngens() > 4:
1793
+ return
1794
+
1795
+ gens = self.gens()
1796
+ b1 = gens[0]
1797
+ b2 = self.an_element()
1798
+ b12 = b1*b2
1799
+ verbose('b12 %s' % b12)
1800
+
1801
+ def check_matrix(representation_type):
1802
+ m1 = b1.matrix(representation_type=representation_type)
1803
+ m2 = b2.matrix(representation_type=representation_type)
1804
+ m12mult = m1*m2
1805
+ m12mat = b12.matrix(representation_type=representation_type)
1806
+ test_matrix = self._tester(**options)
1807
+ test_matrix.assertEqual(m12mult, m12mat)
1808
+
1809
+ from sage.combinat.root_system.reflection_group_real import is_chevie_available
1810
+
1811
+ if is_chevie_available():
1812
+ check_matrix(RepresentationType.SplitIrredChevie)
1813
+ if self.ngens() < 3:
1814
+ check_matrix(RepresentationType.SplitIrredMarin)
1815
+ elif self.ngens() < 4:
1816
+ check_matrix(RepresentationType.SplitIrredMarin)
1817
+
1818
+ if self.ngens() < 3:
1819
+ check_matrix(RepresentationType.RegularLeft)
1820
+ return
1821
+
1822
+ # --------------------------------------------------------------------------
1823
+ # _init_basis_extension
1824
+ # --------------------------------------------------------------------------
1825
+ def _init_basis_extension(self):
1826
+ r"""
1827
+ Return the extension of the basis for more than 4 strands hold
1828
+ in file cache.
1829
+
1830
+ The basis elements from the file are added to the elements of
1831
+ the Marin basis.
1832
+
1833
+ EXAMPLES::
1834
+
1835
+ sage: # optional - database_cubic_hecke
1836
+ sage: CHA5 = algebras.CubicHecke(5)
1837
+ sage: fc = CHA5._filecache
1838
+ sage: be = fc.section.basis_extensions
1839
+ sage: CHA5.reset_filecache(be)
1840
+ sage: fc.read(be)
1841
+ [[4], [-4]]
1842
+ sage: ele = CHA5.an_element()
1843
+ sage: CHA5.inject_variables()
1844
+ Defining c0, c1, c2, c3
1845
+ sage: ele2 = ele * c3
1846
+ sage: bex = fc.read(be)
1847
+ sage: bex.sort(); bex
1848
+ [[-4], [1, -3, 4], [1, -2, 4], [3, 2, 4], [4]]
1849
+ """
1850
+ self._basis_extension = []
1851
+ tietze_list = self._basis_tietze()
1852
+ cbg = self._cubic_braid_group
1853
+ self._finite_sub_basis_tuples = {}
1854
+
1855
+ order_list = [cbg(tup) for tup in tietze_list]
1856
+ # We avoid the call to set_order for speed.
1857
+ # This avoids hashing the keys, which can become expensive.
1858
+ self._order = order_list
1859
+ verbose('finite sub basis length: %s' % (len(order_list)), level=2)
1860
+
1861
+ if self._nstrands < 5:
1862
+ return
1863
+
1864
+ # ----------------------------------------------------------------------
1865
+ # loading the extension of the basis from data file
1866
+ # ----------------------------------------------------------------------
1867
+ fc = self._filecache
1868
+ former_bas_ext = fc.read(fc.section.basis_extensions)
1869
+
1870
+ # ----------------------------------------------------------------------
1871
+ # pre definition of additional basis elements
1872
+ # ----------------------------------------------------------------------
1873
+ cub_braid_group = self.cubic_braid_group()
1874
+ if not former_bas_ext:
1875
+ gens = cub_braid_group.gens()
1876
+ last_gen = gens[len(gens)-1]
1877
+ self._cubic_braid_image(last_gen, check=False)
1878
+ self._cubic_braid_image(~last_gen, check=False)
1879
+ self._filecache.update_basis_extensions(self._basis_extension)
1880
+ return
1881
+
1882
+ # ----------------------------------------------------------------------
1883
+ # Installing the additional basis elements from filecache via the
1884
+ # embedding of the corresponding cubic braid
1885
+ # ----------------------------------------------------------------------
1886
+ for bas_Tietze in former_bas_ext:
1887
+ cub_braid = cub_braid_group(bas_Tietze)
1888
+ self._cubic_braid_image(cub_braid, check=False)
1889
+
1890
+ verbose('finite sub basis (extended) length: %s' % (len(self.get_order())), level=2)
1891
+ self._filecache.update_basis_extensions(self._basis_extension)
1892
+ return
1893
+
1894
+ # --------------------------------------------------------------------------
1895
+ # _braid_image_from_filecache
1896
+ # --------------------------------------------------------------------------
1897
+ def _braid_image_from_filecache(self, braid):
1898
+ r"""
1899
+ Return the image of the given braid in ``self`` from file cache (if
1900
+ contained).
1901
+
1902
+ INPUT:
1903
+
1904
+ - ``braid`` -- braid as instance of the braid group of ``self``
1905
+
1906
+ OUTPUT:
1907
+
1908
+ Image of braid as element of ``self``. ``None`` if the product has
1909
+ not been stored.
1910
+
1911
+ EXAMPLES::
1912
+
1913
+ sage: CHA3 = algebras.CubicHecke(3)
1914
+ sage: b1, b2 = CHA3.braid_group().gens(); br = ~b2*b1*~b2
1915
+ sage: CHA3._braid_image_from_filecache(br)
1916
+ 1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 - u/w*c0*c1*c0^-1
1917
+ sage: F = CHA3.base_ring().fraction_field()
1918
+ sage: par = tuple([F(p) for p in CHA3.cubic_equation_parameters()])
1919
+ sage: CHA3F = algebras.CubicHecke(3, cubic_equation_parameters=par)
1920
+ sage: CHA3F._braid_image_from_filecache(br)
1921
+ 1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 - u/w*c0*c1*c0^-1
1922
+ sage: section = CHA3.filecache_section().braid_images
1923
+ sage: CHA3.reset_filecache(section)
1924
+ sage: CHA3._braid_image_from_filecache(br)
1925
+ """
1926
+ base_ring = self.base_ring()
1927
+ gen_base_ring = self.base_ring(generic=True)
1928
+ result_vect = self._filecache.read_braid_image(braid.Tietze(), gen_base_ring)
1929
+ if result_vect is not None:
1930
+ if gen_base_ring != base_ring:
1931
+ base_map = self._ring_of_definition_map
1932
+ result_vect = vector(base_ring, [base_map(cf) for cf in result_vect])
1933
+ return self.from_vector(result_vect)
1934
+ return None
1935
+
1936
+ # --------------------------------------------------------------------------
1937
+ # _braid_image_to_filecache
1938
+ # --------------------------------------------------------------------------
1939
+ def _braid_image_to_filecache(self, braid_tietze, braid_image_vect):
1940
+ r"""
1941
+ Write the given braid image of to file cache.
1942
+
1943
+ INPUT:
1944
+
1945
+ - ``braid_tietze`` -- braid in Tietze form
1946
+ - ``braid_image_vect`` -- image of the given braid in ``self`` in vector
1947
+ representation
1948
+
1949
+ EXAMPLES::
1950
+
1951
+ sage: CHA2 = algebras.CubicHecke(2)
1952
+ sage: br, = CHA2.braid_group().gens(); br2 = br**2
1953
+ sage: section = CHA2.filecache_section().braid_images
1954
+ sage: CHA2.is_filecache_empty(section) # note: 2-strand images are not automatically cached in file system
1955
+ True
1956
+ sage: CHA2._braid_image_to_filecache(br2.Tietze(), CHA2(br2).to_vector())
1957
+ sage: CHA2._braid_image_from_filecache(br2)
1958
+ w*c^-1 + u*c - v
1959
+ sage: CHA2.reset_filecache(CHA2.filecache_section().braid_images)
1960
+ sage: CHA2._braid_image_from_filecache(br2) == None
1961
+ True
1962
+ """
1963
+ if self.base_ring() != self.base_ring(generic=True):
1964
+ # this should not be done for specialized base rings
1965
+ return
1966
+
1967
+ self._filecache.write_braid_image(braid_tietze, braid_image_vect)
1968
+ return
1969
+
1970
+ # --------------------------------------------------------------------------
1971
+ # _braid_image
1972
+ # --------------------------------------------------------------------------
1973
+ @cached_method
1974
+ def _braid_image(self, braid):
1975
+ r"""
1976
+ Return the image of the given braid in ``self``.
1977
+
1978
+ INPUT:
1979
+
1980
+ - ``braid`` -- :class:`~sage.groups.braid.Braid` whose image
1981
+ in ``self`` should be calculated
1982
+
1983
+ OUTPUT: an instance of the element class of ``self``
1984
+
1985
+ EXAMPLES::
1986
+
1987
+ sage: CHA2 = algebras.CubicHecke(2)
1988
+ sage: br, = CHA2.braid_group().gens(); br2 = br**2
1989
+ sage: CHA2._braid_image(br2)
1990
+ w*c^-1 + u*c - v
1991
+ """
1992
+ # ----------------------------------------------------------------------
1993
+ # first use the cubic equation to express the braid as a linear
1994
+ # combination of braids having no other exponent as 1 and -1 in their
1995
+ # defining word in the braid generators
1996
+ # ----------------------------------------------------------------------
1997
+ coeffs, braids = self._reduce_all_gen_powers(braid.Tietze())
1998
+
1999
+ # ----------------------------------------------------------------------
2000
+ # in the second step the images of these "reduced" braids is calculated
2001
+ # ----------------------------------------------------------------------
2002
+ result = self.zero()
2003
+ for i in range(len(coeffs)):
2004
+ braid_image = self._braid_image_from_reduced_powers(braids[i])
2005
+ result += coeffs[i]*braid_image
2006
+
2007
+ return result
2008
+
2009
+ # --------------------------------------------------------------------------
2010
+ # _braid_image_from_reduced_powers
2011
+ # --------------------------------------------------------------------------
2012
+ @cached_method
2013
+ def _braid_image_from_reduced_powers(self, braid_tietze):
2014
+ r"""
2015
+ Return the image of a braid in ``self`` assuming that no successive
2016
+ repetitions occur in the Tietze form of the braid.
2017
+
2018
+ INPUT:
2019
+
2020
+ - ``braid_tietze`` -- tuple representing the Braid whose image in
2021
+ ``self`` should be computed; it is assumed that no successive
2022
+ repetitions occur among the entries (i.e. ``(1, 1)`` is not allowed
2023
+ but ``(1, -2, 1)`` is)
2024
+
2025
+ OUTPUT: the image of the braid as an element of ``self``
2026
+
2027
+ EXAMPLES::
2028
+
2029
+ sage: CHA3 = algebras.CubicHecke(3)
2030
+ sage: CHA3._braid_image_from_reduced_powers((1, -2, 1))
2031
+ c0*c1^-1*c0
2032
+ sage: CHA3._braid_image_from_reduced_powers((1, -2, 1, 2))
2033
+ w*c0^-1*c1*c0^-1 - v*c1*c0^-1 + u*c0*c1*c0^-1
2034
+ """
2035
+ n = self.ngens()
2036
+ braid_list = list(braid_tietze)
2037
+ len_braid = len(braid_list)
2038
+
2039
+ # ----------------------------------------------------------------------
2040
+ # in the case of two strands we calculate the power of the generator
2041
+ # ----------------------------------------------------------------------
2042
+ if n == 1:
2043
+ if len_braid == 0:
2044
+ return self.one()
2045
+ k = braid_tietze[0]*len_braid
2046
+ result_vect = self._reduce_gen_power(k)
2047
+ result = self.from_vector(result_vect)
2048
+ return result
2049
+
2050
+ # ----------------------------------------------------------------------
2051
+ # Try to use former calculations (from dynamic library) to obtain the
2052
+ # braid image
2053
+ # ----------------------------------------------------------------------
2054
+ result, word_decomposition = self._braid_image_from_former_calculations(braid_tietze)
2055
+
2056
+ if word_decomposition is None:
2057
+ return result
2058
+
2059
+ # ----------------------------------------------------------------------
2060
+ # proceed the calculation by use of the regular representation matrices
2061
+ # (given by Ivan Marin) or in case of more than 4 strands by extension
2062
+ # of the finite sub basis
2063
+ # ----------------------------------------------------------------------
2064
+
2065
+ if n > 3 and (n in braid_tietze or -n in braid_tietze):
2066
+ # ------------------------------------------------------------------
2067
+ # matrices for the regular representation are at the moment just
2068
+ # available in the case of less than five strands. In the higher
2069
+ # cases the basis is realized to grow up from the basis on 4 strands
2070
+ # to use the recursion, only those cubic braids are stored as new
2071
+ # basis elements if they involve the generator with largest index
2072
+ # ------------------------------------------------------------------
2073
+ return self._braid_image_by_basis_extension(braid_tietze)
2074
+
2075
+ word_left, word_result, word_right = word_decomposition
2076
+ result_vect = None
2077
+
2078
+ if word_left is not None:
2079
+ # ------------------------------------------------------------------
2080
+ # Operating from the left on the pre-calculated result
2081
+ # ------------------------------------------------------------------
2082
+ vect = result.to_vector()
2083
+ braid_preimage = tuple(word_result)
2084
+ result_vect = self._mult_by_regular_rep(vect, tuple(word_left), RepresentationType.RegularLeft, braid_preimage)
2085
+
2086
+ if word_right is not None:
2087
+ # ------------------------------------------------------------------
2088
+ # Operating from the right on the pre-calculated result
2089
+ # ------------------------------------------------------------------
2090
+ if result_vect is not None:
2091
+ vect = result_vect
2092
+ braid_preimage = tuple(word_left + word_result)
2093
+ else:
2094
+ vect = result.to_vector()
2095
+ braid_preimage = tuple(word_result)
2096
+ result_vect = self._mult_by_regular_rep(vect, tuple(word_right), RepresentationType.RegularRight, braid_preimage)
2097
+
2098
+ result = self.from_vector(result_vect)
2099
+ return result
2100
+
2101
+ # --------------------------------------------------------------------------
2102
+ # _braid_image_from_former_calculations
2103
+ # --------------------------------------------------------------------------
2104
+ def _braid_image_from_former_calculations(self, braid_tietze):
2105
+ r"""
2106
+ Return the image of a braid in ``self`` as far as this can be done by
2107
+ use of former calculations and is sure not to go into an endless
2108
+ recursion, that is
2109
+
2110
+ - using the cubic Hecke sub-algebra on one strand less
2111
+ - using the file cache.
2112
+
2113
+ If the image can not be calculated from former registered results this
2114
+ method returns None. Therefore, it is just intended to be used as as
2115
+ step in the complete calculation.
2116
+
2117
+ INPUT:
2118
+
2119
+ - ``braid_tietze`` -- tuple representing the braid whose image in
2120
+ ``self`` should be computed; he generator exponents in the braid
2121
+ word are assumed to be ``1`` or ``-1``
2122
+
2123
+ OUTPUT:
2124
+
2125
+ A pair (image, basis_factors) where result is an element of ``self``
2126
+ representing the image of the input if calculation was possible and
2127
+ ``None`` else-wise. If ``image == None`` the output basis_factors is
2128
+ given as a list of basis element whose product equals the input.
2129
+
2130
+ EXAMPLES::
2131
+
2132
+ sage: CHA3 = algebras.CubicHecke(3)
2133
+ sage: CHA3._braid_image_from_former_calculations((1, -2, 1))
2134
+ (c0*c1^-1*c0, None)
2135
+ sage: CHA3._braid_image_from_former_calculations((1, -2, 1, 2))
2136
+ (c0*c1^-1*c0, ([], [1, -2, 1], [2]))
2137
+ """
2138
+ braid_list = list(braid_tietze)
2139
+ len_braid = len(braid_list)
2140
+ result = None
2141
+ n = self.ngens()
2142
+
2143
+ # ----------------------------------------------------------------------
2144
+ # if the braid is in the basis take its image to be the corresponding
2145
+ # monomial
2146
+ # ----------------------------------------------------------------------
2147
+ result = self._tietze_to_finite_sub_basis_monomial(braid_tietze)
2148
+ if result is not None:
2149
+ return result, None
2150
+
2151
+ # ----------------------------------------------------------------------
2152
+ # if the braid lies in a sub-algebra take its image from there.
2153
+ # ----------------------------------------------------------------------
2154
+ sub_alg = self.cubic_hecke_subalgebra()
2155
+ if n not in braid_list and -n not in braid_list:
2156
+ result = self(sub_alg(braid_tietze))
2157
+ verbose('end (%s): %s in smaller algebra' % (braid_list, result), level=2)
2158
+ return result, None
2159
+
2160
+ # ----------------------------------------------------------------------
2161
+ # proceed the calculation by splitting self into a product of basis
2162
+ # elements and try to simplify.
2163
+ # ----------------------------------------------------------------------
2164
+ braid_group = self.braid_group()
2165
+ braid = braid_group(braid_tietze)
2166
+ result = self._braid_image_from_filecache(braid)
2167
+ if result is not None:
2168
+ verbose('end from file cache (%s)' % (list(braid_tietze)), level=2)
2169
+ return result, None
2170
+
2171
+ # ----------------------------------------------------------------------
2172
+ # If we come here len_braid must be larger than 1 (otherwise we already
2173
+ # have found in in the basis). By recursion we check if the subwords
2174
+ # with one generator removed on the left (respectively on the right)
2175
+ # side contain a subword whose image has already been calculated. We
2176
+ # choose the longest such subword as our result.
2177
+ # ----------------------------------------------------------------------
2178
+ braid_list_red_left = [braid_tietze[j] for j in range(1, len_braid)]
2179
+ braid_list_red_right = [braid_tietze[j] for j in range(len_braid - 1)]
2180
+
2181
+ result_left, word_decomp_left = self._braid_image_from_former_calculations(tuple(braid_list_red_left))
2182
+ result_right, word_decomp_right = self._braid_image_from_former_calculations(tuple(braid_list_red_right))
2183
+ if word_decomp_left is None:
2184
+ return result_left, ([braid_tietze[0]], braid_list_red_left, [])
2185
+
2186
+ if word_decomp_right is None:
2187
+ return result_right, ([], braid_list_red_right, [braid_tietze[len_braid - 1]])
2188
+
2189
+ word_decomp_left_left, word_decomp_left_result, word_decomp_left_right = word_decomp_left
2190
+ word_decomp_right_left, word_decomp_right_result, word_decomp_right_right = word_decomp_right
2191
+
2192
+ if len(word_decomp_left_result) >= len(word_decomp_right_result):
2193
+ return result_left, ([braid_tietze[0]] + word_decomp_left_left, word_decomp_left_result, word_decomp_left_right)
2194
+
2195
+ return result_right, (word_decomp_right_left, word_decomp_right_result, word_decomp_right_right + [braid_tietze[len_braid - 1]])
2196
+
2197
+ # --------------------------------------------------------------------------
2198
+ # _braid_image_by_basis_expansion_
2199
+ # --------------------------------------------------------------------------
2200
+ @cached_method
2201
+ def _braid_image_by_basis_extension(self, braid_tietze):
2202
+ r"""
2203
+ Return the given braid as a new basis element of ``self`` expanding the
2204
+ incomplete order (which is just a part of the whole basis) in the case
2205
+ of more than 4 strands.
2206
+
2207
+ INPUT:
2208
+
2209
+ - ``braid_tietze`` -- tuple representing the braid whose image in
2210
+ ``self`` should be computed; he generator exponents in the braid
2211
+ word are assumed to be ``1`` or ``-1``
2212
+
2213
+ OUTPUT: an instance of the element class of ``self``
2214
+
2215
+ EXAMPLES::
2216
+
2217
+ sage: # optional - database_cubic_hecke
2218
+ sage: CHA5 = algebras.CubicHecke(5)
2219
+ sage: be = CHA5.filecache_section().basis_extensions
2220
+ sage: CHA5.reset_filecache(be)
2221
+ sage: CHA5._basis_extension
2222
+ [[4], [-4]]
2223
+ sage: CHA5._braid_image_by_basis_extension((4,1))
2224
+ c3*c0
2225
+ sage: CHA5._basis_extension
2226
+ [[4], [-4], [4, 1]]
2227
+
2228
+ case where the braid already has a corresponding basis element::
2229
+
2230
+ sage: CHA5._braid_image_by_basis_extension((1,)) # optional - database_cubic_hecke
2231
+ c0
2232
+ sage: CHA5._basis_extension # optional - database_cubic_hecke
2233
+ [[4], [-4], [4, 1]]
2234
+
2235
+ case where the braid doesn't have corresponding basis element but depends
2236
+ on them::
2237
+
2238
+ sage: CHA5._braid_image_by_basis_extension((1,1)) # optional - database_cubic_hecke
2239
+ Traceback (most recent call last):
2240
+ ...
2241
+ NotImplementedError: no algorithm available to calculate braid image of (1, 1)
2242
+ """
2243
+ cubic_braid = self._cubic_braid_group(braid_tietze)
2244
+ tup = self._cubic_braid_basis_tuple(cubic_braid)
2245
+ if tup is not None:
2246
+ bgrp = self.braid_group()
2247
+ if bgrp(braid_tietze) != bgrp(tup):
2248
+ raise NotImplementedError('no algorithm available to calculate braid image of %s' % str(braid_tietze))
2249
+ B = self.basis()
2250
+ verbose('braid-image %s in Basis' % str(braid_tietze), level=2)
2251
+ return self.monomial(B[cubic_braid])
2252
+
2253
+ return self._cubic_braid_append_to_basis(cubic_braid)
2254
+
2255
+ # --------------------------------------------------------------------------
2256
+ # _reduce_all_gen_powers
2257
+ # --------------------------------------------------------------------------
2258
+ @cached_method
2259
+ def _reduce_all_gen_powers(self, braid_tietze):
2260
+ r"""
2261
+ Return a linear combination of braids that have no higher powers in the
2262
+ braid generators having the same image in ``self`` than the given braid.
2263
+
2264
+ This linear combination is returned as a pair of lists of braids and
2265
+ corresponding coefficients.
2266
+
2267
+ INPUT:
2268
+
2269
+ - ``braid_tietze`` -- tuple representing the braid whose powers should
2270
+ be reduced given in Tietze form
2271
+
2272
+ OUTPUT:
2273
+
2274
+ A pair of two lists: ``coeffs``, ``braids``. The fist one contains the
2275
+ coefficients corresponding to the braids in Tietze form from the second
2276
+ list of braids.
2277
+
2278
+ EXAMPLES::
2279
+
2280
+ sage: CHA3 = algebras.CubicHecke(3)
2281
+ sage: CHA3._reduce_all_gen_powers((1, 1, -2, -2))
2282
+ ([u*v/w, (-v)/w, (-v^2)/w, (-u^2)/w, u/w, u*v/w, -u, 1, v],
2283
+ [(), (2,), (-2,), (1,), (1, 2), (1, -2), (-1,), (-1, 2), (-1, -2)])
2284
+ """
2285
+ braid_list = list(braid_tietze)
2286
+ len_braid = len(braid_list)
2287
+
2288
+ # ----------------------------------------------------------------------
2289
+ # find a higher power position in braid_list
2290
+ # ----------------------------------------------------------------------
2291
+ power = 0
2292
+ pos = 0
2293
+ for i in range(len_braid - 1):
2294
+ if braid_list[i] != braid_list[i + 1]:
2295
+ continue
2296
+ pos = i
2297
+ for power in range(1, len_braid - pos + 1):
2298
+ if pos+power == len_braid:
2299
+ break
2300
+ if braid_list[pos] != braid_list[pos+power]:
2301
+ break
2302
+ break
2303
+
2304
+ if power == 0:
2305
+ verbose('end (%s) no powers' % braid_list, level=2)
2306
+ return [self.base_ring().one()], [braid_tietze]
2307
+
2308
+ # ----------------------------------------------------------------------
2309
+ # eliminate this power from braid_tietze.
2310
+ # ----------------------------------------------------------------------
2311
+ val = braid_list[pos]
2312
+ if val > 0:
2313
+ gen_ind = val
2314
+ exp = power
2315
+ else:
2316
+ gen_ind = -val
2317
+ exp = -power
2318
+
2319
+ braid_list_start = [braid_list[i] for i in range(pos)]
2320
+ braid_list_end = [braid_list[i] for i in range(pos+power, len_braid)]
2321
+
2322
+ # ----------------------------------------------------------------------
2323
+ # merging the new reduced tuple. Note that all the new tuples are
2324
+ # smaller than the given one, which will make the recursion terminate.
2325
+ # ----------------------------------------------------------------------
2326
+ tuple_one = tuple(braid_list_start + braid_list_end)
2327
+ tuple_gen = tuple(braid_list_start + [gen_ind] + braid_list_end)
2328
+ tuple_gen_inv = tuple(braid_list_start + [-gen_ind] + braid_list_end)
2329
+
2330
+ # ----------------------------------------------------------------------
2331
+ # convert them to braids (to reduce cancellation of inverses and obvious
2332
+ # braid relations) Note that this will not increase the length of the
2333
+ # word. Thus the recursion still must terminate.
2334
+ # ----------------------------------------------------------------------
2335
+ braid_group = self.braid_group()
2336
+ braid_one = braid_group(tuple_one)
2337
+ braid_gen = braid_group(tuple_gen)
2338
+ braid_gen_inv = braid_group(tuple_gen_inv)
2339
+
2340
+ # ----------------------------------------------------------------------
2341
+ # eliminate all powers from braid_tietze by recursion. The recursion
2342
+ # will terminate by the length reduction of the Tietze tuple (but not
2343
+ # necessarily by the number of generators whose exponent must be reduced).
2344
+ # ----------------------------------------------------------------------
2345
+ one_coeffs, one_braids = self._reduce_all_gen_powers(braid_one.Tietze())
2346
+ gen_coeffs, gen_braids = self._reduce_all_gen_powers(braid_gen.Tietze())
2347
+ gen_inv_coeffs, gen_inv_braids = self._reduce_all_gen_powers(braid_gen_inv.Tietze())
2348
+
2349
+ cf_one, cf_gen, cf_gen_inv = self._reduce_gen_power(exp)
2350
+
2351
+ one_coeffs = [cf*cf_one for cf in one_coeffs]
2352
+ gen_coeffs = [cf*cf_gen for cf in gen_coeffs]
2353
+ gen_inv_coeffs = [cf*cf_gen_inv for cf in gen_inv_coeffs]
2354
+
2355
+ return one_coeffs + gen_coeffs + gen_inv_coeffs, one_braids + gen_braids + gen_inv_braids
2356
+
2357
+ # --------------------------------------------------------------------------
2358
+ # _reduce_gen_power
2359
+ # --------------------------------------------------------------------------
2360
+ @cached_method
2361
+ def _reduce_gen_power(self, k):
2362
+ r"""
2363
+ Return the `k`-th power on an arbitrary generator,
2364
+ for example `c_0^k`.
2365
+
2366
+ INPUT:
2367
+
2368
+ - ``k`` -- integer giving the power
2369
+
2370
+ OUTPUT:
2371
+
2372
+ A list ``[coeff_one, coeff_gen, coeff_gen_inverse]`` of the three
2373
+ coefficients of the generators power in the span of the generator.
2374
+
2375
+ EXAMPLES::
2376
+
2377
+ sage: CHA2 = algebras.CubicHecke(2)
2378
+ sage: CHA2._reduce_gen_power(5)
2379
+ (-u^3*v + 2*u*v^2 + u^2*w - 2*v*w, u^4 - 3*u^2*v
2380
+ + v^2 + 2*u*w, u^3*w - 2*u*v*w + w^2)
2381
+ """
2382
+ n = self.ngens()
2383
+
2384
+ # ----------------------------------------------------------------------
2385
+ # take it from smaller sub-algebras if possible
2386
+ # ----------------------------------------------------------------------
2387
+ if n > 1:
2388
+ sub_alg = self.cubic_hecke_subalgebra()
2389
+ return sub_alg._reduce_gen_power(k)
2390
+
2391
+ # ----------------------------------------------------------------------
2392
+ # calculate it in the sub-algebra on 2 strands
2393
+ # ----------------------------------------------------------------------
2394
+
2395
+ if k == 0:
2396
+ result_ele = self.one()
2397
+ result = result_ele.to_vector()
2398
+
2399
+ elif abs(k) == 1:
2400
+ result_ele = self._tietze_to_finite_sub_basis_monomial((k,))
2401
+ result = result_ele.to_vector()
2402
+
2403
+ else:
2404
+ if k < 0:
2405
+ right_vect = self._reduce_gen_power(k + 1)
2406
+ genTietze = (-1,)
2407
+ else:
2408
+ right_vect = self._reduce_gen_power(k - 1)
2409
+ genTietze = (1,)
2410
+ result = self._mult_by_regular_rep(right_vect, genTietze, RepresentationType.RegularLeft)
2411
+ return result
2412
+
2413
+ # --------------------------------------------------------------------------
2414
+ # _mult_by_regular_rep
2415
+ # --------------------------------------------------------------------------
2416
+ @cached_method
2417
+ def _mult_by_regular_rep(self, vect, gen_tuple, representation_type, braid_preimage=None):
2418
+ r"""
2419
+ Return the product of an`element of ``self`` given as a coefficient
2420
+ vector with a sequence (tuple) of generators (that is a braid word)
2421
+ using regular representation matrices.
2422
+
2423
+ The multiplication will be performed form left or right according
2424
+ to the given ``representation_type``.
2425
+
2426
+ INPUT:
2427
+
2428
+ - ``vect`` -- element of ``self`` in vector form (obtained by
2429
+ :meth:`to_vector`)
2430
+ - ``gen_tuple`` -- list of generators (that is a braid in Tietze form)
2431
+ which operates on ``vect``
2432
+ - ``representation_type`` -- instance of :class:`RepresentationType`
2433
+ (one of `RegularLeft` or `RegularRight`)
2434
+ - ``braid_preimage`` -- (optional) a word representing a braid whose
2435
+ image is vect (if it exist). This is used to record intermediate
2436
+ results to the dynamic library
2437
+
2438
+ OUTPUT:
2439
+
2440
+ The coefficient vector resulting after applying the multiplication of all
2441
+ matrices corresponding to the generators from gen_tuple.
2442
+
2443
+ EXAMPLES::
2444
+
2445
+ sage: CHA3 = algebras.CubicHecke(3)
2446
+ sage: CHA3.inject_variables()
2447
+ Defining c0, c1
2448
+ sage: repr_type = CHA3.repr_type.RegularRight
2449
+ sage: CHA3._mult_by_regular_rep(c0.to_vector(), (1, -2, -2), repr_type)
2450
+ (u*v/w, (-u^2)/w, -u, (-v)/w, (-v^2)/w, u/w, u*v/w, 1, v,
2451
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2452
+ """
2453
+ verbose('multiply %s (pre-image %s) by %s using %s'
2454
+ % (vect, braid_preimage, gen_tuple, representation_type), level=2)
2455
+ m = len(gen_tuple)
2456
+ braid_list = None
2457
+ if braid_preimage:
2458
+ braid_list = list(braid_preimage)
2459
+
2460
+ result = vect
2461
+ for i in range(m):
2462
+ verbose('multiply image of %s with position %s' % (braid_list, i), level=2)
2463
+
2464
+ if representation_type == RepresentationType.RegularLeft:
2465
+ gen_ind = gen_tuple[m - i - 1]
2466
+ if braid_list:
2467
+ braid_list = [gen_ind] + braid_list
2468
+ else:
2469
+ gen_ind = gen_tuple[i]
2470
+ if braid_list:
2471
+ braid_list = braid_list + [gen_ind]
2472
+
2473
+ if (gen_ind, representation_type) in list(self._gens_reg_repres_matrix.keys()):
2474
+ mat = self._gens_reg_repres_matrix[(gen_ind, representation_type)]
2475
+ else:
2476
+ if gen_ind > 0:
2477
+ gen = self.gen(gen_ind - 1)
2478
+ mat = gen.matrix(representation_type=representation_type)
2479
+ else:
2480
+ # data of inverse of generators is stored under negative strand-index
2481
+ gen = self.gen(-gen_ind - 1)**(-1)
2482
+ mat = gen.matrix(representation_type=representation_type)
2483
+
2484
+ self._gens_reg_repres_matrix[(gen_ind, representation_type)] = mat
2485
+
2486
+ result = mat * result
2487
+
2488
+ # ------------------------------------------------------------------
2489
+ # save this intermediate result to the dynamic library
2490
+ # ------------------------------------------------------------------
2491
+ if braid_list:
2492
+ verbose('save image of %s to file cache' % braid_list, level=2)
2493
+ self._braid_image_to_filecache(tuple(braid_list), result)
2494
+
2495
+ verbose('multiply %s by %s using %s result %s' % (vect, gen_tuple, representation_type, result), level=2)
2496
+ return result
2497
+
2498
+ # --------------------------------------------------------------------------
2499
+ # _cubic_braid_append_to_basis
2500
+ # --------------------------------------------------------------------------
2501
+
2502
+ def _cubic_braid_append_to_basis(self, cubic_braid):
2503
+ r"""
2504
+ Append the given cubic braid to the finite sub basis which is used for
2505
+ calculation of products and representation matrices.
2506
+
2507
+ This only makes sense if the ``cubic_braid`` is not in this finite
2508
+ sub-basis, before. This can happen if the number of strands is more
2509
+ than 4.
2510
+
2511
+ INPUT:
2512
+
2513
+ - ``cubic_braid`` -- :class:`~sage.groups.cubic_braid.CubicBraid`
2514
+ whose image in ``self`` should be appended
2515
+
2516
+ OUTPUT: the new monomial of ``self``
2517
+
2518
+ EXAMPLES::
2519
+
2520
+ sage: # optional - database_cubic_hecke
2521
+ sage: CHA5 = algebras.CubicHecke(5)
2522
+ sage: be = CHA5.filecache_section().basis_extensions
2523
+ sage: CHA5.reset_filecache(be)
2524
+ sage: CHA5._basis_extension
2525
+ [[4], [-4]]
2526
+ sage: CBG = CHA5.cubic_braid_group()
2527
+ sage: CHA5._cubic_braid_append_to_basis(CBG((4,1)))
2528
+ c3*c0
2529
+ sage: CHA5._basis_extension
2530
+ [[4], [-4], [4, 1]]
2531
+ """
2532
+ cbTietze = list(cubic_braid.Tietze())
2533
+ order = self.get_order()
2534
+ next_index = len(order)
2535
+ self._basis_extension.append(cbTietze)
2536
+ try:
2537
+ self._rank_basis.update({cubic_braid: next_index}) # supporting :meth:`get_order_key`
2538
+ except AttributeError:
2539
+ pass
2540
+ order.append(cubic_braid)
2541
+ monomial = self.monomial(cubic_braid)
2542
+ self._finite_sub_basis_tuples.update({cubic_braid: cbTietze})
2543
+
2544
+ verbose('registering new basis element: %s (par %s ind %s)'
2545
+ % (cubic_braid, cubic_braid.parent(), next_index), level=2)
2546
+ self._filecache.update_basis_extensions(self._basis_extension)
2547
+ return monomial
2548
+
2549
+ # --------------------------------------------------------------------------
2550
+ # _cubic_braid_basis_tuple
2551
+ # --------------------------------------------------------------------------
2552
+ def _cubic_braid_basis_tuple(self, cubic_braid):
2553
+ r"""
2554
+ Return the Tietze tuple that represents the given cubic_braid in the
2555
+ basis of ``self``.
2556
+
2557
+ In the case ``self`` has more than 4 strands it may happen that the
2558
+ given cubic braid is not contained in the finite subbasis, so far.
2559
+ In this case it is automatically added to it.
2560
+
2561
+ INPUT:
2562
+
2563
+ - ``cubic_braid`` -- :class:`~sage.groups.cubic_braid.CubicBraid`
2564
+
2565
+ OUTPUT: a tuple from the basis representing the cubic braid
2566
+
2567
+ EXAMPLES::
2568
+
2569
+ sage: CHA2 = algebras.CubicHecke(2)
2570
+ sage: CBG = CHA2.cubic_braid_group()
2571
+ sage: CHA2._cubic_braid_basis_tuple(CBG((1, 1)))
2572
+ (-1,)
2573
+ """
2574
+ tietze_list = self._basis_tietze()
2575
+ cubic_braid_tietze = cubic_braid.Tietze()
2576
+ if list(cubic_braid_tietze) in tietze_list:
2577
+ verbose('cubic_braid_tietze: %s in basis' % str(cubic_braid_tietze), level=2)
2578
+ return cubic_braid_tietze
2579
+ else:
2580
+ if cubic_braid in self._finite_sub_basis_tuples.keys():
2581
+ verbose('cubic_braid: %s in finite_sub_basis' % cubic_braid, level=2)
2582
+ return self._finite_sub_basis_tuples[cubic_braid]
2583
+
2584
+ for tup in tietze_list:
2585
+ cb_tup = self.cubic_braid_group()(tup)
2586
+ if cubic_braid == cb_tup:
2587
+ self._finite_sub_basis_tuples.update({cb_tup: tup})
2588
+ verbose('cubic_braid: %s added to finite_sub_basis with tuple %s'
2589
+ % (cubic_braid, tup), level=2)
2590
+ return tuple(tup)
2591
+ return None
2592
+
2593
+ # --------------------------------------------------------------------------
2594
+ # _cubic_braid_image
2595
+ # --------------------------------------------------------------------------
2596
+ def _cubic_braid_image(self, cubic_braid, check=True):
2597
+ r"""
2598
+ Return the given cubic braid as monomial of ``self``, that is the image
2599
+ under the map onto the basis.
2600
+
2601
+ If the number of strands is larger than 4, the corresponding basis
2602
+ element may not be contained in the order of ``self``. In this
2603
+ case it will be appended here.
2604
+
2605
+ INPUT:
2606
+
2607
+ - ``cubic_braid`` -- :class:`~sage.groups.cubic_braid.CubicBraid`
2608
+ whose image in ``self`` should be returned
2609
+ - ``check`` -- boolean (default: ``True``); check if the given cubic
2610
+ braid is already registered in the finite sub basis; if set to
2611
+ ``False`` duplicate entries can occur
2612
+
2613
+ EXAMPLES::
2614
+
2615
+ sage: CHA2 = algebras.CubicHecke(2)
2616
+ sage: CBG = CHA2.cubic_braid_group()
2617
+ sage: CHA2._cubic_braid_image(CBG((1,1)))
2618
+ c^-1
2619
+ """
2620
+ if check:
2621
+ tup = self._cubic_braid_basis_tuple(cubic_braid)
2622
+ if tup is not None:
2623
+ return self._tietze_to_finite_sub_basis_monomial(tup)
2624
+ return self._cubic_braid_append_to_basis(cubic_braid)
2625
+
2626
+ # --------------------------------------------------------------------------
2627
+ # _extend_braid_automorphism
2628
+ # --------------------------------------------------------------------------
2629
+ def _extend_braid_automorphism(self, element, braid_automorphism):
2630
+ r"""
2631
+ Return the image of element under the extension of the given braid group
2632
+ automorphism to ``self``. It is assumed that the given
2633
+ ``braid_automorphism`` factors through ``self``.
2634
+
2635
+ INPUT:
2636
+
2637
+ - ``element`` -- an element class of ``self``
2638
+ - ``braid_automorphism`` -- braid group automorphism factoring through
2639
+ ``self``
2640
+
2641
+ OUTPUT:
2642
+
2643
+ Element class of ``self`` representing the image of element
2644
+ under the extension of the given braid group automorphism.
2645
+
2646
+ EXAMPLES::
2647
+
2648
+ sage: CHA2 = algebras.CubicHecke(2)
2649
+ sage: br, = CHA2.gens()
2650
+ sage: CHA2.mirror_isomorphism(br) # indirect doctest
2651
+ c^-1
2652
+ """
2653
+
2654
+ result = self.zero()
2655
+ for braid in element.support():
2656
+ autom_braid = braid_automorphism(braid)
2657
+ img_braid = self._braid_image_from_reduced_powers(autom_braid.Tietze())
2658
+ result += element[braid] * img_braid
2659
+
2660
+ return result
2661
+
2662
+ # --------------------------------------------------------------------------
2663
+ # _markov_trace_module
2664
+ # --------------------------------------------------------------------------
2665
+ def _markov_trace_module(self, extended=False, field_embedding=False):
2666
+ r"""
2667
+ Return the module that contains the formal Markov trace as elements.
2668
+
2669
+ INPUT:
2670
+
2671
+ - ``extended`` -- boolean (default: ``False``); if set to ``True`` the
2672
+ base ring of the module is the Markov trace version of the generic
2673
+ extension ring of ``self``.
2674
+
2675
+ - ``field_embedding`` -- boolean (default: ``False``); if set to ``True`
2676
+ the base ring of the module is the smallest field containing the
2677
+ generic extension ring of ``self``. The keyword is meaningless if
2678
+ ``extended=False``.
2679
+
2680
+ OUTPUT: a :class:`~sage.combinat.free_module.CombinatorialFreeModule`
2681
+
2682
+ EXAMPLES::
2683
+
2684
+ sage: CHA2 = algebras.CubicHecke(2)
2685
+ sage: CHA2._markov_trace_module()
2686
+ Free module generated by {U1, U2}
2687
+ over Multivariate Polynomial Ring in u, v, w, s
2688
+ over Integer Ring localized at (s, w, v, u)
2689
+
2690
+ sage: CHA2._markov_trace_module(extended=True)
2691
+ Free module generated by {U1, U2}
2692
+ over Multivariate Laurent Polynomial Ring in a, b, c, s
2693
+ over Splitting Algebra of x^2 + x + 1 with roots [e3, -e3 - 1]
2694
+ over Integer Ring
2695
+
2696
+ sage: CHA2._markov_trace_module(extended=True, field_embedding=True)
2697
+ Free module generated by {U1, U2}
2698
+ over Fraction Field of Multivariate Polynomial Ring in a, b, c, s
2699
+ over Cyclotomic Field of order 3 and degree 2
2700
+ """
2701
+ from sage.modules.free_module import FreeModule
2702
+ from sage.databases.cubic_hecke_db import MarkovTraceModuleBasis
2703
+ basis = [b for b in MarkovTraceModuleBasis if b.strands() <= self._nstrands]
2704
+ BRM = self.base_ring(generic=True).markov_trace_version()
2705
+ if extended:
2706
+ BRM = BRM.extension_ring()
2707
+ if field_embedding:
2708
+ emb = BRM.field_embedding()
2709
+ BRM = emb.codomain()
2710
+ return FreeModule(BRM, basis)
2711
+
2712
+ # --------------------------------------------------------------------------
2713
+ # _markov_trace_coeffs
2714
+ # --------------------------------------------------------------------------
2715
+ @cached_method
2716
+ def _markov_trace_coeffs(self):
2717
+ r"""
2718
+ Return a list of formal Markov traces of the basis elements of ``self``.
2719
+
2720
+ OUTPUT:
2721
+
2722
+ A list of elements of the Markov trace module (over the Markov trace
2723
+ version of the generic base ring). Each entry of the list corresponds
2724
+ to the according basis element of ``self``.
2725
+
2726
+ EXAMPLES::
2727
+
2728
+ sage: CHA2 = algebras.CubicHecke(2)
2729
+ sage: CHA2._markov_trace_coeffs()
2730
+ [B[U2], s*B[U1], 1/s*B[U1]]
2731
+ sage: M = _[0].parent(); M
2732
+ Free module generated by {U1, U2}
2733
+ over Multivariate Polynomial Ring in u, v, w, s
2734
+ over Integer Ring localized at (s, w, v, u)
2735
+ """
2736
+ M = self._markov_trace_module()
2737
+ Mbas = M.basis().keys()
2738
+ db = self._database
2739
+ sec = db.section.markov_tr_cfs
2740
+ cfs = db.read(sec, variables=M.base_ring().gens(), nstrands=self._nstrands)
2741
+ d = self.dimension()
2742
+ return [sum(cfs[bas_ele][i]*M(bas_ele) for bas_ele in Mbas) for i in range(d)]
2743
+
2744
+ ############################################################################
2745
+ # --------------------------------------------------------------------------
2746
+ # public methods
2747
+ # --------------------------------------------------------------------------
2748
+ ############################################################################
2749
+ def filecache_section(self):
2750
+ r"""
2751
+ Return the ``enum`` to select a section in the file cache.
2752
+
2753
+ EXAMPLES::
2754
+
2755
+ sage: CHA2 = algebras.CubicHecke(2)
2756
+ sage: list(CHA2.filecache_section())
2757
+ [<section.matrix_representations: 'matrix_representations'>,
2758
+ <section.braid_images: 'braid_images'>,
2759
+ <section.basis_extensions: 'basis_extensions'>,
2760
+ <section.markov_trace: 'markov_trace'>]
2761
+ """
2762
+ return self._filecache.section
2763
+
2764
+ def is_filecache_empty(self, section=None):
2765
+ r"""
2766
+ Return ``True`` if the file cache of the given ``section`` is empty.
2767
+ If no ``section`` is given the answer is given for the complete
2768
+ file cache.
2769
+
2770
+ INPUT:
2771
+
2772
+ - ``section`` -- (default: all sections) an element of enum
2773
+ :class:`~sage.databases.cubic_hecke_db.CubicHeckeFileCache.section`
2774
+ that can be selected using :meth:`filecache_section`
2775
+
2776
+ EXAMPLES::
2777
+
2778
+ sage: CHA2 = algebras.CubicHecke(2)
2779
+ sage: CHA2.is_filecache_empty()
2780
+ False
2781
+ """
2782
+ return self._filecache.is_empty(section=section)
2783
+
2784
+ def reset_filecache(self, section=None, commit=True):
2785
+ r"""
2786
+ Reset the file cache of the given ``section`` resp. the complete
2787
+ file cache if no ``section`` is given.
2788
+
2789
+ INPUT:
2790
+
2791
+ - ``section`` -- (default: all sections) an element of enum
2792
+ :class:`~sage.databases.cubic_hecke_db.CubicHeckeFileCache.section`
2793
+ that can be selected using :meth:`filecache_section`
2794
+ - ``commit`` -- boolean (default: ``True``); if set to ``False`` the
2795
+ reset is not written to the filesystem
2796
+
2797
+ EXAMPLES::
2798
+
2799
+ sage: # optional - database_cubic_hecke
2800
+ sage: CHA5 = algebras.CubicHecke(5)
2801
+ sage: be = CHA5.filecache_section().basis_extensions
2802
+ sage: CHA5.is_filecache_empty(be)
2803
+ False
2804
+ sage: CHA5.reset_filecache(be)
2805
+ sage: CHA5.is_filecache_empty(be)
2806
+ True
2807
+ """
2808
+ fc = self._filecache
2809
+ if section == fc.section.basis_extensions:
2810
+ if self._nstrands < 5:
2811
+ raise ValueError('not allowed for less than 5 strand')
2812
+ fc.reset_library(section=section)
2813
+
2814
+ if section == fc.section.basis_extensions:
2815
+ self._init_basis_extension()
2816
+ if commit:
2817
+ fc.write(section=section)
2818
+
2819
+ def strands(self):
2820
+ r"""
2821
+ Return the number of strands of the braid group whose group algebra
2822
+ image is ``self``.
2823
+
2824
+ EXAMPLES::
2825
+
2826
+ sage: CHA4 = algebras.CubicHecke(2)
2827
+ sage: CHA4.strands()
2828
+ 2
2829
+ """
2830
+ return self._nstrands
2831
+
2832
+ # --------------------------------------------------------------------------
2833
+ # Garside involution
2834
+ # --------------------------------------------------------------------------
2835
+ def garside_involution(self, element):
2836
+ r"""
2837
+ Return the image of the given element of ``self`` under the extension of
2838
+ the Garside involution of braids to ``self``.
2839
+
2840
+ This method may be invoked by the ``revert_garside`` method of the
2841
+ element class of ``self``, alternatively.
2842
+
2843
+ INPUT:
2844
+
2845
+ - ``element`` -- instance of the element class of ``self``
2846
+
2847
+ OUTPUT:
2848
+
2849
+ Instance of the element class of ``self`` representing the image of
2850
+ ``element`` under the extension of the Garside involution to ``self``.
2851
+
2852
+ EXAMPLES::
2853
+
2854
+ sage: CHA3 = algebras.CubicHecke(3)
2855
+ sage: ele = CHA3.an_element()
2856
+ sage: ele_gar = CHA3.garside_involution(ele); ele_gar
2857
+ -w*c1*c0^-1 + u*c0 + v*c1 - ((v*w-u)/w)
2858
+ sage: ele == CHA3.garside_involution(ele_gar)
2859
+ True
2860
+ """
2861
+ braid_group = self.braid_group()
2862
+ reverse_gens = list(braid_group.gens())
2863
+ reverse_gens.reverse()
2864
+ brgrp_garside_involution = braid_group.hom(reverse_gens, check=False)
2865
+ return self._extend_braid_automorphism(element, brgrp_garside_involution)
2866
+
2867
+ # --------------------------------------------------------------------------
2868
+ # orientation anti involution
2869
+ # --------------------------------------------------------------------------
2870
+ def orientation_antiinvolution(self, element):
2871
+ r"""
2872
+ Return the image of the given element of ``self`` under the extension of
2873
+ the orientation anti involution of braids to ``self``. The orientation
2874
+ anti involution of a braid is given by reversing the order of generators
2875
+ in the braid word.
2876
+
2877
+ This method may be invoked by the ``revert_orientation`` method of the
2878
+ element class of ``self``, alternatively.
2879
+
2880
+ INPUT:
2881
+
2882
+ - ``element`` -- instance of the element class of ``self``
2883
+
2884
+ OUTPUT:
2885
+
2886
+ Instance of the element class of ``self`` representing the image of
2887
+ ``element`` under the extension of the orientation reversing braid
2888
+ involution to ``self``.
2889
+
2890
+ EXAMPLES::
2891
+
2892
+ sage: CHA3 = algebras.CubicHecke(3)
2893
+ sage: ele = CHA3.an_element()
2894
+ sage: ele_ori = CHA3.orientation_antiinvolution(ele); ele_ori
2895
+ -w*c1^-1*c0 + v*c0 + u*c1 - ((v*w-u)/w)
2896
+ sage: ele == CHA3.orientation_antiinvolution(ele_ori)
2897
+ True
2898
+ """
2899
+ braid_group = self.braid_group()
2900
+
2901
+ def brgrp_orientation_antiinvolution(braid):
2902
+ braid_list = list(braid.Tietze())
2903
+ braid_list.reverse()
2904
+ return braid_group(tuple(braid_list))
2905
+ return self._extend_braid_automorphism(element, brgrp_orientation_antiinvolution)
2906
+
2907
+ # --------------------------------------------------------------------------
2908
+ # mirror isomorphism
2909
+ # --------------------------------------------------------------------------
2910
+ def mirror_isomorphism(self, element):
2911
+ r"""
2912
+ Return the image of the given element of ``self`` under the extension
2913
+ of the mirror involution of braids to ``self``. The mirror involution
2914
+ of a braid is given by inverting all generators in the braid word. It
2915
+ does not factor through ``self`` over the base ring but it factors
2916
+ through ``self`` considered as a `\ZZ`-module relative to the mirror
2917
+ automorphism of the generic base ring. Considering ``self`` as algebra
2918
+ over its base ring this involution defines an isomorphism of ``self``
2919
+ onto a different cubic Hecke algebra with a different cubic equation.
2920
+ This is defined over a different base (and extension) ring than
2921
+ ``self``. It can be obtained by the method ``mirror_image`` or as
2922
+ parent of the output of this method.
2923
+
2924
+ This method may be invoked by the ``CubicHeckeElelemnt.revert_mirror``
2925
+ method of the element class of ``self``, alternatively.
2926
+
2927
+ INPUT:
2928
+
2929
+ - ``element`` -- instance of the element class of ``self``
2930
+
2931
+ OUTPUT:
2932
+
2933
+ Instance of the element class of the mirror image of ``self``
2934
+ representing the image of element under the extension of the braid
2935
+ mirror involution to ``self``.
2936
+
2937
+ EXAMPLES::
2938
+
2939
+ sage: CHA3 = algebras.CubicHecke(3)
2940
+ sage: ele = CHA3.an_element()
2941
+ sage: ele_mirr = CHA3.mirror_isomorphism(ele); ele_mirr
2942
+ -1/w*c0^-1*c1 + u/w*c0^-1 + v/w*c1^-1 + ((v*w-u)/w)
2943
+ sage: ele_mirr2 = ele.revert_mirror() # indirect doctest
2944
+ sage: ele_mirr == ele_mirr2
2945
+ True
2946
+ sage: par_mirr = ele_mirr.parent()
2947
+ sage: par_mirr == CHA3
2948
+ False
2949
+ sage: par_mirr == CHA3.mirror_image()
2950
+ True
2951
+ sage: ele == par_mirr.mirror_isomorphism(ele_mirr)
2952
+ True
2953
+ """
2954
+ mirror_image = self.mirror_image()
2955
+ braid_group = self.braid_group()
2956
+ mirror_involution = braid_group.hom([~g for g in braid_group.gens()], check=False)
2957
+ # Todo: have mirror_involution be a method of :class:`BraidGroup_class`
2958
+ base_ring_mirror = self._base_ring_mirror
2959
+ element_vec = vector([base_ring_mirror(cf) for cf in list(element.to_vector())])
2960
+ element_mirr = mirror_image.from_vector(element_vec)
2961
+ return mirror_image._extend_braid_automorphism(element_mirr, mirror_involution)
2962
+
2963
+ # --------------------------------------------------------------------------
2964
+ # cubic_equation
2965
+ # --------------------------------------------------------------------------
2966
+ def cubic_equation(self, var='h', as_coefficients=False, generic=False):
2967
+ r"""
2968
+ Return the cubic equation attached to ``self``.
2969
+
2970
+ INPUT:
2971
+
2972
+ - ``var`` -- string (default: ``'h'``); setting the indeterminate of the
2973
+ equation
2974
+ - ``as_coefficients`` -- boolean (default: ``False``); if set to ``True``
2975
+ the list of coefficients is returned
2976
+ - ``generic`` -- boolean (default: ``False``); if set to ``True`` the
2977
+ cubic equation will be given over the generic base ring
2978
+
2979
+ OUTPUT:
2980
+
2981
+ A polynomial over the base ring (resp. generic base ring if ``generic``
2982
+ is set to True). In case ``as_coefficients`` is set to ``True`` a list
2983
+ of them is returned.
2984
+
2985
+ EXAMPLES::
2986
+
2987
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(E(3), ~E(3), 1))
2988
+ sage: CHA2.cubic_equation()
2989
+ h^3 - 1
2990
+ sage: CHA2.cubic_equation(generic=True)
2991
+ h^3 - u*h^2 + v*h - w
2992
+ sage: CHA2.cubic_equation(as_coefficients=True, generic=True)
2993
+ [-w, v, -u, 1]
2994
+ sage: CHA2.cubic_equation(as_coefficients=True)
2995
+ [-1, 0, 0, 1]
2996
+ """
2997
+ BaseRing = self.base_ring(generic=generic)
2998
+ if generic:
2999
+ u, v, w = BaseRing.gens()
3000
+ else:
3001
+ u, v, w = self._cubic_equation_parameters
3002
+ cf = [-w, v, -u, 1]
3003
+ if as_coefficients:
3004
+ return cf
3005
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
3006
+ P = PolynomialRing(BaseRing, var)
3007
+ return P(cf)
3008
+
3009
+ # --------------------------------------------------------------------------
3010
+ # cubic_equation_roots
3011
+ # --------------------------------------------------------------------------
3012
+ def cubic_equation_roots(self, generic=False):
3013
+ r"""
3014
+ Return the roots of the underlying cubic equation.
3015
+
3016
+ INPUT:
3017
+
3018
+ - ``generic`` -- boolean (default: ``False``); if set to ``True`` the
3019
+ roots are returned as elements of the generic extension ring
3020
+
3021
+ OUTPUT: a triple consisting of the roots
3022
+
3023
+ EXAMPLES::
3024
+
3025
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
3026
+ sage: CHA2.cubic_equation()
3027
+ h^3 - 12*h^2 + 47*h - 60
3028
+ sage: CHA2.cubic_equation_roots()
3029
+ [3, 4, 5]
3030
+ sage: CHA2.cubic_equation_roots(generic=True)
3031
+ [a, b, c]
3032
+ """
3033
+ if generic:
3034
+ return self._generic_cubic_equation_roots
3035
+ else:
3036
+ return self._cubic_equation_roots
3037
+
3038
+ # --------------------------------------------------------------------------
3039
+ # cubic_equation_roots
3040
+ # --------------------------------------------------------------------------
3041
+ def cubic_equation_parameters(self, generic=False):
3042
+ r"""
3043
+ Return the coefficients of the underlying cubic equation.
3044
+
3045
+ INPUT:
3046
+
3047
+ - ``generic`` -- boolean (default: ``False``); if set to ``True`` the
3048
+ coefficients are returned as elements of the generic base ring
3049
+
3050
+ OUTPUT: a triple consisting of the coefficients
3051
+
3052
+ EXAMPLES::
3053
+
3054
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
3055
+ sage: CHA2.cubic_equation()
3056
+ h^3 - 12*h^2 + 47*h - 60
3057
+ sage: CHA2.cubic_equation_parameters()
3058
+ [12, 47, 60]
3059
+ sage: CHA2.cubic_equation_parameters(generic=True)
3060
+ [u, v, w]
3061
+ """
3062
+ if generic:
3063
+ return self._generic_cubic_equation_parameters
3064
+ else:
3065
+ return self._cubic_equation_parameters
3066
+
3067
+ # --------------------------------------------------------------------------
3068
+ # base_ring
3069
+ # --------------------------------------------------------------------------
3070
+ def base_ring(self, generic=False):
3071
+ r"""
3072
+ Return the base ring of ``self``.
3073
+
3074
+ INPUT:
3075
+
3076
+ - ``generic`` -- boolean (default: ``False``); if ``True`` the ring
3077
+ of definition (here often called the generic base ring) is returned
3078
+
3079
+ EXAMMPLES::
3080
+
3081
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
3082
+ sage: CHA2.base_ring()
3083
+ Integer Ring localized at (2, 3, 5)
3084
+ sage: CHA2.base_ring(generic=True)
3085
+ Multivariate Polynomial Ring in u, v, w
3086
+ over Integer Ring localized at (w,)
3087
+ """
3088
+ if generic:
3089
+ return self._ring_of_definition
3090
+ else:
3091
+ return super().base_ring()
3092
+
3093
+ # --------------------------------------------------------------------------
3094
+ # extension_ring
3095
+ # --------------------------------------------------------------------------
3096
+ def extension_ring(self, generic=False):
3097
+ r"""
3098
+ Return the extension ring of ``self``.
3099
+
3100
+ This is an extension of its base ring containing the roots
3101
+ of the cubic equation.
3102
+
3103
+ INPUT:
3104
+
3105
+ - ``generic`` -- boolean (default: ``False``); if ``True`` the
3106
+ extension ring of definition (here often called the generic
3107
+ extension ring) is returned
3108
+
3109
+ EXAMMPLES::
3110
+
3111
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
3112
+ sage: CHA2.extension_ring()
3113
+ Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
3114
+ over Integer Ring localized at (2, 3, 5)
3115
+ sage: CHA2.extension_ring(generic=True)
3116
+ Multivariate Laurent Polynomial Ring in a, b, c
3117
+ over Splitting Algebra of x^2 + x + 1
3118
+ with roots [e3, -e3 - 1] over Integer Ring
3119
+ """
3120
+ if generic:
3121
+ return self._generic_extension_ring
3122
+ else:
3123
+ return self._extension_ring
3124
+
3125
+ # --------------------------------------------------------------------------
3126
+ # cyclotomic_generator
3127
+ # --------------------------------------------------------------------------
3128
+ def cyclotomic_generator(self, generic=False):
3129
+ r"""
3130
+ Return the third root of unity as element of the extension ring.
3131
+
3132
+ The only thing where this is needed is in the nine dimensional
3133
+ irreducible representations of the cubic Hecke algebra on four strands
3134
+ (see the examples of :meth:`CubicHeckeElement.matrix` for instance).
3135
+
3136
+ INPUT:
3137
+
3138
+ - ``generic`` -- boolean (default: ``False``); if ``True`` the
3139
+ cyclotomic generator is returned as an element extension ring of
3140
+ definition
3141
+
3142
+ EXAMMPLES::
3143
+
3144
+ sage: CHA2 = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
3145
+ sage: CHA2.cyclotomic_generator()
3146
+ E3
3147
+ sage: CHA2.cyclotomic_generator(generic=True)
3148
+ e3
3149
+ """
3150
+ e3gen = self.extension_ring(generic=True).cyclotomic_generator()
3151
+ if generic:
3152
+ return e3gen
3153
+ else:
3154
+ return self._generic_extension_ring_map(e3gen)
3155
+
3156
+ # --------------------------------------------------------------------------
3157
+ # braid_group
3158
+ # --------------------------------------------------------------------------
3159
+ def braid_group(self):
3160
+ r"""
3161
+ Return the braid group attached to ``self``.
3162
+
3163
+ EXAMPLES::
3164
+
3165
+ sage: CHA2 = algebras.CubicHecke(2)
3166
+ sage: CHA2.braid_group()
3167
+ Braid group on 2 strands
3168
+ """
3169
+ return self._braid_group
3170
+
3171
+ # --------------------------------------------------------------------------
3172
+ # cubic_braid_group
3173
+ # --------------------------------------------------------------------------
3174
+ def cubic_braid_group(self):
3175
+ r"""
3176
+ Return the cubic braid group attached to ``self``.
3177
+
3178
+ EXAMPLES::
3179
+
3180
+ sage: CHA2 = algebras.CubicHecke(2)
3181
+ sage: CHA2.cubic_braid_group()
3182
+ Cubic Braid group on 2 strands
3183
+ """
3184
+ return self._cubic_braid_group
3185
+
3186
+ # --------------------------------------------------------------------------
3187
+ # braid_group_algebra
3188
+ # --------------------------------------------------------------------------
3189
+ def braid_group_algebra(self):
3190
+ r"""
3191
+ Return the group algebra of braid group attached to ``self`` over the
3192
+ base ring of ``self``.
3193
+
3194
+ EXAMPLES::
3195
+
3196
+ sage: CHA2 = algebras.CubicHecke(2)
3197
+ sage: CHA2.braid_group_algebra()
3198
+ Algebra of Braid group on 2 strands
3199
+ over Multivariate Polynomial Ring in u, v, w
3200
+ over Integer Ring localized at (w,)
3201
+ """
3202
+ return self._braid_group_algebra
3203
+
3204
+ # --------------------------------------------------------------------------
3205
+ # cubic_braid_group_algebra
3206
+ # --------------------------------------------------------------------------
3207
+ def cubic_braid_group_algebra(self):
3208
+ r"""
3209
+ Return the group algebra of cubic braid group attached to ``self`` over
3210
+ the base ring of ``self``.
3211
+
3212
+ EXAMPLES::
3213
+
3214
+ sage: CHA2 = algebras.CubicHecke(2)
3215
+ sage: CHA2.cubic_braid_group_algebra()
3216
+ Algebra of Cubic Braid group on 2 strands
3217
+ over Multivariate Polynomial Ring in u, v, w
3218
+ over Integer Ring localized at (w,)
3219
+ """
3220
+ return self._cubic_braid_group_algebra
3221
+
3222
+ # --------------------------------------------------------------------------
3223
+ # creating a CubicHeckeAlgebra as sub-algebra of self on less strands
3224
+ # --------------------------------------------------------------------------
3225
+ def cubic_hecke_subalgebra(self, nstrands=None):
3226
+ r"""
3227
+ Return a :class:`CubicHeckeAlgebra` that realizes a sub-algebra
3228
+ of ``self`` on the first ``n_strands`` strands.
3229
+
3230
+ INPUT:
3231
+
3232
+ - ``nstrands`` -- integer at least 1 and at most :meth:`strands` giving
3233
+ the number of strands for the subgroup; the default is one strand
3234
+ less than ``self`` has
3235
+
3236
+ OUTPUT: an instance of this class realizing the sub-algebra
3237
+
3238
+ EXAMPLES::
3239
+
3240
+ sage: CHA3 = algebras.CubicHecke(3, cubic_equation_roots=(3, 4, 5))
3241
+ sage: CHA3.cubic_hecke_subalgebra()
3242
+ Cubic Hecke algebra on 2 strands
3243
+ over Integer Ring localized at (2, 3, 5)
3244
+ with cubic equation: h^3 - 12*h^2 + 47*h - 60 = 0
3245
+ """
3246
+ if nstrands is None:
3247
+ nstrands = self._nstrands - 1
3248
+ n = self._nstrands
3249
+ nstrands = ZZ(nstrands)
3250
+
3251
+ if nstrands >= n or nstrands <= 0:
3252
+ raise ValueError('nstrands must be positive and less than %s' % self._nstrands)
3253
+
3254
+ names = self.variable_names()
3255
+ if nstrands == self._nstrands - 1 and self._cubic_hecke_subalgebra is not None:
3256
+ return self._cubic_hecke_subalgebra
3257
+
3258
+ names_red = names[:nstrands - 1]
3259
+ if self.base_ring() == self.base_ring(generic=True):
3260
+ SubHeckeAlg = CubicHeckeAlgebra(names=names_red)
3261
+ else:
3262
+ SubHeckeAlg = CubicHeckeAlgebra(names=names_red,
3263
+ cubic_equation_parameters=tuple(self._cubic_equation_parameters),
3264
+ cubic_equation_roots=tuple(self._cubic_equation_roots))
3265
+
3266
+ if nstrands == self._nstrands - 1:
3267
+ self._cubic_hecke_subalgebra = SubHeckeAlg
3268
+ return SubHeckeAlg
3269
+
3270
+ # --------------------------------------------------------------------------
3271
+ # mirror image
3272
+ # --------------------------------------------------------------------------
3273
+ def mirror_image(self):
3274
+ r"""
3275
+ Return a copy of ``self`` with the mirrored cubic equation, that is:
3276
+ the cubic equation has the inverse roots to the roots with respect
3277
+ to ``self``.
3278
+
3279
+ This is needed since the mirror involution of the braid group does
3280
+ not factor through ``self`` (considered as an algebra over the base
3281
+ ring, just considered as `\ZZ`-algebra). Therefore, the mirror
3282
+ involution of an element of ``self`` belongs to ``mirror_image``.
3283
+
3284
+ OUTPUT:
3285
+
3286
+ A cubic Hecke algebra over the same base and extension ring,
3287
+ but whose cubic equation is transformed by the mirror involution
3288
+ applied to its coefficients and roots.
3289
+
3290
+ EXAMPLES::
3291
+
3292
+ sage: CHA2 = algebras.CubicHecke(2)
3293
+ sage: ce = CHA2.cubic_equation(); ce
3294
+ h^3 - u*h^2 + v*h - w
3295
+ sage: CHA2m = CHA2.mirror_image()
3296
+ sage: cem = CHA2m.cubic_equation(); cem
3297
+ h^3 + ((-v)/w)*h^2 + u/w*h + (-1)/w
3298
+ sage: mi = CHA2.base_ring().mirror_involution(); mi
3299
+ Ring endomorphism of Multivariate Polynomial Ring in u, v, w
3300
+ over Integer Ring localized at (w,)
3301
+ Defn: u |--> v/w
3302
+ v |--> u/w
3303
+ w |--> 1/w
3304
+ sage: cem == cem.parent()([mi(cf) for cf in ce.coefficients()])
3305
+ True
3306
+
3307
+ Note that both cubic Hecke algebras have the same ring of definition
3308
+ and identical generic cubic equation::
3309
+
3310
+ sage: cemg = CHA2m.cubic_equation(generic=True)
3311
+ sage: CHA2.cubic_equation(generic=True) == cemg
3312
+ True
3313
+ sage: CHA2.cubic_equation() == cemg
3314
+ True
3315
+ sage: a, b, c = CHA2.cubic_equation_roots()
3316
+ sage: CHA2m.cubic_equation_roots(generic=True) == [a, b, c]
3317
+ True
3318
+ sage: CHA2m.cubic_equation_roots()
3319
+ [((-1)/(-w))*a^2 + (u/(-w))*a + (-v)/(-w),
3320
+ ((1/(-w))*a)*b + (1/(-w))*a^2 + ((-u)/(-w))*a,
3321
+ (((-1)/(-w))*a)*b]
3322
+ sage: ai, bi, ci = _
3323
+ sage: ai == ~a, bi == ~b, ci == ~c
3324
+ (True, True, True)
3325
+ sage: CHA2.extension_ring(generic=True).mirror_involution()
3326
+ Ring endomorphism of Multivariate Laurent Polynomial Ring in a, b, c
3327
+ over Splitting Algebra of x^2 + x + 1
3328
+ with roots [e3, -e3 - 1] over Integer Ring
3329
+ Defn: a |--> a^-1
3330
+ b |--> b^-1
3331
+ c |--> c^-1
3332
+ with map of base ring
3333
+
3334
+ The mirror image can not be obtained for specialized cubic Hecke
3335
+ algebras if the specialization does not factor through the mirror
3336
+ involution on the ring if definition::
3337
+
3338
+ sage: CHA2s = algebras.CubicHecke(2, cubic_equation_roots=(3, 4, 5))
3339
+ sage: CHA2s
3340
+ Cubic Hecke algebra on 2 strands
3341
+ over Integer Ring localized at (2, 3, 5)
3342
+ with cubic equation: h^3 - 12*h^2 + 47*h - 60 = 0
3343
+
3344
+ In the next example it is not clear what the mirror image of ``7``
3345
+ should be::
3346
+
3347
+ sage: CHA2s.mirror_image()
3348
+ Traceback (most recent call last):
3349
+ ...
3350
+ RuntimeError: base ring Integer Ring localized at (2, 3, 5)
3351
+ does not factor through mirror involution
3352
+ """
3353
+ base_ring = self.base_ring()
3354
+ base_gen = self.base_ring(generic=True)
3355
+
3356
+ base_gen_mirror = base_gen.mirror_involution()
3357
+ base_ring_mirror = self._base_ring_mirror
3358
+ cepg = self.cubic_equation_parameters(generic=True)
3359
+ cerg = self.cubic_equation_roots(generic=True)
3360
+ if not base_ring_mirror:
3361
+ mirr_paras_gen = [base_gen_mirror(par) for par in cepg]
3362
+ mirr_paras = [base_ring(mirr_para) for mirr_para in mirr_paras_gen]
3363
+ try:
3364
+ base_ring_mirror = base_ring.hom(mirr_paras)
3365
+ except (TypeError, ValueError, NotImplementedError):
3366
+ raise RuntimeError('base ring %s does not factor through mirror involution' % base_ring)
3367
+
3368
+ # check for involution
3369
+ mirr_paras_back = [base_ring_mirror(mirr_para) for mirr_para in mirr_paras]
3370
+ if mirr_paras_back != self.cubic_equation_parameters():
3371
+ raise RuntimeError('base ring %s does not factor through mirror involution' % base_ring)
3372
+ self._base_ring_mirror = base_ring_mirror
3373
+
3374
+ mirror_image = self._mirror_image
3375
+ if mirror_image is None:
3376
+ extension_ring = self.extension_ring()
3377
+ extension_gen = self.extension_ring(generic=True)
3378
+ extension_gen_mirror = extension_gen.mirror_involution()
3379
+
3380
+ mirr_paras_gen = [base_gen_mirror(par) for par in cepg]
3381
+ mirr_roots_gen = [extension_gen_mirror(root) for root in cerg]
3382
+
3383
+ mirr_paras = tuple([base_ring(par) for par in mirr_paras_gen])
3384
+ mirr_roots = tuple([extension_ring(root) for root in mirr_roots_gen])
3385
+ n = self._nstrands
3386
+
3387
+ mirror_image = CubicHeckeAlgebra(n, cubic_equation_parameters=mirr_paras, cubic_equation_roots=mirr_roots)
3388
+
3389
+ # go back by involution property
3390
+ mirror_image._mirror_image = self
3391
+ mirror_image._base_ring_mirror = base_ring_mirror
3392
+ mirror_image._ring_of_definition._mirror_ = base_gen_mirror
3393
+ mirror_image._is_mirror = True
3394
+
3395
+ self._mirror_image = mirror_image
3396
+
3397
+ return mirror_image
3398
+
3399
+ # --------------------------------------------------------------------------
3400
+ # Schur elements
3401
+ # --------------------------------------------------------------------------
3402
+ def schur_elements(self, generic=False):
3403
+ r"""
3404
+ Return the list of Schur elements of ``self`` as elements
3405
+ of the extension ring of ``self``.
3406
+
3407
+ .. NOTE::
3408
+
3409
+ This method needs ``GAP3`` installed with package ``CHEVIE``.
3410
+
3411
+ INPUT:
3412
+
3413
+ - ``generic`` -- boolean (default: ``False``); if ``True``,
3414
+ the element is returned as element of the generic
3415
+ extension ring
3416
+
3417
+ EXAMPLES::
3418
+
3419
+ sage: CHA3 = algebras.CubicHecke(3) # optional gap3
3420
+ sage: sch_eles = CHA3.schur_elements() # optional gap3
3421
+ sage: sch_eles[6] # optional gap3
3422
+ (u^3*w + v^3 - 6*u*v*w + 8*w^2)/w^2
3423
+ """
3424
+ gap3_result = self.chevie().SchurElements()
3425
+ GER = self.extension_ring(generic=True)
3426
+ generic_result = [GER(s) for s in gap3_result]
3427
+ if generic:
3428
+ return list(generic_result)
3429
+ else:
3430
+ ER = self.extension_ring()
3431
+ return [ER(s) for s in generic_result]
3432
+
3433
+ # --------------------------------------------------------------------------
3434
+ # Schur element
3435
+ # --------------------------------------------------------------------------
3436
+ def schur_element(self, item, generic=False):
3437
+ r"""
3438
+ Return a single Schur element of ``self`` as elements
3439
+ of the extension ring of ``self``.
3440
+
3441
+ .. NOTE::
3442
+
3443
+ This method needs ``GAP3`` installed with package ``CHEVIE``.
3444
+
3445
+ INPUT:
3446
+
3447
+ - ``item`` -- an element of :class:`AbsIrreducibeRep` to give
3448
+ the irreducible representation of ``self`` to which the Schur
3449
+ element should be returned
3450
+ - ``generic`` -- boolean (default: ``False``); if ``True``,
3451
+ the element is returned as element of the generic
3452
+ extension ring
3453
+
3454
+ EXAMPLES::
3455
+
3456
+ sage: CHA3 = algebras.CubicHecke(3) # optional gap3
3457
+ sage: CHA3.schur_element(CHA3.irred_repr.W3_111) # optional gap3
3458
+ (u^3*w + v^3 - 6*u*v*w + 8*w^2)/w^2
3459
+ """
3460
+ if not isinstance(item, AbsIrreducibeRep):
3461
+ raise ValueError('item must be an instance of %s' % AbsIrreducibeRep)
3462
+ return self.schur_elements(generic=generic)[item.gap_index()]
3463
+
3464
+ # --------------------------------------------------------------------------
3465
+ # characters
3466
+ # --------------------------------------------------------------------------
3467
+ def characters(self, irr=None, original=True):
3468
+ r"""
3469
+ Return the irreducible characters of ``self``.
3470
+
3471
+ By default the values are given in the generic extension ring.
3472
+ Setting the keyword ``original`` to ``False`` you can obtain
3473
+ the values in the (non generic) extension ring (compare the
3474
+ same keyword for :meth:`CubicHeckeElement.matrix`).
3475
+
3476
+ INPUT:
3477
+
3478
+ - ``irr`` -- (optional) instance of :class:`AbsIrreducibeRep`
3479
+ selecting the irreducible representation corresponding to the
3480
+ character; if not given a list of all characters is returned
3481
+ - ``original`` -- boolean (default: ``True``); see description above
3482
+
3483
+ OUTPUT:
3484
+
3485
+ Function or list of Functions from the element class of ``self`` to
3486
+ the (generic or non generic) extension ring depending on the given
3487
+ keyword arguments.
3488
+
3489
+ EXAMPLES::
3490
+
3491
+ sage: CHA3 = algebras.CubicHecke(3)
3492
+ sage: ch = CHA3.characters()
3493
+ sage: e = CHA3.an_element()
3494
+ sage: ch[0](e)
3495
+ a^2*b + a^2*c + a^2 - b*c + b^-1*c^-1 + a^-1*c^-1 + a^-1*b^-1
3496
+ sage: _.parent()
3497
+ Multivariate Laurent Polynomial Ring in a, b, c
3498
+ over Splitting Algebra of x^2 + x + 1 with roots [e3, -e3 - 1]
3499
+ over Integer Ring
3500
+ sage: ch_w3_100 = CHA3.characters(irr=CHA3.irred_repr.W3_100)
3501
+ sage: ch_w3_100(e) == ch[0](e)
3502
+ True
3503
+ sage: ch_x = CHA3.characters(original=False)
3504
+ sage: ch_x[0](e)
3505
+ (u + v)*a + (-v*w - w^2 + u)/w
3506
+ sage: _.parent()
3507
+ Splitting Algebra of T^2 + T + 1 with roots [E3, -E3 - 1]
3508
+ over Splitting Algebra of h^3 - u*h^2 + v*h - w
3509
+ with roots [a, b, -b - a + u]
3510
+ over Multivariate Polynomial Ring in u, v, w
3511
+ over Integer Ring localized at (w,)
3512
+ """
3513
+ def char_function(ele):
3514
+ if isinstance(ele, self.element_class):
3515
+ m = ele.matrix(original=original)
3516
+ return m[irr].trace()
3517
+ if irr:
3518
+ return char_function
3519
+ irrs = [irr for irr in self.irred_repr if irr.number_gens() == self._nstrands - 1]
3520
+ return [self.characters(irrs[i], original=original) for i in range(len(irrs))]