passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,2628 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ # sage.doctest: needs sage.graphs sage.combinat sage.modules
3
+ r"""
4
+ Crystals
5
+
6
+ TESTS:
7
+
8
+ Catch warnings produced by :func:`check_tkz_graph`::
9
+
10
+ sage: from sage.graphs.graph_latex import check_tkz_graph
11
+ sage: check_tkz_graph() # random
12
+ """
13
+
14
+ #*****************************************************************************
15
+ # Copyright (C) 2010 Anne Schilling <anne at math.ucdavis.edu>
16
+ #
17
+ # This program is free software: you can redistribute it and/or modify
18
+ # it under the terms of the GNU General Public License as published by
19
+ # the Free Software Foundation, either version 2 of the License, or
20
+ # (at your option) any later version.
21
+ # https://www.gnu.org/licenses/
22
+ #*****************************************************************************
23
+
24
+ import collections.abc
25
+
26
+ from sage.misc.cachefunc import cached_method
27
+ from sage.misc.abstract_method import abstract_method
28
+ from sage.misc.lazy_import import LazyImport
29
+ from sage.categories.category_singleton import Category_singleton
30
+ from sage.categories.enumerated_sets import EnumeratedSets
31
+ from sage.categories.tensor import TensorProductsCategory
32
+ from sage.categories.morphism import Morphism
33
+ from sage.categories.homset import Hom, Homset
34
+
35
+
36
+ class Crystals(Category_singleton):
37
+ r"""
38
+ The category of crystals.
39
+
40
+ See :mod:`sage.combinat.crystals.crystals` for an introduction to crystals.
41
+
42
+ EXAMPLES::
43
+
44
+ sage: C = Crystals()
45
+ sage: C
46
+ Category of crystals
47
+ sage: C.super_categories()
48
+ [Category of... enumerated sets]
49
+ sage: C.example()
50
+ Highest weight crystal of type A_3 of highest weight omega_1
51
+
52
+ Parents in this category should implement the following methods:
53
+
54
+ - either an attribute ``_cartan_type`` or a method ``cartan_type``
55
+
56
+ - ``module_generators``: a list (or container) of distinct elements
57
+ which generate the crystal using `f_i`
58
+
59
+ Furthermore, their elements ``x`` should implement the following
60
+ methods:
61
+
62
+ - ``x.e(i)`` (returning `e_i(x)`)
63
+
64
+ - ``x.f(i)`` (returning `f_i(x)`)
65
+
66
+ - ``x.epsilon(i)`` (returning `\varepsilon_i(x)`)
67
+
68
+ - ``x.phi(i)`` (returning `\varphi_i(x)`)
69
+
70
+ EXAMPLES::
71
+
72
+ sage: from sage.misc.abstract_method import abstract_methods_of_class
73
+ sage: abstract_methods_of_class(Crystals().element_class)
74
+ {'optional': [], 'required': ['e', 'epsilon', 'f', 'phi', 'weight']}
75
+
76
+ TESTS::
77
+
78
+ sage: TestSuite(C).run()
79
+ sage: B = Crystals().example()
80
+ sage: TestSuite(B).run(verbose = True)
81
+ running ._test_an_element() . . . pass
82
+ running ._test_cardinality() . . . pass
83
+ running ._test_category() . . . pass
84
+ running ._test_construction() . . . pass
85
+ running ._test_elements() . . .
86
+ Running the test suite of self.an_element()
87
+ running ._test_category() . . . pass
88
+ running ._test_eq() . . . pass
89
+ running ._test_new() . . . pass
90
+ running ._test_not_implemented_methods() . . . pass
91
+ running ._test_pickling() . . . pass
92
+ running ._test_stembridge_local_axioms() . . . pass
93
+ pass
94
+ running ._test_elements_eq_reflexive() . . . pass
95
+ running ._test_elements_eq_symmetric() . . . pass
96
+ running ._test_elements_eq_transitive() . . . pass
97
+ running ._test_elements_neq() . . . pass
98
+ running ._test_enumerated_set_contains() . . . pass
99
+ running ._test_enumerated_set_iter_cardinality() . . . pass
100
+ running ._test_enumerated_set_iter_list() . . . pass
101
+ running ._test_eq() . . . pass
102
+ running ._test_fast_iter() . . . pass
103
+ running ._test_new() . . . pass
104
+ running ._test_not_implemented_methods() . . . pass
105
+ running ._test_pickling() . . . pass
106
+ running ._test_some_elements() . . . pass
107
+ running ._test_stembridge_local_axioms() . . . pass
108
+ """
109
+
110
+ def super_categories(self):
111
+ r"""
112
+ EXAMPLES::
113
+
114
+ sage: Crystals().super_categories()
115
+ [Category of enumerated sets]
116
+ """
117
+ return [EnumeratedSets()]
118
+
119
+ def example(self, choice='highwt', **kwds):
120
+ r"""
121
+ Return an example of a crystal, as per
122
+ :meth:`Category.example()
123
+ <sage.categories.category.Category.example>`.
124
+
125
+ INPUT:
126
+
127
+ - ``choice`` -- string (default: ``'highwt'``); can be either ``'highwt'``
128
+ for the highest weight crystal of type A, or ``'naive'`` for an
129
+ example of a broken crystal
130
+
131
+ - ``**kwds`` -- keyword arguments passed onto the constructor for the
132
+ chosen crystal
133
+
134
+ EXAMPLES::
135
+
136
+ sage: Crystals().example(choice='highwt', n=5)
137
+ Highest weight crystal of type A_5 of highest weight omega_1
138
+ sage: Crystals().example(choice='naive')
139
+ A broken crystal, defined by digraph, of dimension five.
140
+ """
141
+ import sage.categories.examples.crystals as examples
142
+ if choice == "naive":
143
+ return examples.NaiveCrystal(**kwds)
144
+ else:
145
+ from sage.rings.integer import Integer
146
+ if isinstance(choice, Integer):
147
+ return examples.HighestWeightCrystalOfTypeA(n=choice, **kwds)
148
+ else:
149
+ return examples.HighestWeightCrystalOfTypeA(**kwds)
150
+
151
+ class MorphismMethods:
152
+ @cached_method
153
+ def is_isomorphism(self):
154
+ """
155
+ Check if ``self`` is a crystal isomorphism.
156
+
157
+ EXAMPLES::
158
+
159
+ sage: B = crystals.Tableaux(['C',2], shape=[1,1])
160
+ sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
161
+ sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
162
+ sage: psi.is_isomorphism()
163
+ False
164
+ """
165
+ if self.domain().cardinality() != self.codomain().cardinality():
166
+ return False
167
+ if self.domain().cardinality() == float('inf'):
168
+ raise NotImplementedError("unable to determine if an isomorphism")
169
+
170
+ index_set = self._cartan_type.index_set()
171
+ G = self.domain().digraph(index_set=index_set)
172
+ if self.codomain().cardinality() != G.num_verts():
173
+ return False
174
+ H = self.codomain().digraph(index_set=index_set)
175
+ return G.is_isomorphic(H, edge_labels=True)
176
+
177
+ # TODO: This could be moved to sets
178
+ @cached_method
179
+ def is_embedding(self):
180
+ """
181
+ Check if ``self`` is an injective crystal morphism.
182
+
183
+ EXAMPLES::
184
+
185
+ sage: B = crystals.Tableaux(['C',2], shape=[1,1])
186
+ sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
187
+ sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
188
+ sage: psi.is_embedding()
189
+ True
190
+
191
+ sage: C = crystals.Tableaux(['A',2], shape=[2,1])
192
+ sage: B = crystals.infinity.Tableaux(['A',2])
193
+ sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
194
+ sage: W = crystals.elementary.T(['A',2], La[1]+La[2])
195
+ sage: T = W.tensor(B)
196
+ sage: mg = T(W.module_generators[0], B.module_generators[0])
197
+ sage: psi = Hom(C,T)([mg])
198
+ sage: psi.is_embedding()
199
+ True
200
+ """
201
+ if self.domain().cardinality() > self.codomain().cardinality():
202
+ return False
203
+ if self.domain().cardinality() == float('inf'):
204
+ raise NotImplementedError("unable to determine if an embedding")
205
+ S = set()
206
+ for x in self.domain():
207
+ y = self(x)
208
+ if y is None or y in S:
209
+ return False
210
+ S.add(y)
211
+ return True
212
+
213
+ @cached_method
214
+ def is_strict(self):
215
+ """
216
+ Check if ``self`` is a strict crystal morphism.
217
+
218
+ EXAMPLES::
219
+
220
+ sage: B = crystals.Tableaux(['C',2], shape=[1,1])
221
+ sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
222
+ sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
223
+ sage: psi.is_strict()
224
+ True
225
+ """
226
+ if self.domain().cardinality() == float('inf'):
227
+ raise NotImplementedError("unable to determine if strict")
228
+ index_set = self._cartan_type.index_set()
229
+ for x in self.domain():
230
+ y = self(x)
231
+ if any(self(x.f(i)) != y.f(i) or self(x.e(i)) != y.e(i)
232
+ for i in index_set):
233
+ return False
234
+ return True
235
+
236
+ class ParentMethods:
237
+
238
+ def an_element(self):
239
+ """
240
+ Return an element of ``self``.
241
+
242
+ sage: C = crystals.Letters(['A', 5])
243
+ sage: C.an_element()
244
+ 1
245
+ """
246
+ return self.first()
247
+
248
+ @cached_method
249
+ def weight_lattice_realization(self):
250
+ """
251
+ Return the weight lattice realization used to express weights
252
+ in ``self``.
253
+
254
+ This default implementation uses the ambient space of the
255
+ root system for (non relabelled) finite types and the
256
+ weight lattice otherwise. This is a legacy from when
257
+ ambient spaces were partially implemented, and may be
258
+ changed in the future.
259
+
260
+ For affine types, this returns the extended weight lattice
261
+ by default.
262
+
263
+ EXAMPLES::
264
+
265
+ sage: C = crystals.Letters(['A', 5])
266
+ sage: C.weight_lattice_realization()
267
+ Ambient space of the Root system of type ['A', 5]
268
+ sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1)
269
+ sage: K.weight_lattice_realization()
270
+ Weight lattice of the Root system of type ['A', 2, 1]
271
+
272
+ TESTS:
273
+
274
+ Check that crystals have the correct weight lattice realization::
275
+
276
+ sage: A = crystals.KirillovReshetikhin(['A',2,1], 1, 1).affinization()
277
+ sage: A.weight_lattice_realization()
278
+ Extended weight lattice of the Root system of type ['A', 2, 1]
279
+
280
+ sage: B = crystals.AlcovePaths(['A',2,1],[1,0,0])
281
+ sage: B.weight_lattice_realization()
282
+ Extended weight lattice of the Root system of type ['A', 2, 1]
283
+
284
+ sage: C = crystals.AlcovePaths("B3",[1,0,0])
285
+ sage: C.weight_lattice_realization()
286
+ Ambient space of the Root system of type ['B', 3]
287
+
288
+ sage: M = crystals.infinity.NakajimaMonomials(['A',3,2])
289
+ sage: M.weight_lattice_realization()
290
+ Extended weight lattice of the Root system of type ['B', 2, 1]^*
291
+ sage: M = crystals.infinity.NakajimaMonomials(['A',2])
292
+ sage: M.weight_lattice_realization()
293
+ Ambient space of the Root system of type ['A', 2]
294
+ sage: A = CartanMatrix([[2,-3],[-3,2]])
295
+ sage: M = crystals.infinity.NakajimaMonomials(A)
296
+ sage: M.weight_lattice_realization()
297
+ Weight lattice of the Root system of type Dynkin diagram of rank 2
298
+
299
+ sage: Y = crystals.infinity.GeneralizedYoungWalls(3)
300
+ sage: Y.weight_lattice_realization()
301
+ Extended weight lattice of the Root system of type ['A', 3, 1]
302
+ """
303
+ F = self.cartan_type().root_system()
304
+ if self.cartan_type().is_finite() and F.ambient_space() is not None:
305
+ return F.ambient_space()
306
+ if self.cartan_type().is_affine():
307
+ return F.weight_lattice(extended=True)
308
+ return F.weight_lattice()
309
+
310
+ def cartan_type(self):
311
+ """
312
+ Return the Cartan type of the crystal.
313
+
314
+ EXAMPLES::
315
+
316
+ sage: C = crystals.Letters(['A',2])
317
+ sage: C.cartan_type()
318
+ ['A', 2]
319
+ """
320
+ return self._cartan_type
321
+
322
+ @cached_method
323
+ def index_set(self):
324
+ """
325
+ Return the index set of the Dynkin diagram underlying the crystal.
326
+
327
+ EXAMPLES::
328
+
329
+ sage: C = crystals.Letters(['A', 5])
330
+ sage: C.index_set()
331
+ (1, 2, 3, 4, 5)
332
+ """
333
+ return self.cartan_type().index_set()
334
+
335
+ def Lambda(self):
336
+ """
337
+ Return the fundamental weights in the weight lattice
338
+ realization for the root system associated with the crystal
339
+
340
+ EXAMPLES::
341
+
342
+ sage: C = crystals.Letters(['A', 5])
343
+ sage: C.Lambda()
344
+ Finite family {1: (1, 0, 0, 0, 0, 0), 2: (1, 1, 0, 0, 0, 0), 3: (1, 1, 1, 0, 0, 0), 4: (1, 1, 1, 1, 0, 0), 5: (1, 1, 1, 1, 1, 0)}
345
+ """
346
+ return self.weight_lattice_realization().fundamental_weights()
347
+
348
+ def __iter__(self, index_set=None, max_depth=float('inf')):
349
+ """
350
+ Return an iterator over the elements of ``self``.
351
+
352
+ INPUT:
353
+
354
+ - ``index_set`` -- (default: ``None``) the index set; if ``None``
355
+ then use the index set of the crystal
356
+
357
+ - ``max_depth`` -- (default: infinity) the maximum depth to build
358
+
359
+ The iteration order is not specified except that, if
360
+ ``max_depth`` is finite, then the iteration goes depth by
361
+ depth.
362
+
363
+ EXAMPLES::
364
+
365
+ sage: C = crystals.LSPaths(['A',2,1],[-1,0,1])
366
+ sage: C.__iter__.__module__
367
+ 'sage.categories.crystals'
368
+ sage: g = C.__iter__()
369
+ sage: for _ in range(5): next(g)
370
+ (-Lambda[0] + Lambda[2],)
371
+ (Lambda[1] - Lambda[2],)
372
+ (Lambda[0] - Lambda[1] + delta,)
373
+ (Lambda[0] - Lambda[1],)
374
+ (Lambda[1] - Lambda[2] + delta,)
375
+
376
+ sage: sorted(C.__iter__(index_set=[1,2]), key=str)
377
+ [(-Lambda[0] + Lambda[2],),
378
+ (Lambda[0] - Lambda[1],),
379
+ (Lambda[1] - Lambda[2],)]
380
+
381
+ sage: sorted(C.__iter__(max_depth=1), key=str)
382
+ [(-Lambda[0] + Lambda[2],),
383
+ (Lambda[0] - Lambda[1] + delta,),
384
+ (Lambda[1] - Lambda[2],)]
385
+ """
386
+ if index_set is None:
387
+ index_set = self.index_set()
388
+ succ = lambda x: [x.f(i) for i in index_set] + [x.e(i) for i in index_set]
389
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
390
+ R = RecursivelyEnumeratedSet(self.module_generators, succ, structure=None)
391
+ return R.breadth_first_search_iterator(max_depth)
392
+
393
+ def subcrystal(self, index_set=None, generators=None, max_depth=float('inf'),
394
+ direction='both', contained=None,
395
+ virtualization=None, scaling_factors=None,
396
+ cartan_type=None, category=None):
397
+ r"""
398
+ Construct the subcrystal from ``generators`` using `e_i` and/or
399
+ `f_i` for all `i` in ``index_set``.
400
+
401
+ INPUT:
402
+
403
+ - ``index_set`` -- (default: ``None``) the index set; if ``None``
404
+ then use the index set of the crystal
405
+
406
+ - ``generators`` -- (default: ``None``) the list of generators; if
407
+ ``None`` then use the module generators of the crystal
408
+
409
+ - ``max_depth`` -- (default: infinity) the maximum depth to build
410
+
411
+ - ``direction`` -- (default: ``'both'``) the direction to build
412
+ the subcrystal; it can be one of the following:
413
+
414
+ - ``'both'`` -- using both `e_i` and `f_i`
415
+ - ``'upper'`` -- using `e_i`
416
+ - ``'lower'`` -- using `f_i`
417
+
418
+ - ``contained`` -- (optional) a set or function defining the
419
+ containment in the subcrystal
420
+
421
+ - ``virtualization``, ``scaling_factors`` -- (optional)
422
+ dictionaries whose key `i` corresponds to the sets `\sigma_i`
423
+ and `\gamma_i` respectively used to define virtual crystals; see
424
+ :class:`~sage.combinat.crystals.virtual_crystal.VirtualCrystal`
425
+
426
+ - ``cartan_type`` -- (optional) specify the Cartan type of the
427
+ subcrystal
428
+
429
+ - ``category`` -- (optional) specify the category of the subcrystal
430
+
431
+ EXAMPLES::
432
+
433
+ sage: C = crystals.KirillovReshetikhin(['A',3,1], 1, 2)
434
+ sage: S = list(C.subcrystal(index_set=[1,2])); S
435
+ [[[1, 1]], [[1, 2]], [[2, 2]], [[1, 3]], [[2, 3]], [[3, 3]]]
436
+ sage: C.cardinality()
437
+ 10
438
+ sage: len(S)
439
+ 6
440
+ sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)]))
441
+ [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
442
+ sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], max_depth=1))
443
+ [[[1, 4]], [[2, 4]], [[1, 3]]]
444
+ sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='upper'))
445
+ [[[1, 4]], [[1, 3]]]
446
+ sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='lower'))
447
+ [[[1, 4]], [[2, 4]]]
448
+
449
+ sage: G = C.subcrystal(index_set=[1,2,3]).digraph()
450
+ sage: GA = crystals.Tableaux('A3', shape=[2]).digraph()
451
+ sage: G.is_isomorphic(GA, edge_labels=True)
452
+ True
453
+
454
+ We construct the subcrystal which contains the necessary data
455
+ to construct the corresponding dual equivalence graph::
456
+
457
+ sage: C = crystals.Tableaux(['A',5], shape=[3,3])
458
+ sage: is_wt0 = lambda x: all(x.epsilon(i) == x.phi(i) for i in x.parent().index_set())
459
+ sage: def check(x):
460
+ ....: if is_wt0(x):
461
+ ....: return True
462
+ ....: for i in x.parent().index_set()[:-1]:
463
+ ....: L = [x.e(i), x.e_string([i,i+1]), x.f(i), x.f_string([i,i+1])]
464
+ ....: if any(y is not None and is_wt0(y) for y in L):
465
+ ....: return True
466
+ ....: return False
467
+ sage: wt0 = [x for x in C if is_wt0(x)]
468
+ sage: S = C.subcrystal(contained=check, generators=wt0)
469
+ sage: S.module_generators[0]
470
+ [[1, 3, 5], [2, 4, 6]]
471
+ sage: S.module_generators[0].e(2).e(3).f(2).f(3)
472
+ [[1, 2, 5], [3, 4, 6]]
473
+
474
+ An example of a type `B_2` virtual crystal inside of a
475
+ type `A_3` ambient crystal::
476
+
477
+ sage: A = crystals.Tableaux(['A',3], shape=[2,1,1])
478
+ sage: S = A.subcrystal(virtualization={1:[1,3], 2:[2]},
479
+ ....: scaling_factors={1:1,2:1}, cartan_type=['B',2])
480
+ sage: B = crystals.Tableaux(['B',2], shape=[1])
481
+ sage: S.digraph().is_isomorphic(B.digraph(), edge_labels=True)
482
+ True
483
+
484
+ TESTS:
485
+
486
+ Check that :issue:`23942` is fixed::
487
+
488
+ sage: B = crystals.infinity.Tableaux(['A',2])
489
+ sage: S = B.subcrystal(max_depth=3, category=HighestWeightCrystals())
490
+ sage: S.category()
491
+ Category of finite highest weight crystals
492
+
493
+ sage: K = crystals.KirillovReshetikhin(['A',3,1], 2,3)
494
+ sage: S = K.subcrystal(index_set=[1,3], category=HighestWeightCrystals())
495
+ sage: S.category()
496
+ Category of finite highest weight crystals
497
+ """
498
+ from sage.combinat.crystals.subcrystal import Subcrystal
499
+ from sage.categories.finite_crystals import FiniteCrystals
500
+
501
+ if cartan_type is None:
502
+ cartan_type = self.cartan_type()
503
+ else:
504
+ from sage.combinat.root_system.cartan_type import CartanType
505
+ cartan_type = CartanType(cartan_type)
506
+ if index_set is None:
507
+ index_set = cartan_type.index_set()
508
+ if generators is None:
509
+ generators = self.module_generators
510
+
511
+ if max_depth == float('inf'):
512
+ if self not in FiniteCrystals():
513
+ if (contained is None and index_set == self.index_set()
514
+ and generators == self.module_generators
515
+ and scaling_factors is None and virtualization is None):
516
+ return self
517
+ return Subcrystal(self, contained, generators,
518
+ virtualization, scaling_factors,
519
+ cartan_type, index_set, category)
520
+
521
+ # else self is a finite crystal
522
+ if direction == 'both':
523
+ if category is None:
524
+ category = FiniteCrystals()
525
+ else:
526
+ category = FiniteCrystals() & category
527
+ return Subcrystal(self, contained, generators,
528
+ virtualization, scaling_factors,
529
+ cartan_type, index_set, category)
530
+
531
+ # TODO: Make this work for virtual crystals as well
532
+ if direction == 'both':
533
+ succ = lambda x: [x.f(i) for i in index_set] + [x.e(i) for i in index_set]
534
+ elif direction == 'upper':
535
+ succ = lambda x: [x.e(i) for i in index_set]
536
+ elif direction == 'lower':
537
+ succ = lambda x: [x.f(i) for i in index_set]
538
+ else:
539
+ raise ValueError("direction must be either 'both', 'upper', or 'lower'")
540
+
541
+ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
542
+ subset = RecursivelyEnumeratedSet(generators, succ,
543
+ structure=None, enumeration='breadth',
544
+ max_depth=max_depth)
545
+
546
+ # We perform the filtering here since checking containment
547
+ # in a frozenset should be fast
548
+ if contained is not None:
549
+ try:
550
+ subset = frozenset(x for x in subset if x in contained)
551
+ except TypeError: # It does not have a containment test
552
+ subset = frozenset(x for x in subset if contained(x))
553
+ else:
554
+ subset = frozenset(subset)
555
+
556
+ if category is None:
557
+ category = FiniteCrystals()
558
+ else:
559
+ category = FiniteCrystals() & category
560
+
561
+ if self in FiniteCrystals() and len(subset) == self.cardinality():
562
+ if index_set == self.index_set():
563
+ return self
564
+
565
+ return Subcrystal(self, subset, generators,
566
+ virtualization, scaling_factors,
567
+ cartan_type, index_set, category)
568
+
569
+ def _Hom_(self, Y, category=None, **options):
570
+ r"""
571
+ Return the homset from ``self`` to ``Y`` in the
572
+ category ``category``.
573
+
574
+ INPUT:
575
+
576
+ - ``Y`` -- a crystal
577
+ - ``category`` -- a subcategory of :class:`Crystals`() or ``None``
578
+
579
+ The sole purpose of this method is to construct the homset
580
+ as a :class:`~sage.categories.crystals.CrystalHomset`. If
581
+ ``category`` is specified and is not a subcategory of
582
+ :class:`Crystals`, a :exc:`TypeError` is raised instead.
583
+
584
+ This method is not meant to be called directly. Please use
585
+ :func:`sage.categories.homset.Hom` instead.
586
+
587
+ EXAMPLES::
588
+
589
+ sage: B = crystals.elementary.B(['A',2], 1)
590
+ sage: H = B._Hom_(B); H
591
+ Set of Crystal Morphisms from The 1-elementary crystal of type ['A', 2]
592
+ to The 1-elementary crystal of type ['A', 2]
593
+ """
594
+ if category is None:
595
+ category = self.category()
596
+ elif not category.is_subcategory(Crystals()):
597
+ raise TypeError("{} is not a subcategory of Crystals()".format(category))
598
+ if Y not in Crystals():
599
+ raise TypeError("{} is not a crystal".format(Y))
600
+ return CrystalHomset(self, Y, category=category, **options)
601
+
602
+ def crystal_morphism(self, on_gens, codomain=None,
603
+ cartan_type=None, index_set=None, generators=None,
604
+ automorphism=None,
605
+ virtualization=None, scaling_factors=None,
606
+ category=None, check=True):
607
+ r"""
608
+ Construct a crystal morphism from ``self`` to another crystal
609
+ ``codomain``.
610
+
611
+ INPUT:
612
+
613
+ - ``on_gens`` -- a function or list that determines the image
614
+ of the generators (if given a list, then this uses the order
615
+ of the generators of the domain) of ``self`` under the
616
+ crystal morphism
617
+ - ``codomain`` -- (default: ``self``) the codomain of the morphism
618
+ - ``cartan_type`` -- (optional) the Cartan type of the morphism;
619
+ the default is the Cartan type of ``self``
620
+ - ``index_set`` -- (optional) the index set of the morphism;
621
+ the default is the index set of the Cartan type
622
+ - ``generators`` -- (optional) the generators to define the
623
+ morphism; the default is the generators of ``self``
624
+ - ``automorphism`` -- (optional) the automorphism to perform the
625
+ twisting
626
+ - ``virtualization`` -- (optional) a dictionary whose keys are
627
+ in the index set of the domain and whose values are lists of
628
+ entries in the index set of the codomain; the default is the
629
+ identity dictionary
630
+ - ``scaling_factors`` -- (optional) a dictionary whose keys are
631
+ in the index set of the domain and whose values are scaling
632
+ factors for the weight, `\varepsilon` and `\varphi`; the
633
+ default are all scaling factors to be one
634
+ - ``category`` -- (optional) the category for the crystal morphism;
635
+ the default is the category of :class:`Crystals`.
636
+ - ``check`` -- boolean (default: ``True``); check if the crystal
637
+ morphism is valid
638
+
639
+ .. SEEALSO::
640
+
641
+ For more examples, see
642
+ :class:`sage.categories.crystals.CrystalHomset`.
643
+
644
+ EXAMPLES:
645
+
646
+ We construct the natural embedding of a crystal using tableaux
647
+ into the tensor product of single boxes via the reading word::
648
+
649
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
650
+ sage: F = crystals.Tableaux(['A',2], shape=[1])
651
+ sage: T = crystals.TensorProduct(F, F, F)
652
+ sage: mg = T.highest_weight_vectors()[2]; mg
653
+ [[[1]], [[2]], [[1]]]
654
+ sage: psi = B.crystal_morphism([mg], codomain=T); psi
655
+ ['A', 2] Crystal morphism:
656
+ From: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
657
+ To: Full tensor product of the crystals
658
+ [The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
659
+ The crystal of tableaux of type ['A', 2] and shape(s) [[1]],
660
+ The crystal of tableaux of type ['A', 2] and shape(s) [[1]]]
661
+ Defn: [[1, 1], [2]] |--> [[[1]], [[2]], [[1]]]
662
+ sage: b = B.module_generators[0]
663
+ sage: b.pp()
664
+ 1 1
665
+ 2
666
+ sage: psi(b)
667
+ [[[1]], [[2]], [[1]]]
668
+ sage: psi(b.f(2))
669
+ [[[1]], [[3]], [[1]]]
670
+ sage: psi(b.f_string([2,1,1]))
671
+ [[[2]], [[3]], [[2]]]
672
+ sage: lw = b.to_lowest_weight()[0]
673
+ sage: lw.pp()
674
+ 2 3
675
+ 3
676
+ sage: psi(lw)
677
+ [[[3]], [[3]], [[2]]]
678
+ sage: psi(lw) == mg.to_lowest_weight()[0]
679
+ True
680
+
681
+ We now take the other isomorphic highest weight component
682
+ in the tensor product::
683
+
684
+ sage: mg = T.highest_weight_vectors()[1]; mg
685
+ [[[2]], [[1]], [[1]]]
686
+ sage: psi = B.crystal_morphism([mg], codomain=T)
687
+ sage: psi(lw)
688
+ [[[3]], [[2]], [[3]]]
689
+
690
+ We construct a crystal morphism of classical crystals using a
691
+ Kirillov-Reshetikhin crystal::
692
+
693
+ sage: B = crystals.Tableaux(['D', 4], shape=[1,1])
694
+ sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,2)
695
+ sage: K.module_generators
696
+ [[], [[1], [2]], [[1, 1], [2, 2]]]
697
+ sage: v = K.module_generators[1]
698
+ sage: psi = B.crystal_morphism([v], codomain=K, category=FiniteCrystals())
699
+ sage: psi
700
+ ['D', 4] -> ['D', 4, 1] Virtual Crystal morphism:
701
+ From: The crystal of tableaux of type ['D', 4] and shape(s) [[1, 1]]
702
+ To: Kirillov-Reshetikhin crystal of type ['D', 4, 1] with (r,s)=(2,2)
703
+ Defn: [[1], [2]] |--> [[1], [2]]
704
+ sage: b = B.module_generators[0]
705
+ sage: psi(b)
706
+ [[1], [2]]
707
+ sage: psi(b.to_lowest_weight()[0])
708
+ [[-2], [-1]]
709
+
710
+ We can define crystal morphisms using a different set of
711
+ generators. For example, we construct an example using the
712
+ lowest weight vector::
713
+
714
+ sage: B = crystals.Tableaux(['A',2], shape=[1])
715
+ sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
716
+ sage: T = crystals.elementary.T(['A',2], La[2])
717
+ sage: Bp = T.tensor(B)
718
+ sage: C = crystals.Tableaux(['A',2], shape=[2,1])
719
+ sage: x = C.module_generators[0].f_string([1,2])
720
+ sage: psi = Bp.crystal_morphism([x], generators=Bp.lowest_weight_vectors())
721
+ sage: psi(Bp.highest_weight_vector())
722
+ [[1, 1], [2]]
723
+
724
+ We can also use a dictionary to specify the generators and
725
+ their images::
726
+
727
+ sage: psi = Bp.crystal_morphism({Bp.lowest_weight_vectors()[0]: x})
728
+ sage: psi(Bp.highest_weight_vector())
729
+ [[1, 1], [2]]
730
+
731
+ We construct a twisted crystal morphism induced from the diagram
732
+ automorphism of type `A_3^{(1)}`::
733
+
734
+ sage: La = RootSystem(['A',3,1]).weight_lattice(extended=True).fundamental_weights()
735
+ sage: B0 = crystals.GeneralizedYoungWalls(3, La[0])
736
+ sage: B1 = crystals.GeneralizedYoungWalls(3, La[1])
737
+ sage: phi = B0.crystal_morphism(B1.module_generators, automorphism={0:1, 1:2, 2:3, 3:0})
738
+ sage: phi
739
+ ['A', 3, 1] Twisted Crystal morphism:
740
+ From: Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[0]
741
+ To: Highest weight crystal of generalized Young walls of Cartan type ['A', 3, 1] and highest weight Lambda[1]
742
+ Defn: [] |--> []
743
+ sage: x = B0.module_generators[0].f_string([0,1,2,3]); x
744
+ [[0, 3], [1], [2]]
745
+ sage: phi(x)
746
+ [[], [1, 0], [2], [3]]
747
+
748
+ We construct a virtual crystal morphism from type `G_2` into
749
+ type `D_4`::
750
+
751
+ sage: D = crystals.Tableaux(['D',4], shape=[1,1])
752
+ sage: G = crystals.Tableaux(['G',2], shape=[1])
753
+ sage: psi = G.crystal_morphism(D.module_generators,
754
+ ....: virtualization={1:[2],2:[1,3,4]},
755
+ ....: scaling_factors={1:1, 2:1})
756
+ sage: for x in G:
757
+ ....: ascii_art(x, psi(x), sep=' |--> ')
758
+ ....: print("")
759
+ 1
760
+ 1 |--> 2
761
+ <BLANKLINE>
762
+ 1
763
+ 2 |--> 3
764
+ <BLANKLINE>
765
+ 2
766
+ 3 |--> -3
767
+ <BLANKLINE>
768
+ 3
769
+ 0 |--> -3
770
+ <BLANKLINE>
771
+ 3
772
+ -3 |--> -2
773
+ <BLANKLINE>
774
+ -3
775
+ -2 |--> -1
776
+ <BLANKLINE>
777
+ -2
778
+ -1 |--> -1
779
+ """
780
+ # Determine the codomain
781
+ if codomain is None:
782
+ if hasattr(on_gens, 'codomain'):
783
+ codomain = on_gens.codomain()
784
+ elif isinstance(on_gens, collections.abc.Sequence):
785
+ if on_gens:
786
+ codomain = on_gens[0].parent()
787
+ elif isinstance(on_gens, collections.abc.Mapping):
788
+ if on_gens:
789
+ codomain = next(iter(on_gens.values())).parent()
790
+ else:
791
+ for x in self.module_generators:
792
+ y = on_gens(x)
793
+ if y is not None:
794
+ codomain = y.parent()
795
+ break
796
+ if codomain is None:
797
+ codomain = self
798
+ elif codomain not in Crystals():
799
+ raise ValueError("the codomain must be a crystal")
800
+
801
+ homset = Hom(self, codomain, category=category)
802
+ return homset(on_gens, cartan_type, index_set, generators,
803
+ automorphism, virtualization, scaling_factors, check)
804
+
805
+ def digraph(self, subset=None, index_set=None):
806
+ """
807
+ Return the :class:`DiGraph` associated to ``self``.
808
+
809
+ INPUT:
810
+
811
+ - ``subset`` -- (optional) a subset of vertices for
812
+ which the digraph should be constructed
813
+
814
+ - ``index_set`` -- (optional) the index set to draw arrows
815
+
816
+ EXAMPLES::
817
+
818
+ sage: C = Crystals().example(5)
819
+ sage: C.digraph()
820
+ Digraph on 6 vertices
821
+
822
+ The edges of the crystal graph are by default colored using
823
+ blue for edge 1, red for edge 2, and green for edge 3::
824
+
825
+ sage: C = Crystals().example(3)
826
+ sage: G = C.digraph()
827
+ sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
828
+
829
+ One may also overwrite the colors::
830
+
831
+ sage: C = Crystals().example(3)
832
+ sage: G = C.digraph()
833
+ sage: G.set_latex_options(color_by_label = {1:"red", 2:"purple", 3:"blue"})
834
+ sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
835
+
836
+ Or one may add colors to yet unspecified edges::
837
+
838
+ sage: C = Crystals().example(4)
839
+ sage: G = C.digraph()
840
+ sage: C.cartan_type()._index_set_coloring[4]="purple"
841
+ sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
842
+
843
+ Here is an example of how to take the top part up to a
844
+ given depth of an infinite dimensional crystal::
845
+
846
+ sage: C = CartanType(['C',2,1])
847
+ sage: La = C.root_system().weight_lattice().fundamental_weights()
848
+ sage: T = crystals.HighestWeight(La[0])
849
+ sage: S = T.subcrystal(max_depth=3)
850
+ sage: G = T.digraph(subset=S); G
851
+ Digraph on 5 vertices
852
+ sage: G.vertices(sort=True, key=str)
853
+ [(-Lambda[0] + 2*Lambda[1] - delta,),
854
+ (1/2*Lambda[0] + Lambda[1] - Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
855
+ (1/2*Lambda[0] - Lambda[1] + Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
856
+ (Lambda[0] - 2*Lambda[1] + 2*Lambda[2] - delta,),
857
+ (Lambda[0],)]
858
+
859
+ Here is a way to construct a picture of a Demazure crystal using
860
+ the ``subset`` option::
861
+
862
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
863
+ sage: t = B.highest_weight_vector()
864
+ sage: D = B.demazure_subcrystal(t, [2,1])
865
+ sage: list(D)
866
+ [[[1, 1], [2]], [[1, 2], [2]], [[1, 1], [3]],
867
+ [[1, 3], [2]], [[1, 3], [3]]]
868
+ sage: view(D) # optional - dot2tex graphviz, not tested (opens external window)
869
+
870
+ We can also choose to display particular arrows using the
871
+ ``index_set`` option::
872
+
873
+ sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1)
874
+ sage: G = C.digraph(index_set=[1,3])
875
+ sage: len(G.edges(sort=False))
876
+ 20
877
+ sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
878
+
879
+ TESTS:
880
+
881
+ We check that infinite crystals raise an error (:issue:`21986`)::
882
+
883
+ sage: B = crystals.infinity.Tableaux(['A',2])
884
+ sage: B.digraph()
885
+ Traceback (most recent call last):
886
+ ...
887
+ NotImplementedError: crystals not known to be finite
888
+ must specify either the subset or depth
889
+ sage: B.digraph(depth=10)
890
+ Digraph on 161 vertices
891
+
892
+ .. TODO:: Add more tests.
893
+ """
894
+ from sage.graphs.digraph import DiGraph
895
+ d = {}
896
+
897
+ # Parse optional arguments
898
+ if subset is None:
899
+ if self not in Crystals().Finite():
900
+ raise NotImplementedError("crystals not known to be finite"
901
+ " must specify the subset")
902
+ subset = self
903
+ if index_set is None:
904
+ index_set = self.index_set()
905
+
906
+ for x in subset:
907
+ d[x] = {}
908
+ for i in index_set:
909
+ child = x.f(i)
910
+ if child is None or child not in subset:
911
+ continue
912
+ d[x][child] = i
913
+ G = DiGraph(d)
914
+ from sage.graphs.dot2tex_utils import have_dot2tex
915
+ if have_dot2tex():
916
+ G.set_latex_options(format='dot2tex',
917
+ edge_labels=True,
918
+ color_by_label=self.cartan_type()._index_set_coloring)
919
+ return G
920
+
921
+ def latex_file(self, filename):
922
+ r"""
923
+ Export a file, suitable for pdflatex, to ``filename``.
924
+
925
+ This requires
926
+ a proper installation of ``dot2tex`` in sage-python. For more
927
+ information see the documentation for ``self.latex()``.
928
+
929
+ EXAMPLES::
930
+
931
+ sage: C = crystals.Letters(['A', 5])
932
+ sage: fn = tmp_filename(ext='.tex')
933
+ sage: C.latex_file(fn)
934
+ """
935
+ header = r"""\documentclass{article}
936
+ \usepackage[x11names, rgb]{xcolor}
937
+ \usepackage[utf8]{inputenc}
938
+ \usepackage{tikz}
939
+ \usetikzlibrary{snakes,arrows,shapes}
940
+ \usepackage{amsmath}
941
+ \usepackage[active,tightpage]{preview}
942
+ \newenvironment{bla}{}{}
943
+ \PreviewEnvironment{bla}
944
+
945
+ \begin{document}
946
+ \begin{bla}"""
947
+
948
+ footer = r"""\end{bla}
949
+ \end{document}"""
950
+
951
+ f = open(filename, 'w')
952
+ f.write(header + self.latex() + footer)
953
+ f.close()
954
+
955
+ def _latex_(self, **options):
956
+ r"""
957
+ Return the crystal graph as a latex string. This can be exported
958
+ to a file with ``self.latex_file('filename')``.
959
+
960
+ EXAMPLES::
961
+
962
+ sage: T = crystals.Tableaux(['A',2],shape=[1])
963
+ sage: T._latex_()
964
+ '...tikzpicture...'
965
+ sage: view(T) # optional - dot2tex graphviz, not tested (opens external window)
966
+
967
+ One can for example also color the edges using the following options::
968
+
969
+ sage: T = crystals.Tableaux(['A',2],shape=[1])
970
+ sage: T._latex_(color_by_label={0:"black", 1:"red", 2:"blue"})
971
+ '...tikzpicture...'
972
+ """
973
+ G = self.digraph()
974
+ G.set_latex_options(**options)
975
+ return G._latex_()
976
+
977
+ latex = _latex_
978
+
979
+ def metapost(self, filename, thicklines=False, labels=True, scaling_factor=1.0, tallness=1.0):
980
+ r"""
981
+ Export a file, suitable for MetaPost, to ``filename``.
982
+
983
+ Root operators `e(1)` or `f(1)` move along red lines, `e(2)` or `f(2)`
984
+ along green. The highest weight is in the lower left. Vertices with
985
+ the same weight are kept close together. The concise labels on the
986
+ nodes are strings introduced by Berenstein and Zelevinsky and
987
+ Littelmann; see Littelmann's paper Cones, Crystals, Patterns,
988
+ sections 5 and 6.
989
+
990
+ For Cartan types B2 or C2, the pattern has the form
991
+
992
+ `a_2 a_3 a_4 a_1`
993
+
994
+ where `c*a_2 = a_3 = 2*a_4 = 0` and `a_1=0`, with `c=2` for B2, `c=1` for C2.
995
+ Applying `e(2)` `a_1` times, `e(1)` `a_2` times, `e(2)` `a_3` times, `e(1)` `a_4` times
996
+ returns to the highest weight. (Observe that Littelmann writes the
997
+ roots in opposite of the usual order, so our `e(1)` is his `e(2)` for
998
+ these Cartan types.) For type A2, the pattern has the form
999
+
1000
+ `a_3 a_2 a_1`
1001
+
1002
+ where applying `e(1)` `a_3` times, `e(2)` `a_2` times then `e(1)` `a_1` times
1003
+ returns to the highest weight. These data determine the vertex and
1004
+ may be translated into a Gelfand-Tsetlin pattern or tableau.
1005
+
1006
+ INPUT:
1007
+
1008
+ - ``filename`` -- name of the output file, e.g., ``'filename.mp'``
1009
+
1010
+ - ``thicklines`` -- boolean (default: ``True``); for thicker edges
1011
+
1012
+ - ``labels`` -- boolean (default: ``False``); whether to suppress
1013
+ labeling of the vertices
1014
+
1015
+ - ``scaling_factor`` -- (default: ``1.0``) increasing or decreasing the
1016
+ scaling factor changes the size of the image
1017
+
1018
+ - ``tallness`` -- (default: ``1.0``) increasing makes the image taller
1019
+ without increasing the width
1020
+
1021
+ EXAMPLES::
1022
+
1023
+ sage: C = crystals.Letters(['A', 2])
1024
+ sage: C.metapost(tmp_filename())
1025
+
1026
+ ::
1027
+
1028
+ sage: C = crystals.Letters(['A', 5])
1029
+ sage: C.metapost(tmp_filename())
1030
+ Traceback (most recent call last):
1031
+ ...
1032
+ NotImplementedError
1033
+ """
1034
+ # FIXME: those tests are not robust
1035
+ # Should use instead self.cartan_type() == CartanType(['B',2])
1036
+ if self.cartan_type()[0] == 'B' and self.cartan_type()[1] == 2:
1037
+ word = [2,1,2,1]
1038
+ elif self.cartan_type()[0] == 'C' and self.cartan_type()[1] == 2:
1039
+ word = [2,1,2,1]
1040
+ elif self.cartan_type()[0] == 'A' and self.cartan_type()[1] == 2:
1041
+ word = [1,2,1]
1042
+ else:
1043
+ raise NotImplementedError
1044
+ size = self.cardinality()
1045
+ string_data = []
1046
+ for i in range(size):
1047
+ turtle = self.list()[i]
1048
+ string_datum = []
1049
+ for j in word:
1050
+ turtlewalk = 0
1051
+ while turtle.e(j) is not None:
1052
+ turtle = turtle.e(j)
1053
+ turtlewalk += 1
1054
+ string_datum.append(turtlewalk)
1055
+ string_data.append(string_datum)
1056
+
1057
+ if self.cartan_type()[0] == 'A':
1058
+ if labels:
1059
+ c0 = int(55*scaling_factor)
1060
+ c1 = int(-25*scaling_factor)
1061
+ c2 = int(45*tallness*scaling_factor)
1062
+ c3 = int(-12*scaling_factor)
1063
+ c4 = int(-12*scaling_factor)
1064
+ else:
1065
+ c0 = int(45*scaling_factor)
1066
+ c1 = int(-20*scaling_factor)
1067
+ c2 = int(35*tallness*scaling_factor)
1068
+ c3 = int(12*scaling_factor)
1069
+ c4 = int(-12*scaling_factor)
1070
+ outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\nsx:=35; sy:=30;\n\nz1000=(%d,0);\nz1001=(%d,%d);\nz1002=(%d,%d);\nz2001=(-3,3);\nz2002=(3,3);\nz2003=(0,-3);\nz2004=(7,0);\nz2005=(0,7);\nz2006=(-7,0);\nz2007=(0,7);\n\n" % (c0,c1,c2,c3,c4)
1071
+ else:
1072
+ if labels:
1073
+ outstring = "verbatimtex\n\\magnification=600\netex\n\nbeginfig(-1);\n\nsx := %d;\nsy=%d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-16,-10);\n\nz2001=(0,-3);\nz2002=(-5,3);\nz2003=(0,3);\nz2004=(5,3);\nz2005=(10,1);\nz2006=(0,10);\nz2007=(-10,1);\nz2008=(0,-8);\n\n" % (int(scaling_factor*40),int(tallness*scaling_factor*40))
1074
+ else:
1075
+ outstring = "beginfig(-1);\n\nsx := %d;\nsy := %d;\n\nz1000=(2*sx,0);\nz1001=(-sx,sy);\nz1002=(-5,-5);\n\nz1003=(10,10);\n\n" % (int(scaling_factor*35),int(tallness*scaling_factor*35))
1076
+ for i in range(size):
1077
+ if self.cartan_type()[0] == 'A':
1078
+ [a1,a2,a3] = string_data[i]
1079
+ else:
1080
+ [a1,a2,a3,a4] = string_data[i]
1081
+ shift = 0
1082
+ for j in range(i):
1083
+ if self.cartan_type()[0] == 'A':
1084
+ [b1,b2,b3] = string_data[j]
1085
+ if b1+b3 == a1+a3 and b2 == a2:
1086
+ shift += 1
1087
+ else:
1088
+ [b1,b2,b3,b4] = string_data[j]
1089
+ if b1+b3 == a1+a3 and b2+b4 == a2+a4:
1090
+ shift += 1
1091
+ if self.cartan_type()[0] == 'A':
1092
+ outstring = outstring + "z%d=%d*z1000+%d*z1001+%d*z1002;\n" % (i,a1+a3,a2,shift)
1093
+ else:
1094
+ outstring = outstring + "z%d=%d*z1000+%d*z1001+%d*z1002;\n" % (i,a1+a3,a2+a4,shift)
1095
+ outstring = outstring + "\n"
1096
+ if thicklines:
1097
+ outstring = outstring + "pickup pencircle scaled 2\n\n"
1098
+ for i in range(size):
1099
+ for j in range(1,3):
1100
+ dest = self.list()[i].f(j)
1101
+ if dest is not None:
1102
+ dest = self.list().index(dest)
1103
+ if j == 1:
1104
+ col = "red;"
1105
+ else:
1106
+ col = "green; "
1107
+ if self.cartan_type()[0] == 'A':
1108
+ [a1,a2,a3] = string_data[i] # included to facilitate hand editing of the .mp file
1109
+ outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d\n" % (i,dest,col,a1,a2,a3)
1110
+ else:
1111
+ [a1,a2,a3,a4] = string_data[i]
1112
+ outstring = outstring+"draw z%d--z%d withcolor %s %% %d %d %d %d\n" % (i,dest,col,a1,a2,a3,a4)
1113
+ outstring += "\npickup pencircle scaled 3;\n\n"
1114
+ for i in range(self.cardinality()):
1115
+ if labels:
1116
+ if self.cartan_type()[0] == 'A':
1117
+ outstring = outstring+"pickup pencircle scaled 15;\nfill z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\npickup pencircle scaled .5;\ndraw z%d+z2004..z%d+z2006..z%d+z2006..z%d+z2007..cycle;\n" % (i,i,i,i,string_data[i][2],i,string_data[i][1],i,string_data[i][0],i,i,i,i,i)
1118
+ else:
1119
+ outstring = outstring+"%%%d %d %d %d\npickup pencircle scaled 1;\nfill z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle withcolor white;\nlabel(btex %d etex, z%d+z2001);\nlabel(btex %d etex, z%d+z2002);\nlabel(btex %d etex, z%d+z2003);\nlabel(btex %d etex, z%d+z2004);\npickup pencircle scaled .5;\ndraw z%d+z2005..z%d+z2006..z%d+z2007..z%d+z2008..cycle;\n\n" % (string_data[i][0],string_data[i][1],string_data[i][2],string_data[i][3],i,i,i,i,string_data[i][0],i,string_data[i][1],i,string_data[i][2],i,string_data[i][3],i,i,i,i,i)
1120
+ else:
1121
+ outstring += "drawdot z%d;\n" % i
1122
+ outstring += "\nendfig;\n\nend;\n\n"
1123
+
1124
+ f = open(filename, 'w')
1125
+ f.write(outstring)
1126
+ f.close()
1127
+
1128
+ def dot_tex(self):
1129
+ r"""
1130
+ Return a dot_tex string representation of ``self``.
1131
+
1132
+ EXAMPLES::
1133
+
1134
+ sage: C = crystals.Letters(['A',2])
1135
+ sage: C.dot_tex()
1136
+ 'digraph G { \n node [ shape=plaintext ];\n N_0 [ label = " ", texlbl = "$1$" ];\n N_1 [ label = " ", texlbl = "$2$" ];\n N_2 [ label = " ", texlbl = "$3$" ];\n N_0 -> N_1 [ label = " ", texlbl = "1" ];\n N_1 -> N_2 [ label = " ", texlbl = "2" ];\n}'
1137
+ """
1138
+ import re
1139
+ from sage.combinat import ranker
1140
+
1141
+ rank = ranker.from_list(self.list())[0]
1142
+ vertex_key = lambda x: "N_"+str(rank(x))
1143
+
1144
+ # To do: check the regular expression
1145
+ # Removing %-style comments, newlines, quotes
1146
+ # This should probably be moved to sage.misc.latex
1147
+ from sage.misc.latex import latex
1148
+ quoted_latex = lambda x: re.sub("\"|\r|(%[^\n]*)?\n","", latex(x))
1149
+
1150
+ result = "digraph G { \n node [ shape=plaintext ];\n"
1151
+
1152
+ for x in self:
1153
+ result += " " + vertex_key(x) + " [ label = \" \", texlbl = \"$"+quoted_latex(x)+"$\" ];\n"
1154
+ for x in self:
1155
+ for i in self.index_set():
1156
+ child = x.f(i)
1157
+ if child is None:
1158
+ continue
1159
+ # result += " " + vertex_key(x) + " -> "+vertex_key(child)+ " [ label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n"
1160
+ if i == 0:
1161
+ option = "dir = back, "
1162
+ (source, target) = (child, x)
1163
+ else:
1164
+ option = ""
1165
+ (source, target) = (x, child)
1166
+ result += " " + vertex_key(source) + " -> "+vertex_key(target) + " [ "+option+"label = \" \", texlbl = \""+quoted_latex(i)+"\" ];\n"
1167
+ result += "}"
1168
+ return result
1169
+
1170
+ def plot(self, **options):
1171
+ """
1172
+ Return the plot of ``self`` as a directed graph.
1173
+
1174
+ EXAMPLES::
1175
+
1176
+ sage: C = crystals.Letters(['A', 5])
1177
+ sage: print(C.plot()) # needs sage.plot
1178
+ Graphics object consisting of 17 graphics primitives
1179
+ """
1180
+ return self.digraph().plot(edge_labels=True, vertex_size=0, **options)
1181
+
1182
+ def plot3d(self, **options):
1183
+ """
1184
+ Return the 3-dimensional plot of ``self`` as a directed graph.
1185
+
1186
+ EXAMPLES::
1187
+
1188
+ sage: C = crystals.KirillovReshetikhin(['A',3,1],2,1)
1189
+ sage: print(C.plot3d()) # needs sage.plot
1190
+ Graphics3d Object
1191
+ """
1192
+ G = self.digraph(**options)
1193
+ return G.plot3d()
1194
+
1195
+ def tensor(self, *crystals, **options):
1196
+ """
1197
+ Return the tensor product of ``self`` with the crystals ``B``.
1198
+
1199
+ EXAMPLES::
1200
+
1201
+ sage: C = crystals.Letters(['A', 3])
1202
+ sage: B = crystals.infinity.Tableaux(['A', 3])
1203
+ sage: T = C.tensor(C, B); T
1204
+ Full tensor product of the crystals
1205
+ [The crystal of letters for type ['A', 3],
1206
+ The crystal of letters for type ['A', 3],
1207
+ The infinity crystal of tableaux of type ['A', 3]]
1208
+ sage: tensor([C, C, B]) is T
1209
+ True
1210
+
1211
+ sage: C = crystals.Letters(['A',2])
1212
+ sage: T = C.tensor(C, C, generators=[[C(2),C(1),C(1)],[C(1),C(2),C(1)]]); T
1213
+ The tensor product of the crystals
1214
+ [The crystal of letters for type ['A', 2],
1215
+ The crystal of letters for type ['A', 2],
1216
+ The crystal of letters for type ['A', 2]]
1217
+ sage: T.module_generators
1218
+ ([2, 1, 1], [1, 2, 1])
1219
+ """
1220
+ from sage.combinat.crystals.tensor_product import TensorProductOfCrystals
1221
+ return TensorProductOfCrystals(self, *crystals, **options)
1222
+
1223
+ def direct_sum(self, X):
1224
+ """
1225
+ Return the direct sum of ``self`` with ``X``.
1226
+
1227
+ EXAMPLES::
1228
+
1229
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1230
+ sage: C = crystals.Letters(['A',2])
1231
+ sage: B.direct_sum(C)
1232
+ Direct sum of the crystals Family
1233
+ (The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
1234
+ The crystal of letters for type ['A', 2])
1235
+
1236
+ As a shorthand, we can use ``+``::
1237
+
1238
+ sage: B + C
1239
+ Direct sum of the crystals Family
1240
+ (The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
1241
+ The crystal of letters for type ['A', 2])
1242
+ """
1243
+ if X not in Crystals():
1244
+ raise ValueError("{} is not a crystal".format(X))
1245
+ from sage.combinat.crystals.direct_sum import DirectSumOfCrystals
1246
+ return DirectSumOfCrystals([self, X])
1247
+
1248
+ __add__ = direct_sum
1249
+
1250
+ @abstract_method(optional=True)
1251
+ def connected_components_generators(self):
1252
+ """
1253
+ Return a tuple of generators for each of the connected components
1254
+ of ``self``.
1255
+
1256
+ EXAMPLES::
1257
+
1258
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1259
+ sage: C = crystals.Letters(['A',2])
1260
+ sage: T = crystals.TensorProduct(B,C)
1261
+ sage: T.connected_components_generators()
1262
+ ([[[1, 1], [2]], 1], [[[1, 2], [2]], 1], [[[1, 2], [3]], 1])
1263
+ """
1264
+
1265
+ def connected_components(self):
1266
+ """
1267
+ Return the connected components of ``self`` as subcrystals.
1268
+
1269
+ EXAMPLES::
1270
+
1271
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1272
+ sage: C = crystals.Letters(['A',2])
1273
+ sage: T = crystals.TensorProduct(B,C)
1274
+ sage: T.connected_components()
1275
+ [Subcrystal of Full tensor product of the crystals
1276
+ [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
1277
+ The crystal of letters for type ['A', 2]],
1278
+ Subcrystal of Full tensor product of the crystals
1279
+ [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
1280
+ The crystal of letters for type ['A', 2]],
1281
+ Subcrystal of Full tensor product of the crystals
1282
+ [The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]],
1283
+ The crystal of letters for type ['A', 2]]]
1284
+ """
1285
+ return [self.subcrystal(generators=[mg])
1286
+ for mg in self.connected_components_generators()]
1287
+
1288
+ def number_of_connected_components(self):
1289
+ """
1290
+ Return the number of connected components of ``self``.
1291
+
1292
+ EXAMPLES::
1293
+
1294
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1295
+ sage: C = crystals.Letters(['A',2])
1296
+ sage: T = crystals.TensorProduct(B,C)
1297
+ sage: T.number_of_connected_components()
1298
+ 3
1299
+ """
1300
+ return len(self.connected_components_generators())
1301
+
1302
+ def is_connected(self):
1303
+ """
1304
+ Return ``True`` if ``self`` is a connected crystal.
1305
+
1306
+ EXAMPLES::
1307
+
1308
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1309
+ sage: C = crystals.Letters(['A',2])
1310
+ sage: T = crystals.TensorProduct(B,C)
1311
+ sage: B.is_connected()
1312
+ True
1313
+ sage: T.is_connected()
1314
+ False
1315
+ """
1316
+ return self.number_of_connected_components() == 1
1317
+
1318
+ class ElementMethods:
1319
+
1320
+ @cached_method
1321
+ def index_set(self):
1322
+ """
1323
+ EXAMPLES::
1324
+
1325
+ sage: C = crystals.Letters(['A',5])
1326
+ sage: C(1).index_set()
1327
+ (1, 2, 3, 4, 5)
1328
+ """
1329
+ return self.parent().index_set()
1330
+
1331
+ def cartan_type(self):
1332
+ """
1333
+ Return the Cartan type associated to ``self``.
1334
+
1335
+ EXAMPLES::
1336
+
1337
+ sage: C = crystals.Letters(['A', 5])
1338
+ sage: C(1).cartan_type()
1339
+ ['A', 5]
1340
+ """
1341
+ return self.parent().cartan_type()
1342
+
1343
+ @abstract_method
1344
+ def e(self, i):
1345
+ r"""
1346
+ Return `e_i` of ``self`` if it exists or ``None`` otherwise.
1347
+
1348
+ This method should be implemented by the element class of
1349
+ the crystal.
1350
+
1351
+ EXAMPLES::
1352
+
1353
+ sage: C = Crystals().example(5)
1354
+ sage: x = C[2]; x
1355
+ 3
1356
+ sage: x.e(1), x.e(2), x.e(3)
1357
+ (None, 2, None)
1358
+ """
1359
+
1360
+ @abstract_method
1361
+ def f(self, i):
1362
+ r"""
1363
+ Return `f_i` of ``self`` if it exists or ``None`` otherwise.
1364
+
1365
+ This method should be implemented by the element class of
1366
+ the crystal.
1367
+
1368
+ EXAMPLES::
1369
+
1370
+ sage: C = Crystals().example(5)
1371
+ sage: x = C[1]; x
1372
+ 2
1373
+ sage: x.f(1), x.f(2), x.f(3)
1374
+ (None, 3, None)
1375
+ """
1376
+
1377
+ @abstract_method
1378
+ def epsilon(self, i):
1379
+ r"""
1380
+ EXAMPLES::
1381
+
1382
+ sage: C = crystals.Letters(['A',5])
1383
+ sage: C(1).epsilon(1)
1384
+ 0
1385
+ sage: C(2).epsilon(1)
1386
+ 1
1387
+ """
1388
+
1389
+ @abstract_method
1390
+ def phi(self, i):
1391
+ r"""
1392
+ EXAMPLES::
1393
+
1394
+ sage: C = crystals.Letters(['A',5])
1395
+ sage: C(1).phi(1)
1396
+ 1
1397
+ sage: C(2).phi(1)
1398
+ 0
1399
+ """
1400
+
1401
+ @abstract_method
1402
+ def weight(self):
1403
+ r"""
1404
+ Return the weight of this crystal element.
1405
+
1406
+ This method should be implemented by the element class of
1407
+ the crystal.
1408
+
1409
+ EXAMPLES::
1410
+
1411
+ sage: C = crystals.Letters(['A',5])
1412
+ sage: C(1).weight()
1413
+ (1, 0, 0, 0, 0, 0)
1414
+ """
1415
+
1416
+ def phi_minus_epsilon(self, i):
1417
+ r"""
1418
+ Return `\varphi_i - \varepsilon_i` of ``self``.
1419
+
1420
+ There are sometimes better implementations using the
1421
+ weight for this. It is used for reflections along a string.
1422
+
1423
+ EXAMPLES::
1424
+
1425
+ sage: C = crystals.Letters(['A',5])
1426
+ sage: C(1).phi_minus_epsilon(1)
1427
+ 1
1428
+ """
1429
+ return self.phi(i) - self.epsilon(i)
1430
+
1431
+ def Epsilon(self):
1432
+ """
1433
+ EXAMPLES::
1434
+
1435
+ sage: C = crystals.Letters(['A',5])
1436
+ sage: C(0).Epsilon()
1437
+ (0, 0, 0, 0, 0, 0)
1438
+ sage: C(1).Epsilon()
1439
+ (0, 0, 0, 0, 0, 0)
1440
+ sage: C(2).Epsilon()
1441
+ (1, 0, 0, 0, 0, 0)
1442
+ """
1443
+ Lambda = self.parent().Lambda()
1444
+ return sum(self.epsilon(i) * Lambda[i] for i in self.index_set())
1445
+
1446
+ def Phi(self):
1447
+ """
1448
+ EXAMPLES::
1449
+
1450
+ sage: C = crystals.Letters(['A',5])
1451
+ sage: C(0).Phi()
1452
+ (0, 0, 0, 0, 0, 0)
1453
+ sage: C(1).Phi()
1454
+ (1, 0, 0, 0, 0, 0)
1455
+ sage: C(2).Phi()
1456
+ (1, 1, 0, 0, 0, 0)
1457
+ """
1458
+ Lambda = self.parent().Lambda()
1459
+ return sum(self.phi(i) * Lambda[i] for i in self.index_set())
1460
+
1461
+ def f_string(self, list):
1462
+ r"""
1463
+ Applies `f_{i_r} \cdots f_{i_1}` to ``self`` for ``list`` as
1464
+ `[i_1, ..., i_r]`
1465
+
1466
+ EXAMPLES::
1467
+
1468
+ sage: C = crystals.Letters(['A',3])
1469
+ sage: b = C(1)
1470
+ sage: b.f_string([1,2])
1471
+ 3
1472
+ sage: b.f_string([2,1])
1473
+ """
1474
+ b = self
1475
+ for i in list:
1476
+ b = b.f(i)
1477
+ if b is None:
1478
+ return None
1479
+ return b
1480
+
1481
+ def e_string(self, list):
1482
+ r"""
1483
+ Applies `e_{i_r} \cdots e_{i_1}` to ``self`` for ``list`` as
1484
+ `[i_1, ..., i_r]`
1485
+
1486
+ EXAMPLES::
1487
+
1488
+ sage: C = crystals.Letters(['A',3])
1489
+ sage: b = C(3)
1490
+ sage: b.e_string([2,1])
1491
+ 1
1492
+ sage: b.e_string([1,2])
1493
+ """
1494
+ b = self
1495
+ for i in list:
1496
+ b = b.e(i)
1497
+ if b is None:
1498
+ return None
1499
+ return b
1500
+
1501
+ def s(self, i):
1502
+ r"""
1503
+ Return the reflection of ``self`` along its `i`-string.
1504
+
1505
+ EXAMPLES::
1506
+
1507
+ sage: C = crystals.Tableaux(['A',2], shape=[2,1])
1508
+ sage: b = C(rows=[[1,1],[3]])
1509
+ sage: b.s(1)
1510
+ [[2, 2], [3]]
1511
+ sage: b = C(rows=[[1,2],[3]])
1512
+ sage: b.s(2)
1513
+ [[1, 2], [3]]
1514
+ sage: T = crystals.Tableaux(['A',2],shape=[4])
1515
+ sage: t = T(rows=[[1,2,2,2]])
1516
+ sage: t.s(1)
1517
+ [[1, 1, 1, 2]]
1518
+ """
1519
+ d = self.phi_minus_epsilon(i)
1520
+ b = self
1521
+ if d > 0:
1522
+ for j in range(d):
1523
+ b = b.f(i)
1524
+ else:
1525
+ for j in range(-d):
1526
+ b = b.e(i)
1527
+ return b
1528
+
1529
+ def is_highest_weight(self, index_set=None):
1530
+ r"""
1531
+ Return ``True`` if ``self`` is a highest weight.
1532
+
1533
+ Specifying the option ``index_set`` to be a subset `I` of the
1534
+ index set of the underlying crystal, finds all highest
1535
+ weight vectors for arrows in `I`.
1536
+
1537
+ EXAMPLES::
1538
+
1539
+ sage: C = crystals.Letters(['A',5])
1540
+ sage: C(1).is_highest_weight()
1541
+ True
1542
+ sage: C(2).is_highest_weight()
1543
+ False
1544
+ sage: C(2).is_highest_weight(index_set = [2,3,4,5])
1545
+ True
1546
+ """
1547
+ if index_set is None:
1548
+ index_set = self.index_set()
1549
+ return all(self.e(i) is None for i in index_set)
1550
+
1551
+ def is_lowest_weight(self, index_set=None):
1552
+ r"""
1553
+ Return ``True`` if ``self`` is a lowest weight.
1554
+ Specifying the option ``index_set`` to be a subset `I` of the
1555
+ index set of the underlying crystal, finds all lowest
1556
+ weight vectors for arrows in `I`.
1557
+
1558
+ EXAMPLES::
1559
+
1560
+ sage: C = crystals.Letters(['A',5])
1561
+ sage: C(1).is_lowest_weight()
1562
+ False
1563
+ sage: C(6).is_lowest_weight()
1564
+ True
1565
+ sage: C(4).is_lowest_weight(index_set = [1,3])
1566
+ True
1567
+ """
1568
+ if index_set is None:
1569
+ index_set = self.index_set()
1570
+ return all(self.f(i) is None for i in index_set)
1571
+
1572
+ def to_highest_weight(self, index_set=None):
1573
+ r"""
1574
+ Return the highest weight element `u` and a list `[i_1,...,i_k]`
1575
+ such that ``self`` `= f_{i_1} ... f_{i_k} u`, where `i_1,...,i_k` are
1576
+ elements in ``index_set``.
1577
+
1578
+ By default the ``index_set`` is assumed to be
1579
+ the full index set of ``self``.
1580
+
1581
+ EXAMPLES::
1582
+
1583
+ sage: T = crystals.Tableaux(['A',3], shape = [1])
1584
+ sage: t = T(rows = [[3]])
1585
+ sage: t.to_highest_weight()
1586
+ [[[1]], [2, 1]]
1587
+ sage: T = crystals.Tableaux(['A',3], shape = [2,1])
1588
+ sage: t = T(rows = [[1,2],[4]])
1589
+ sage: t.to_highest_weight()
1590
+ [[[1, 1], [2]], [1, 3, 2]]
1591
+ sage: t.to_highest_weight(index_set = [3])
1592
+ [[[1, 2], [3]], [3]]
1593
+ sage: K = crystals.KirillovReshetikhin(['A',3,1],2,1)
1594
+ sage: t = K(rows=[[2],[3]]); t.to_highest_weight(index_set=[1])
1595
+ [[[1], [3]], [1]]
1596
+ sage: t.to_highest_weight()
1597
+ Traceback (most recent call last):
1598
+ ...
1599
+ ValueError: this is not a highest weight crystal
1600
+ """
1601
+ from sage.categories.highest_weight_crystals import HighestWeightCrystals
1602
+ if index_set is None:
1603
+ if HighestWeightCrystals() not in self.parent().categories():
1604
+ raise ValueError("this is not a highest weight crystal")
1605
+ index_set = self.index_set()
1606
+ for i in index_set:
1607
+ next = self.e(i)
1608
+ if next is not None:
1609
+ hw = next.to_highest_weight(index_set=index_set)
1610
+ return [hw[0], [i] + hw[1]]
1611
+ return [self, []]
1612
+
1613
+ def to_lowest_weight(self, index_set=None):
1614
+ r"""
1615
+ Return the lowest weight element `u` and a list `[i_1,...,i_k]`
1616
+ such that ``self`` `= e_{i_1} ... e_{i_k} u`, where `i_1,...,i_k` are
1617
+ elements in ``index_set``.
1618
+
1619
+ By default the ``index_set`` is assumed to be the full index
1620
+ set of ``self``.
1621
+
1622
+ EXAMPLES::
1623
+
1624
+ sage: T = crystals.Tableaux(['A',3], shape = [1])
1625
+ sage: t = T(rows = [[3]])
1626
+ sage: t.to_lowest_weight()
1627
+ [[[4]], [3]]
1628
+ sage: T = crystals.Tableaux(['A',3], shape = [2,1])
1629
+ sage: t = T(rows = [[1,2],[4]])
1630
+ sage: t.to_lowest_weight()
1631
+ [[[3, 4], [4]], [1, 2, 2, 3]]
1632
+ sage: t.to_lowest_weight(index_set = [3])
1633
+ [[[1, 2], [4]], []]
1634
+ sage: K = crystals.KirillovReshetikhin(['A',3,1],2,1)
1635
+ sage: t = K.module_generator(); t
1636
+ [[1], [2]]
1637
+ sage: t.to_lowest_weight(index_set=[1,2,3])
1638
+ [[[3], [4]], [2, 1, 3, 2]]
1639
+ sage: t.to_lowest_weight()
1640
+ Traceback (most recent call last):
1641
+ ...
1642
+ ValueError: this is not a highest weight crystal
1643
+ """
1644
+ from sage.categories.highest_weight_crystals import HighestWeightCrystals
1645
+ if index_set is None:
1646
+ if HighestWeightCrystals() not in self.parent().categories():
1647
+ raise ValueError("this is not a highest weight crystal")
1648
+ index_set = self.index_set()
1649
+ for i in index_set:
1650
+ next = self.f(i)
1651
+ if next is not None:
1652
+ lw = next.to_lowest_weight(index_set=index_set)
1653
+ return [lw[0], [i] + lw[1]]
1654
+ return [self, []]
1655
+
1656
+ def all_paths_to_highest_weight(self, index_set=None):
1657
+ r"""
1658
+ Iterate over all paths to the highest weight from ``self``
1659
+ with respect to ``index_set``.
1660
+
1661
+ INPUT:
1662
+
1663
+ - ``index_set`` -- (optional) a subset of the index set of ``self``
1664
+
1665
+ EXAMPLES::
1666
+
1667
+ sage: B = crystals.infinity.Tableaux("A2")
1668
+ sage: b0 = B.highest_weight_vector()
1669
+ sage: b = b0.f_string([1, 2, 1, 2])
1670
+ sage: L = b.all_paths_to_highest_weight()
1671
+ sage: list(L)
1672
+ [[2, 1, 2, 1], [2, 2, 1, 1]]
1673
+
1674
+ sage: Y = crystals.infinity.GeneralizedYoungWalls(3)
1675
+ sage: y0 = Y.highest_weight_vector()
1676
+ sage: y = y0.f_string([0, 1, 2, 3, 2, 1, 0])
1677
+ sage: list(y.all_paths_to_highest_weight())
1678
+ [[0, 1, 2, 3, 2, 1, 0],
1679
+ [0, 1, 3, 2, 2, 1, 0],
1680
+ [0, 3, 1, 2, 2, 1, 0],
1681
+ [0, 3, 2, 1, 1, 0, 2],
1682
+ [0, 3, 2, 1, 1, 2, 0]]
1683
+
1684
+ sage: B = crystals.Tableaux("A3", shape=[4,2,1])
1685
+ sage: b0 = B.highest_weight_vector()
1686
+ sage: b = b0.f_string([1, 1, 2, 3])
1687
+ sage: list(b.all_paths_to_highest_weight())
1688
+ [[1, 3, 2, 1], [3, 1, 2, 1], [3, 2, 1, 1]]
1689
+ """
1690
+ if index_set is None:
1691
+ index_set = self.index_set()
1692
+ hw = True
1693
+ for i in index_set:
1694
+ next = self.e(i)
1695
+ if next is not None:
1696
+ for x in next.all_paths_to_highest_weight(index_set):
1697
+ yield [i] + x
1698
+ hw = False
1699
+ if hw:
1700
+ yield []
1701
+
1702
+ def subcrystal(self, index_set=None, max_depth=float("inf"), direction='both',
1703
+ contained=None, cartan_type=None, category=None):
1704
+ r"""
1705
+ Construct the subcrystal generated by ``self`` using `e_i` and/or
1706
+ `f_i` for all `i` in ``index_set``.
1707
+
1708
+ INPUT:
1709
+
1710
+ - ``index_set`` -- (default: ``None``) the index set; if ``None``
1711
+ then use the index set of the crystal
1712
+
1713
+ - ``max_depth`` -- (default: infinity) the maximum depth to build
1714
+
1715
+ - ``direction`` -- (default: ``'both'``) the direction to build
1716
+ the subcrystal; it can be one of the following:
1717
+
1718
+ - ``'both'`` -- using both `e_i` and `f_i`
1719
+ - ``'upper'`` -- using `e_i`
1720
+ - ``'lower'`` -- using `f_i`
1721
+
1722
+ - ``contained`` -- (optional) a set (or function) defining the
1723
+ containment in the subcrystal
1724
+
1725
+ - ``cartan_type`` -- (optional) specify the Cartan type of the
1726
+ subcrystal
1727
+
1728
+ - ``category`` -- (optional) specify the category of the subcrystal
1729
+
1730
+ .. SEEALSO::
1731
+
1732
+ - :meth:`Crystals.ParentMethods.subcrystal()`
1733
+
1734
+ EXAMPLES::
1735
+
1736
+ sage: C = crystals.KirillovReshetikhin(['A',3,1], 1, 2)
1737
+ sage: elt = C(1,4)
1738
+ sage: list(elt.subcrystal(index_set=[1,3]))
1739
+ [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]]
1740
+ sage: list(elt.subcrystal(index_set=[1,3], max_depth=1))
1741
+ [[[1, 4]], [[2, 4]], [[1, 3]]]
1742
+ sage: list(elt.subcrystal(index_set=[1,3], direction='upper'))
1743
+ [[[1, 4]], [[1, 3]]]
1744
+ sage: list(elt.subcrystal(index_set=[1,3], direction='lower'))
1745
+ [[[1, 4]], [[2, 4]]]
1746
+
1747
+ TESTS:
1748
+
1749
+ Check that :issue:`23942` is fixed::
1750
+
1751
+ sage: K = crystals.KirillovReshetikhin(['A',2,1], 1,1)
1752
+ sage: cat = HighestWeightCrystals().Finite()
1753
+ sage: S = K.module_generator().subcrystal(index_set=[1,2], category=cat)
1754
+ sage: S.category()
1755
+ Category of finite highest weight crystals
1756
+ """
1757
+ return self.parent().subcrystal(generators=[self], index_set=index_set,
1758
+ max_depth=max_depth, direction=direction,
1759
+ category=category)
1760
+
1761
+ def tensor(self, *elts):
1762
+ r"""
1763
+ Return the tensor product of ``self`` with the crystal
1764
+ elements ``elts``.
1765
+
1766
+ EXAMPLES::
1767
+
1768
+ sage: C = crystals.Letters(['A', 3])
1769
+ sage: B = crystals.infinity.Tableaux(['A', 3])
1770
+ sage: c = C[0]
1771
+ sage: b = B.highest_weight_vector()
1772
+ sage: t = c.tensor(c, b)
1773
+ sage: ascii_art(t)
1774
+ 1 1 1
1775
+ 1 # 1 # 2 2
1776
+ 3
1777
+ sage: tensor([c, c, b]) == t
1778
+ True
1779
+ sage: ascii_art(tensor([b, b, c]))
1780
+ 1 1 1 1 1 1
1781
+ 2 2 # 2 2 # 1
1782
+ 3 3
1783
+ """
1784
+ T = self.parent().tensor(*[b.parent() for b in elts])
1785
+ return T(self, *elts)
1786
+
1787
+ class SubcategoryMethods:
1788
+ """
1789
+ Methods for all subcategories.
1790
+ """
1791
+ def TensorProducts(self):
1792
+ r"""
1793
+ Return the full subcategory of objects of ``self`` constructed
1794
+ as tensor products.
1795
+
1796
+ .. SEEALSO::
1797
+
1798
+ - :class:`.tensor.TensorProductsCategory`
1799
+ - :class:`~.covariant_functorial_construction.RegressiveCovariantFunctorialConstruction`.
1800
+
1801
+ EXAMPLES::
1802
+
1803
+ sage: HighestWeightCrystals().TensorProducts()
1804
+ Category of tensor products of highest weight crystals
1805
+ """
1806
+ return TensorProductsCategory.category_of(self)
1807
+
1808
+ class TensorProducts(TensorProductsCategory):
1809
+ """
1810
+ The category of crystals constructed by tensor product of crystals.
1811
+ """
1812
+ @cached_method
1813
+ def extra_super_categories(self):
1814
+ """
1815
+ EXAMPLES::
1816
+
1817
+ sage: Crystals().TensorProducts().extra_super_categories()
1818
+ [Category of crystals]
1819
+ """
1820
+ return [self.base_category()]
1821
+
1822
+ Finite = LazyImport('sage.categories.finite_crystals', 'FiniteCrystals')
1823
+
1824
+ ###############################################################################
1825
+ ## Morphisms
1826
+
1827
+
1828
+ class CrystalMorphism(Morphism):
1829
+ r"""
1830
+ A crystal morphism.
1831
+
1832
+ INPUT:
1833
+
1834
+ - ``parent`` -- a homset
1835
+ - ``cartan_type`` -- (optional) a Cartan type; the default is the
1836
+ Cartan type of the domain
1837
+ - ``virtualization`` -- (optional) a dictionary whose keys are in
1838
+ the index set of the domain and whose values are lists of entries
1839
+ in the index set of the codomain
1840
+ - ``scaling_factors`` -- (optional) a dictionary whose keys are in
1841
+ the index set of the domain and whose values are scaling factors
1842
+ for the weight, `\varepsilon` and `\varphi`
1843
+ """
1844
+ def __init__(self, parent, cartan_type=None,
1845
+ virtualization=None, scaling_factors=None):
1846
+ """
1847
+ Initialize ``self``.
1848
+
1849
+ TESTS::
1850
+
1851
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1852
+ sage: H = Hom(B, B)
1853
+ sage: psi = H.an_element()
1854
+ """
1855
+ if cartan_type is None:
1856
+ cartan_type = parent.domain().cartan_type()
1857
+ self._cartan_type = cartan_type
1858
+
1859
+ index_set = cartan_type.index_set()
1860
+ if scaling_factors is None:
1861
+ scaling_factors = {i: 1 for i in index_set}
1862
+ if virtualization is None:
1863
+ virtualization = {i: (i,) for i in index_set}
1864
+ elif not isinstance(virtualization, collections.abc.Mapping):
1865
+ try:
1866
+ virtualization = dict(virtualization)
1867
+ except (TypeError, ValueError):
1868
+ virtualization = {i: (virtualization(i),) for i in index_set}
1869
+ from sage.sets.family import Family
1870
+ self._virtualization = Family(virtualization)
1871
+ self._scaling_factors = Family(scaling_factors)
1872
+
1873
+ Morphism.__init__(self, parent)
1874
+
1875
+ def _repr_type(self):
1876
+ """
1877
+ Used internally in printing this morphism.
1878
+
1879
+ TESTS::
1880
+
1881
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1882
+ sage: H = Hom(B, B)
1883
+ sage: psi = H.an_element()
1884
+ sage: psi._repr_type()
1885
+ "['A', 2] Crystal"
1886
+
1887
+ sage: psi = H(lambda x: None, index_set=[1])
1888
+ sage: psi._repr_type()
1889
+ "['A', 1] -> ['A', 2] Virtual Crystal"
1890
+
1891
+ sage: B = crystals.Tableaux(['A',3], shape=[1])
1892
+ sage: BT = crystals.Tableaux(['A',3], shape=[1,1,1])
1893
+ sage: psi = B.crystal_morphism(BT.module_generators, automorphism={1:3, 2:2, 3:1})
1894
+ sage: psi._repr_type()
1895
+ "['A', 3] Twisted Crystal"
1896
+
1897
+ sage: KD = crystals.KirillovReshetikhin(['D',3,1], 2,1)
1898
+ sage: KA = crystals.KirillovReshetikhin(['A',3,1], 2,1)
1899
+ sage: psi = KD.crystal_morphism(KA.module_generators)
1900
+ sage: psi._repr_type()
1901
+ "['D', 3, 1] -> ['A', 3, 1] Virtual Crystal"
1902
+ """
1903
+ if self.codomain().cartan_type() != self._cartan_type:
1904
+ return "{} -> {} Virtual Crystal".format(self._cartan_type, self.codomain().cartan_type())
1905
+ if any(self._virtualization[i] != (i,) for i in self._cartan_type.index_set()):
1906
+ return "{} Twisted Crystal".format(self._cartan_type)
1907
+ return "{} Crystal".format(self._cartan_type)
1908
+
1909
+ def cartan_type(self):
1910
+ """
1911
+ Return the Cartan type of ``self``.
1912
+
1913
+ EXAMPLES::
1914
+
1915
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1916
+ sage: psi = Hom(B, B).an_element()
1917
+ sage: psi.cartan_type()
1918
+ ['A', 2]
1919
+ """
1920
+ return self._cartan_type
1921
+
1922
+ # This is needed because is_injective is defined in a superclass, so
1923
+ # we can't overwrite it with the category
1924
+ def is_injective(self):
1925
+ """
1926
+ Return if ``self`` is an injective crystal morphism.
1927
+
1928
+ EXAMPLES::
1929
+
1930
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1931
+ sage: psi = Hom(B, B).an_element()
1932
+ sage: psi.is_injective()
1933
+ False
1934
+ """
1935
+ return self.is_embedding()
1936
+
1937
+ # This is here because is_surjective is defined in a superclass, so
1938
+ # we can't overwrite it with the category
1939
+ # TODO: This could be moved to sets
1940
+ @cached_method
1941
+ def is_surjective(self):
1942
+ """
1943
+ Check if ``self`` is a surjective crystal morphism.
1944
+
1945
+ EXAMPLES::
1946
+
1947
+ sage: B = crystals.Tableaux(['C',2], shape=[1,1])
1948
+ sage: C = crystals.Tableaux(['C',2], ([2,1], [1,1]))
1949
+ sage: psi = B.crystal_morphism(C.module_generators[1:], codomain=C)
1950
+ sage: psi.is_surjective()
1951
+ False
1952
+ sage: im_gens = [None, B.module_generators[0]]
1953
+ sage: psi = C.crystal_morphism(im_gens, codomain=B)
1954
+ sage: psi.is_surjective()
1955
+ True
1956
+
1957
+ sage: C = crystals.Tableaux(['A',2], shape=[2,1])
1958
+ sage: B = crystals.infinity.Tableaux(['A',2])
1959
+ sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
1960
+ sage: W = crystals.elementary.T(['A',2], La[1]+La[2])
1961
+ sage: T = W.tensor(B)
1962
+ sage: mg = T(W.module_generators[0], B.module_generators[0])
1963
+ sage: psi = Hom(C,T)([mg])
1964
+ sage: psi.is_surjective()
1965
+ False
1966
+ """
1967
+ if self.domain().cardinality() == float('inf'):
1968
+ raise NotImplementedError("unable to determine if surjective")
1969
+ if self.domain().cardinality() < self.codomain().cardinality():
1970
+ return False
1971
+ S = set(self.codomain())
1972
+ for x in self.domain():
1973
+ S.discard(self(x))
1974
+ if not S:
1975
+ return True
1976
+ return False
1977
+
1978
+ def __call__(self, x, *args, **kwds):
1979
+ """
1980
+ Apply this map to ``x``. We need to do special processing
1981
+ for ``None``.
1982
+
1983
+ EXAMPLES::
1984
+
1985
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
1986
+ sage: F = crystals.Tableaux(['A',2], shape=[1])
1987
+ sage: T = crystals.TensorProduct(F, F, F)
1988
+ sage: H = Hom(T, B)
1989
+ sage: b = B.module_generators[0]
1990
+ sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors())
1991
+ sage: psi(None) # needs sage.symbolic
1992
+ sage: [psi(v) for v in T.highest_weight_vectors()]
1993
+ [None, [[1, 1], [2]], [[1, 1], [2]], None]
1994
+ """
1995
+ if x is None:
1996
+ return None
1997
+ return super().__call__(x, *args, **kwds)
1998
+
1999
+ def virtualization(self):
2000
+ r"""
2001
+ Return the virtualization sets `\sigma_i`.
2002
+
2003
+ EXAMPLES::
2004
+
2005
+ sage: B = crystals.Tableaux(['B',3], shape=[1])
2006
+ sage: C = crystals.Tableaux(['D',4], shape=[2])
2007
+ sage: psi = B.crystal_morphism(C.module_generators)
2008
+ sage: psi.virtualization()
2009
+ Finite family {1: (1,), 2: (2,), 3: (3, 4)}
2010
+ """
2011
+ return self._virtualization
2012
+
2013
+ def scaling_factors(self):
2014
+ r"""
2015
+ Return the scaling factors `\gamma_i`.
2016
+
2017
+ EXAMPLES::
2018
+
2019
+ sage: B = crystals.Tableaux(['B',3], shape=[1])
2020
+ sage: C = crystals.Tableaux(['D',4], shape=[2])
2021
+ sage: psi = B.crystal_morphism(C.module_generators)
2022
+ sage: psi.scaling_factors()
2023
+ Finite family {1: 2, 2: 2, 3: 1}
2024
+ """
2025
+ return self._scaling_factors
2026
+
2027
+
2028
+ class CrystalMorphismByGenerators(CrystalMorphism):
2029
+ r"""
2030
+ A crystal morphism defined by a set of generators which create a virtual
2031
+ crystal inside the codomain.
2032
+
2033
+ INPUT:
2034
+
2035
+ - ``parent`` -- a homset
2036
+ - ``on_gens`` -- a function or list that determines the image of the
2037
+ generators (if given a list, then this uses the order of the
2038
+ generators of the domain) of the domain under ``self``
2039
+ - ``cartan_type`` -- (optional) a Cartan type; the default is the
2040
+ Cartan type of the domain
2041
+ - ``virtualization`` -- (optional) a dictionary whose keys are in
2042
+ the index set of the domain and whose values are lists of entries
2043
+ in the index set of the codomain
2044
+ - ``scaling_factors`` -- (optional) a dictionary whose keys are in
2045
+ the index set of the domain and whose values are scaling factors
2046
+ for the weight, `\varepsilon` and `\varphi`
2047
+ - ``gens`` -- (optional) a finite list of generators to define the
2048
+ morphism; the default is to use the highest weight vectors of the crystal
2049
+ - ``check`` -- boolean (default: ``True``); check if the crystal morphism
2050
+ is valid
2051
+
2052
+ .. SEEALSO::
2053
+
2054
+ :meth:`sage.categories.crystals.Crystals.ParentMethods.crystal_morphism`
2055
+ """
2056
+ def __init__(self, parent, on_gens, cartan_type=None,
2057
+ virtualization=None, scaling_factors=None,
2058
+ gens=None, check=True):
2059
+ """
2060
+ Construct a virtual crystal morphism.
2061
+
2062
+ TESTS::
2063
+
2064
+ sage: B = crystals.Tableaux(['D',4], shape=[1])
2065
+ sage: H = Hom(B, B)
2066
+ sage: d = {1:1, 2:2, 3:4, 4:3}
2067
+ sage: psi = H(B.module_generators, automorphism=d)
2068
+
2069
+ sage: B = crystals.Tableaux(['B',3], shape=[1])
2070
+ sage: C = crystals.Tableaux(['D',4], shape=[2])
2071
+ sage: H = Hom(B, C)
2072
+ sage: psi = H(C.module_generators)
2073
+ """
2074
+ CrystalMorphism.__init__(self, parent, cartan_type,
2075
+ virtualization, scaling_factors)
2076
+
2077
+ if gens is None:
2078
+ if isinstance(on_gens, collections.abc.Mapping):
2079
+ gens = on_gens.keys()
2080
+ else:
2081
+ gens = parent.domain().module_generators
2082
+ self._gens = tuple(gens)
2083
+
2084
+ # Make sure on_gens is a function
2085
+ if isinstance(on_gens, collections.abc.Mapping):
2086
+ f = lambda x: on_gens[x]
2087
+ elif isinstance(on_gens, collections.abc.Sequence):
2088
+ if len(self._gens) != len(on_gens):
2089
+ raise ValueError("invalid generator images")
2090
+ d = dict(zip(self._gens, on_gens))
2091
+ f = lambda x: d[x]
2092
+ else:
2093
+ f = on_gens
2094
+ self._on_gens = f
2095
+ self._path_mg_cache = {x: (x, [], []) for x in self._gens}
2096
+
2097
+ # Now that everything is initialized, run the check (if it is wanted)
2098
+ if check:
2099
+ self._check()
2100
+
2101
+ def _repr_defn(self):
2102
+ """
2103
+ Used in constructing string representation of ``self``.
2104
+
2105
+ EXAMPLES::
2106
+
2107
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
2108
+ sage: F = crystals.Tableaux(['A',2], shape=[1])
2109
+ sage: T = crystals.TensorProduct(F, F, F)
2110
+ sage: H = Hom(T, B)
2111
+ sage: b = B.highest_weight_vector()
2112
+ sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors())
2113
+ sage: print(psi._repr_defn())
2114
+ [[[1]], [[1]], [[1]]] |--> None
2115
+ [[[2]], [[1]], [[1]]] |--> [[1, 1], [2]]
2116
+ [[[1]], [[2]], [[1]]] |--> [[1, 1], [2]]
2117
+ [[[3]], [[2]], [[1]]] |--> None
2118
+ """
2119
+ return '\n'.join('{} |--> {}'.format(mg, im)
2120
+ for mg, im in zip(self._gens, self.im_gens()))
2121
+
2122
+ def _check(self):
2123
+ """
2124
+ Check if ``self`` is a valid virtual crystal morphism.
2125
+
2126
+ TESTS::
2127
+
2128
+ sage: B = crystals.Tableaux(['D',4], shape=[1])
2129
+ sage: H = Hom(B, B)
2130
+ sage: d = {1:1, 2:2, 3:4, 4:3}
2131
+ sage: psi = H(B.module_generators, automorphism=d) # indirect doctest
2132
+
2133
+ sage: B = crystals.Tableaux(['B',3], shape=[1])
2134
+ sage: C = crystals.Tableaux(['D',4], shape=[2])
2135
+ sage: H = Hom(B, C)
2136
+ sage: psi = H(C.module_generators) # indirect doctest
2137
+ """
2138
+ index_set = self._cartan_type.index_set()
2139
+ acx = self.domain().weight_lattice_realization().simple_coroots()
2140
+ acy = self.codomain().weight_lattice_realization().simple_coroots()
2141
+ v = self._virtualization
2142
+ sf = self._scaling_factors
2143
+ for x in self._gens:
2144
+ y = self._on_gens(x)
2145
+ if y is None:
2146
+ continue
2147
+ xwt = x.weight()
2148
+ ywt = y.weight()
2149
+ for i in index_set:
2150
+ ind = v[i]
2151
+ if any(sf[i] * xwt.scalar(acx[i]) != ywt.scalar(acy[j]) for j in ind):
2152
+ raise ValueError("invalid crystal morphism: weights do not match")
2153
+ if any(sf[i] * x.epsilon(i) != y.epsilon(j) for j in ind):
2154
+ raise ValueError("invalid crystal morphism: epsilons are not aligned")
2155
+ if any(sf[i] * x.phi(i) != y.phi(j) for j in ind):
2156
+ raise ValueError("invalid crystal morphism: phis are not aligned")
2157
+
2158
+ def _call_(self, x):
2159
+ """
2160
+ Return the image of ``x`` under ``self``.
2161
+
2162
+ EXAMPLES::
2163
+
2164
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
2165
+ sage: H = Hom(B, B)
2166
+ sage: psi = H(B.module_generators)
2167
+ sage: psi(B.highest_weight_vector())
2168
+ [[1, 1], [2]]
2169
+
2170
+ sage: B = crystals.Tableaux(['D',4], shape=[1])
2171
+ sage: H = Hom(B, B)
2172
+ sage: d = {1:1, 2:2, 3:4, 4:3}
2173
+ sage: psi = H(B.module_generators, automorphism=d)
2174
+ sage: b = B.highest_weight_vector()
2175
+ sage: psi(b.f_string([1,2,3]))
2176
+ [[-4]]
2177
+ sage: psi(b.f_string([1,2,4]))
2178
+ [[4]]
2179
+
2180
+ sage: B = crystals.Tableaux(['B',3], shape=[1])
2181
+ sage: C = crystals.Tableaux(['D',4], shape=[2])
2182
+ sage: H = Hom(B, C)
2183
+ sage: psi = H(C.module_generators)
2184
+ sage: psi(B.highest_weight_vector())
2185
+ [[1, 1]]
2186
+ """
2187
+ mg, ef, indices = self.to_module_generator(x)
2188
+ cur = self._on_gens(mg)
2189
+ for op, i in reversed(list(zip(ef, indices))):
2190
+ if cur is None:
2191
+ return None
2192
+
2193
+ s = []
2194
+ sf = self._scaling_factors[i]
2195
+ for j in self._virtualization[i]:
2196
+ s += [j]*sf
2197
+ if op == 'e':
2198
+ cur = cur.f_string(s)
2199
+ elif op == 'f':
2200
+ cur = cur.e_string(s)
2201
+ return cur
2202
+
2203
+ def __bool__(self) -> bool:
2204
+ """
2205
+ Return if ``self`` is a nonzero morphism.
2206
+
2207
+ EXAMPLES::
2208
+
2209
+ sage: B = crystals.elementary.Elementary(['A',2], 2)
2210
+ sage: H = Hom(B, B)
2211
+ sage: psi = H(B.module_generators)
2212
+ sage: bool(psi)
2213
+ True
2214
+ sage: psi = H(lambda x: None)
2215
+ sage: bool(psi)
2216
+ False
2217
+ """
2218
+ return any(self._on_gens(mg) is not None for mg in self._gens)
2219
+
2220
+ # TODO: Does this belong in the element_class of the Crystals() category?
2221
+ def to_module_generator(self, x):
2222
+ """
2223
+ Return a generator ``mg`` and a path of `e_i` and `f_i` operations
2224
+ to ``mg``.
2225
+
2226
+ OUTPUT: a tuple consisting of:
2227
+
2228
+ - a module generator,
2229
+ - a list of ``'e'`` and ``'f'`` to denote which operation, and
2230
+ - a list of matching indices.
2231
+
2232
+ EXAMPLES::
2233
+
2234
+ sage: B = crystals.elementary.Elementary(['A',2], 2)
2235
+ sage: psi = B.crystal_morphism(B.module_generators)
2236
+ sage: psi.to_module_generator(B(4))
2237
+ (0, ['f', 'f', 'f', 'f'], [2, 2, 2, 2])
2238
+ sage: psi.to_module_generator(B(-2))
2239
+ (0, ['e', 'e'], [2, 2])
2240
+ """
2241
+ if x in self._path_mg_cache:
2242
+ return self._path_mg_cache[x]
2243
+
2244
+ mg = set(self._path_mg_cache.keys())
2245
+ visited = {None, x}
2246
+ index_set = self._cartan_type.index_set()
2247
+ todo = [x]
2248
+ ef = [[]]
2249
+ indices = [[]]
2250
+
2251
+ while todo:
2252
+ cur = todo.pop(0)
2253
+ cur_ef = ef.pop(0)
2254
+ cur_indices = indices.pop(0)
2255
+ for i in index_set:
2256
+ next = cur.e(i)
2257
+ if next in mg:
2258
+ gen,ef,indices = self._path_mg_cache[next]
2259
+ ef = cur_ef + ['e'] + ef
2260
+ indices = cur_indices + [i] + indices
2261
+ self._path_mg_cache[x] = (gen, ef, indices)
2262
+ return (gen, ef, indices)
2263
+ if next not in visited:
2264
+ todo.append(next)
2265
+ ef.append(cur_ef + ['e'])
2266
+ indices.append(cur_indices + [i])
2267
+ visited.add(next)
2268
+
2269
+ # Now for f's
2270
+ next = cur.f(i)
2271
+ if next in mg:
2272
+ gen,ef,indices = self._path_mg_cache[next]
2273
+ ef = cur_ef + ['f'] + ef
2274
+ indices = cur_indices + [i] + indices
2275
+ self._path_mg_cache[x] = (gen, ef, indices)
2276
+ return (gen, ef, indices)
2277
+ if next not in visited:
2278
+ todo.append(next)
2279
+ ef.append(cur_ef + ['f'])
2280
+ indices.append(cur_indices + [i])
2281
+ visited.add(next)
2282
+ raise ValueError("no module generator in the component of {}".format(x))
2283
+
2284
+ @cached_method
2285
+ def im_gens(self):
2286
+ """
2287
+ Return the image of the generators of ``self`` as a tuple.
2288
+
2289
+ EXAMPLES::
2290
+
2291
+ sage: B = crystals.Tableaux(['A',2], shape=[2,1])
2292
+ sage: F = crystals.Tableaux(['A',2], shape=[1])
2293
+ sage: T = crystals.TensorProduct(F, F, F)
2294
+ sage: H = Hom(T, B)
2295
+ sage: b = B.highest_weight_vector()
2296
+ sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors())
2297
+ sage: psi.im_gens()
2298
+ (None, [[1, 1], [2]], [[1, 1], [2]], None)
2299
+ """
2300
+ return tuple([self._on_gens(g) for g in self._gens])
2301
+
2302
+ def image(self):
2303
+ """
2304
+ Return the image of ``self`` in the codomain as a
2305
+ :class:`~sage.combinat.crystals.subcrystal.Subcrystal`.
2306
+
2307
+ .. WARNING::
2308
+
2309
+ This assumes that ``self`` is a strict crystal morphism.
2310
+
2311
+ EXAMPLES::
2312
+
2313
+ sage: B = crystals.Tableaux(['B',3], shape=[1])
2314
+ sage: C = crystals.Tableaux(['D',4], shape=[2])
2315
+ sage: H = Hom(B, C)
2316
+ sage: psi = H(C.module_generators)
2317
+ sage: psi.image()
2318
+ Virtual crystal of The crystal of tableaux of type ['D', 4] and shape(s) [[2]] of type ['B', 3]
2319
+ """
2320
+ #if not self.is_strict():
2321
+ # raise NotImplementedError
2322
+ from sage.combinat.crystals.subcrystal import Subcrystal
2323
+ return Subcrystal(self.codomain(),
2324
+ virtualization=self._virtualization,
2325
+ scaling_factors=self._scaling_factors,
2326
+ generators=self.im_gens(),
2327
+ cartan_type=self._cartan_type,
2328
+ index_set=self._cartan_type.index_set(),
2329
+ category=self.domain().category())
2330
+
2331
+ ###############################################################################
2332
+ ## Homset
2333
+
2334
+
2335
+ class CrystalHomset(Homset):
2336
+ r"""
2337
+ The set of crystal morphisms from one crystal to another.
2338
+
2339
+ An `U_q(\mathfrak{g})` `I`-crystal morphism `\Psi : B \to C` is a map
2340
+ `\Psi : B \cup \{ 0 \} \to C \cup \{ 0 \}` such that:
2341
+
2342
+ - `\Psi(0) = 0`.
2343
+ - If `b \in B` and `\Psi(b) \in C`, then
2344
+ `\mathrm{wt}(\Psi(b)) = \mathrm{wt}(b)`,
2345
+ `\varepsilon_i(\Psi(b)) = \varepsilon_i(b)`, and
2346
+ `\varphi_i(\Psi(b)) = \varphi_i(b)` for all `i \in I`.
2347
+ - If `b, b^{\prime} \in B`, `\Psi(b), \Psi(b^{\prime}) \in C` and
2348
+ `f_i b = b^{\prime}`, then `f_i \Psi(b) = \Psi(b^{\prime})` and
2349
+ `\Psi(b) = e_i \Psi(b^{\prime})` for all `i \in I`.
2350
+
2351
+ If the Cartan type is unambiguous, it is suppressed from the notation.
2352
+
2353
+ We can also generalize the definition of a crystal morphism by considering
2354
+ a map of `\sigma` of the (now possibly different) Dynkin diagrams
2355
+ corresponding to `B` and `C` along with scaling factors
2356
+ `\gamma_i \in \ZZ` for `i \in I`. Let `\sigma_i` denote the orbit of
2357
+ `i` under `\sigma`. We write objects for `B` as `X` with
2358
+ corresponding objects of `C` as `\widehat{X}`.
2359
+ Then a *virtual* crystal morphism `\Psi` is a map such that
2360
+ the following holds:
2361
+
2362
+ - `\Psi(0) = 0`.
2363
+ - If `b \in B` and `\Psi(b) \in C`, then for all `j \in \sigma_i`:
2364
+
2365
+ .. MATH::
2366
+
2367
+ \varepsilon_i(b) = \frac{1}{\gamma_j} \widehat{\varepsilon}_j(\Psi(b)),
2368
+ \quad \varphi_i(b) = \frac{1}{\gamma_j} \widehat{\varphi}_j(\Psi(b)),
2369
+ \quad \mathrm{wt}(\Psi(b)) = \sum_i c_i \sum_{j \in \sigma_i} \gamma_j
2370
+ \widehat{\Lambda}_j,
2371
+
2372
+ where `\mathrm{wt}(b) = \sum_i c_i \Lambda_i`.
2373
+
2374
+ - If `b, b^{\prime} \in B`, `\Psi(b), \Psi(b^{\prime}) \in C` and
2375
+ `f_i b = b^{\prime}`, then independent of the ordering of `\sigma_i`
2376
+ we have:
2377
+
2378
+ .. MATH::
2379
+
2380
+ \Psi(b^{\prime}) = e_i \Psi(b) =
2381
+ \prod_{j \in \sigma_i} \widehat{e}_j^{\gamma_i} \Psi(b), \quad
2382
+ \Psi(b^{\prime}) = f_i \Psi(b) =
2383
+ \prod_{j \in \sigma_i} \widehat{f}_j^{\gamma_i} \Psi(b).
2384
+
2385
+ If `\gamma_i = 1` for all `i \in I` and the Dynkin diagrams are
2386
+ the same, then we call `\Psi` a *twisted* crystal morphism.
2387
+
2388
+ INPUT:
2389
+
2390
+ - ``X`` -- the domain
2391
+ - ``Y`` -- the codomain
2392
+ - ``category`` -- (optional) the category of the crystal morphisms
2393
+
2394
+ .. SEEALSO::
2395
+
2396
+ For the construction of an element of the homset, see
2397
+ :class:`CrystalMorphismByGenerators` and
2398
+ :meth:`~sage.categories.crystals.Crystals.ParentMethods.crystal_morphism`.
2399
+
2400
+ EXAMPLES:
2401
+
2402
+ We begin with the natural embedding of `B(2\Lambda_1)` into
2403
+ `B(\Lambda_1) \otimes B(\Lambda_1)` in type `A_1`::
2404
+
2405
+ sage: B = crystals.Tableaux(['A',1], shape=[2])
2406
+ sage: F = crystals.Tableaux(['A',1], shape=[1])
2407
+ sage: T = crystals.TensorProduct(F, F)
2408
+ sage: v = T.highest_weight_vectors()[0]; v
2409
+ [[[1]], [[1]]]
2410
+ sage: H = Hom(B, T)
2411
+ sage: psi = H([v])
2412
+ sage: b = B.highest_weight_vector(); b
2413
+ [[1, 1]]
2414
+ sage: psi(b)
2415
+ [[[1]], [[1]]]
2416
+ sage: b.f(1)
2417
+ [[1, 2]]
2418
+ sage: psi(b.f(1))
2419
+ [[[1]], [[2]]]
2420
+
2421
+ We now look at the decomposition of `B(\Lambda_1) \otimes B(\Lambda_1)`
2422
+ into `B(2\Lambda_1) \oplus B(0)`::
2423
+
2424
+ sage: B0 = crystals.Tableaux(['A',1], shape=[])
2425
+ sage: D = crystals.DirectSum([B, B0])
2426
+ sage: H = Hom(T, D)
2427
+ sage: psi = H(D.module_generators)
2428
+ sage: psi
2429
+ ['A', 1] Crystal morphism:
2430
+ From: Full tensor product of the crystals
2431
+ [The crystal of tableaux of type ['A', 1] and shape(s) [[1]],
2432
+ The crystal of tableaux of type ['A', 1] and shape(s) [[1]]]
2433
+ To: Direct sum of the crystals Family
2434
+ (The crystal of tableaux of type ['A', 1] and shape(s) [[2]],
2435
+ The crystal of tableaux of type ['A', 1] and shape(s) [[]])
2436
+ Defn: [[[1]], [[1]]] |--> [[1, 1]]
2437
+ [[[2]], [[1]]] |--> []
2438
+ sage: psi.is_isomorphism()
2439
+ True
2440
+
2441
+ We can always construct the trivial morphism which sends
2442
+ everything to `0`::
2443
+
2444
+ sage: Binf = crystals.infinity.Tableaux(['B', 2])
2445
+ sage: B = crystals.Tableaux(['B',2], shape=[1])
2446
+ sage: H = Hom(Binf, B)
2447
+ sage: psi = H(lambda x: None)
2448
+ sage: psi(Binf.highest_weight_vector())
2449
+
2450
+ For Kirillov-Reshetikhin crystals, we consider the map to the
2451
+ corresponding classical crystal::
2452
+
2453
+ sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,1)
2454
+ sage: B = K.classical_decomposition()
2455
+ sage: H = Hom(K, B)
2456
+ sage: psi = H(lambda x: x.lift(), cartan_type=['D',4])
2457
+ sage: L = [psi(mg) for mg in K.module_generators]; L
2458
+ [[], [[1], [2]]]
2459
+ sage: all(x.parent() == B for x in L)
2460
+ True
2461
+
2462
+ Next we consider a type `D_4` crystal morphism where we twist by
2463
+ `3 \leftrightarrow 4`::
2464
+
2465
+ sage: B = crystals.Tableaux(['D',4], shape=[1])
2466
+ sage: H = Hom(B, B)
2467
+ sage: d = {1:1, 2:2, 3:4, 4:3}
2468
+ sage: psi = H(B.module_generators, automorphism=d)
2469
+ sage: b = B.highest_weight_vector()
2470
+ sage: b.f_string([1,2,3])
2471
+ [[4]]
2472
+ sage: b.f_string([1,2,4])
2473
+ [[-4]]
2474
+ sage: psi(b.f_string([1,2,3]))
2475
+ [[-4]]
2476
+ sage: psi(b.f_string([1,2,4]))
2477
+ [[4]]
2478
+
2479
+ We construct the natural virtual embedding of a type `B_3` into a type
2480
+ `D_4` crystal::
2481
+
2482
+ sage: B = crystals.Tableaux(['B',3], shape=[1])
2483
+ sage: C = crystals.Tableaux(['D',4], shape=[2])
2484
+ sage: H = Hom(B, C)
2485
+ sage: psi = H(C.module_generators)
2486
+ sage: psi
2487
+ ['B', 3] -> ['D', 4] Virtual Crystal morphism:
2488
+ From: The crystal of tableaux of type ['B', 3] and shape(s) [[1]]
2489
+ To: The crystal of tableaux of type ['D', 4] and shape(s) [[2]]
2490
+ Defn: [[1]] |--> [[1, 1]]
2491
+ sage: for b in B: print("{} |--> {}".format(b, psi(b)))
2492
+ [[1]] |--> [[1, 1]]
2493
+ [[2]] |--> [[2, 2]]
2494
+ [[3]] |--> [[3, 3]]
2495
+ [[0]] |--> [[3, -3]]
2496
+ [[-3]] |--> [[-3, -3]]
2497
+ [[-2]] |--> [[-2, -2]]
2498
+ [[-1]] |--> [[-1, -1]]
2499
+ """
2500
+ def __init__(self, X, Y, category=None):
2501
+ """
2502
+ Initialize ``self``.
2503
+
2504
+ TESTS::
2505
+
2506
+ sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
2507
+ sage: H = Hom(B, B)
2508
+ sage: Binf = crystals.infinity.Tableaux(['B',2])
2509
+ sage: H = Hom(Binf, B)
2510
+ """
2511
+ if category is None:
2512
+ category = Crystals()
2513
+ # TODO: Should we make one of the types of morphisms into the self.Element?
2514
+ Homset.__init__(self, X, Y, category)
2515
+
2516
+ def _repr_(self):
2517
+ """
2518
+ TESTS::
2519
+
2520
+ sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
2521
+ sage: Hom(B, B)
2522
+ Set of Crystal Morphisms from The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
2523
+ to The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
2524
+ """
2525
+ return "Set of Crystal Morphisms from {} to {}".format(self.domain(), self.codomain())
2526
+
2527
+ def _coerce_impl(self, x):
2528
+ """
2529
+ Check to see if we can coerce ``x`` into a morphism with the
2530
+ correct parameters.
2531
+
2532
+ EXAMPLES::
2533
+
2534
+ sage: B = crystals.Tableaux(['B',3], shape=[2,1])
2535
+ sage: H = Hom(B, B)
2536
+ sage: H(H.an_element()) # indirect doctest
2537
+ ['B', 3] Crystal endomorphism of The crystal of tableaux of type ['B', 3] and shape(s) [[2, 1]]
2538
+ Defn: [[1, 1], [2]] |--> None
2539
+ """
2540
+ if not isinstance(x, CrystalMorphism):
2541
+ raise TypeError
2542
+
2543
+ if x.parent() is self:
2544
+ return x
2545
+
2546
+ # Case 1: the parent fits
2547
+ if x.parent() == self:
2548
+ return self.element_class(self, x._on_gens,
2549
+ x._virtualization, x._scaling_factors,
2550
+ x._cartan_type, x._gens)
2551
+
2552
+ # TODO: Should we try extraordinary measures (like twisting)?
2553
+ raise ValueError
2554
+
2555
+ def __call__(self, on_gens, cartan_type=None, index_set=None, generators=None,
2556
+ automorphism=None, virtualization=None, scaling_factors=None, check=True):
2557
+ """
2558
+ Construct a crystal morphism.
2559
+
2560
+ EXAMPLES::
2561
+
2562
+ sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
2563
+ sage: H = Hom(B, B)
2564
+ sage: psi = H(B.module_generators)
2565
+
2566
+ sage: F = crystals.Tableaux(['A',3], shape=[1])
2567
+ sage: T = crystals.TensorProduct(F, F, F)
2568
+ sage: H = Hom(B, T)
2569
+ sage: v = T.highest_weight_vectors()[2]
2570
+ sage: psi = H([v], cartan_type=['A',2])
2571
+ """
2572
+ if isinstance(on_gens, CrystalMorphism):
2573
+ return self._coerce_impl(on_gens)
2574
+
2575
+ if cartan_type is None:
2576
+ cartan_type = self.domain().cartan_type()
2577
+ else:
2578
+ from sage.combinat.root_system.cartan_type import CartanType
2579
+ cartan_type = CartanType(cartan_type)
2580
+ if index_set is None:
2581
+ index_set = cartan_type.index_set()
2582
+ else:
2583
+ cartan_type = cartan_type.subtype(index_set)
2584
+
2585
+ # Try as a natural folding
2586
+ if cartan_type != self.codomain().cartan_type():
2587
+ fct = self.domain().cartan_type().as_folding()
2588
+ if fct.folding_of() == self.codomain().cartan_type():
2589
+ if virtualization is None:
2590
+ virtualization = fct.folding_orbit()
2591
+ if scaling_factors is None:
2592
+ scaling_factors = fct.scaling_factors()
2593
+
2594
+ if automorphism is not None:
2595
+ if virtualization is not None:
2596
+ raise ValueError("the automorphism and virtualization cannot both be specified")
2597
+ if not isinstance(automorphism, collections.abc.Mapping):
2598
+ try:
2599
+ automorphism = dict(automorphism)
2600
+ virtualization = {i: (automorphism[i],) for i in automorphism}
2601
+ except (TypeError, ValueError):
2602
+ virtualization = {i: (automorphism(i),) for i in index_set}
2603
+ else:
2604
+ virtualization = {i: (automorphism[i],) for i in automorphism}
2605
+
2606
+ return self.element_class(self, on_gens, cartan_type,
2607
+ virtualization, scaling_factors,
2608
+ generators, check)
2609
+
2610
+ def _an_element_(self):
2611
+ """
2612
+ Return an element of ``self``. Every homset has the crystal morphism
2613
+ which sends all elements to ``None``.
2614
+
2615
+ EXAMPLES::
2616
+
2617
+ sage: B = crystals.Tableaux(['A', 2], shape=[2,1])
2618
+ sage: C = crystals.infinity.Tableaux(['A', 2])
2619
+ sage: H = Hom(B, C)
2620
+ sage: H.an_element()
2621
+ ['A', 2] Crystal morphism:
2622
+ From: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
2623
+ To: The infinity crystal of tableaux of type ['A', 2]
2624
+ Defn: [[1, 1], [2]] |--> None
2625
+ """
2626
+ return self.element_class(self, lambda x: None)
2627
+
2628
+ Element = CrystalMorphismByGenerators