passagemath-singular 10.6.31rc3__cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

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

Potentially problematic release.


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

Files changed (491) hide show
  1. PySingular.cpython-314-x86_64-linux-gnu.so +0 -0
  2. passagemath_singular-10.6.31rc3.dist-info/METADATA +183 -0
  3. passagemath_singular-10.6.31rc3.dist-info/RECORD +491 -0
  4. passagemath_singular-10.6.31rc3.dist-info/WHEEL +6 -0
  5. passagemath_singular-10.6.31rc3.dist-info/top_level.txt +3 -0
  6. passagemath_singular.libs/libSingular-4-20aec911.4.1.so +0 -0
  7. passagemath_singular.libs/libcddgmp-21acf0c6.so.0.1.3 +0 -0
  8. passagemath_singular.libs/libfactory-4-fcee31da.4.1.so +0 -0
  9. passagemath_singular.libs/libflint-66e12231.so.21.0.0 +0 -0
  10. passagemath_singular.libs/libgf2x-a4cdec90.so.3.0.0 +0 -0
  11. passagemath_singular.libs/libgfortran-83c28eba.so.5.0.0 +0 -0
  12. passagemath_singular.libs/libgmp-6e109695.so.10.5.0 +0 -0
  13. passagemath_singular.libs/libgsl-cda90e79.so.28.0.0 +0 -0
  14. passagemath_singular.libs/libmpfr-82690d50.so.6.2.1 +0 -0
  15. passagemath_singular.libs/libntl-e6f0d543.so.44.0.1 +0 -0
  16. passagemath_singular.libs/libomalloc-0-5c9e866e.9.6.so +0 -0
  17. passagemath_singular.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
  18. passagemath_singular.libs/libpolys-4-5c0a87e0.4.1.so +0 -0
  19. passagemath_singular.libs/libquadmath-2284e583.so.0.0.0 +0 -0
  20. passagemath_singular.libs/libreadline-ea270e21.so.8.2 +0 -0
  21. passagemath_singular.libs/libsingular_resources-4-a1aafc6d.4.1.so +0 -0
  22. passagemath_singular.libs/libtinfo-ceb117d9.so.6.3 +0 -0
  23. sage/algebras/all__sagemath_singular.py +3 -0
  24. sage/algebras/fusion_rings/all.py +19 -0
  25. sage/algebras/fusion_rings/f_matrix.py +2448 -0
  26. sage/algebras/fusion_rings/fast_parallel_fmats_methods.cpython-314-x86_64-linux-gnu.so +0 -0
  27. sage/algebras/fusion_rings/fast_parallel_fmats_methods.pxd +5 -0
  28. sage/algebras/fusion_rings/fast_parallel_fmats_methods.pyx +538 -0
  29. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.cpython-314-x86_64-linux-gnu.so +0 -0
  30. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pxd +3 -0
  31. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pyx +331 -0
  32. sage/algebras/fusion_rings/fusion_double.py +899 -0
  33. sage/algebras/fusion_rings/fusion_ring.py +1580 -0
  34. sage/algebras/fusion_rings/poly_tup_engine.cpython-314-x86_64-linux-gnu.so +0 -0
  35. sage/algebras/fusion_rings/poly_tup_engine.pxd +24 -0
  36. sage/algebras/fusion_rings/poly_tup_engine.pyx +579 -0
  37. sage/algebras/fusion_rings/shm_managers.cpython-314-x86_64-linux-gnu.so +0 -0
  38. sage/algebras/fusion_rings/shm_managers.pxd +24 -0
  39. sage/algebras/fusion_rings/shm_managers.pyx +780 -0
  40. sage/algebras/letterplace/all.py +1 -0
  41. sage/algebras/letterplace/free_algebra_element_letterplace.cpython-314-x86_64-linux-gnu.so +0 -0
  42. sage/algebras/letterplace/free_algebra_element_letterplace.pxd +18 -0
  43. sage/algebras/letterplace/free_algebra_element_letterplace.pyx +755 -0
  44. sage/algebras/letterplace/free_algebra_letterplace.cpython-314-x86_64-linux-gnu.so +0 -0
  45. sage/algebras/letterplace/free_algebra_letterplace.pxd +35 -0
  46. sage/algebras/letterplace/free_algebra_letterplace.pyx +914 -0
  47. sage/algebras/letterplace/letterplace_ideal.cpython-314-x86_64-linux-gnu.so +0 -0
  48. sage/algebras/letterplace/letterplace_ideal.pyx +408 -0
  49. sage/algebras/quatalg/all.py +2 -0
  50. sage/algebras/quatalg/quaternion_algebra.py +4778 -0
  51. sage/algebras/quatalg/quaternion_algebra_cython.cpython-314-x86_64-linux-gnu.so +0 -0
  52. sage/algebras/quatalg/quaternion_algebra_cython.pyx +261 -0
  53. sage/algebras/quatalg/quaternion_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
  54. sage/algebras/quatalg/quaternion_algebra_element.pxd +29 -0
  55. sage/algebras/quatalg/quaternion_algebra_element.pyx +2176 -0
  56. sage/all__sagemath_singular.py +11 -0
  57. sage/ext_data/all__sagemath_singular.py +1 -0
  58. sage/ext_data/singular/function_field/core.lib +98 -0
  59. sage/interfaces/all__sagemath_singular.py +1 -0
  60. sage/interfaces/singular.py +2835 -0
  61. sage/libs/all__sagemath_singular.py +1 -0
  62. sage/libs/singular/__init__.py +1 -0
  63. sage/libs/singular/decl.pxd +1168 -0
  64. sage/libs/singular/function.cpython-314-x86_64-linux-gnu.so +0 -0
  65. sage/libs/singular/function.pxd +87 -0
  66. sage/libs/singular/function.pyx +1901 -0
  67. sage/libs/singular/function_factory.py +61 -0
  68. sage/libs/singular/groebner_strategy.cpython-314-x86_64-linux-gnu.so +0 -0
  69. sage/libs/singular/groebner_strategy.pxd +22 -0
  70. sage/libs/singular/groebner_strategy.pyx +582 -0
  71. sage/libs/singular/option.cpython-314-x86_64-linux-gnu.so +0 -0
  72. sage/libs/singular/option.pyx +671 -0
  73. sage/libs/singular/polynomial.cpython-314-x86_64-linux-gnu.so +0 -0
  74. sage/libs/singular/polynomial.pxd +39 -0
  75. sage/libs/singular/polynomial.pyx +661 -0
  76. sage/libs/singular/ring.cpython-314-x86_64-linux-gnu.so +0 -0
  77. sage/libs/singular/ring.pxd +58 -0
  78. sage/libs/singular/ring.pyx +893 -0
  79. sage/libs/singular/singular.cpython-314-x86_64-linux-gnu.so +0 -0
  80. sage/libs/singular/singular.pxd +72 -0
  81. sage/libs/singular/singular.pyx +1944 -0
  82. sage/libs/singular/standard_options.py +145 -0
  83. sage/matrix/all__sagemath_singular.py +1 -0
  84. sage/matrix/matrix_mpolynomial_dense.cpython-314-x86_64-linux-gnu.so +0 -0
  85. sage/matrix/matrix_mpolynomial_dense.pxd +7 -0
  86. sage/matrix/matrix_mpolynomial_dense.pyx +615 -0
  87. sage/rings/all__sagemath_singular.py +1 -0
  88. sage/rings/function_field/all__sagemath_singular.py +1 -0
  89. sage/rings/function_field/derivations_polymod.py +911 -0
  90. sage/rings/function_field/element_polymod.cpython-314-x86_64-linux-gnu.so +0 -0
  91. sage/rings/function_field/element_polymod.pyx +406 -0
  92. sage/rings/function_field/function_field_polymod.py +2611 -0
  93. sage/rings/function_field/ideal_polymod.py +1775 -0
  94. sage/rings/function_field/order_polymod.py +1475 -0
  95. sage/rings/function_field/place_polymod.py +681 -0
  96. sage/rings/polynomial/all__sagemath_singular.py +1 -0
  97. sage/rings/polynomial/multi_polynomial_ideal_libsingular.cpython-314-x86_64-linux-gnu.so +0 -0
  98. sage/rings/polynomial/multi_polynomial_ideal_libsingular.pxd +5 -0
  99. sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx +339 -0
  100. sage/rings/polynomial/multi_polynomial_libsingular.cpython-314-x86_64-linux-gnu.so +0 -0
  101. sage/rings/polynomial/multi_polynomial_libsingular.pxd +30 -0
  102. sage/rings/polynomial/multi_polynomial_libsingular.pyx +6277 -0
  103. sage/rings/polynomial/plural.cpython-314-x86_64-linux-gnu.so +0 -0
  104. sage/rings/polynomial/plural.pxd +48 -0
  105. sage/rings/polynomial/plural.pyx +3171 -0
  106. sage/symbolic/all__sagemath_singular.py +1 -0
  107. sage/symbolic/comparison_impl.pxi +428 -0
  108. sage/symbolic/constants_c_impl.pxi +178 -0
  109. sage/symbolic/expression.cpython-314-x86_64-linux-gnu.so +0 -0
  110. sage/symbolic/expression.pxd +7 -0
  111. sage/symbolic/expression.pyx +14200 -0
  112. sage/symbolic/getitem_impl.pxi +202 -0
  113. sage/symbolic/pynac.pxi +572 -0
  114. sage/symbolic/pynac_constant_impl.pxi +133 -0
  115. sage/symbolic/pynac_function_impl.pxi +206 -0
  116. sage/symbolic/pynac_impl.pxi +2576 -0
  117. sage/symbolic/pynac_wrap.h +124 -0
  118. sage/symbolic/series_impl.pxi +272 -0
  119. sage/symbolic/substitution_map_impl.pxi +94 -0
  120. sage_wheels/bin/ESingular +0 -0
  121. sage_wheels/bin/Singular +0 -0
  122. sage_wheels/bin/TSingular +0 -0
  123. sage_wheels/lib/singular/MOD/cohomo.la +41 -0
  124. sage_wheels/lib/singular/MOD/cohomo.so +0 -0
  125. sage_wheels/lib/singular/MOD/customstd.la +41 -0
  126. sage_wheels/lib/singular/MOD/customstd.so +0 -0
  127. sage_wheels/lib/singular/MOD/freealgebra.la +41 -0
  128. sage_wheels/lib/singular/MOD/freealgebra.so +0 -0
  129. sage_wheels/lib/singular/MOD/gfanlib.la +41 -0
  130. sage_wheels/lib/singular/MOD/gfanlib.so +0 -0
  131. sage_wheels/lib/singular/MOD/gitfan.la +41 -0
  132. sage_wheels/lib/singular/MOD/gitfan.so +0 -0
  133. sage_wheels/lib/singular/MOD/interval.la +41 -0
  134. sage_wheels/lib/singular/MOD/interval.so +0 -0
  135. sage_wheels/lib/singular/MOD/loctriv.la +41 -0
  136. sage_wheels/lib/singular/MOD/loctriv.so +0 -0
  137. sage_wheels/lib/singular/MOD/machinelearning.la +41 -0
  138. sage_wheels/lib/singular/MOD/machinelearning.so +0 -0
  139. sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.la +41 -0
  140. sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.so +0 -0
  141. sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.la +41 -0
  142. sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.so +0 -0
  143. sage_wheels/lib/singular/MOD/p_Procs_FieldQ.la +41 -0
  144. sage_wheels/lib/singular/MOD/p_Procs_FieldQ.so +0 -0
  145. sage_wheels/lib/singular/MOD/p_Procs_FieldZp.la +41 -0
  146. sage_wheels/lib/singular/MOD/p_Procs_FieldZp.so +0 -0
  147. sage_wheels/lib/singular/MOD/partialgb.la +41 -0
  148. sage_wheels/lib/singular/MOD/partialgb.so +0 -0
  149. sage_wheels/lib/singular/MOD/pyobject.la +41 -0
  150. sage_wheels/lib/singular/MOD/pyobject.so +0 -0
  151. sage_wheels/lib/singular/MOD/singmathic.la +41 -0
  152. sage_wheels/lib/singular/MOD/singmathic.so +0 -0
  153. sage_wheels/lib/singular/MOD/sispasm.la +41 -0
  154. sage_wheels/lib/singular/MOD/sispasm.so +0 -0
  155. sage_wheels/lib/singular/MOD/subsets.la +41 -0
  156. sage_wheels/lib/singular/MOD/subsets.so +0 -0
  157. sage_wheels/lib/singular/MOD/systhreads.la +41 -0
  158. sage_wheels/lib/singular/MOD/systhreads.so +0 -0
  159. sage_wheels/lib/singular/MOD/syzextra.la +41 -0
  160. sage_wheels/lib/singular/MOD/syzextra.so +0 -0
  161. sage_wheels/libexec/singular/MOD/change_cost +0 -0
  162. sage_wheels/libexec/singular/MOD/singularsurf +11 -0
  163. sage_wheels/libexec/singular/MOD/singularsurf_jupyter +9 -0
  164. sage_wheels/libexec/singular/MOD/singularsurf_win +10 -0
  165. sage_wheels/libexec/singular/MOD/solve_IP +0 -0
  166. sage_wheels/libexec/singular/MOD/surfex +16 -0
  167. sage_wheels/libexec/singular/MOD/toric_ideal +0 -0
  168. sage_wheels/share/factory/gftables/10201 +342 -0
  169. sage_wheels/share/factory/gftables/1024 +37 -0
  170. sage_wheels/share/factory/gftables/10609 +356 -0
  171. sage_wheels/share/factory/gftables/11449 +384 -0
  172. sage_wheels/share/factory/gftables/11881 +398 -0
  173. sage_wheels/share/factory/gftables/121 +6 -0
  174. sage_wheels/share/factory/gftables/12167 +408 -0
  175. sage_wheels/share/factory/gftables/125 +7 -0
  176. sage_wheels/share/factory/gftables/12769 +428 -0
  177. sage_wheels/share/factory/gftables/128 +7 -0
  178. sage_wheels/share/factory/gftables/1331 +47 -0
  179. sage_wheels/share/factory/gftables/1369 +48 -0
  180. sage_wheels/share/factory/gftables/14641 +490 -0
  181. sage_wheels/share/factory/gftables/15625 +523 -0
  182. sage_wheels/share/factory/gftables/16 +3 -0
  183. sage_wheels/share/factory/gftables/16129 +540 -0
  184. sage_wheels/share/factory/gftables/16384 +549 -0
  185. sage_wheels/share/factory/gftables/16807 +563 -0
  186. sage_wheels/share/factory/gftables/1681 +58 -0
  187. sage_wheels/share/factory/gftables/169 +8 -0
  188. sage_wheels/share/factory/gftables/17161 +574 -0
  189. sage_wheels/share/factory/gftables/1849 +64 -0
  190. sage_wheels/share/factory/gftables/18769 +628 -0
  191. sage_wheels/share/factory/gftables/19321 +646 -0
  192. sage_wheels/share/factory/gftables/19683 +659 -0
  193. sage_wheels/share/factory/gftables/2048 +71 -0
  194. sage_wheels/share/factory/gftables/2187 +75 -0
  195. sage_wheels/share/factory/gftables/2197 +76 -0
  196. sage_wheels/share/factory/gftables/2209 +76 -0
  197. sage_wheels/share/factory/gftables/22201 +742 -0
  198. sage_wheels/share/factory/gftables/22801 +762 -0
  199. sage_wheels/share/factory/gftables/2401 +82 -0
  200. sage_wheels/share/factory/gftables/243 +11 -0
  201. sage_wheels/share/factory/gftables/24389 +815 -0
  202. sage_wheels/share/factory/gftables/24649 +824 -0
  203. sage_wheels/share/factory/gftables/25 +3 -0
  204. sage_wheels/share/factory/gftables/256 +11 -0
  205. sage_wheels/share/factory/gftables/26569 +888 -0
  206. sage_wheels/share/factory/gftables/27 +3 -0
  207. sage_wheels/share/factory/gftables/27889 +932 -0
  208. sage_wheels/share/factory/gftables/2809 +96 -0
  209. sage_wheels/share/factory/gftables/28561 +954 -0
  210. sage_wheels/share/factory/gftables/289 +12 -0
  211. sage_wheels/share/factory/gftables/29791 +995 -0
  212. sage_wheels/share/factory/gftables/29929 +1000 -0
  213. sage_wheels/share/factory/gftables/3125 +107 -0
  214. sage_wheels/share/factory/gftables/32 +4 -0
  215. sage_wheels/share/factory/gftables/32041 +1070 -0
  216. sage_wheels/share/factory/gftables/32761 +1094 -0
  217. sage_wheels/share/factory/gftables/32768 +1095 -0
  218. sage_wheels/share/factory/gftables/343 +14 -0
  219. sage_wheels/share/factory/gftables/3481 +118 -0
  220. sage_wheels/share/factory/gftables/361 +14 -0
  221. sage_wheels/share/factory/gftables/36481 +1218 -0
  222. sage_wheels/share/factory/gftables/3721 +126 -0
  223. sage_wheels/share/factory/gftables/37249 +1244 -0
  224. sage_wheels/share/factory/gftables/38809 +1296 -0
  225. sage_wheels/share/factory/gftables/39601 +1322 -0
  226. sage_wheels/share/factory/gftables/4 +3 -0
  227. sage_wheels/share/factory/gftables/4096 +139 -0
  228. sage_wheels/share/factory/gftables/44521 +1486 -0
  229. sage_wheels/share/factory/gftables/4489 +152 -0
  230. sage_wheels/share/factory/gftables/49 +4 -0
  231. sage_wheels/share/factory/gftables/4913 +166 -0
  232. sage_wheels/share/factory/gftables/49729 +1660 -0
  233. sage_wheels/share/factory/gftables/5041 +170 -0
  234. sage_wheels/share/factory/gftables/50653 +1691 -0
  235. sage_wheels/share/factory/gftables/512 +20 -0
  236. sage_wheels/share/factory/gftables/51529 +1720 -0
  237. sage_wheels/share/factory/gftables/52441 +1750 -0
  238. sage_wheels/share/factory/gftables/529 +20 -0
  239. sage_wheels/share/factory/gftables/5329 +180 -0
  240. sage_wheels/share/factory/gftables/54289 +1812 -0
  241. sage_wheels/share/factory/gftables/57121 +1906 -0
  242. sage_wheels/share/factory/gftables/58081 +1938 -0
  243. sage_wheels/share/factory/gftables/59049 +1971 -0
  244. sage_wheels/share/factory/gftables/6241 +210 -0
  245. sage_wheels/share/factory/gftables/625 +23 -0
  246. sage_wheels/share/factory/gftables/63001 +2102 -0
  247. sage_wheels/share/factory/gftables/64 +5 -0
  248. sage_wheels/share/factory/gftables/6561 +221 -0
  249. sage_wheels/share/factory/gftables/6859 +231 -0
  250. sage_wheels/share/factory/gftables/6889 +232 -0
  251. sage_wheels/share/factory/gftables/729 +27 -0
  252. sage_wheels/share/factory/gftables/7921 +266 -0
  253. sage_wheels/share/factory/gftables/8 +3 -0
  254. sage_wheels/share/factory/gftables/81 +5 -0
  255. sage_wheels/share/factory/gftables/8192 +276 -0
  256. sage_wheels/share/factory/gftables/841 +30 -0
  257. sage_wheels/share/factory/gftables/9 +3 -0
  258. sage_wheels/share/factory/gftables/9409 +316 -0
  259. sage_wheels/share/factory/gftables/961 +34 -0
  260. sage_wheels/share/info/singular.info +191898 -0
  261. sage_wheels/share/singular/LIB/GND.lib +1359 -0
  262. sage_wheels/share/singular/LIB/JMBTest.lib +976 -0
  263. sage_wheels/share/singular/LIB/JMSConst.lib +1363 -0
  264. sage_wheels/share/singular/LIB/KVequiv.lib +699 -0
  265. sage_wheels/share/singular/LIB/SingularityDBM.lib +491 -0
  266. sage_wheels/share/singular/LIB/VecField.lib +1542 -0
  267. sage_wheels/share/singular/LIB/absfact.lib +959 -0
  268. sage_wheels/share/singular/LIB/ainvar.lib +730 -0
  269. sage_wheels/share/singular/LIB/aksaka.lib +419 -0
  270. sage_wheels/share/singular/LIB/alexpoly.lib +2542 -0
  271. sage_wheels/share/singular/LIB/algebra.lib +1193 -0
  272. sage_wheels/share/singular/LIB/all.lib +136 -0
  273. sage_wheels/share/singular/LIB/arcpoint.lib +514 -0
  274. sage_wheels/share/singular/LIB/arnold.lib +4553 -0
  275. sage_wheels/share/singular/LIB/arnoldclassify.lib +2058 -0
  276. sage_wheels/share/singular/LIB/arr.lib +3486 -0
  277. sage_wheels/share/singular/LIB/assprimeszerodim.lib +755 -0
  278. sage_wheels/share/singular/LIB/autgradalg.lib +3361 -0
  279. sage_wheels/share/singular/LIB/bfun.lib +1964 -0
  280. sage_wheels/share/singular/LIB/bimodules.lib +774 -0
  281. sage_wheels/share/singular/LIB/brillnoether.lib +226 -0
  282. sage_wheels/share/singular/LIB/brnoeth.lib +5017 -0
  283. sage_wheels/share/singular/LIB/central.lib +2169 -0
  284. sage_wheels/share/singular/LIB/chern.lib +4162 -0
  285. sage_wheels/share/singular/LIB/cimonom.lib +571 -0
  286. sage_wheels/share/singular/LIB/cisimplicial.lib +1835 -0
  287. sage_wheels/share/singular/LIB/classify.lib +3239 -0
  288. sage_wheels/share/singular/LIB/classify2.lib +1462 -0
  289. sage_wheels/share/singular/LIB/classifyMapGerms.lib +1515 -0
  290. sage_wheels/share/singular/LIB/classify_aeq.lib +3253 -0
  291. sage_wheels/share/singular/LIB/classifyceq.lib +2092 -0
  292. sage_wheels/share/singular/LIB/classifyci.lib +1133 -0
  293. sage_wheels/share/singular/LIB/combinat.lib +91 -0
  294. sage_wheels/share/singular/LIB/compregb.lib +276 -0
  295. sage_wheels/share/singular/LIB/control.lib +1636 -0
  296. sage_wheels/share/singular/LIB/crypto.lib +3795 -0
  297. sage_wheels/share/singular/LIB/curveInv.lib +667 -0
  298. sage_wheels/share/singular/LIB/curvepar.lib +1817 -0
  299. sage_wheels/share/singular/LIB/customstd.lib +100 -0
  300. sage_wheels/share/singular/LIB/deRham.lib +5979 -0
  301. sage_wheels/share/singular/LIB/decodegb.lib +2134 -0
  302. sage_wheels/share/singular/LIB/decomp.lib +1655 -0
  303. sage_wheels/share/singular/LIB/deflation.lib +872 -0
  304. sage_wheels/share/singular/LIB/deform.lib +925 -0
  305. sage_wheels/share/singular/LIB/difform.lib +3055 -0
  306. sage_wheels/share/singular/LIB/divisors.lib +750 -0
  307. sage_wheels/share/singular/LIB/dmod.lib +5817 -0
  308. sage_wheels/share/singular/LIB/dmodapp.lib +3269 -0
  309. sage_wheels/share/singular/LIB/dmodideal.lib +1211 -0
  310. sage_wheels/share/singular/LIB/dmodloc.lib +2645 -0
  311. sage_wheels/share/singular/LIB/dmodvar.lib +818 -0
  312. sage_wheels/share/singular/LIB/dummy.lib +17 -0
  313. sage_wheels/share/singular/LIB/elim.lib +1009 -0
  314. sage_wheels/share/singular/LIB/ellipticcovers.lib +548 -0
  315. sage_wheels/share/singular/LIB/enumpoints.lib +146 -0
  316. sage_wheels/share/singular/LIB/equising.lib +2127 -0
  317. sage_wheels/share/singular/LIB/ffmodstd.lib +2384 -0
  318. sage_wheels/share/singular/LIB/ffsolve.lib +1289 -0
  319. sage_wheels/share/singular/LIB/findifs.lib +778 -0
  320. sage_wheels/share/singular/LIB/finitediff.lib +1768 -0
  321. sage_wheels/share/singular/LIB/finvar.lib +7989 -0
  322. sage_wheels/share/singular/LIB/fpadim.lib +2429 -0
  323. sage_wheels/share/singular/LIB/fpalgebras.lib +1666 -0
  324. sage_wheels/share/singular/LIB/fpaprops.lib +1462 -0
  325. sage_wheels/share/singular/LIB/freegb.lib +3853 -0
  326. sage_wheels/share/singular/LIB/general.lib +1350 -0
  327. sage_wheels/share/singular/LIB/gfan.lib +1768 -0
  328. sage_wheels/share/singular/LIB/gitfan.lib +3130 -0
  329. sage_wheels/share/singular/LIB/gkdim.lib +99 -0
  330. sage_wheels/share/singular/LIB/gmspoly.lib +589 -0
  331. sage_wheels/share/singular/LIB/gmssing.lib +1739 -0
  332. sage_wheels/share/singular/LIB/goettsche.lib +909 -0
  333. sage_wheels/share/singular/LIB/graal.lib +1366 -0
  334. sage_wheels/share/singular/LIB/gradedModules.lib +2541 -0
  335. sage_wheels/share/singular/LIB/graphics.lib +360 -0
  336. sage_wheels/share/singular/LIB/grobcov.lib +7706 -0
  337. sage_wheels/share/singular/LIB/groups.lib +1123 -0
  338. sage_wheels/share/singular/LIB/grwalk.lib +507 -0
  339. sage_wheels/share/singular/LIB/hdepth.lib +194 -0
  340. sage_wheels/share/singular/LIB/help.cnf +57 -0
  341. sage_wheels/share/singular/LIB/hess.lib +1946 -0
  342. sage_wheels/share/singular/LIB/hnoether.lib +4292 -0
  343. sage_wheels/share/singular/LIB/hodge.lib +400 -0
  344. sage_wheels/share/singular/LIB/homolog.lib +1965 -0
  345. sage_wheels/share/singular/LIB/hyperel.lib +975 -0
  346. sage_wheels/share/singular/LIB/inout.lib +679 -0
  347. sage_wheels/share/singular/LIB/integralbasis.lib +6224 -0
  348. sage_wheels/share/singular/LIB/interval.lib +1418 -0
  349. sage_wheels/share/singular/LIB/intprog.lib +778 -0
  350. sage_wheels/share/singular/LIB/invar.lib +443 -0
  351. sage_wheels/share/singular/LIB/involut.lib +980 -0
  352. sage_wheels/share/singular/LIB/jacobson.lib +1215 -0
  353. sage_wheels/share/singular/LIB/kskernel.lib +534 -0
  354. sage_wheels/share/singular/LIB/latex.lib +3146 -0
  355. sage_wheels/share/singular/LIB/lejeune.lib +651 -0
  356. sage_wheels/share/singular/LIB/linalg.lib +2040 -0
  357. sage_wheels/share/singular/LIB/locnormal.lib +212 -0
  358. sage_wheels/share/singular/LIB/lrcalc.lib +526 -0
  359. sage_wheels/share/singular/LIB/makedbm.lib +294 -0
  360. sage_wheels/share/singular/LIB/mathml.lib +813 -0
  361. sage_wheels/share/singular/LIB/matrix.lib +1372 -0
  362. sage_wheels/share/singular/LIB/maxlike.lib +1132 -0
  363. sage_wheels/share/singular/LIB/methods.lib +212 -0
  364. sage_wheels/share/singular/LIB/moddiq.lib +322 -0
  365. sage_wheels/share/singular/LIB/modfinduni.lib +181 -0
  366. sage_wheels/share/singular/LIB/modnormal.lib +218 -0
  367. sage_wheels/share/singular/LIB/modprimdec.lib +1278 -0
  368. sage_wheels/share/singular/LIB/modquotient.lib +269 -0
  369. sage_wheels/share/singular/LIB/modstd.lib +1024 -0
  370. sage_wheels/share/singular/LIB/modular.lib +545 -0
  371. sage_wheels/share/singular/LIB/modules.lib +2561 -0
  372. sage_wheels/share/singular/LIB/modwalk.lib +609 -0
  373. sage_wheels/share/singular/LIB/mondromy.lib +1016 -0
  374. sage_wheels/share/singular/LIB/monomialideal.lib +3851 -0
  375. sage_wheels/share/singular/LIB/mprimdec.lib +2353 -0
  376. sage_wheels/share/singular/LIB/mregular.lib +1863 -0
  377. sage_wheels/share/singular/LIB/multigrading.lib +5629 -0
  378. sage_wheels/share/singular/LIB/ncHilb.lib +777 -0
  379. sage_wheels/share/singular/LIB/ncModslimgb.lib +791 -0
  380. sage_wheels/share/singular/LIB/ncalg.lib +16311 -0
  381. sage_wheels/share/singular/LIB/ncall.lib +31 -0
  382. sage_wheels/share/singular/LIB/ncdecomp.lib +468 -0
  383. sage_wheels/share/singular/LIB/ncfactor.lib +13371 -0
  384. sage_wheels/share/singular/LIB/ncfrac.lib +1023 -0
  385. sage_wheels/share/singular/LIB/nchilbert.lib +448 -0
  386. sage_wheels/share/singular/LIB/nchomolog.lib +759 -0
  387. sage_wheels/share/singular/LIB/ncloc.lib +361 -0
  388. sage_wheels/share/singular/LIB/ncpreim.lib +795 -0
  389. sage_wheels/share/singular/LIB/ncrat.lib +2849 -0
  390. sage_wheels/share/singular/LIB/nctools.lib +1887 -0
  391. sage_wheels/share/singular/LIB/nets.lib +1456 -0
  392. sage_wheels/share/singular/LIB/nfmodstd.lib +1000 -0
  393. sage_wheels/share/singular/LIB/nfmodsyz.lib +732 -0
  394. sage_wheels/share/singular/LIB/noether.lib +1106 -0
  395. sage_wheels/share/singular/LIB/normal.lib +8700 -0
  396. sage_wheels/share/singular/LIB/normaliz.lib +2226 -0
  397. sage_wheels/share/singular/LIB/ntsolve.lib +362 -0
  398. sage_wheels/share/singular/LIB/numerAlg.lib +560 -0
  399. sage_wheels/share/singular/LIB/numerDecom.lib +2261 -0
  400. sage_wheels/share/singular/LIB/olga.lib +1933 -0
  401. sage_wheels/share/singular/LIB/orbitparam.lib +351 -0
  402. sage_wheels/share/singular/LIB/parallel.lib +319 -0
  403. sage_wheels/share/singular/LIB/paraplanecurves.lib +3110 -0
  404. sage_wheels/share/singular/LIB/perron.lib +202 -0
  405. sage_wheels/share/singular/LIB/pfd.lib +2223 -0
  406. sage_wheels/share/singular/LIB/phindex.lib +642 -0
  407. sage_wheels/share/singular/LIB/pointid.lib +673 -0
  408. sage_wheels/share/singular/LIB/polybori.lib +1430 -0
  409. sage_wheels/share/singular/LIB/polyclass.lib +525 -0
  410. sage_wheels/share/singular/LIB/polylib.lib +1174 -0
  411. sage_wheels/share/singular/LIB/polymake.lib +1902 -0
  412. sage_wheels/share/singular/LIB/presolve.lib +1533 -0
  413. sage_wheels/share/singular/LIB/primdec.lib +9576 -0
  414. sage_wheels/share/singular/LIB/primdecint.lib +1782 -0
  415. sage_wheels/share/singular/LIB/primitiv.lib +401 -0
  416. sage_wheels/share/singular/LIB/puiseuxexpansions.lib +1631 -0
  417. sage_wheels/share/singular/LIB/purityfiltration.lib +960 -0
  418. sage_wheels/share/singular/LIB/qhmoduli.lib +1561 -0
  419. sage_wheels/share/singular/LIB/qmatrix.lib +293 -0
  420. sage_wheels/share/singular/LIB/random.lib +455 -0
  421. sage_wheels/share/singular/LIB/ratgb.lib +489 -0
  422. sage_wheels/share/singular/LIB/realclassify.lib +5759 -0
  423. sage_wheels/share/singular/LIB/realizationMatroids.lib +772 -0
  424. sage_wheels/share/singular/LIB/realrad.lib +1197 -0
  425. sage_wheels/share/singular/LIB/recover.lib +2628 -0
  426. sage_wheels/share/singular/LIB/redcgs.lib +3984 -0
  427. sage_wheels/share/singular/LIB/reesclos.lib +465 -0
  428. sage_wheels/share/singular/LIB/resbinomial.lib +2802 -0
  429. sage_wheels/share/singular/LIB/resgraph.lib +789 -0
  430. sage_wheels/share/singular/LIB/resjung.lib +820 -0
  431. sage_wheels/share/singular/LIB/resolve.lib +5110 -0
  432. sage_wheels/share/singular/LIB/resources.lib +170 -0
  433. sage_wheels/share/singular/LIB/reszeta.lib +5473 -0
  434. sage_wheels/share/singular/LIB/ring.lib +1328 -0
  435. sage_wheels/share/singular/LIB/ringgb.lib +343 -0
  436. sage_wheels/share/singular/LIB/rinvar.lib +1153 -0
  437. sage_wheels/share/singular/LIB/rootisolation.lib +1481 -0
  438. sage_wheels/share/singular/LIB/rootsmr.lib +709 -0
  439. sage_wheels/share/singular/LIB/rootsur.lib +886 -0
  440. sage_wheels/share/singular/LIB/rstandard.lib +607 -0
  441. sage_wheels/share/singular/LIB/rwalk.lib +336 -0
  442. sage_wheels/share/singular/LIB/sagbi.lib +1353 -0
  443. sage_wheels/share/singular/LIB/sagbiNormaliz.lib +1622 -0
  444. sage_wheels/share/singular/LIB/sagbiNormaliz0.lib +1498 -0
  445. sage_wheels/share/singular/LIB/sagbigrob.lib +449 -0
  446. sage_wheels/share/singular/LIB/schreyer.lib +321 -0
  447. sage_wheels/share/singular/LIB/schubert.lib +2551 -0
  448. sage_wheels/share/singular/LIB/sets.lib +524 -0
  449. sage_wheels/share/singular/LIB/sheafcoh.lib +1663 -0
  450. sage_wheels/share/singular/LIB/signcond.lib +437 -0
  451. sage_wheels/share/singular/LIB/sing.lib +1094 -0
  452. sage_wheels/share/singular/LIB/sing4ti2.lib +419 -0
  453. sage_wheels/share/singular/LIB/solve.lib +2243 -0
  454. sage_wheels/share/singular/LIB/spcurve.lib +1077 -0
  455. sage_wheels/share/singular/LIB/spectrum.lib +62 -0
  456. sage_wheels/share/singular/LIB/sresext.lib +757 -0
  457. sage_wheels/share/singular/LIB/ssi.lib +143 -0
  458. sage_wheels/share/singular/LIB/standard.lib +2769 -0
  459. sage_wheels/share/singular/LIB/stanleyreisner.lib +473 -0
  460. sage_wheels/share/singular/LIB/stdmodule.lib +547 -0
  461. sage_wheels/share/singular/LIB/stratify.lib +1070 -0
  462. sage_wheels/share/singular/LIB/surf.lib +506 -0
  463. sage_wheels/share/singular/LIB/surf_jupyter.lib +223 -0
  464. sage_wheels/share/singular/LIB/surfacesignature.lib +522 -0
  465. sage_wheels/share/singular/LIB/surfex.lib +1462 -0
  466. sage_wheels/share/singular/LIB/swalk.lib +877 -0
  467. sage_wheels/share/singular/LIB/symodstd.lib +1570 -0
  468. sage_wheels/share/singular/LIB/systhreads.lib +74 -0
  469. sage_wheels/share/singular/LIB/tasks.lib +1324 -0
  470. sage_wheels/share/singular/LIB/tateProdCplxNegGrad.lib +2412 -0
  471. sage_wheels/share/singular/LIB/teachstd.lib +858 -0
  472. sage_wheels/share/singular/LIB/template.lib +116 -0
  473. sage_wheels/share/singular/LIB/toric.lib +1119 -0
  474. sage_wheels/share/singular/LIB/transformation.lib +116 -0
  475. sage_wheels/share/singular/LIB/triang.lib +1197 -0
  476. sage_wheels/share/singular/LIB/tropical.lib +8741 -0
  477. sage_wheels/share/singular/LIB/tropicalEllipticCovers.lib +2922 -0
  478. sage_wheels/share/singular/LIB/tropicalNewton.lib +1128 -0
  479. sage_wheels/share/singular/LIB/tst.lib +1108 -0
  480. sage_wheels/share/singular/LIB/weierstr.lib +241 -0
  481. sage_wheels/share/singular/LIB/zeroset.lib +1478 -0
  482. sage_wheels/share/singular/emacs/.emacs-general +184 -0
  483. sage_wheels/share/singular/emacs/.emacs-singular +234 -0
  484. sage_wheels/share/singular/emacs/COPYING +44 -0
  485. sage_wheels/share/singular/emacs/cmd-cmpl.el +241 -0
  486. sage_wheels/share/singular/emacs/ex-cmpl.el +1681 -0
  487. sage_wheels/share/singular/emacs/hlp-cmpl.el +4318 -0
  488. sage_wheels/share/singular/emacs/lib-cmpl.el +179 -0
  489. sage_wheels/share/singular/emacs/singular.el +4273 -0
  490. sage_wheels/share/singular/emacs/singular.xpm +39 -0
  491. sage_wheels/share/singular/singular.idx +5002 -0
@@ -0,0 +1,1580 @@
1
+ # sage_setup: distribution = sagemath-singular
2
+ """
3
+ Fusion rings
4
+ """
5
+ # ****************************************************************************
6
+ # Copyright (C) 2019 Daniel Bump <bump at match.stanford.edu>
7
+ # Guillermo Aboumrad <gh_willieab>
8
+ # Travis Scrimshaw <tcscrims at gmail.com>
9
+ # Nicolas Thiery <nthiery at users.sf.net>
10
+ # 2022 Guillermo Aboumrad <gh_willieab>
11
+ #
12
+ # This program is free software: you can redistribute it and/or modify
13
+ # it under the terms of the GNU General Public License as published by
14
+ # the Free Software Foundation, either version 2 of the License, or
15
+ # (at your option) any later version.
16
+ # https://www.gnu.org/licenses/
17
+ # ****************************************************************************
18
+
19
+ from itertools import product, zip_longest
20
+ from multiprocessing import Pool, set_start_method
21
+ from sage.combinat.q_analogues import q_int
22
+ from sage.algebras.fusion_rings.fast_parallel_fusion_ring_braid_repn import (
23
+ executor,
24
+ _unflatten_entries
25
+ )
26
+ from sage.combinat.root_system.weyl_characters import WeylCharacterRing
27
+ from sage.matrix.constructor import matrix
28
+ from sage.matrix.special import diagonal_matrix
29
+ from sage.misc.cachefunc import cached_method
30
+ from sage.misc.misc import inject_variable
31
+ from sage.rings.integer_ring import ZZ
32
+ from sage.rings.number_field.number_field import CyclotomicField
33
+ from sage.rings.qqbar import QQbar
34
+
35
+
36
+ class FusionRing(WeylCharacterRing):
37
+ r"""
38
+ Return the Fusion Ring (Verlinde Algebra) of level ``k``.
39
+
40
+ INPUT:
41
+
42
+ - ``ct`` -- the Cartan type of a simple (finite-dimensional) Lie algebra
43
+ - ``k`` -- nonnegative integer
44
+ - ``conjugate`` -- (default: ``False``) set ``True`` to obtain
45
+ the complex conjugate ring
46
+ - ``cyclotomic_order`` -- (default: computed depending on ``ct`` and ``k``)
47
+ - ``fusion_labels`` -- (default: ``None``) either a tuple of strings to use as labels of the
48
+ basis of simple objects, or a string from which the labels will be
49
+ constructed
50
+ - ``inject_variables`` -- (default: ``False``) use with ``fusion_labels``.
51
+ If ``inject_variables`` is ``True``, the fusion labels will be variables
52
+ that can be accessed from the command line
53
+
54
+ The cyclotomic order is an integer `N` such that all computations
55
+ will return elements of the cyclotomic field of `N`-th roots of unity.
56
+ Normally you will never need to change this but consider changing it
57
+ if :meth:`root_of_unity` raises a :exc:`ValueError`.
58
+
59
+ This algebra has a basis (sometimes called *primary fields* but here
60
+ called *simple objects*) indexed by the weights of level `\leq k`.
61
+ These arise as the fusion algebras of Wess-Zumino-Witten (WZW) conformal
62
+ field theories, or as Grothendieck groups of tilting modules for quantum
63
+ groups at roots of unity. The :class:`FusionRing` class is implemented as
64
+ a variant of the :class:`WeylCharacterRing`.
65
+
66
+ REFERENCES:
67
+
68
+ - [BaKi2001]_ Chapter 3
69
+ - [DFMS1996]_ Chapter 16
70
+ - [EGNO2015]_ Chapter 8
71
+ - [Feingold2004]_
72
+ - [Fuchs1994]_
73
+ - [Row2006]_
74
+ - [Walton1990]_
75
+ - [Wan2010]_
76
+
77
+ EXAMPLES::
78
+
79
+ sage: A22 = FusionRing("A2", 2)
80
+ sage: [f1, f2] = A22.fundamental_weights()
81
+ sage: M = [A22(x) for x in [0*f1, 2*f1, 2*f2, f1+f2, f2, f1]]
82
+ sage: [M[3] * x for x in M]
83
+ [A22(1,1),
84
+ A22(0,1),
85
+ A22(1,0),
86
+ A22(0,0) + A22(1,1),
87
+ A22(0,1) + A22(2,0),
88
+ A22(1,0) + A22(0,2)]
89
+
90
+ You may assign your own labels to the basis elements. In the next
91
+ example, we create the `SO(5)` fusion ring of level `2`, check the
92
+ weights of the basis elements, then assign new labels to them while
93
+ injecting them into the global namespace::
94
+
95
+ sage: B22 = FusionRing("B2", 2)
96
+ sage: b = [B22(x) for x in B22.get_order()]; b
97
+ [B22(0,0), B22(1,0), B22(0,1), B22(2,0), B22(1,1), B22(0,2)]
98
+ sage: [x.weight() for x in b]
99
+ [(0, 0), (1, 0), (1/2, 1/2), (2, 0), (3/2, 1/2), (1, 1)]
100
+ sage: B22.fusion_labels(['I0', 'Y1', 'X', 'Z', 'Xp', 'Y2'], inject_variables=True)
101
+ sage: b = [B22(x) for x in B22.get_order()]; b
102
+ [I0, Y1, X, Z, Xp, Y2]
103
+ sage: [(x, x.weight()) for x in b]
104
+ [(I0, (0, 0)),
105
+ (Y1, (1, 0)),
106
+ (X, (1/2, 1/2)),
107
+ (Z, (2, 0)),
108
+ (Xp, (3/2, 1/2)),
109
+ (Y2, (1, 1))]
110
+ sage: X * Y1
111
+ X + Xp
112
+ sage: Z * Z
113
+ I0
114
+
115
+ A fixed order of the basis keys is available with :meth:`get_order`.
116
+ This is the order used by methods such as :meth:`s_matrix`. You may
117
+ use :meth:`CombinatorialFreeModule.set_order` to reorder the basis::
118
+
119
+ sage: B22.set_order([x.weight() for x in [I0, Y1, Y2, X, Xp, Z]])
120
+ sage: [B22(x) for x in B22.get_order()]
121
+ [I0, Y1, Y2, X, Xp, Z]
122
+
123
+ To reset the labels, you may run :meth:`fusion_labels` with no parameter::
124
+
125
+ sage: B22.fusion_labels()
126
+ sage: [B22(x) for x in B22.get_order()]
127
+ [B22(0,0), B22(1,0), B22(0,2), B22(0,1), B22(1,1), B22(2,0)]
128
+
129
+ To reset the order to the default, simply set it to the list of basis
130
+ element keys::
131
+
132
+ sage: B22.set_order(B22.basis().keys().list())
133
+ sage: [B22(x) for x in B22.get_order()]
134
+ [B22(0,0), B22(1,0), B22(0,1), B22(2,0), B22(1,1), B22(0,2)]
135
+
136
+ The fusion ring has a number of methods that reflect its role
137
+ as the Grothendieck ring of a *modular tensor category* (MTC). These
138
+ include twist methods :meth:`Element.twist` and :meth:`Element.ribbon`
139
+ for its elements related to the ribbon structure, and the
140
+ `S`-matrix :meth:`s_ij`.
141
+
142
+ There are two natural normalizations of the `S`-matrix. Both
143
+ are explained in Chapter 3 of [BaKi2001]_. The one that is computed
144
+ by the method :meth:`s_matrix`, or whose individual entries
145
+ are computed by :meth:`s_ij` is denoted `\tilde{s}` in
146
+ [BaKi2001]_. It is not unitary.
147
+
148
+ The unitary `S`-matrix is `s=D^{-1/2}\tilde{s}` where
149
+
150
+ .. MATH::
151
+
152
+ D = \sum_V d_i(V)^2.
153
+
154
+ The sum is over all simple objects `V` with
155
+ `d_i(V)` the *quantum dimension*. We will call quantity `D`
156
+ the *global quantum dimension* and `\sqrt{D}` the
157
+ *total quantum order*. They are computed by :meth:`global_q_dimension`
158
+ and :meth:`total_q_order`. The unitary `S`-matrix `s` may be obtained
159
+ using :meth:`s_matrix` with the option ``unitary=True``.
160
+
161
+ Let us check the Verlinde formula, which is [DFMS1996]_ (16.3). This
162
+ famous identity states that
163
+
164
+ .. MATH::
165
+
166
+ N^k_{ij} = \sum_l \frac{s(i, \ell)\, s(j, \ell)\, \overline{s(k, \ell)}}{s(I, \ell)},
167
+
168
+ where `N^k_{ij}` are the fusion coefficients, i.e. the structure
169
+ constants of the fusion ring, and ``I`` is the unit object.
170
+ The `S`-matrix has the property that if `i*` denotes the dual
171
+ object of `i`, implemented in Sage as ``i.dual()``, then
172
+
173
+ .. MATH::
174
+
175
+ s(i*, j) = s(i, j*) = \overline{s(i, j)}.
176
+
177
+ This is equation (16.5) in [DFMS1996]_. Thus with `N_{ijk}=N^{k*}_{ij}`
178
+ the Verlinde formula is equivalent to
179
+
180
+ .. MATH::
181
+
182
+ N_{ijk} = \sum_l \frac{s(i, \ell)\, s(j, \ell)\, s(k, \ell)}{s(I, \ell)},
183
+
184
+ In this formula `s` is the normalized unitary `S`-matrix
185
+ denoted `s` in [BaKi2001]_. We may define a function that
186
+ corresponds to the right-hand side, except using
187
+ `\tilde{s}` instead of `s`::
188
+
189
+ sage: def V(i, j, k):
190
+ ....: R = i.parent()
191
+ ....: return sum(R.s_ij(i, l) * R.s_ij(j, l) * R.s_ij(k, l) / R.s_ij(R.one(), l)
192
+ ....: for l in R.basis())
193
+
194
+ This does not produce ``self.N_ijk(i, j, k)`` exactly, because of the
195
+ missing normalization factor. The following code to check the
196
+ Verlinde formula takes this into account::
197
+
198
+ sage: def test_verlinde(R):
199
+ ....: b0 = R.one()
200
+ ....: c = R.global_q_dimension()
201
+ ....: return all(V(i, j, k) == c * R.N_ijk(i, j, k) for i in R.basis()
202
+ ....: for j in R.basis() for k in R.basis())
203
+
204
+ Every fusion ring should pass this test::
205
+
206
+ sage: test_verlinde(FusionRing("A2", 1))
207
+ True
208
+ sage: test_verlinde(FusionRing("B4", 2)) # long time (.56s)
209
+ True
210
+
211
+ As an exercise, the reader may verify the examples in
212
+ Section 5.3 of [RoStWa2009]_. Here we check the example
213
+ of the Ising modular tensor category, which is related
214
+ to the Belavin, Polyakov, Zamolodchikov minimal model `M(4, 3)`
215
+ or to an `E_8` coset model. See [DFMS1996]_ Sections 7.4.2 and 18.4.1.
216
+ [RoStWa2009]_ Example 5.3.4 tells us how to
217
+ construct it as the conjugate of the `E_8` level 2
218
+ :class:`FusionRing`::
219
+
220
+ sage: I = FusionRing("E8", 2, conjugate=True)
221
+ sage: I.fusion_labels(["i0", "p", "s"], inject_variables=True)
222
+ sage: b = I.basis().list(); b
223
+ [i0, p, s]
224
+ sage: Matrix([[x*y for x in b] for y in b]) # long time (.93s)
225
+ [ i0 p s]
226
+ [ p i0 s]
227
+ [ s s i0 + p]
228
+ sage: [x.twist() for x in b]
229
+ [0, 1, 1/8]
230
+ sage: [x.ribbon() for x in b]
231
+ [1, -1, zeta128^8]
232
+ sage: [I.r_matrix(i, j, k) for (i, j, k) in [(s, s, i0), (p, p, i0), (p, s, s), (s, p, s), (s, s, p)]]
233
+ [-zeta128^56, -1, -zeta128^32, -zeta128^32, zeta128^24]
234
+ sage: I.r_matrix(s, s, i0) == I.root_of_unity(-1/8)
235
+ True
236
+ sage: I.global_q_dimension()
237
+ 4
238
+ sage: I.total_q_order()
239
+ 2
240
+ sage: [x.q_dimension()^2 for x in b]
241
+ [1, 1, 2]
242
+ sage: I.s_matrix()
243
+ [ 1 1 -zeta128^48 + zeta128^16]
244
+ [ 1 1 zeta128^48 - zeta128^16]
245
+ [-zeta128^48 + zeta128^16 zeta128^48 - zeta128^16 0]
246
+ sage: I.s_matrix().apply_map(lambda x:x^2)
247
+ [1 1 2]
248
+ [1 1 2]
249
+ [2 2 0]
250
+
251
+ The term *modular tensor category* refers to the fact that associated
252
+ with the category there is a projective representation of the modular
253
+ group `SL(2, \ZZ)`. We recall that this group is generated by
254
+
255
+ .. MATH::
256
+
257
+ S = \begin{pmatrix} & -1\\1\end{pmatrix}, \qquad
258
+ T = \begin{pmatrix} 1 & 1\\ &1 \end{pmatrix}
259
+
260
+ subject to the relations `(ST)^3 = S^2`, `S^2T = TS^2`, and `S^4 = I`.
261
+ Let `s` be the normalized `S`-matrix, and
262
+ `t` the diagonal matrix whose entries are the twists of the simple
263
+ objects. Let `s` the unitary `S`-matrix and `t` the matrix of twists,
264
+ and `C` the conjugation matrix :meth:`conj_matrix`. Let
265
+
266
+ .. MATH::
267
+
268
+ D_+ = \sum_i d_i^2 \theta_i, \qquad D_- = d_i^2 \theta_i^{-1},
269
+
270
+ where `d_i` and `\theta_i` are the quantum dimensions and twists of the
271
+ simple objects. Let `c` be the Virasoro central charge, a rational number
272
+ that is computed in :meth:`virasoro_central_charge`. It is known that
273
+
274
+ .. MATH::
275
+
276
+ \sqrt{\frac{D_+}{D_-}} = e^{i\pi c/4}.
277
+
278
+ It is proved in [BaKi2001]_ Equation (3.1.17) that
279
+
280
+ .. MATH::
281
+
282
+ (st)^3 = e^{i\pi c/4} s^2, \qquad
283
+ s^2 = C, \qquad C^2 = 1, \qquad Ct = tC.
284
+
285
+ Therefore `S \mapsto s, T \mapsto t` is a projective representation
286
+ of `SL(2, \ZZ)`. Let us confirm these identities for the Fibonacci MTC
287
+ ``FusionRing("G2", 1)``::
288
+
289
+ sage: R = FusionRing("G2", 1)
290
+ sage: S = R.s_matrix(unitary=True)
291
+ sage: T = R.twists_matrix()
292
+ sage: C = R.conj_matrix()
293
+ sage: c = R.virasoro_central_charge(); c
294
+ 14/5
295
+ sage: (S*T)^3 == R.root_of_unity(c/4) * S^2
296
+ True
297
+ sage: S^2 == C
298
+ True
299
+ sage: C*T == T*C
300
+ True
301
+ """
302
+ @staticmethod
303
+ def __classcall__(cls, ct, k, base_ring=ZZ, prefix=None, style='coroots', conjugate=False, cyclotomic_order=None, fusion_labels=None, inject_variables=False):
304
+ """
305
+ Normalize input to ensure a unique representation.
306
+
307
+ TESTS::
308
+
309
+ sage: F1 = FusionRing('B3', 2)
310
+ sage: F2 = FusionRing(CartanType('B3'), QQ(2), ZZ)
311
+ sage: F3 = FusionRing(CartanType('B3'), int(2), style='coroots')
312
+ sage: F1 is F2 and F2 is F3
313
+ True
314
+
315
+ sage: A23 = FusionRing('A2', 3)
316
+ sage: TestSuite(A23).run()
317
+
318
+ sage: B22 = FusionRing('B2', 2)
319
+ sage: TestSuite(B22).run()
320
+
321
+ sage: C31 = FusionRing('C3', 1)
322
+ sage: TestSuite(C31).run()
323
+
324
+ sage: D41 = FusionRing('D4', 1)
325
+ sage: TestSuite(D41).run()
326
+
327
+ sage: G22 = FusionRing('G2', 2)
328
+ sage: TestSuite(G22).run()
329
+
330
+ sage: F41 = FusionRing('F4', 1)
331
+ sage: TestSuite(F41).run()
332
+
333
+ sage: E61 = FusionRing('E6', 1)
334
+ sage: TestSuite(E61).run()
335
+
336
+ sage: E71 = FusionRing('E7', 1)
337
+ sage: TestSuite(E71).run()
338
+
339
+ sage: E81 = FusionRing('E8', 1)
340
+ sage: TestSuite(E81).run()
341
+ """
342
+ return super().__classcall__(cls, ct, base_ring=base_ring,
343
+ prefix=prefix, style=style, k=k,
344
+ conjugate=conjugate,
345
+ cyclotomic_order=cyclotomic_order,
346
+ fusion_labels=fusion_labels,
347
+ inject_variables=inject_variables)
348
+
349
+ def _test_verlinde(self, **options):
350
+ """
351
+ Check the Verlinde formula for this :class:`FusionRing` instance.
352
+
353
+ EXAMPLES::
354
+
355
+ sage: G22 = FusionRing("G2", 2)
356
+ sage: G22._test_verlinde()
357
+ """
358
+ tester = self._tester(**options)
359
+ c = self.global_q_dimension()
360
+ i0 = self.one()
361
+ from sage.misc.misc import some_tuples
362
+ B = self.basis()
363
+ for x, y, z in some_tuples(B, 3, tester._max_runs):
364
+ v = sum(self.s_ij(x, w) * self.s_ij(y, w) * self.s_ij(z, w) / self.s_ij(i0, w) for w in B)
365
+ tester.assertEqual(v, c * self.N_ijk(x, y, z))
366
+
367
+ def _test_total_q_order(self, **options):
368
+ r"""
369
+ Check that the total quantum order is real and positive.
370
+
371
+ The total quantum order is the positive square root
372
+ of the global quantum dimension. This indirectly test the
373
+ Virasoro central charge.
374
+
375
+ EXAMPLES::
376
+
377
+ sage: G22 = FusionRing("G2", 2)
378
+ sage: G22._test_total_q_order()
379
+ """
380
+ tester = self._tester(**options)
381
+ tqo = self.total_q_order(base_coercion=False)
382
+ tester.assertTrue(tqo.is_real_positive())
383
+ tester.assertEqual(tqo**2, self.global_q_dimension(base_coercion=False))
384
+
385
+ def test_braid_representation(self, max_strands=6, anyon=None):
386
+ """
387
+ Check that we can compute valid braid group representations.
388
+
389
+ INPUT:
390
+
391
+ - ``max_strands`` -- (default: 6) maximum number of braid group strands
392
+ - ``anyon`` -- (optional) run this test on this particular simple object
393
+
394
+ Create a braid group representation using :meth:`get_braid_generators`
395
+ and confirms the braid relations. This test indirectly partially
396
+ verifies the correctness of the orthogonal F-matrix solver. If the
397
+ code were incorrect the method would not be deterministic because the
398
+ fusing anyon is chosen randomly. (A different choice is made for each
399
+ number of strands tested.) However the doctest is deterministic since
400
+ it will always return ``True``. If the anyon parameter is omitted,
401
+ a random anyon is tested for each number of strands up to ``max_strands``.
402
+
403
+ EXAMPLES::
404
+
405
+ sage: A21 = FusionRing("A2", 1)
406
+ sage: A21.test_braid_representation(max_strands=4)
407
+ True
408
+ sage: F41 = FusionRing("F4", 1) # long time
409
+ sage: F41.test_braid_representation() # long time
410
+ True
411
+ """
412
+ if not self.is_multiplicity_free(): # Braid group representation is not available if self is not multiplicity free
413
+ raise NotImplementedError("only implemented for multiplicity free fusion rings")
414
+ b = self.basis()
415
+ results = []
416
+ # Test with different numbers of strands
417
+ for n_strands in range(3, max_strands+1):
418
+ # Randomly select a fusing anyon. Skip the identity element, since
419
+ # its braiding matrices are trivial
420
+ if anyon is not None:
421
+ a = anyon
422
+ else:
423
+ while True:
424
+ a = b.random_element()
425
+ if a != self.one():
426
+ break
427
+ pow = a ** n_strands
428
+ d = pow.monomials()[0]
429
+ # Try to find 'interesting' braid group reps i.e. skip 1-d reps
430
+ for k, v in pow.monomial_coefficients().items():
431
+ if v > 1:
432
+ d = self(k)
433
+ break
434
+ comp_basis, sig = self.get_braid_generators(a, d, n_strands, verbose=False)
435
+ results.append(len(comp_basis) > 0)
436
+ results.append(self.gens_satisfy_braid_gp_rels(sig))
437
+ return all(results)
438
+
439
+ def fusion_labels(self, labels=None, inject_variables=False):
440
+ r"""
441
+ Set the labels of the basis.
442
+
443
+ INPUT:
444
+
445
+ - ``labels`` -- (default: ``None``) a list of strings or string
446
+ - ``inject_variables`` -- boolean (default: ``False``); if ``True``,
447
+ then inject the variable names into the global namespace; note that
448
+ this could override objects already defined
449
+
450
+ If ``labels`` is a list, the length of the list must equal the
451
+ number of basis elements. These become the names of
452
+ the basis elements.
453
+
454
+ If ``labels`` is a string, this is treated as a prefix and a
455
+ list of names is generated.
456
+
457
+ If ``labels`` is ``None``, then this resets the labels to the default.
458
+
459
+ EXAMPLES::
460
+
461
+ sage: A13 = FusionRing("A1", 3)
462
+ sage: A13.fusion_labels("x")
463
+ sage: fb = list(A13.basis()); fb
464
+ [x0, x1, x2, x3]
465
+ sage: Matrix([[x*y for y in A13.basis()] for x in A13.basis()])
466
+ [ x0 x1 x2 x3]
467
+ [ x1 x0 + x2 x1 + x3 x2]
468
+ [ x2 x1 + x3 x0 + x2 x1]
469
+ [ x3 x2 x1 x0]
470
+
471
+ We give an example where the variables are injected into the
472
+ global namespace::
473
+
474
+ sage: A13.fusion_labels("y", inject_variables=True)
475
+ sage: y0
476
+ y0
477
+ sage: y0.parent() is A13
478
+ True
479
+
480
+ We reset the labels to the default::
481
+
482
+ sage: A13.fusion_labels()
483
+ sage: fb
484
+ [A13(0), A13(1), A13(2), A13(3)]
485
+ sage: y0
486
+ A13(0)
487
+ """
488
+ if labels is None:
489
+ # Remove the fusion labels
490
+ self._fusion_labels = None
491
+ return
492
+
493
+ B = self.basis()
494
+ if isinstance(labels, str):
495
+ labels = [labels + str(k) for k in range(len(B))]
496
+ elif len(labels) != len(B):
497
+ raise ValueError('invalid data')
498
+
499
+ d = {}
500
+ ac = self.simple_coroots()
501
+ for j, b in enumerate(self.get_order()):
502
+ t = tuple([b.inner_product(x) for x in ac])
503
+ d[t] = labels[j]
504
+ if inject_variables:
505
+ inject_variable(labels[j], B[b])
506
+ self._fusion_labels = d
507
+
508
+ @cached_method
509
+ def field(self):
510
+ r"""
511
+ Return a cyclotomic field large enough to
512
+ contain the `2 \ell`-th roots of unity, as well as
513
+ all the `S`-matrix entries.
514
+
515
+ EXAMPLES::
516
+
517
+ sage: FusionRing("A2", 2).field()
518
+ Cyclotomic Field of order 60 and degree 16
519
+ sage: FusionRing("B2", 2).field()
520
+ Cyclotomic Field of order 40 and degree 16
521
+ """
522
+ # if self._field is None:
523
+ # self._field = CyclotomicField(4 * self._cyclotomic_order)
524
+ # return self._field
525
+ return CyclotomicField(4 * self._cyclotomic_order)
526
+
527
+ def fvars_field(self):
528
+ r"""
529
+ Return a field containing the ``CyclotomicField`` computed by
530
+ :meth:`field` as well as all the F-symbols of the associated
531
+ ``FMatrix`` factory object.
532
+
533
+ This method is only available if ``self`` is multiplicity-free.
534
+
535
+ OUTPUT:
536
+
537
+ Depending on the ``CartanType`` associated to ``self`` and whether
538
+ a call to an F-matrix solver has been made, this method
539
+ will return the same field as :meth:`field`, a :func:`NumberField`,
540
+ or the :class:`QQbar<AlgebraicField>`.
541
+ See :meth:`FMatrix.attempt_number_field_computation` for more details.
542
+
543
+ Before running an F-matrix solver, the output of this method matches
544
+ that of :meth:`field`. However, the output may change upon successfully
545
+ computing F-symbols. Requesting braid generators triggers a call to
546
+ :meth:`FMatrix.find_orthogonal_solution`, so the output of this method
547
+ may change after such a computation.
548
+
549
+ By default, the output of methods like :meth:`r_matrix`,
550
+ :meth:`s_matrix`, :meth:`twists_matrix`, etc. will lie in the
551
+ ``fvars_field``, unless the ``base_coercion`` option is set to
552
+ ``False``.
553
+
554
+ This method does not trigger a solver run.
555
+
556
+ EXAMPLES::
557
+
558
+ sage: A13 = FusionRing("A1", 3, fusion_labels='a', inject_variables=True)
559
+ sage: A13.fvars_field()
560
+ Cyclotomic Field of order 40 and degree 16
561
+ sage: A13.field()
562
+ Cyclotomic Field of order 40 and degree 16
563
+ sage: a2**4
564
+ 2*a0 + 3*a2
565
+ sage: comp_basis, sig = A13.get_braid_generators(a2, a2, 3, verbose=False) # long time (<3s)
566
+ sage: A13.fvars_field() # long time
567
+ Number Field in a with defining polynomial y^32 - ... - 500*y^2 + 25
568
+ sage: a2.q_dimension().parent() # long time
569
+ Number Field in a with defining polynomial y^32 - ... - 500*y^2 + 25
570
+ sage: A13.field()
571
+ Cyclotomic Field of order 40 and degree 16
572
+
573
+ In some cases, the :meth:`NumberField.optimized_representation()
574
+ <sage.rings.number_field.number_field.NumberField_absolute.optimized_representation>`
575
+ may be used to obtain a better defining polynomial for the
576
+ computed :func:`NumberField`.
577
+ """
578
+ if self.is_multiplicity_free():
579
+ return self.get_fmatrix().field()
580
+ raise NotImplementedError("method is only available for multiplicity free fusion rings")
581
+
582
+ def root_of_unity(self, r, base_coercion=True):
583
+ r"""
584
+ Return `e^{i\pi r}` as an element of ``self.field()`` if possible.
585
+
586
+ INPUT:
587
+
588
+ - ``r`` -- a rational number
589
+
590
+ EXAMPLES::
591
+
592
+ sage: A11 = FusionRing("A1", 1)
593
+ sage: A11.field()
594
+ Cyclotomic Field of order 24 and degree 8
595
+ sage: for n in [1..7]:
596
+ ....: try:
597
+ ....: print(n, A11.root_of_unity(2/n))
598
+ ....: except ValueError as err:
599
+ ....: print(n, err)
600
+ 1 1
601
+ 2 -1
602
+ 3 zeta24^4 - 1
603
+ 4 zeta24^6
604
+ 5 not a root of unity in the field
605
+ 6 zeta24^4
606
+ 7 not a root of unity in the field
607
+ """
608
+ n = 2 * r * self._cyclotomic_order
609
+ if n not in ZZ:
610
+ raise ValueError("not a root of unity in the field")
611
+ ret = self.field().gen() ** n
612
+ if (not base_coercion) or (self._basecoer is None):
613
+ return ret
614
+ return self._basecoer(ret)
615
+
616
+ def get_order(self):
617
+ r"""
618
+ Return the weights of the basis vectors in a fixed order.
619
+
620
+ You may change the order of the basis using :meth:`CombinatorialFreeModule.set_order`
621
+
622
+ EXAMPLES::
623
+
624
+ sage: A15 = FusionRing("A1", 5)
625
+ sage: w = A15.get_order(); w
626
+ [(0, 0), (1/2, -1/2), (1, -1), (3/2, -3/2), (2, -2), (5/2, -5/2)]
627
+ sage: A15.set_order([w[k] for k in [0, 4, 1, 3, 5, 2]])
628
+ sage: [A15(x) for x in A15.get_order()]
629
+ [A15(0), A15(4), A15(1), A15(3), A15(5), A15(2)]
630
+
631
+ .. WARNING::
632
+
633
+ This duplicates :meth:`get_order` from
634
+ :class:`CombinatorialFreeModule` except the result
635
+ is *not* cached. Caching of
636
+ :meth:`CombinatorialFreeModule.get_order` causes inconsistent
637
+ results after calling :meth:`CombinatorialFreeModule.set_order`.
638
+ """
639
+ if self._order is None:
640
+ self.set_order(self.basis().keys().list())
641
+ return self._order
642
+
643
+ def some_elements(self):
644
+ """
645
+ Return some elements of ``self``.
646
+
647
+ EXAMPLES::
648
+
649
+ sage: D41 = FusionRing('D4', 1)
650
+ sage: D41.some_elements()
651
+ [D41(1,0,0,0), D41(0,0,1,0), D41(0,0,0,1)]
652
+ """
653
+ return [self.monomial(x) for x in self.fundamental_weights()
654
+ if self.level(x) <= self._k]
655
+
656
+ def fusion_level(self):
657
+ r"""
658
+ Return the level `k` of ``self``.
659
+
660
+ EXAMPLES::
661
+
662
+ sage: B22 = FusionRing('B2', 2)
663
+ sage: B22.fusion_level()
664
+ 2
665
+ """
666
+ return self._k
667
+
668
+ def fusion_l(self):
669
+ r"""
670
+ Return the product `\ell = m_g(k + h^\vee)`, where `m_g` denotes the
671
+ square of the ratio of the lengths of long to short roots of
672
+ the underlying Lie algebra, `k` denotes the level of the FusionRing,
673
+ and `h^\vee` denotes the dual Coxeter number of the underlying Lie
674
+ algebra.
675
+
676
+ This value is used to define the associated root `2\ell`-th
677
+ of unity `q = e^{i\pi/\ell}`.
678
+
679
+ EXAMPLES::
680
+
681
+ sage: B22 = FusionRing('B2', 2)
682
+ sage: B22.fusion_l()
683
+ 10
684
+ sage: D52 = FusionRing('D5', 2)
685
+ sage: D52.fusion_l()
686
+ 10
687
+ """
688
+ return self._l
689
+
690
+ def virasoro_central_charge(self):
691
+ r"""
692
+ Return the Virasoro central charge of the WZW conformal
693
+ field theory associated with the Fusion Ring.
694
+
695
+ If `\mathfrak{g}` is the corresponding semisimple Lie algebra, this is
696
+
697
+ .. MATH::
698
+
699
+ \frac{k\dim\mathfrak{g}}{k+h^\vee},
700
+
701
+ where `k` is the level and `h^\vee` is the dual Coxeter number.
702
+ See [DFMS1996]_ Equation (15.61).
703
+
704
+ Let `d_i` and `\theta_i` be the quantum dimensions and
705
+ twists of the simple objects. By Proposition 2.3 in [RoStWa2009]_,
706
+ there exists a rational number `c` such that
707
+ `D_+ / \sqrt{D} = e^{i\pi c/4}`, where `D_+ = \sum d_i^2 \theta_i`
708
+ is computed in :meth:`D_plus` and `D = \sum d_i^2 > 0` is computed
709
+ by :meth:`global_q_dimension`. Squaring this identity and
710
+ remembering that `D_+ D_- = D` gives
711
+
712
+ .. MATH::
713
+
714
+ D_+ / D_- = e^{i\pi c/2}.
715
+
716
+ EXAMPLES::
717
+
718
+ sage: R = FusionRing("A1", 2)
719
+ sage: c = R.virasoro_central_charge(); c
720
+ 3/2
721
+ sage: Dp = R.D_plus(); Dp
722
+ 2*zeta32^6
723
+ sage: Dm = R.D_minus(); Dm
724
+ -2*zeta32^10
725
+ sage: Dp / Dm == R.root_of_unity(c/2)
726
+ True
727
+ """
728
+ dim_g = len(self.space().roots()) + self.cartan_type().rank()
729
+ return self._conj * self._k * dim_g / (self._k + self._h_check)
730
+
731
+ def conj_matrix(self):
732
+ r"""
733
+ Return the conjugation matrix, which is the permutation matrix
734
+ for the conjugation (dual) operation on basis elements.
735
+
736
+ EXAMPLES::
737
+
738
+ sage: FusionRing("A2", 1).conj_matrix()
739
+ [1 0 0]
740
+ [0 0 1]
741
+ [0 1 0]
742
+ """
743
+ b = self.basis().list()
744
+ return matrix(ZZ, [[i == j.dual() for i in b] for j in b])
745
+
746
+ def twists_matrix(self):
747
+ r"""
748
+ Return a diagonal matrix describing the twist corresponding to
749
+ each simple object in the ``FusionRing``.
750
+
751
+ EXAMPLES::
752
+
753
+ sage: B21=FusionRing("B2", 1)
754
+ sage: [x.twist() for x in B21.basis().list()]
755
+ [0, 1, 5/8]
756
+ sage: [B21.root_of_unity(x.twist()) for x in B21.basis().list()]
757
+ [1, -1, zeta32^10]
758
+ sage: B21.twists_matrix()
759
+ [ 1 0 0]
760
+ [ 0 -1 0]
761
+ [ 0 0 zeta32^10]
762
+ """
763
+ B = self.basis()
764
+ return diagonal_matrix(B[x].ribbon() for x in self.get_order())
765
+
766
+ @cached_method
767
+ def N_ijk(self, elt_i, elt_j, elt_k):
768
+ r"""
769
+ Return the symmetric fusion coefficient `N_{ijk}`.
770
+
771
+ INPUT:
772
+
773
+ - ``elt_i``, ``elt_j``, ``elt_k`` -- elements of the fusion basis
774
+
775
+ This is the same as `N_{ij}^{k\ast}`, where `N_{ij}^k` are
776
+ the structure coefficients of the ring (see :meth:`Nk_ij`),
777
+ and `k\ast` denotes the dual element. The coefficient `N_{ijk}`
778
+ is unchanged under permutations of the three basis vectors.
779
+
780
+ EXAMPLES::
781
+
782
+ sage: G23 = FusionRing("G2", 3)
783
+ sage: G23.fusion_labels("g")
784
+ sage: b = G23.basis().list(); b
785
+ [g0, g1, g2, g3, g4, g5]
786
+ sage: [(x, y, z) for x in b for y in b for z in b if G23.N_ijk(x, y, z) > 1]
787
+ [(g3, g3, g3), (g3, g3, g4), (g3, g4, g3), (g4, g3, g3)]
788
+ sage: all(G23.N_ijk(x, y, z)==G23.N_ijk(y, z, x) for x in b for y in b for z in b)
789
+ True
790
+ sage: all(G23.N_ijk(x, y, z)==G23.N_ijk(y, x, z) for x in b for y in b for z in b)
791
+ True
792
+ """
793
+ return (elt_i * elt_j).monomial_coefficients().get(elt_k.dual().weight(), 0)
794
+
795
+ @cached_method
796
+ def Nk_ij(self, elt_i, elt_j, elt_k):
797
+ r"""
798
+ Return the fusion coefficient `N^k_{ij}`.
799
+
800
+ These are the structure coefficients of the fusion ring, so
801
+
802
+ .. MATH::
803
+
804
+ i * j = \sum_{k} N_{ij}^k k.
805
+
806
+ EXAMPLES::
807
+
808
+ sage: A22 = FusionRing("A2", 2)
809
+ sage: b = A22.basis().list()
810
+ sage: all(x*y == sum(A22.Nk_ij(x, y, k)*k for k in b) for x in b for y in b)
811
+ True
812
+ """
813
+ return (elt_i * elt_j).monomial_coefficients(copy=False).get(elt_k.weight(), 0)
814
+
815
+ @cached_method
816
+ def s_ij(self, elt_i, elt_j, base_coercion=True):
817
+ r"""
818
+ Return the element of the `S`-matrix of this fusion ring corresponding to
819
+ the given elements.
820
+
821
+ This is the unnormalized `S`-matrix, denoted `\tilde{s}_{ij}`
822
+ in [BaKi2001]_ . To obtain the normalized `S`-matrix, divide by
823
+ :meth:`global_q_dimension()` or use :meth:`S_matrix()` with
824
+ the option ``unitary=True``.
825
+
826
+ This is computed using the formula
827
+
828
+ .. MATH::
829
+
830
+ s_{i, j} = \frac{1}{\theta_i\theta_j} \sum_k N_{ik}^j d_k \theta_k,
831
+
832
+ where `\theta_k` is the twist and `d_k` is the quantum
833
+ dimension. See [Row2006]_ Equation (2.2) or [EGNO2015]_
834
+ Proposition 8.13.8.
835
+
836
+ INPUT:
837
+
838
+ - ``elt_i``, ``elt_j`` -- elements of the fusion basis
839
+
840
+ EXAMPLES::
841
+
842
+ sage: G21 = FusionRing("G2", 1)
843
+ sage: b = G21.basis()
844
+ sage: [G21.s_ij(x, y) for x in b for y in b]
845
+ [1, -zeta60^14 + zeta60^6 + zeta60^4, -zeta60^14 + zeta60^6 + zeta60^4, -1]
846
+ """
847
+ ijtwist = elt_i.twist() + elt_j.twist()
848
+ ret = sum(k.q_dimension(base_coercion=False) * self.Nk_ij(elt_i, k, elt_j)
849
+ * self.root_of_unity(k.twist() - ijtwist, base_coercion=False)
850
+ for k in self.basis())
851
+ if (not base_coercion) or (self._basecoer is None):
852
+ return ret
853
+ return self._basecoer(ret)
854
+
855
+ def s_ijconj(self, elt_i, elt_j, base_coercion=True):
856
+ """
857
+ Return the conjugate of the element of the `S`-matrix given by
858
+ ``self.s_ij(elt_i, elt_j, base_coercion=base_coercion)``.
859
+
860
+ See :meth:`s_ij`.
861
+
862
+ EXAMPLES::
863
+
864
+ sage: G21 = FusionRing("G2", 1)
865
+ sage: b = G21.basis()
866
+ sage: [G21.s_ijconj(x, y) for x in b for y in b]
867
+ [1, -zeta60^14 + zeta60^6 + zeta60^4, -zeta60^14 + zeta60^6 + zeta60^4, -1]
868
+
869
+ This method works with all possible types of fields returned by
870
+ ``self.fmats.field()``.
871
+
872
+ TESTS::
873
+
874
+ sage: E62 = FusionRing("E6", 2)
875
+ sage: E62.fusion_labels("e", inject_variables=True)
876
+ sage: E62.s_ij(e8, e1).conjugate() == E62.s_ijconj(e8, e1)
877
+ True
878
+ sage: F41 = FusionRing("F4", 1)
879
+ sage: fmats = F41.get_fmatrix()
880
+ sage: fmats.find_orthogonal_solution(verbose=False)
881
+ sage: b = F41.basis()
882
+ sage: all(F41.s_ijconj(x, y) == F41._basecoer(F41.s_ij(x, y, base_coercion=False).conjugate()) for x in b for y in b)
883
+ True
884
+ sage: G22 = FusionRing("G2", 2)
885
+ sage: fmats = G22.get_fmatrix()
886
+ sage: fmats.find_orthogonal_solution(verbose=False) # long time (~11 s)
887
+ sage: b = G22.basis() # long time
888
+ sage: all(G22.s_ijconj(x, y) == fmats.field()(G22.s_ij(x, y, base_coercion=False).conjugate()) for x in b for y in b) # long time
889
+ True
890
+ """
891
+ ret = self.s_ij(elt_i, elt_j, base_coercion=False).conjugate()
892
+ if (not base_coercion) or (self._basecoer is None):
893
+ return ret
894
+ return self._basecoer(ret)
895
+
896
+ def s_matrix(self, unitary=False, base_coercion=True):
897
+ r"""
898
+ Return the `S`-matrix of this fusion ring.
899
+
900
+ OPTIONAL:
901
+
902
+ - ``unitary`` -- boolean (default: ``False``); set to ``True`` to
903
+ obtain the unitary `S`-matrix
904
+
905
+ Without the ``unitary`` parameter, this is the matrix denoted
906
+ `\widetilde{s}` in [BaKi2001]_.
907
+
908
+ EXAMPLES::
909
+
910
+ sage: D91 = FusionRing("D9", 1)
911
+ sage: D91.s_matrix()
912
+ [ 1 1 1 1]
913
+ [ 1 1 -1 -1]
914
+ [ 1 -1 -zeta136^34 zeta136^34]
915
+ [ 1 -1 zeta136^34 -zeta136^34]
916
+ sage: S = D91.s_matrix(unitary=True); S
917
+ [ 1/2 1/2 1/2 1/2]
918
+ [ 1/2 1/2 -1/2 -1/2]
919
+ [ 1/2 -1/2 -1/2*zeta136^34 1/2*zeta136^34]
920
+ [ 1/2 -1/2 1/2*zeta136^34 -1/2*zeta136^34]
921
+ sage: S*S.conjugate()
922
+ [1 0 0 0]
923
+ [0 1 0 0]
924
+ [0 0 1 0]
925
+ [0 0 0 1]
926
+ """
927
+ b = self.basis()
928
+ S = matrix([[self.s_ij(b[x], b[y], base_coercion=base_coercion)
929
+ for x in self.get_order()] for y in self.get_order()])
930
+ if unitary:
931
+ return S / self.total_q_order(base_coercion=base_coercion)
932
+ return S
933
+
934
+ @cached_method
935
+ def r_matrix(self, i, j, k, base_coercion=True):
936
+ r"""
937
+ Return the R-matrix entry corresponding to the subobject ``k``
938
+ in the tensor product of ``i`` with ``j``.
939
+
940
+ .. WARNING::
941
+
942
+ This method only gives complete information when `N_{ij}^k = 1`
943
+ (an important special case). Tables of MTC including R-matrices
944
+ may be found in Section 5.3 of [RoStWa2009]_ and in [Bond2007]_.
945
+
946
+ The R-matrix is a homomorphism `i \otimes j \rightarrow j \otimes i`.
947
+ This may be hard to describe since the object `i \otimes j`
948
+ may be reducible. However if `k` is a simple subobject of
949
+ `i \otimes j` it is also a subobject of `j \otimes i`. If we fix
950
+ embeddings `k \rightarrow i \otimes j`, `k \rightarrow j \otimes i`
951
+ we may ask for the scalar automorphism of `k` induced by the
952
+ R-matrix. This method computes that scalar. It is possible to
953
+ adjust the set of embeddings `k \rightarrow i \otimes j` (called
954
+ a *gauge*) so that this scalar equals
955
+
956
+ .. MATH::
957
+
958
+ \pm \sqrt{\frac{ \theta_k }{ \theta_i \theta_j }}.
959
+
960
+ If `i \neq j`, the gauge may be used to control the sign of
961
+ the square root. But if `i = j` then we must be careful
962
+ about the sign. These cases are computed by a formula
963
+ of [BDGRTW2019]_, Proposition 2.3.
964
+
965
+ EXAMPLES::
966
+
967
+ sage: I = FusionRing("E8", 2, conjugate=True) # Ising MTC
968
+ sage: I.fusion_labels(["i0", "p", "s"], inject_variables=True)
969
+ sage: I.r_matrix(s, s, i0) == I.root_of_unity(-1/8)
970
+ True
971
+ sage: I.r_matrix(p, p, i0)
972
+ -1
973
+ sage: I.r_matrix(p, s, s) == I.root_of_unity(-1/2)
974
+ True
975
+ sage: I.r_matrix(s, p, s) == I.root_of_unity(-1/2)
976
+ True
977
+ sage: I.r_matrix(s, s, p) == I.root_of_unity(3/8)
978
+ True
979
+ """
980
+ if self.Nk_ij(i, j, k) == 0:
981
+ return self.field().zero() if (not base_coercion) or (self._basecoer is None) else self.fvars_field().zero()
982
+ if i != j:
983
+ ret = self.root_of_unity((k.twist(reduced=False) - i.twist(reduced=False) - j.twist(reduced=False)) / 2, base_coercion=False)
984
+ else:
985
+ i0 = self.one()
986
+ B = self.basis()
987
+ ret = sum(y.ribbon(base_coercion=False)**2 / (i.ribbon(base_coercion=False) * x.ribbon(base_coercion=False)**2)
988
+ * self.s_ij(i0, y, base_coercion=False) * self.s_ij(i, z, base_coercion=False) * self.s_ijconj(x, z, base_coercion=False)
989
+ * self.s_ijconj(k, x, base_coercion=False) * self.s_ijconj(y, z, base_coercion=False) / self.s_ij(i0, z, base_coercion=False)
990
+ for x in B for y in B for z in B) / (self.total_q_order(base_coercion=False)**4)
991
+ if (not base_coercion) or (self._basecoer is None):
992
+ return ret
993
+ return self._basecoer(ret)
994
+
995
+ def global_q_dimension(self, base_coercion=True):
996
+ r"""
997
+ Return `\sum d_i^2`, where the sum is over all simple objects
998
+ and `d_i` is the quantum dimension.
999
+
1000
+ The global `q`-dimension is a positive real number.
1001
+
1002
+ EXAMPLES::
1003
+
1004
+ sage: FusionRing("E6", 1).global_q_dimension()
1005
+ 3
1006
+ """
1007
+ ret = sum(x.q_dimension(base_coercion=False) ** 2 for x in self.basis())
1008
+ if (not base_coercion) or (self._basecoer is None):
1009
+ return ret
1010
+ return self._basecoer(ret)
1011
+
1012
+ def total_q_order(self, base_coercion=True):
1013
+ r"""
1014
+ Return the positive square root of :meth:`self.global_q_dimension()
1015
+ <global_q_dimension>` as an element of :meth:`self.field() <field>`.
1016
+
1017
+ This is implemented as `D_{+}e^{-i\pi c/4}`, where `D_+` is
1018
+ :meth:`D_plus()` and `c` is :meth:`virasoro_central_charge()`.
1019
+
1020
+ EXAMPLES::
1021
+
1022
+ sage: F = FusionRing("G2", 1)
1023
+ sage: tqo=F.total_q_order(); tqo
1024
+ zeta60^15 - zeta60^11 - zeta60^9 + 2*zeta60^3 + zeta60
1025
+ sage: tqo.is_real_positive()
1026
+ True
1027
+ sage: tqo^2 == F.global_q_dimension()
1028
+ True
1029
+ """
1030
+ c = self.virasoro_central_charge()
1031
+ ret = self.D_plus(base_coercion=False) * self.root_of_unity(-c/4, base_coercion=False)
1032
+ if (not base_coercion) or (self._basecoer is None):
1033
+ return ret
1034
+ return self._basecoer(ret)
1035
+
1036
+ def D_plus(self, base_coercion=True):
1037
+ r"""
1038
+ Return `\sum d_i^2\theta_i` where `i` runs through the simple objects,
1039
+ `d_i` is the quantum dimension and `\theta_i` is the twist.
1040
+
1041
+ This is denoted `p_+` in [BaKi2001]_ Chapter 3.
1042
+
1043
+ EXAMPLES::
1044
+
1045
+ sage: B31 = FusionRing("B3", 1)
1046
+ sage: Dp = B31.D_plus(); Dp
1047
+ 2*zeta48^13 - 2*zeta48^5
1048
+ sage: Dm = B31.D_minus(); Dm
1049
+ -2*zeta48^3
1050
+ sage: Dp*Dm == B31.global_q_dimension()
1051
+ True
1052
+ sage: c = B31.virasoro_central_charge(); c
1053
+ 7/2
1054
+ sage: Dp/Dm == B31.root_of_unity(c/2)
1055
+ True
1056
+ """
1057
+ ret = sum((x.q_dimension(base_coercion=False))**2 * x.ribbon(base_coercion=False) for x in self.basis())
1058
+ if (not base_coercion) or (self._basecoer is None):
1059
+ return ret
1060
+ return self._basecoer(ret)
1061
+
1062
+ def D_minus(self, base_coercion=True):
1063
+ r"""
1064
+ Return `\sum d_i^2\theta_i^{-1}` where `i` runs through the simple
1065
+ objects, `d_i` is the quantum dimension and `\theta_i` is the twist.
1066
+
1067
+ This is denoted `p_-` in [BaKi2001]_ Chapter 3.
1068
+
1069
+ EXAMPLES::
1070
+
1071
+ sage: E83 = FusionRing("E8", 3, conjugate=True)
1072
+ sage: [Dp, Dm] = [E83.D_plus(), E83.D_minus()]
1073
+ sage: Dp*Dm == E83.global_q_dimension()
1074
+ True
1075
+ sage: c = E83.virasoro_central_charge(); c
1076
+ -248/11
1077
+ sage: Dp*Dm == E83.global_q_dimension()
1078
+ True
1079
+ """
1080
+ ret = sum((x.q_dimension(base_coercion=False))**2 / x.ribbon(base_coercion=False) for x in self.basis())
1081
+ if (not base_coercion) or (self._basecoer is None):
1082
+ return ret
1083
+ return self._basecoer(ret)
1084
+
1085
+ def is_multiplicity_free(self):
1086
+ r"""
1087
+ Return ``True`` if the fusion multiplicities
1088
+ :meth:`Nk_ij` are bounded by 1.
1089
+
1090
+ The :class:`FMatrix` is available only for multiplicity free
1091
+ instances of :class:`FusionRing`.
1092
+
1093
+ EXAMPLES::
1094
+
1095
+ sage: [FusionRing(ct, k).is_multiplicity_free() for ct in ("A1", "A2", "B2", "C3") for k in (1, 2, 3)]
1096
+ [True, True, True, True, True, False, True, True, False, True, False, False]
1097
+ """
1098
+ ct = self.cartan_type()
1099
+ k = self.fusion_level()
1100
+ if ct.letter == 'A':
1101
+ if ct.n == 1:
1102
+ return True
1103
+ return k <= 2
1104
+ # if ct.letter in ['B', 'D', 'G', 'F', 'E']:
1105
+ if ct.letter in ['B', 'D', 'F', 'G']:
1106
+ return k <= 2
1107
+ if ct.letter == 'C':
1108
+ if ct.n == 2:
1109
+ return k <= 2
1110
+ return k == 1
1111
+ if ct.letter == 'E':
1112
+ if ct.n == 8:
1113
+ return k <= 3
1114
+ return k <= 2
1115
+
1116
+ ###################################
1117
+ # Braid group representations #
1118
+ ###################################
1119
+
1120
+ def get_computational_basis(self, a, b, n_strands):
1121
+ r"""
1122
+ Return the so-called computational basis for `\text{Hom}(b, a^n)`.
1123
+
1124
+ INPUT:
1125
+
1126
+ - ``a`` -- a basis element
1127
+ - ``b`` -- another basis element
1128
+ - ``n_strands`` -- the number of strands for a braid group
1129
+
1130
+ Let `n=` ``n_strands`` and let `k` be the greatest integer `\leq n/2`.
1131
+ The braid group acts on `\text{Hom}(b, a^n)`. This action
1132
+ is computed in :meth:`get_braid_generators`. This method
1133
+ returns the computational basis in the form of a list of
1134
+ fusion trees. Each tree is represented by an `(n-2)`-tuple
1135
+
1136
+ .. MATH::
1137
+
1138
+ (m_1, \ldots, m_k, l_1, \ldots, l_{k-2})
1139
+
1140
+ such that each `m_j` is an irreducible constituent in `a \otimes a`
1141
+ and
1142
+
1143
+ .. MATH::
1144
+
1145
+ \begin{array}{l}
1146
+ b \in l_{k-2} \otimes m_{k}, \\
1147
+ l_{k-2} \in l_{k-3} \otimes m_{k-1}, \\
1148
+ \cdots, \\
1149
+ l_2 \in l_1 \otimes m_3, \\
1150
+ l_1 \in m_1 \otimes m_2,
1151
+ \end{array}
1152
+
1153
+ where `z \in x \otimes y` means `N_{xy}^z \neq 0`.
1154
+
1155
+ As a computational device when ``n_strands`` is odd, we pad the
1156
+ vector `(m_1, \ldots, m_k)` with an additional `m_{k+1}` equal to `a`.
1157
+ However, this `m_{k+1}` does *not* appear in the output of this method.
1158
+
1159
+ The following example appears in Section 3.1 of [CW2015]_.
1160
+
1161
+ EXAMPLES::
1162
+
1163
+ sage: A14 = FusionRing("A1", 4)
1164
+ sage: A14.get_order()
1165
+ [(0, 0), (1/2, -1/2), (1, -1), (3/2, -3/2), (2, -2)]
1166
+ sage: A14.fusion_labels(["zero", "one", "two", "three", "four"], inject_variables=True)
1167
+ sage: [A14(x) for x in A14.get_order()]
1168
+ [zero, one, two, three, four]
1169
+ sage: A14.get_computational_basis(one, two, 4)
1170
+ [(two, two), (two, zero), (zero, two)]
1171
+ """
1172
+ def _get_trees(fr, top_row, root):
1173
+ if len(top_row) == 2:
1174
+ m1, m2 = top_row
1175
+ return [[]] if fr.Nk_ij(m1, m2, root) else []
1176
+ else:
1177
+ m1, m2 = top_row[:2]
1178
+ return [(l, *b) for l in fr.basis() for b in _get_trees(fr, [l]+top_row[2:], root) if fr.Nk_ij(m1, m2, l)]
1179
+
1180
+ comp_basis = []
1181
+ for top in product((a*a).monomials(), repeat=n_strands//2):
1182
+ # If the n_strands is odd, we must extend the top row by a fusing anyon
1183
+ top_row = list(top)+[a]*(n_strands % 2)
1184
+ comp_basis.extend((*top, *levels) for levels in _get_trees(self, top_row, b))
1185
+ return comp_basis
1186
+
1187
+ def get_fmatrix(self, *args, **kwargs):
1188
+ r"""
1189
+ Construct an :class:`FMatrix` factory to solve the pentagon relations
1190
+ and organize the resulting F-symbols.
1191
+
1192
+ EXAMPLES::
1193
+
1194
+ sage: A15 = FusionRing("A1", 5)
1195
+ sage: A15.get_fmatrix()
1196
+ F-Matrix factory for The Fusion Ring of Type A1 and level 5 with Integer Ring coefficients
1197
+ """
1198
+ # Initialize fresh FMatrix object. Useful if you need to reset
1199
+ # FMatrix properties and there are various FusionRing objects (unique)
1200
+ # associated to same level and algebra.
1201
+ if not hasattr(self, 'fmats') or kwargs.get('new', False):
1202
+ kwargs.pop('new', None)
1203
+ from sage.algebras.fusion_rings.f_matrix import FMatrix
1204
+ self.fmats = FMatrix(self, *args, **kwargs)
1205
+ return self.fmats
1206
+
1207
+ def _emap(self, mapper, input_args, worker_pool=None):
1208
+ r"""
1209
+ Apply the given mapper to each element of the given input iterable
1210
+ and return the results (with no duplicates) in a list.
1211
+
1212
+ INPUT:
1213
+
1214
+ - ``mapper`` -- string specifying the name of a function defined
1215
+ in the ``fast_parallel_fusion_ring_braid_repn`` module
1216
+ - ``input_args`` -- tuple of arguments to be passed to mapper
1217
+
1218
+ This method applies the mapper in parallel if a ``worker_pool``
1219
+ is provided.
1220
+
1221
+ .. NOTE::
1222
+
1223
+ If ``worker_pool`` is not provided, function maps and reduces on
1224
+ a single process. If ``worker_pool`` is provided, the function
1225
+ attempts to determine whether it should use multiprocessing
1226
+ based on the length of the input iterable. If it cannot determine
1227
+ the length of the input iterable then it uses multiprocessing
1228
+ with the default chunksize of `1` if chunksize is not
1229
+ explicitly provided.
1230
+
1231
+ EXAMPLES::
1232
+
1233
+ sage: FR = FusionRing("A1", 4)
1234
+ sage: FR.fusion_labels(['idd', 'one', 'two', 'three', 'four'], inject_variables=True)
1235
+ sage: fmats = FR.get_fmatrix()
1236
+ sage: fmats.find_orthogonal_solution(verbose=False) # long time
1237
+ sage: len(FR._emap('sig_2k', (1, one, one, 5))) # long time
1238
+ 13
1239
+ sage: FR = FusionRing("A1", 2)
1240
+ sage: FR.fusion_labels("a", inject_variables=True)
1241
+ sage: fmats = FR.get_fmatrix()
1242
+ sage: fmats.find_orthogonal_solution(verbose=False)
1243
+ sage: len(FR._emap('odd_one_out', (a1, a1, 7)))
1244
+ 16
1245
+ """
1246
+ n_proc = worker_pool._processes if worker_pool is not None else 1
1247
+ input_iter = [(child_id, n_proc, input_args) for child_id in range(n_proc)]
1248
+ no_mp = worker_pool is None
1249
+ # Map phase
1250
+ input_iter = zip_longest([], input_iter, fillvalue=(mapper, id(self)))
1251
+ results = []
1252
+ if no_mp:
1253
+ mapped = map(executor, input_iter)
1254
+ else:
1255
+ mapped = worker_pool.imap_unordered(executor, input_iter, chunksize=1)
1256
+ # Reduce phase
1257
+ for worker_results in mapped:
1258
+ results.extend(worker_results)
1259
+ return results
1260
+
1261
+ def get_braid_generators(self,
1262
+ fusing_anyon,
1263
+ total_charge_anyon,
1264
+ n_strands,
1265
+ checkpoint=False,
1266
+ save_results='',
1267
+ warm_start='',
1268
+ use_mp=True,
1269
+ verbose=True):
1270
+ r"""
1271
+ Compute generators of the Artin braid group on ``n_strands`` strands.
1272
+
1273
+ If `a = ` ``fusing_anyon`` and `b = ` ``total_charge_anyon``
1274
+ the generators are endomorphisms of `\text{Hom}(b, a^n)`.
1275
+
1276
+ INPUT:
1277
+
1278
+ - ``fusing_anyon`` -- a basis element of ``self``
1279
+ - ``total_charge_anyon`` -- a basis element of ``self``
1280
+ - ``n_strands`` -- positive integer greater than 2
1281
+ - ``checkpoint`` -- boolean (default: ``False``);
1282
+ whether the F-matrix solver should pickle checkpoints
1283
+ - ``save_results`` -- (optional) a string indicating the name of
1284
+ a file in which to pickle computed F-symbols for later use
1285
+ - ``warm_start`` -- (optional) a string indicating the name of a
1286
+ pickled checkpoint file to "warm" start the F-matrix solver.
1287
+ The pickle may be a checkpoint generated by the solver, or
1288
+ a file containing solver results. If all F-symbols are known,
1289
+ we don't run the solver again.
1290
+ - ``use_mp`` -- boolean (default: ``True``); whether
1291
+ to use multiprocessing to speed up the computation; this is
1292
+ highly recommended.
1293
+ - ``verbose`` -- boolean (default: ``True``); whether
1294
+ to be verbose with the computation
1295
+
1296
+ For more information on the optional parameters, see
1297
+ :meth:`FMatrix.find_orthogonal_solution`.
1298
+
1299
+ Given a simple object in the fusion category, here called
1300
+ ``fusing_anyon`` allowing the universal R-matrix to act on adjacent
1301
+ pairs in the fusion of ``n_strands`` copies of ``fusing_anyon``
1302
+ produces an action of the braid group. This representation can
1303
+ be decomposed over another anyon, here called ``total_charge_anyon``.
1304
+ See [CHW2015]_.
1305
+
1306
+ OUTPUT:
1307
+
1308
+ The method outputs a pair of data ``(comp_basis, sig)`` where
1309
+ ``comp_basis`` is a list of basis elements of the braid group
1310
+ module, parametrized by a list of fusion ring elements describing
1311
+ a fusion tree. For example with 5 strands the fusion tree
1312
+ is as follows. See :meth:`get_computational_basis`
1313
+ for more information.
1314
+
1315
+ .. IMAGE:: ../../../media/fusiontree.png
1316
+ :scale: 45
1317
+ :align: center
1318
+
1319
+ ``sig`` is a list of braid group generators as matrices. In
1320
+ some cases these will be represented as sparse matrices.
1321
+
1322
+ In the following example we compute a 5-dimensional braid group
1323
+ representation on 5 strands associated to the spin representation
1324
+ in the modular tensor category `SU(2)_4 \cong SO(3)_2`.
1325
+
1326
+ EXAMPLES::
1327
+
1328
+ sage: A14 = FusionRing("A1", 4)
1329
+ sage: A14.get_order()
1330
+ [(0, 0), (1/2, -1/2), (1, -1), (3/2, -3/2), (2, -2)]
1331
+ sage: A14.fusion_labels(["one", "two", "three", "four", "five"], inject_variables=True)
1332
+ sage: [A14(x) for x in A14.get_order()]
1333
+ [one, two, three, four, five]
1334
+ sage: two ** 5
1335
+ 5*two + 4*four
1336
+ sage: comp_basis, sig = A14.get_braid_generators(two, two, 5, verbose=False) # long time
1337
+ sage: A14.gens_satisfy_braid_gp_rels(sig) # long time
1338
+ True
1339
+ sage: len(comp_basis) == 5 # long time
1340
+ True
1341
+ """
1342
+ if n_strands < 3:
1343
+ raise ValueError("the number of strands must be an integer at least 3")
1344
+ # Construct associated FMatrix object and solve for F-symbols
1345
+ self.get_fmatrix()
1346
+ if self.fmats._chkpt_status < 7:
1347
+ self.fmats.find_orthogonal_solution(checkpoint=checkpoint,
1348
+ save_results=save_results,
1349
+ warm_start=warm_start,
1350
+ use_mp=use_mp,
1351
+ verbose=verbose)
1352
+
1353
+ # Set multiprocessing parameters. Context can only be set once, so we try to set it
1354
+ try:
1355
+ set_start_method('fork')
1356
+ except RuntimeError:
1357
+ pass
1358
+ # Turn off multiprocessing when field is QQbar due to pickling issues introduced by PARI upgrade in github issue #30537
1359
+ pool = Pool() if use_mp and self.fvars_field() != QQbar else None
1360
+
1361
+ # Set up computational basis and compute generators one at a time
1362
+ a, b = fusing_anyon, total_charge_anyon
1363
+ comp_basis = self.get_computational_basis(a, b, n_strands)
1364
+ d = len(comp_basis)
1365
+ if verbose:
1366
+ print("Computing an {}-dimensional representation of the Artin braid group on {} strands...".format(d, n_strands))
1367
+
1368
+ # Compute diagonal odd-indexed generators using the 3j-symbols
1369
+ gens = {2*i+1: diagonal_matrix(self.r_matrix(a, a, c[i]) for c in comp_basis) for i in range(n_strands//2)}
1370
+
1371
+ # Compute even-indexed generators using F-matrices
1372
+ for k in range(1, n_strands//2):
1373
+ entries = self._emap('sig_2k', (k, a, b, n_strands), pool)
1374
+
1375
+ # Build cyclotomic field element objects from tuple of rationals repn
1376
+ _unflatten_entries(self, entries)
1377
+ gens[2*k] = matrix(dict(entries))
1378
+
1379
+ # If n_strands is odd, we compute the final generator
1380
+ if n_strands % 2:
1381
+ entries = self._emap('odd_one_out', (a, b, n_strands), pool)
1382
+
1383
+ # Build cyclotomic field element objects from tuple of rationals repn
1384
+ _unflatten_entries(self, entries)
1385
+ gens[n_strands-1] = matrix(dict(entries))
1386
+
1387
+ return comp_basis, [gens[k] for k in sorted(gens)]
1388
+
1389
+ def gens_satisfy_braid_gp_rels(self, sig):
1390
+ r"""
1391
+ Return ``True`` if the matrices in the list ``sig`` satisfy
1392
+ the braid relations.
1393
+
1394
+ This if `n` is the cardinality of ``sig``, this
1395
+ confirms that these matrices define a representation of
1396
+ the Artin braid group on `n+1` strands. Tests correctness of
1397
+ :meth:`get_braid_generators`.
1398
+
1399
+ EXAMPLES::
1400
+
1401
+ sage: F41 = FusionRing("F4", 1, fusion_labels='f', inject_variables=True)
1402
+ sage: f1*f1
1403
+ f0 + f1
1404
+ sage: comp, sig = F41.get_braid_generators(f1, f0, 4, verbose=False)
1405
+ sage: F41.gens_satisfy_braid_gp_rels(sig)
1406
+ True
1407
+ """
1408
+ n = len(sig)
1409
+ braid_rels = all(sig[i] * sig[i+1] * sig[i] == sig[i+1] * sig[i] * sig[i+1] for i in range(n-1))
1410
+ far_comm = all(sig[i] * sig[j] == sig[j] * sig[i] for i, j in product(range(n), repeat=2) if abs(i-j) > 1 and i > j)
1411
+ singular = any(s.is_singular() for s in sig)
1412
+ return braid_rels and far_comm and not singular
1413
+
1414
+ class Element(WeylCharacterRing.Element):
1415
+ """
1416
+ A class for FusionRing elements.
1417
+ """
1418
+ def is_simple_object(self):
1419
+ r"""
1420
+ Determine whether ``self`` is a simple object of the fusion ring.
1421
+
1422
+ EXAMPLES::
1423
+
1424
+ sage: A22 = FusionRing("A2", 2)
1425
+ sage: x = A22(1, 0); x
1426
+ A22(1,0)
1427
+ sage: x.is_simple_object()
1428
+ True
1429
+ sage: x^2
1430
+ A22(0,1) + A22(2,0)
1431
+ sage: (x^2).is_simple_object()
1432
+ False
1433
+ """
1434
+ return self.parent()._k is not None and len(self._monomial_coefficients) == 1
1435
+
1436
+ def weight(self):
1437
+ r"""
1438
+ Return the parametrizing dominant weight in the level `k` alcove.
1439
+
1440
+ This method is only available for basis elements.
1441
+
1442
+ EXAMPLES::
1443
+
1444
+ sage: A21 = FusionRing("A2", 1)
1445
+ sage: [x.weight() for x in A21.basis().list()]
1446
+ [(0, 0, 0), (2/3, -1/3, -1/3), (1/3, 1/3, -2/3)]
1447
+ """
1448
+ if len(self._monomial_coefficients) != 1:
1449
+ raise ValueError("fusion weight is valid for basis elements only")
1450
+ return next(iter(self._monomial_coefficients))
1451
+
1452
+ def twist(self, reduced=True):
1453
+ r"""
1454
+ Return a rational number `h` such that `\theta = e^{i \pi h}`
1455
+ is the twist of ``self``. The quantity `e^{i \pi h}` is
1456
+ also available using :meth:`ribbon`.
1457
+
1458
+ This method is only available for simple objects. If
1459
+ `\lambda` is the weight of the object, then
1460
+ `h = \langle \lambda, \lambda+2\rho \rangle`, where
1461
+ `\rho` is half the sum of the positive roots.
1462
+ As in [Row2006]_, this requires normalizing
1463
+ the invariant bilinear form so that
1464
+ `\langle \alpha, \alpha \rangle = 2` for short roots.
1465
+
1466
+ INPUT:
1467
+
1468
+ - ``reduced`` -- boolean (default: ``True``); if ``True``
1469
+ then return the twist reduced modulo 2
1470
+
1471
+ EXAMPLES::
1472
+
1473
+ sage: G21 = FusionRing("G2", 1)
1474
+ sage: [x.twist() for x in G21.basis()]
1475
+ [0, 4/5]
1476
+ sage: [G21.root_of_unity(x.twist()) for x in G21.basis()]
1477
+ [1, zeta60^14 - zeta60^4]
1478
+ sage: zeta60 = G21.field().gen()
1479
+ sage: zeta60^((4/5)*(60/2))
1480
+ zeta60^14 - zeta60^4
1481
+
1482
+ sage: F42 = FusionRing("F4", 2)
1483
+ sage: [x.twist() for x in F42.basis()]
1484
+ [0, 18/11, 2/11, 12/11, 4/11]
1485
+
1486
+ sage: E62 = FusionRing("E6", 2)
1487
+ sage: [x.twist() for x in E62.basis()]
1488
+ [0, 26/21, 12/7, 8/21, 8/21, 26/21, 2/3, 4/7, 2/3]
1489
+ """
1490
+ if not self.is_simple_object():
1491
+ raise ValueError("quantum twist is only available for simple objects of a FusionRing")
1492
+ P = self.parent()
1493
+ rho = P.space().rho()
1494
+ # We copy self.weight() to skip the test (which was already done
1495
+ # by self.is_simple_object()).
1496
+ lam = next(iter(self._monomial_coefficients))
1497
+ inner = lam.inner_product(lam + 2*rho)
1498
+ twist = P._conj * P._nf * inner / P.fusion_l()
1499
+ # Reduce modulo 2
1500
+ if reduced:
1501
+ f = twist.floor()
1502
+ twist -= f
1503
+ return twist + (f % 2)
1504
+ return twist
1505
+
1506
+ def ribbon(self, base_coercion=True):
1507
+ r"""
1508
+ Return the twist or ribbon element of ``self``.
1509
+
1510
+ If `h` is the rational number modulo 2 produced by
1511
+ ``self.twist()``, this method produces `e^{i\pi h}`.
1512
+
1513
+ .. SEEALSO::
1514
+
1515
+ An additive version of this is available as :meth:`twist`.
1516
+
1517
+ EXAMPLES::
1518
+
1519
+ sage: F = FusionRing("A1", 3)
1520
+ sage: [x.twist() for x in F.basis()]
1521
+ [0, 3/10, 4/5, 3/2]
1522
+ sage: [x.ribbon(base_coercion=False) for x in F.basis()]
1523
+ [1, zeta40^6, zeta40^12 - zeta40^8 + zeta40^4 - 1, -zeta40^10]
1524
+ sage: [F.root_of_unity(x, base_coercion=False) for x in [0, 3/10, 4/5, 3/2]]
1525
+ [1, zeta40^6, zeta40^12 - zeta40^8 + zeta40^4 - 1, -zeta40^10]
1526
+ """
1527
+ ret = self.parent().root_of_unity(self.twist(), base_coercion=False)
1528
+ if (not base_coercion) or (self.parent()._basecoer is None):
1529
+ return ret
1530
+ return self.parent()._basecoer(ret)
1531
+
1532
+ @cached_method
1533
+ def q_dimension(self, base_coercion=True):
1534
+ r"""
1535
+ Return the quantum dimension as an element of the cyclotomic
1536
+ field of the `2\ell`-th roots of unity, where `l = m (k+h^\vee)`
1537
+ with `m=1, 2, 3` depending on whether type is simply, doubly or
1538
+ triply laced, `k` is the level and `h^\vee` is the dual
1539
+ Coxeter number.
1540
+
1541
+ EXAMPLES::
1542
+
1543
+ sage: B22 = FusionRing("B2", 2)
1544
+ sage: [(b.q_dimension())^2 for b in B22.basis()]
1545
+ [1, 4, 5, 1, 5, 4]
1546
+ """
1547
+ if not self.is_simple_object():
1548
+ raise ValueError("quantum dimension is only available for simple objects of a FusionRing")
1549
+ P = self.parent()
1550
+ lam = self.weight()
1551
+ space = P.space()
1552
+ rho = space.rho()
1553
+ powers = {}
1554
+ for alpha in space.positive_roots():
1555
+ val = alpha.inner_product(lam + rho)
1556
+ if val in powers:
1557
+ powers[val] += 1
1558
+ else:
1559
+ powers[val] = 1
1560
+ val = alpha.inner_product(rho)
1561
+ if val in powers:
1562
+ powers[val] -= 1
1563
+ else:
1564
+ powers[val] = -1
1565
+ R = ZZ['q']
1566
+ q = R.gen()
1567
+ expr = R.fraction_field().one()
1568
+ for val, exp in powers.items():
1569
+ if exp > 0:
1570
+ expr *= q_int(P._nf * val, q)**exp
1571
+ elif exp < 0:
1572
+ expr /= q_int(P._nf * val, q)**(-exp)
1573
+ expr = R(expr)
1574
+ expr = expr.substitute(q=q**4) / (q**(2 * expr.degree()))
1575
+ zet = P.field().gen() ** (P._cyclotomic_order / P._l)
1576
+ ret = expr.substitute(q=zet)
1577
+
1578
+ if (not base_coercion) or (self.parent()._basecoer is None):
1579
+ return ret
1580
+ return self.parent()._basecoer(ret)