passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. passagemath_combinat/__init__.py +3 -0
  2. passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
  3. passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
  4. passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
  5. passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
  6. passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  7. passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
  8. sage/algebras/affine_nil_temperley_lieb.py +263 -0
  9. sage/algebras/all.py +24 -0
  10. sage/algebras/all__sagemath_combinat.py +35 -0
  11. sage/algebras/askey_wilson.py +935 -0
  12. sage/algebras/associated_graded.py +345 -0
  13. sage/algebras/cellular_basis.py +350 -0
  14. sage/algebras/cluster_algebra.py +2766 -0
  15. sage/algebras/down_up_algebra.py +860 -0
  16. sage/algebras/free_algebra.py +1698 -0
  17. sage/algebras/free_algebra_element.py +345 -0
  18. sage/algebras/free_algebra_quotient.py +405 -0
  19. sage/algebras/free_algebra_quotient_element.py +295 -0
  20. sage/algebras/free_zinbiel_algebra.py +885 -0
  21. sage/algebras/hall_algebra.py +783 -0
  22. sage/algebras/hecke_algebras/all.py +4 -0
  23. sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
  24. sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
  25. sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
  26. sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
  27. sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
  28. sage/algebras/iwahori_hecke_algebra.py +3095 -0
  29. sage/algebras/jordan_algebra.py +1773 -0
  30. sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
  31. sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
  32. sage/algebras/lie_conformal_algebras/all.py +18 -0
  33. sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
  34. sage/algebras/lie_conformal_algebras/examples.py +43 -0
  35. sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
  36. sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
  37. sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
  38. sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
  39. sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
  40. sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
  41. sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
  42. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
  43. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
  44. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
  45. sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
  46. sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
  47. sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
  48. sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
  49. sage/algebras/nil_coxeter_algebra.py +191 -0
  50. sage/algebras/q_commuting_polynomials.py +673 -0
  51. sage/algebras/q_system.py +608 -0
  52. sage/algebras/quantum_clifford.py +959 -0
  53. sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
  54. sage/algebras/quantum_groups/all.py +9 -0
  55. sage/algebras/quantum_groups/fock_space.py +2219 -0
  56. sage/algebras/quantum_groups/q_numbers.py +207 -0
  57. sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
  58. sage/algebras/quantum_groups/representations.py +591 -0
  59. sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
  60. sage/algebras/quantum_oscillator.py +623 -0
  61. sage/algebras/quaternion_algebra.py +20 -0
  62. sage/algebras/quaternion_algebra_element.py +55 -0
  63. sage/algebras/rational_cherednik_algebra.py +525 -0
  64. sage/algebras/schur_algebra.py +670 -0
  65. sage/algebras/shuffle_algebra.py +1011 -0
  66. sage/algebras/splitting_algebra.py +779 -0
  67. sage/algebras/tensor_algebra.py +709 -0
  68. sage/algebras/yangian.py +1082 -0
  69. sage/algebras/yokonuma_hecke_algebra.py +1018 -0
  70. sage/all__sagemath_combinat.py +35 -0
  71. sage/combinat/SJT.py +255 -0
  72. sage/combinat/affine_permutation.py +2405 -0
  73. sage/combinat/algebraic_combinatorics.py +55 -0
  74. sage/combinat/all.py +53 -0
  75. sage/combinat/all__sagemath_combinat.py +195 -0
  76. sage/combinat/alternating_sign_matrix.py +2063 -0
  77. sage/combinat/baxter_permutations.py +346 -0
  78. sage/combinat/bijectionist.py +3220 -0
  79. sage/combinat/binary_recurrence_sequences.py +1180 -0
  80. sage/combinat/blob_algebra.py +685 -0
  81. sage/combinat/catalog_partitions.py +27 -0
  82. sage/combinat/chas/all.py +23 -0
  83. sage/combinat/chas/fsym.py +1180 -0
  84. sage/combinat/chas/wqsym.py +2601 -0
  85. sage/combinat/cluster_complex.py +326 -0
  86. sage/combinat/colored_permutations.py +2039 -0
  87. sage/combinat/colored_permutations_representations.py +964 -0
  88. sage/combinat/composition_signed.py +142 -0
  89. sage/combinat/composition_tableau.py +855 -0
  90. sage/combinat/constellation.py +1729 -0
  91. sage/combinat/core.py +751 -0
  92. sage/combinat/counting.py +12 -0
  93. sage/combinat/crystals/affine.py +742 -0
  94. sage/combinat/crystals/affine_factorization.py +518 -0
  95. sage/combinat/crystals/affinization.py +331 -0
  96. sage/combinat/crystals/alcove_path.py +2013 -0
  97. sage/combinat/crystals/all.py +22 -0
  98. sage/combinat/crystals/bkk_crystals.py +141 -0
  99. sage/combinat/crystals/catalog.py +115 -0
  100. sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
  101. sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
  102. sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
  103. sage/combinat/crystals/crystals.py +257 -0
  104. sage/combinat/crystals/direct_sum.py +260 -0
  105. sage/combinat/crystals/elementary_crystals.py +1251 -0
  106. sage/combinat/crystals/fast_crystals.py +441 -0
  107. sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
  108. sage/combinat/crystals/generalized_young_walls.py +1076 -0
  109. sage/combinat/crystals/highest_weight_crystals.py +436 -0
  110. sage/combinat/crystals/induced_structure.py +695 -0
  111. sage/combinat/crystals/infinity_crystals.py +730 -0
  112. sage/combinat/crystals/kac_modules.py +863 -0
  113. sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
  114. sage/combinat/crystals/kyoto_path_model.py +497 -0
  115. sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
  116. sage/combinat/crystals/letters.pxd +79 -0
  117. sage/combinat/crystals/letters.pyx +3056 -0
  118. sage/combinat/crystals/littelmann_path.py +1518 -0
  119. sage/combinat/crystals/monomial_crystals.py +1262 -0
  120. sage/combinat/crystals/multisegments.py +462 -0
  121. sage/combinat/crystals/mv_polytopes.py +467 -0
  122. sage/combinat/crystals/pbw_crystal.py +511 -0
  123. sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
  124. sage/combinat/crystals/pbw_datum.pxd +4 -0
  125. sage/combinat/crystals/pbw_datum.pyx +487 -0
  126. sage/combinat/crystals/polyhedral_realization.py +372 -0
  127. sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/combinat/crystals/spins.pxd +21 -0
  129. sage/combinat/crystals/spins.pyx +756 -0
  130. sage/combinat/crystals/star_crystal.py +290 -0
  131. sage/combinat/crystals/subcrystal.py +464 -0
  132. sage/combinat/crystals/tensor_product.py +1177 -0
  133. sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
  134. sage/combinat/crystals/tensor_product_element.pxd +35 -0
  135. sage/combinat/crystals/tensor_product_element.pyx +1870 -0
  136. sage/combinat/crystals/virtual_crystal.py +420 -0
  137. sage/combinat/cyclic_sieving_phenomenon.py +204 -0
  138. sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/combinat/debruijn_sequence.pyx +355 -0
  140. sage/combinat/decorated_permutation.py +270 -0
  141. sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
  142. sage/combinat/degree_sequences.pyx +588 -0
  143. sage/combinat/derangements.py +527 -0
  144. sage/combinat/descent_algebra.py +1008 -0
  145. sage/combinat/diagram.py +1551 -0
  146. sage/combinat/diagram_algebras.py +5886 -0
  147. sage/combinat/dyck_word.py +4349 -0
  148. sage/combinat/e_one_star.py +1623 -0
  149. sage/combinat/enumerated_sets.py +123 -0
  150. sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
  151. sage/combinat/expnums.pyx +148 -0
  152. sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
  153. sage/combinat/fast_vector_partitions.pyx +346 -0
  154. sage/combinat/fqsym.py +1977 -0
  155. sage/combinat/free_dendriform_algebra.py +954 -0
  156. sage/combinat/free_prelie_algebra.py +1141 -0
  157. sage/combinat/fully_commutative_elements.py +1077 -0
  158. sage/combinat/fully_packed_loop.py +1523 -0
  159. sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
  160. sage/combinat/gray_codes.py +311 -0
  161. sage/combinat/grossman_larson_algebras.py +667 -0
  162. sage/combinat/growth.py +4352 -0
  163. sage/combinat/hall_polynomial.py +188 -0
  164. sage/combinat/hillman_grassl.py +866 -0
  165. sage/combinat/integer_matrices.py +329 -0
  166. sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
  167. sage/combinat/k_tableau.py +4564 -0
  168. sage/combinat/kazhdan_lusztig.py +215 -0
  169. sage/combinat/key_polynomial.py +885 -0
  170. sage/combinat/knutson_tao_puzzles.py +2286 -0
  171. sage/combinat/lr_tableau.py +311 -0
  172. sage/combinat/matrices/all.py +24 -0
  173. sage/combinat/matrices/hadamard_matrix.py +3790 -0
  174. sage/combinat/matrices/latin.py +2912 -0
  175. sage/combinat/misc.py +401 -0
  176. sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
  177. sage/combinat/ncsf_qsym/all.py +21 -0
  178. sage/combinat/ncsf_qsym/combinatorics.py +317 -0
  179. sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
  180. sage/combinat/ncsf_qsym/ncsf.py +5637 -0
  181. sage/combinat/ncsf_qsym/qsym.py +4053 -0
  182. sage/combinat/ncsf_qsym/tutorial.py +447 -0
  183. sage/combinat/ncsym/all.py +21 -0
  184. sage/combinat/ncsym/bases.py +855 -0
  185. sage/combinat/ncsym/dual.py +593 -0
  186. sage/combinat/ncsym/ncsym.py +2076 -0
  187. sage/combinat/necklace.py +551 -0
  188. sage/combinat/non_decreasing_parking_function.py +634 -0
  189. sage/combinat/nu_dyck_word.py +1474 -0
  190. sage/combinat/output.py +861 -0
  191. sage/combinat/parallelogram_polyomino.py +4326 -0
  192. sage/combinat/parking_functions.py +1602 -0
  193. sage/combinat/partition_algebra.py +1998 -0
  194. sage/combinat/partition_kleshchev.py +1982 -0
  195. sage/combinat/partition_shifting_algebras.py +584 -0
  196. sage/combinat/partition_tuple.py +3114 -0
  197. sage/combinat/path_tableaux/all.py +13 -0
  198. sage/combinat/path_tableaux/catalog.py +29 -0
  199. sage/combinat/path_tableaux/dyck_path.py +380 -0
  200. sage/combinat/path_tableaux/frieze.py +476 -0
  201. sage/combinat/path_tableaux/path_tableau.py +728 -0
  202. sage/combinat/path_tableaux/semistandard.py +510 -0
  203. sage/combinat/perfect_matching.py +779 -0
  204. sage/combinat/plane_partition.py +3300 -0
  205. sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
  206. sage/combinat/q_bernoulli.pyx +128 -0
  207. sage/combinat/quickref.py +81 -0
  208. sage/combinat/recognizable_series.py +2051 -0
  209. sage/combinat/regular_sequence.py +4316 -0
  210. sage/combinat/regular_sequence_bounded.py +543 -0
  211. sage/combinat/restricted_growth.py +81 -0
  212. sage/combinat/ribbon.py +20 -0
  213. sage/combinat/ribbon_shaped_tableau.py +489 -0
  214. sage/combinat/ribbon_tableau.py +1180 -0
  215. sage/combinat/rigged_configurations/all.py +46 -0
  216. sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
  217. sage/combinat/rigged_configurations/bij_infinity.py +370 -0
  218. sage/combinat/rigged_configurations/bij_type_A.py +163 -0
  219. sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
  220. sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
  221. sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
  222. sage/combinat/rigged_configurations/bij_type_B.py +900 -0
  223. sage/combinat/rigged_configurations/bij_type_C.py +267 -0
  224. sage/combinat/rigged_configurations/bij_type_D.py +771 -0
  225. sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
  226. sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
  227. sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
  228. sage/combinat/rigged_configurations/bijection.py +143 -0
  229. sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
  230. sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
  231. sage/combinat/rigged_configurations/rc_crystal.py +461 -0
  232. sage/combinat/rigged_configurations/rc_infinity.py +540 -0
  233. sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
  234. sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
  235. sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
  236. sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
  237. sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
  238. sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
  239. sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
  240. sage/combinat/rsk.py +3438 -0
  241. sage/combinat/schubert_polynomial.py +508 -0
  242. sage/combinat/set_partition.py +3318 -0
  243. sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/combinat/set_partition_iterator.pyx +136 -0
  245. sage/combinat/set_partition_ordered.py +1590 -0
  246. sage/combinat/sf/abreu_nigro.py +346 -0
  247. sage/combinat/sf/all.py +52 -0
  248. sage/combinat/sf/character.py +576 -0
  249. sage/combinat/sf/classical.py +319 -0
  250. sage/combinat/sf/dual.py +996 -0
  251. sage/combinat/sf/elementary.py +549 -0
  252. sage/combinat/sf/hall_littlewood.py +1028 -0
  253. sage/combinat/sf/hecke.py +336 -0
  254. sage/combinat/sf/homogeneous.py +464 -0
  255. sage/combinat/sf/jack.py +1428 -0
  256. sage/combinat/sf/k_dual.py +1458 -0
  257. sage/combinat/sf/kfpoly.py +447 -0
  258. sage/combinat/sf/llt.py +789 -0
  259. sage/combinat/sf/macdonald.py +2019 -0
  260. sage/combinat/sf/monomial.py +525 -0
  261. sage/combinat/sf/multiplicative.py +113 -0
  262. sage/combinat/sf/new_kschur.py +1786 -0
  263. sage/combinat/sf/ns_macdonald.py +964 -0
  264. sage/combinat/sf/orthogonal.py +246 -0
  265. sage/combinat/sf/orthotriang.py +355 -0
  266. sage/combinat/sf/powersum.py +963 -0
  267. sage/combinat/sf/schur.py +880 -0
  268. sage/combinat/sf/sf.py +1653 -0
  269. sage/combinat/sf/sfa.py +7053 -0
  270. sage/combinat/sf/symplectic.py +253 -0
  271. sage/combinat/sf/witt.py +721 -0
  272. sage/combinat/shifted_primed_tableau.py +2735 -0
  273. sage/combinat/shuffle.py +830 -0
  274. sage/combinat/sidon_sets.py +146 -0
  275. sage/combinat/similarity_class_type.py +1721 -0
  276. sage/combinat/sine_gordon.py +618 -0
  277. sage/combinat/six_vertex_model.py +784 -0
  278. sage/combinat/skew_partition.py +2053 -0
  279. sage/combinat/skew_tableau.py +2989 -0
  280. sage/combinat/sloane_functions.py +8935 -0
  281. sage/combinat/specht_module.py +1403 -0
  282. sage/combinat/species/all.py +48 -0
  283. sage/combinat/species/characteristic_species.py +321 -0
  284. sage/combinat/species/composition_species.py +273 -0
  285. sage/combinat/species/cycle_species.py +284 -0
  286. sage/combinat/species/empty_species.py +155 -0
  287. sage/combinat/species/functorial_composition_species.py +148 -0
  288. sage/combinat/species/generating_series.py +673 -0
  289. sage/combinat/species/library.py +148 -0
  290. sage/combinat/species/linear_order_species.py +169 -0
  291. sage/combinat/species/misc.py +83 -0
  292. sage/combinat/species/partition_species.py +290 -0
  293. sage/combinat/species/permutation_species.py +268 -0
  294. sage/combinat/species/product_species.py +423 -0
  295. sage/combinat/species/recursive_species.py +476 -0
  296. sage/combinat/species/set_species.py +192 -0
  297. sage/combinat/species/species.py +820 -0
  298. sage/combinat/species/structure.py +539 -0
  299. sage/combinat/species/subset_species.py +243 -0
  300. sage/combinat/species/sum_species.py +225 -0
  301. sage/combinat/subword.py +564 -0
  302. sage/combinat/subword_complex.py +2122 -0
  303. sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
  304. sage/combinat/subword_complex_c.pyx +119 -0
  305. sage/combinat/super_tableau.py +821 -0
  306. sage/combinat/superpartition.py +1154 -0
  307. sage/combinat/symmetric_group_algebra.py +3774 -0
  308. sage/combinat/symmetric_group_representations.py +1830 -0
  309. sage/combinat/t_sequences.py +877 -0
  310. sage/combinat/tableau.py +9506 -0
  311. sage/combinat/tableau_residues.py +860 -0
  312. sage/combinat/tableau_tuple.py +5353 -0
  313. sage/combinat/tiling.py +2432 -0
  314. sage/combinat/triangles_FHM.py +777 -0
  315. sage/combinat/tutorial.py +1857 -0
  316. sage/combinat/vector_partition.py +337 -0
  317. sage/combinat/words/abstract_word.py +1722 -0
  318. sage/combinat/words/all.py +59 -0
  319. sage/combinat/words/alphabet.py +268 -0
  320. sage/combinat/words/finite_word.py +7201 -0
  321. sage/combinat/words/infinite_word.py +113 -0
  322. sage/combinat/words/lyndon_word.py +652 -0
  323. sage/combinat/words/morphic.py +351 -0
  324. sage/combinat/words/morphism.py +3878 -0
  325. sage/combinat/words/paths.py +2932 -0
  326. sage/combinat/words/shuffle_product.py +278 -0
  327. sage/combinat/words/suffix_trees.py +1873 -0
  328. sage/combinat/words/word.py +769 -0
  329. sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
  330. sage/combinat/words/word_char.pyx +847 -0
  331. sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
  332. sage/combinat/words/word_datatypes.pxd +4 -0
  333. sage/combinat/words/word_datatypes.pyx +1067 -0
  334. sage/combinat/words/word_generators.py +2026 -0
  335. sage/combinat/words/word_infinite_datatypes.py +1218 -0
  336. sage/combinat/words/word_options.py +99 -0
  337. sage/combinat/words/words.py +2396 -0
  338. sage/data_structures/all__sagemath_combinat.py +1 -0
  339. sage/databases/all__sagemath_combinat.py +13 -0
  340. sage/databases/findstat.py +4897 -0
  341. sage/databases/oeis.py +2058 -0
  342. sage/databases/sloane.py +393 -0
  343. sage/dynamics/all__sagemath_combinat.py +14 -0
  344. sage/dynamics/cellular_automata/all.py +7 -0
  345. sage/dynamics/cellular_automata/catalog.py +34 -0
  346. sage/dynamics/cellular_automata/elementary.py +612 -0
  347. sage/dynamics/cellular_automata/glca.py +477 -0
  348. sage/dynamics/cellular_automata/solitons.py +1463 -0
  349. sage/dynamics/finite_dynamical_system.py +1249 -0
  350. sage/dynamics/finite_dynamical_system_catalog.py +382 -0
  351. sage/games/all.py +7 -0
  352. sage/games/hexad.py +704 -0
  353. sage/games/quantumino.py +591 -0
  354. sage/games/sudoku.py +889 -0
  355. sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
  356. sage/games/sudoku_backtrack.pyx +189 -0
  357. sage/groups/all__sagemath_combinat.py +1 -0
  358. sage/groups/indexed_free_group.py +489 -0
  359. sage/libs/all__sagemath_combinat.py +6 -0
  360. sage/libs/lrcalc/__init__.py +1 -0
  361. sage/libs/lrcalc/lrcalc.py +525 -0
  362. sage/libs/symmetrica/__init__.py +7 -0
  363. sage/libs/symmetrica/all.py +101 -0
  364. sage/libs/symmetrica/kostka.pxi +168 -0
  365. sage/libs/symmetrica/part.pxi +193 -0
  366. sage/libs/symmetrica/plet.pxi +42 -0
  367. sage/libs/symmetrica/sab.pxi +196 -0
  368. sage/libs/symmetrica/sb.pxi +332 -0
  369. sage/libs/symmetrica/sc.pxi +192 -0
  370. sage/libs/symmetrica/schur.pxi +956 -0
  371. sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
  372. sage/libs/symmetrica/symmetrica.pxi +1172 -0
  373. sage/libs/symmetrica/symmetrica.pyx +39 -0
  374. sage/monoids/all.py +13 -0
  375. sage/monoids/automatic_semigroup.py +1054 -0
  376. sage/monoids/free_abelian_monoid.py +315 -0
  377. sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
  378. sage/monoids/free_abelian_monoid_element.pxd +16 -0
  379. sage/monoids/free_abelian_monoid_element.pyx +397 -0
  380. sage/monoids/free_monoid.py +335 -0
  381. sage/monoids/free_monoid_element.py +431 -0
  382. sage/monoids/hecke_monoid.py +65 -0
  383. sage/monoids/string_monoid.py +817 -0
  384. sage/monoids/string_monoid_element.py +547 -0
  385. sage/monoids/string_ops.py +143 -0
  386. sage/monoids/trace_monoid.py +972 -0
  387. sage/rings/all__sagemath_combinat.py +2 -0
  388. sage/sat/all.py +4 -0
  389. sage/sat/boolean_polynomials.py +405 -0
  390. sage/sat/converters/__init__.py +6 -0
  391. sage/sat/converters/anf2cnf.py +14 -0
  392. sage/sat/converters/polybori.py +611 -0
  393. sage/sat/solvers/__init__.py +5 -0
  394. sage/sat/solvers/cryptominisat.py +287 -0
  395. sage/sat/solvers/dimacs.py +783 -0
  396. sage/sat/solvers/picosat.py +228 -0
  397. sage/sat/solvers/sat_lp.py +156 -0
  398. sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
  399. sage/sat/solvers/satsolver.pxd +3 -0
  400. sage/sat/solvers/satsolver.pyx +405 -0
@@ -0,0 +1,1729 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.groups
3
+ r"""
4
+ Constellations
5
+
6
+ A constellation is a tuple `(g_0, g_1, \dots, g_k)` of permutations
7
+ such that the product `g_0 g_1 ... g_k` is the identity. One often
8
+ assumes that the group generated by `g_0, g_1, \dots, g_k` acts
9
+ transitively ([LZ2004]_ definition 1). Geometrically, it corresponds
10
+ to a covering of the 2-sphere ramified over `k` points (the transitivity
11
+ condition corresponds to the connectivity of the covering).
12
+
13
+ EXAMPLES::
14
+
15
+ sage: c = Constellation(['(1,2)', '(1,3)', None])
16
+ sage: c
17
+ Constellation of length 3 and degree 3
18
+ g0 (1,2)(3)
19
+ g1 (1,3)(2)
20
+ g2 (1,3,2)
21
+ sage: C = Constellations(3,4); C
22
+ Connected constellations of length 3 and degree 4 on {1, 2, 3, 4}
23
+ sage: C.cardinality() # long time
24
+ 426
25
+
26
+ sage: C = Constellations(3, 4, domain=('a', 'b', 'c', 'd'))
27
+ sage: C
28
+ Connected constellations of length 3 and degree 4 on {'a', 'b', 'c', 'd'}
29
+ sage: c = C(('a','c'),(('b','c'),('a','d')), None)
30
+ sage: c
31
+ Constellation of length 3 and degree 4
32
+ g0 ('a','c')('b')('d')
33
+ g1 ('a','d')('b','c')
34
+ g2 ('a','d','c','b')
35
+ sage: c.is_connected()
36
+ True
37
+ sage: c.euler_characteristic()
38
+ 2
39
+ sage: TestSuite(C).run()
40
+ """
41
+
42
+ # ****************************************************************************
43
+ # Copyright (C) 2015-2016 Vincent Delecroix <20100.delecroix@gmail.com>
44
+ # Frédéric Chapoton <fchapoton2@gmail.com>
45
+ #
46
+ # This program is free software: you can redistribute it and/or modify
47
+ # it under the terms of the GNU General Public License as published by
48
+ # the Free Software Foundation, either version 2 of the License, or
49
+ # (at your option) any later version.
50
+ # https://www.gnu.org/licenses/
51
+ # ****************************************************************************
52
+ from itertools import repeat, product
53
+
54
+ from sage.structure.element import parent
55
+ from sage.structure.parent import Parent
56
+ from sage.structure.element import Element
57
+ from sage.structure.unique_representation import UniqueRepresentation
58
+ from sage.structure.richcmp import (op_NE, op_EQ, richcmp_not_equal,
59
+ rich_to_bool)
60
+
61
+ from sage.rings.integer import Integer
62
+ from sage.combinat.partition import Partition
63
+ from sage.misc.misc_c import prod
64
+ from sage.misc.lazy_import import lazy_import
65
+ from sage.categories.groups import Groups
66
+
67
+ lazy_import('sage.graphs.graph', 'Graph')
68
+ lazy_import('sage.graphs.digraph', 'DiGraph')
69
+ lazy_import('sage.groups.perm_gps.permgroup_named', 'SymmetricGroup')
70
+
71
+ # constructors
72
+
73
+
74
+ def Constellations(*data, **options):
75
+ r"""
76
+ Build a set of constellations.
77
+
78
+ INPUT:
79
+
80
+ - ``profile`` -- an optional profile
81
+
82
+ - ``length`` -- an optional length
83
+
84
+ - ``degree`` -- an optional degree
85
+
86
+ - ``connected`` -- an optional boolean
87
+
88
+ EXAMPLES::
89
+
90
+ sage: Constellations(4,2)
91
+ Connected constellations of length 4 and degree 2 on {1, 2}
92
+
93
+ sage: Constellations([[3,2,1],[3,3],[3,3]])
94
+ Connected constellations with profile ([3, 2, 1], [3, 3], [3, 3]) on {1, 2, 3, 4, 5, 6}
95
+ """
96
+ profile = options.get('profile', None)
97
+ length = options.get('length', None)
98
+ degree = options.get('degree', None)
99
+ connected = options.get('connected', True)
100
+ domain = options.get('domain', None)
101
+ if domain is not None:
102
+ domain = tuple(domain)
103
+
104
+ if data:
105
+ if len(data) == 1:
106
+ if isinstance(data[0], (tuple, list)):
107
+ profile = data[0]
108
+ else:
109
+ length = Integer(data[0])
110
+ elif len(data) == 2:
111
+ length = Integer(data[0])
112
+ degree = Integer(data[1])
113
+
114
+ if profile:
115
+ profile = tuple(map(Partition, profile))
116
+ return Constellations_p(profile, domain, bool(connected))
117
+ elif degree is not None and length is not None:
118
+ if domain is None:
119
+ sym = SymmetricGroup(degree)
120
+ else:
121
+ sym = SymmetricGroup(domain)
122
+ if len(sym.domain()) != degree:
123
+ raise ValueError("the size of the domain should be equal to the degree")
124
+
125
+ return Constellations_ld(Integer(length), Integer(degree),
126
+ sym, bool(connected))
127
+ else:
128
+ raise ValueError("you must either provide a profile or a pair (length, degree)")
129
+
130
+
131
+ def Constellation(g=None, mutable=False, connected=True, check=True):
132
+ r"""
133
+ Constellation.
134
+
135
+ INPUT:
136
+
137
+ - ``g`` -- list of permutations
138
+
139
+ - ``mutable`` -- boolean (default: ``False``); whether the result is
140
+ mutable or not
141
+
142
+ - ``connected`` -- boolean (default: ``True``); whether the result should
143
+ be connected
144
+
145
+ - ``check`` -- boolean (default: ``True``); whether or not to check. If it
146
+ is ``True``, then the list ``g`` must contain no ``None``.
147
+
148
+ EXAMPLES:
149
+
150
+ Simple initialization::
151
+
152
+ sage: Constellation(['(0,1)','(0,3)(1,2)','(0,3,1,2)'])
153
+ Constellation of length 3 and degree 4
154
+ g0 (0,1)(2)(3)
155
+ g1 (0,3)(1,2)
156
+ g2 (0,3,1,2)
157
+
158
+ One of the permutation can be omitted::
159
+
160
+ sage: Constellation(['(0,1)', None, '(0,4)(1,2,3)'])
161
+ Constellation of length 3 and degree 5
162
+ g0 (0,1)(2)(3)(4)
163
+ g1 (0,3,2,1,4)
164
+ g2 (0,4)(1,2,3)
165
+
166
+ One can define mutable constellations::
167
+
168
+ sage: Constellation(([0,2,1], [2,1,0], [1,2,0]), mutable=True)
169
+ Constellation of length 3 and degree 3
170
+ g0 (0)(1,2)
171
+ g1 (0,2)(1)
172
+ g2 (0,1,2)
173
+ """
174
+ l = len(g)
175
+ sym, _ = perms_sym_init([x for x in g if x is not None])
176
+ d = len(sym.domain())
177
+ return Constellations(l, d,
178
+ domain=sym.domain(),
179
+ connected=connected)(g, mutable=mutable, check=check)
180
+
181
+ # classes
182
+
183
+
184
+ class Constellation_class(Element):
185
+ r"""
186
+ Constellation.
187
+
188
+ A constellation or a tuple of permutations `(g_0,g_1,...,g_k)`
189
+ such that the product `g_0 g_1 ... g_k` is the identity.
190
+ """
191
+
192
+ def __init__(self, parent, g, connected, mutable, check):
193
+ r"""
194
+ TESTS::
195
+
196
+ sage: c = Constellation([[1,2,0],[0,2,1],[1,0,2],None])
197
+ sage: c == loads(dumps(c))
198
+ True
199
+ sage: g0 = '(0,1)(2,4)'
200
+ sage: g1 = '(0,3)(1,4)'
201
+ sage: g2 = '(2,4,3)'
202
+ sage: g3 = '(0,3)(1,2)'
203
+ sage: c0 = Constellation([g0,g1,g2,g3])
204
+ sage: c0 == Constellation([None,g1,g2,g3])
205
+ True
206
+ sage: c0 == Constellation([g0,None,g2,g3])
207
+ True
208
+ sage: c0 == Constellation([g0,g1,None,g3])
209
+ True
210
+ sage: c0 == Constellation([g0,g1,g2,None])
211
+ True
212
+ """
213
+ Element.__init__(self, parent)
214
+ self._connected = connected
215
+ self._mutable = mutable
216
+ self._g = g
217
+ if check:
218
+ self._check()
219
+
220
+ def __hash__(self):
221
+ r"""
222
+ Return a hash for ``self``.
223
+
224
+ EXAMPLES::
225
+
226
+ sage: c = Constellation(([0,2,1],[2,1,0],[1,2,0]), mutable=False)
227
+ sage: hash(c) == hash(tuple(c._g))
228
+ True
229
+ """
230
+ if self._mutable:
231
+ raise ValueError("cannot hash mutable constellation")
232
+ return hash(tuple(self._g))
233
+
234
+ def set_immutable(self):
235
+ r"""
236
+ Do nothing, as ``self`` is already immutable.
237
+
238
+ EXAMPLES::
239
+
240
+ sage: c = Constellation(([0,2,1],[2,1,0],[1,2,0]), mutable=False)
241
+ sage: c.set_immutable()
242
+ sage: c.is_mutable()
243
+ False
244
+ """
245
+ self._mutable = False
246
+
247
+ def is_mutable(self):
248
+ r"""
249
+ Return ``False`` as ``self`` is immutable.
250
+
251
+ EXAMPLES::
252
+
253
+ sage: c = Constellation(([0,2,1],[2,1,0],[1,2,0]), mutable=False)
254
+ sage: c.is_mutable()
255
+ False
256
+ """
257
+ return self._mutable
258
+
259
+ def switch(self, i, j0, j1):
260
+ r"""
261
+ Perform the multiplication by the transposition `(j0, j1)` between the
262
+ permutations `g_i` and `g_{i+1}`.
263
+
264
+ The modification is local in the sense that it modifies `g_i`
265
+ and `g_{i+1}` but does not modify the product `g_i g_{i+1}`. The new
266
+ constellation is
267
+
268
+ .. MATH::
269
+
270
+ (g_0, \ldots, g_{i-1}, g_{i} (j0 j1), (j0 j1) g_{i+1}, g_{i+2}, \ldots, g_k)
271
+
272
+ EXAMPLES::
273
+
274
+ sage: c = Constellation(['(0,1)(2,3,4)','(1,4)',None], mutable=True); c
275
+ Constellation of length 3 and degree 5
276
+ g0 (0,1)(2,3,4)
277
+ g1 (0)(1,4)(2)(3)
278
+ g2 (0,1,3,2,4)
279
+ sage: c.is_mutable()
280
+ True
281
+ sage: c.switch(1,2,3); c
282
+ Constellation of length 3 and degree 5
283
+ g0 (0,1)(2,3,4)
284
+ g1 (0)(1,4)(2,3)
285
+ g2 (0,1,3,4)(2)
286
+ sage: c._check()
287
+ sage: c.switch(2,1,3); c
288
+ Constellation of length 3 and degree 5
289
+ g0 (0,1,4,2,3)
290
+ g1 (0)(1,4)(2,3)
291
+ g2 (0,3,4)(1)(2)
292
+ sage: c._check()
293
+ sage: c.switch(0,0,1); c
294
+ Constellation of length 3 and degree 5
295
+ g0 (0)(1,4,2,3)
296
+ g1 (0,4,1)(2,3)
297
+ g2 (0,3,4)(1)(2)
298
+ sage: c._check()
299
+ """
300
+ if not self._mutable:
301
+ raise ValueError("this constellation is immutable."
302
+ " Take a mutable copy first.")
303
+ S = SymmetricGroup(list(range(self.degree())))
304
+ tr = S((j0, j1))
305
+ i = int(i)
306
+ if i < 0 or i >= len(self._g):
307
+ raise ValueError("index out of range")
308
+
309
+ ii = i + 1
310
+ if ii == len(self._g):
311
+ ii = 0
312
+ self._g[i] = self._g[i] * tr
313
+ self._g[ii] = tr * self._g[ii]
314
+
315
+ def euler_characteristic(self):
316
+ r"""
317
+ Return the Euler characteristic of the surface.
318
+
319
+ ALGORITHM:
320
+
321
+ Hurwitz formula
322
+
323
+ EXAMPLES::
324
+
325
+ sage: c = Constellation(['(0,1)', '(0,2)', None])
326
+ sage: c.euler_characteristic()
327
+ 2
328
+
329
+ sage: c = Constellation(['(0,1,2,3)','(1,3,0,2)', '(0,3,1,2)', None])
330
+ sage: c.euler_characteristic()
331
+ -4
332
+
333
+ TESTS::
334
+
335
+ sage: parent(c.euler_characteristic())
336
+ Integer Ring
337
+ """
338
+ return Integer(self.degree() * 2 -
339
+ sum(sum(j - 1 for j in self.profile(i))
340
+ for i in range(self.length())))
341
+
342
+ def genus(self):
343
+ r"""
344
+ Return the genus of the surface.
345
+
346
+ EXAMPLES::
347
+
348
+ sage: c = Constellation(['(0,1)', '(0,2)', None])
349
+ sage: c.genus()
350
+ 0
351
+
352
+ sage: c = Constellation(['(0,1)(2,3,4)','(1,3,4)(2,0)', None])
353
+ sage: c.genus()
354
+ 1
355
+
356
+ TESTS::
357
+
358
+ sage: parent(c.genus())
359
+ Integer Ring
360
+ """
361
+ return 1 - self.euler_characteristic() // 2
362
+
363
+ def _check(self):
364
+ r"""
365
+ Check that the constellation is valid and if not raise
366
+ :exc:`ValueError`.
367
+
368
+ TESTS::
369
+
370
+ sage: c = Constellation([[0,1],[1,0]], mutable=True, check=False)
371
+ sage: c._check()
372
+ Traceback (most recent call last):
373
+ ...
374
+ ValueError: the product is not identity
375
+
376
+ sage: c = Constellation([[0,1],[0,1]], mutable=True, check=False)
377
+ sage: c._check()
378
+ Traceback (most recent call last):
379
+ ...
380
+ ValueError: not connected
381
+ """
382
+ d = self.degree()
383
+ Sd = self.parent()._sym
384
+
385
+ if prod(self._g, Sd.one()) != Sd.one():
386
+ raise ValueError("the product is not identity")
387
+
388
+ if self._connected and not perms_are_connected(self._g, d):
389
+ raise ValueError("not connected")
390
+
391
+ def __copy__(self):
392
+ r"""
393
+ Return a copy of ``self``.
394
+
395
+ TESTS::
396
+
397
+ sage: c = Constellation([[0,2,1],[1,0,2],[2,1,0],None])
398
+ sage: c == copy(c)
399
+ True
400
+ sage: c is copy(c)
401
+ False
402
+ sage: c = Constellation([[0,2,1],[1,0,2],[2,1,0],None],mutable=True)
403
+ sage: c == copy(c)
404
+ True
405
+ sage: c is copy(c)
406
+ False
407
+ """
408
+ return self.parent()(list(self._g),
409
+ check=False,
410
+ mutable=self._mutable)
411
+
412
+ copy = __copy__
413
+
414
+ def mutable_copy(self):
415
+ r"""
416
+ Return a mutable copy of ``self``.
417
+
418
+ EXAMPLES::
419
+
420
+ sage: c = Constellation(([0,2,1],[2,1,0],[1,2,0]), mutable=False)
421
+ sage: d = c.mutable_copy()
422
+ sage: d.is_mutable()
423
+ True
424
+ """
425
+ return self.parent()(list(self._g),
426
+ check=False,
427
+ mutable=True)
428
+
429
+ # GENERAL PROPERTIES
430
+
431
+ def is_connected(self):
432
+ r"""
433
+ Test of connectedness.
434
+
435
+ EXAMPLES::
436
+
437
+ sage: c = Constellation(['(0,1)(2)', None, '(0,1)(2)'], connected=False)
438
+ sage: c.is_connected()
439
+ False
440
+ sage: c = Constellation(['(0,1,2)', None], connected=False)
441
+ sage: c.is_connected()
442
+ True
443
+ """
444
+ if self._connected:
445
+ return True
446
+ else:
447
+ return perms_are_connected(self._g, self.degree())
448
+
449
+ def connected_components(self):
450
+ """
451
+ Return the connected components.
452
+
453
+ OUTPUT: list of connected constellations
454
+
455
+ EXAMPLES::
456
+
457
+ sage: c = Constellation(['(0,1)(2)', None, '(0,1)(2)'], connected=False)
458
+ sage: cc = c.connected_components(); cc
459
+ [Constellation of length 3 and degree 2
460
+ g0 (0,1)
461
+ g1 (0)(1)
462
+ g2 (0,1),
463
+ Constellation of length 3 and degree 1
464
+ g0 (0)
465
+ g1 (0)
466
+ g2 (0)]
467
+ sage: all(c2.is_connected() for c2 in cc)
468
+ True
469
+
470
+ sage: c = Constellation(['(0,1,2)', None], connected=False)
471
+ sage: c.connected_components()
472
+ [Constellation of length 2 and degree 3
473
+ g0 (0,1,2)
474
+ g1 (0,2,1)]
475
+ """
476
+ if self._connected:
477
+ return [self]
478
+ G = Graph()
479
+ G.add_vertices(list(range(self.degree())))
480
+ for p in self._g:
481
+ G.add_edges(enumerate(p.domain()), loops=False)
482
+ m = G.connected_components(sort=False)
483
+ if len(m) == 1:
484
+ return [self]
485
+ for mm in m:
486
+ mm.sort()
487
+ m.sort()
488
+ g = [[] for _ in repeat(None, len(m))]
489
+ m_inv = [None] * self.degree()
490
+ for t, mt in enumerate(m):
491
+ for i, mti in enumerate(mt):
492
+ m_inv[mti] = i
493
+ for k in range(self.length()):
494
+ tmp = [None] * len(mt)
495
+ for i, mti in enumerate(mt):
496
+ tmp[i] = m_inv[self._g[k](mti)]
497
+ g[t].append(tmp)
498
+ return [Constellation(g=g[i], check=False) for i in range(len(m))]
499
+
500
+ def _richcmp_(self, other, op):
501
+ r"""
502
+ Do the comparison.
503
+
504
+ TESTS::
505
+
506
+ sage: Constellation(['(0,1,2)', None]) == Constellation(['(0,1,2)', None])
507
+ True
508
+ sage: Constellation(['(0,1)','(0,2)',None]) == Constellation(['(0,1)',None,'(0,2)'])
509
+ False
510
+
511
+ sage: Constellation(['(0,1,2)', None]) != Constellation(['(0,1,2)', None])
512
+ False
513
+ sage: Constellation(['(0,1)','(0,2)',None]) != Constellation(['(0,1)',None,'(0,2)'])
514
+ True
515
+
516
+ sage: c1 = Constellation([[1,2,0],None])
517
+ sage: c2 = Constellation([[2,0,1],None])
518
+ sage: c1 < c2
519
+ True
520
+ sage: c2 > c1
521
+ True
522
+ """
523
+ if not isinstance(other, Constellation_class):
524
+ return op == op_NE
525
+ if op == op_EQ:
526
+ return self._g == other._g
527
+ if op == op_NE:
528
+ return self._g != other._g
529
+
530
+ lx = self.length()
531
+ rx = other.length()
532
+ if lx != rx:
533
+ return richcmp_not_equal(lx, rx, op)
534
+
535
+ lx = self.degree()
536
+ rx = other.degree()
537
+ if lx != rx:
538
+ return richcmp_not_equal(lx, rx, op)
539
+
540
+ for i in range(self.length() - 1):
541
+ lx = self._g[i]
542
+ rx = other._g[i]
543
+ if lx != rx:
544
+ return richcmp_not_equal(lx, rx, op)
545
+ return rich_to_bool(op, 0)
546
+
547
+ def is_isomorphic(self, other, return_map=False):
548
+ r"""
549
+ Test of isomorphism.
550
+
551
+ Return ``True`` if the constellations are isomorphic
552
+ (*i.e.* related by a common conjugacy) and return the permutation that
553
+ conjugate the two permutations if ``return_map`` is ``True`` in
554
+ such a way that ``self.relabel(m) == other``.
555
+
556
+ ALGORITHM:
557
+
558
+ uses canonical labels obtained from the method :meth:`relabel`.
559
+
560
+ EXAMPLES::
561
+
562
+ sage: c = Constellation([[1,0,2],[2,1,0],[0,2,1],None])
563
+ sage: d = Constellation([[2,1,0],[0,2,1],[1,0,2],None])
564
+ sage: answer, mapping = c.is_isomorphic(d,return_map=True)
565
+ sage: answer
566
+ True
567
+ sage: c.relabel(mapping) == d
568
+ True
569
+ """
570
+ if return_map:
571
+ if not (self.degree() == other.degree() and
572
+ self.length() == other.length()):
573
+ return False, None
574
+ sn, sn_map = self.relabel(return_map=True)
575
+ on, on_map = other.relabel(return_map=True)
576
+ if sn != on:
577
+ return False, None
578
+ return True, sn_map * ~on_map
579
+
580
+ return (self.degree() == other.degree() and
581
+ self.length() == other.length() and
582
+ self.relabel() == other.relabel())
583
+
584
+ def _repr_(self):
585
+ r"""
586
+ Return a string representation.
587
+
588
+ EXAMPLES::
589
+
590
+ sage: c = Constellation([[1,0,2],[2,1,0],[0,2,1],None])
591
+ sage: c._repr_()
592
+ 'Constellation of length 4 and degree 3\ng0 (0,1)(2)\ng1 (0,2)(1)\ng2 (0)(1,2)\ng3 (0,2)(1)'
593
+ """
594
+ s = "Constellation of length {} and degree {}".format(self.length(),
595
+ self.degree())
596
+ for i in range(self.length()):
597
+ s += "\ng{} {}".format(i, self._g[i].cycle_string(True))
598
+ return s
599
+
600
+ def degree(self):
601
+ r"""
602
+ Return the degree of the constellation.
603
+
604
+ The degree of a constellation is the number `n` that
605
+ corresponds to the symmetric group `S(n)` in which the
606
+ permutations of the constellation are defined.
607
+
608
+ EXAMPLES::
609
+
610
+ sage: c = Constellation([])
611
+ sage: c.degree()
612
+ 0
613
+ sage: c = Constellation(['(0,1)',None])
614
+ sage: c.degree()
615
+ 2
616
+ sage: c = Constellation(['(0,1)','(0,3,2)(1,5)',None,'(4,3,2,1)'])
617
+ sage: c.degree()
618
+ 6
619
+
620
+ TESTS::
621
+
622
+ sage: parent(c.degree())
623
+ Integer Ring
624
+ """
625
+ return self.parent()._degree
626
+
627
+ def length(self):
628
+ r"""
629
+ Return the number of permutations.
630
+
631
+ EXAMPLES::
632
+
633
+ sage: c = Constellation(['(0,1)','(0,2)','(0,3)',None])
634
+ sage: c.length()
635
+ 4
636
+ sage: c = Constellation(['(0,1,3)',None,'(1,2)'])
637
+ sage: c.length()
638
+ 3
639
+
640
+ TESTS::
641
+
642
+ sage: parent(c.length())
643
+ Integer Ring
644
+ """
645
+ return Integer(len(self._g))
646
+
647
+ def profile(self, i=None):
648
+ r"""
649
+ Return the profile of ``self``.
650
+
651
+ The profile of a constellation is the tuple of partitions
652
+ associated to the conjugacy classes of the permutations of the
653
+ constellation.
654
+
655
+ This is also called the passport.
656
+
657
+ EXAMPLES::
658
+
659
+ sage: c = Constellation(['(0,1,2)(3,4)','(0,3)',None])
660
+ sage: c.profile()
661
+ ([3, 2], [2, 1, 1, 1], [5])
662
+ """
663
+ if i is None:
664
+ return tuple(self.profile(j) for j in range(self.length()))
665
+ else:
666
+ parts = [len(cy) for cy in self._g[i].cycle_tuples(True)]
667
+ return Partition(sorted(parts, reverse=True))
668
+
669
+ passport = profile
670
+
671
+ # ACCESS TO INDIVIDUAL PERMUTATION
672
+
673
+ def g(self, i=None):
674
+ r"""
675
+ Return the permutation `g_i` of the constellation.
676
+
677
+ INPUT:
678
+
679
+ - ``i`` -- integer or ``None`` (default)
680
+
681
+ If ``None`` , return instead the list of all `g_i`.
682
+
683
+ EXAMPLES::
684
+
685
+ sage: c = Constellation(['(0,1,2)(3,4)','(0,3)',None])
686
+ sage: c.g(0)
687
+ (0,1,2)(3,4)
688
+ sage: c.g(1)
689
+ (0,3)
690
+ sage: c.g(2)
691
+ (0,4,3,2,1)
692
+ sage: c.g()
693
+ [(0,1,2)(3,4), (0,3), (0,4,3,2,1)]
694
+ """
695
+ from copy import copy
696
+ if i is None:
697
+ return copy(self._g)
698
+ else:
699
+ gi = self._g[i]
700
+ return gi.parent()(gi)
701
+
702
+ def relabel(self, perm=None, return_map=False):
703
+ r"""
704
+ Relabel ``self``.
705
+
706
+ If ``perm`` is provided then relabel with respect to ``perm``. Otherwise
707
+ use canonical labels. In that case, if ``return_map`` is provided, the
708
+ return also the map used for canonical labels.
709
+
710
+ Algorithm:
711
+
712
+ the cycle for g(0) are adjacent and the cycle are joined with
713
+ respect to the other permutations. The minimum is taken for
714
+ all possible renumerotations.
715
+
716
+ EXAMPLES::
717
+
718
+ sage: c = Constellation(['(0,1)(2,3,4)','(1,4)',None]); c
719
+ Constellation of length 3 and degree 5
720
+ g0 (0,1)(2,3,4)
721
+ g1 (0)(1,4)(2)(3)
722
+ g2 (0,1,3,2,4)
723
+ sage: c2 = c.relabel(); c2
724
+ Constellation of length 3 and degree 5
725
+ g0 (0,1)(2,3,4)
726
+ g1 (0)(1,2)(3)(4)
727
+ g2 (0,1,4,3,2)
728
+
729
+ The map returned when the option ``return_map`` is set to
730
+ ``True`` can be used to set the relabelling::
731
+
732
+ sage: c3, perm = c.relabel(return_map=True)
733
+ sage: c3 == c2 and c3 == c.relabel(perm=perm)
734
+ True
735
+
736
+ sage: S5 = SymmetricGroup(range(5))
737
+ sage: d = c.relabel(S5([4,3,1,0,2])); d
738
+ Constellation of length 3 and degree 5
739
+ g0 (0,2,1)(3,4)
740
+ g1 (0)(1)(2,3)(4)
741
+ g2 (0,1,2,4,3)
742
+ sage: d.is_isomorphic(c)
743
+ True
744
+
745
+ We check that after a random relabelling the new constellation is
746
+ isomorphic to the initial one::
747
+
748
+ sage: c = Constellation(['(0,1)(2,3,4)','(1,4)',None])
749
+ sage: p = S5.random_element()
750
+ sage: cc = c.relabel(perm=p)
751
+ sage: cc.is_isomorphic(c)
752
+ True
753
+
754
+ Check that it works for "non standard" labels::
755
+
756
+ sage: c = Constellation([(('a','b'),('c','d','e')),('b','d'), None])
757
+ sage: c.relabel()
758
+ Constellation of length 3 and degree 5
759
+ g0 ('a','b')('c','d','e')
760
+ g1 ('a')('b','c')('d')('e')
761
+ g2 ('a','b','e','d','c')
762
+ """
763
+ if perm is not None:
764
+ g = [[None] * self.degree() for _ in range(self.length())]
765
+ for i in range(len(perm.domain())):
766
+ for k in range(self.length()):
767
+ g[k][perm(i)] = perm(self._g[k](i))
768
+ return Constellation(g=g, check=False, mutable=self.is_mutable())
769
+
770
+ if return_map:
771
+ try:
772
+ return self._normal_form, self._normal_form_map
773
+ except AttributeError:
774
+ pass
775
+ else:
776
+ try:
777
+ return self._normal_form
778
+ except AttributeError:
779
+ pass
780
+
781
+ # compute canonical labels
782
+ if not self.is_connected():
783
+ raise ValueError("no canonical labels implemented for"
784
+ " non connected constellation")
785
+
786
+ # get the permutations on {0, 1, ..., d-1}
787
+ # compute the canonical labels
788
+ # map it back to the domain
789
+ # TODO: a lot of time is lost here!
790
+ domain = list(self.parent()._sym.domain())
791
+ index = {e: i for i, e in enumerate(domain)}
792
+ g = [[index[gg(i)] for i in domain] for gg in self._g]
793
+ c_win, m_win = perms_canonical_labels(g)
794
+ c_win = [[domain[i] for i in gg] for gg in c_win]
795
+ m_win = self.parent()._sym([domain[i] for i in m_win])
796
+ c_win = self.parent()(c_win, mutable=False, check=False)
797
+
798
+ if not self.is_mutable():
799
+ self._normal_form = c_win
800
+ self._normal_form_map = m_win
801
+
802
+ c_win._normal_form = c_win
803
+ c_win._normal_form_map = m_win
804
+
805
+ if return_map:
806
+ return c_win, m_win
807
+ else:
808
+ return c_win
809
+
810
+ # BRAID GROUP ACTION
811
+
812
+ def braid_group_action(self, i):
813
+ r"""
814
+ Act on ``self`` as the braid group generator that exchanges
815
+ position `i` and `i+1`.
816
+
817
+ INPUT:
818
+
819
+ - ``i`` -- integer in `[0, n-1]` where `n` is the length of ``self``
820
+
821
+ EXAMPLES::
822
+
823
+ sage: sigma = lambda c, i: c.braid_group_action(i)
824
+
825
+ sage: c = Constellation(['(0,1)(2,3,4)','(1,4)',None]); c
826
+ Constellation of length 3 and degree 5
827
+ g0 (0,1)(2,3,4)
828
+ g1 (0)(1,4)(2)(3)
829
+ g2 (0,1,3,2,4)
830
+ sage: sigma(c, 1)
831
+ Constellation of length 3 and degree 5
832
+ g0 (0,1)(2,3,4)
833
+ g1 (0,1,3,2,4)
834
+ g2 (0,3)(1)(2)(4)
835
+
836
+ Check the commutation relation::
837
+
838
+ sage: c = Constellation(['(0,1)(2,3,4)','(1,4)','(2,5)(0,4)',None])
839
+ sage: d = Constellation(['(0,1,3,5)','(2,3,4)','(0,3,5)',None])
840
+ sage: c13 = sigma(sigma(c, 0), 2)
841
+ sage: c31 = sigma(sigma(c, 2), 0)
842
+ sage: c13 == c31
843
+ True
844
+ sage: d13 = sigma(sigma(d, 0), 2)
845
+ sage: d31 = sigma(sigma(d, 2), 0)
846
+ sage: d13 == d31
847
+ True
848
+
849
+ Check the braid relation::
850
+
851
+ sage: c121 = sigma(sigma(sigma(c, 1), 2), 1)
852
+ sage: c212 = sigma(sigma(sigma(c, 2), 1), 2)
853
+ sage: c121 == c212
854
+ True
855
+ sage: d121 = sigma(sigma(sigma(d, 1), 2), 1)
856
+ sage: d212 = sigma(sigma(sigma(d, 2), 1), 2)
857
+ sage: d121 == d212
858
+ True
859
+ """
860
+ if i < 0 or i >= self.length():
861
+ txt = "i should be between 0 and {}"
862
+ raise ValueError(txt.format(self.length() - 1))
863
+ j = i + 1
864
+ if j == self.length(): # wrap around the cylinder
865
+ j = 0
866
+ h = self.copy()
867
+ si = self._g[i]
868
+ sj = self._g[j]
869
+ h._g[i] = sj
870
+ h._g[j] = (~sj * si) * sj
871
+ return h
872
+
873
+ def braid_group_orbit(self):
874
+ r"""
875
+ Return the graph of the action of the braid group.
876
+
877
+ The action is considered up to isomorphism of constellation.
878
+
879
+ EXAMPLES::
880
+
881
+ sage: c = Constellation(['(0,1)(2,3,4)','(1,4)',None]); c
882
+ Constellation of length 3 and degree 5
883
+ g0 (0,1)(2,3,4)
884
+ g1 (0)(1,4)(2)(3)
885
+ g2 (0,1,3,2,4)
886
+ sage: G = c.braid_group_orbit()
887
+ sage: G.num_verts()
888
+ 4
889
+ sage: G.num_edges()
890
+ 12
891
+ """
892
+ G = DiGraph(multiedges=True, loops=True)
893
+ waiting = [self.relabel()]
894
+
895
+ while waiting:
896
+ c = waiting.pop()
897
+ G.add_vertex(c)
898
+ for i in range(self.length()):
899
+ cc = self.braid_group_action(i).relabel()
900
+ if cc not in G:
901
+ waiting.append(cc)
902
+ G.add_edge(c, cc, i)
903
+ return G
904
+
905
+
906
+ class Constellations_ld(UniqueRepresentation, Parent):
907
+ r"""
908
+ Constellations of given length and degree.
909
+
910
+ EXAMPLES::
911
+
912
+ sage: C = Constellations(2,3); C
913
+ Connected constellations of length 2 and degree 3 on {1, 2, 3}
914
+ sage: C([[2,3,1],[3,1,2]])
915
+ Constellation of length 2 and degree 3
916
+ g0 (1,2,3)
917
+ g1 (1,3,2)
918
+ sage: C.cardinality()
919
+ 2
920
+ sage: Constellations(2,3,connected=False).cardinality()
921
+ 6
922
+ """
923
+ Element = Constellation_class
924
+
925
+ def __init__(self, length, degree, sym=None, connected=True):
926
+ """
927
+ TESTS::
928
+
929
+ sage: TestSuite(Constellations(length=6,degree=4)).run(skip='_test_cardinality')
930
+ """
931
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
932
+ Parent.__init__(self, category=FiniteEnumeratedSets())
933
+ self._length = length
934
+ self._degree = degree
935
+ if self._length < 0:
936
+ raise ValueError("length should be a nonnegative integer")
937
+ if self._degree < 0:
938
+ raise ValueError("degree should be a nonnegative integer")
939
+
940
+ self._sym = sym
941
+
942
+ self._connected = bool(connected)
943
+
944
+ def is_empty(self):
945
+ r"""
946
+ Return whether this set of constellations is empty.
947
+
948
+ EXAMPLES::
949
+
950
+ sage: Constellations(2, 3).is_empty()
951
+ False
952
+ sage: Constellations(1, 2).is_empty()
953
+ True
954
+ sage: Constellations(1, 2, connected=False).is_empty()
955
+ False
956
+ """
957
+ return self._connected and self._length == 1 and self._degree > 1
958
+
959
+ def __contains__(self, elt):
960
+ r"""
961
+ TESTS::
962
+
963
+ sage: C = Constellations(2, 3, connected=True)
964
+ sage: D = Constellations(2, 3, connected=False)
965
+ sage: e1 = [[3,1,2], None]
966
+ sage: e2 = [[1,2,3], None]
967
+ sage: C(e1) in C
968
+ True
969
+ sage: D(e1) in C
970
+ True
971
+ sage: D(e1) in D
972
+ True
973
+ sage: D(e2) in C
974
+ False
975
+ sage: D(e2) in D
976
+ True
977
+
978
+ sage: e1 in C and e1 in D
979
+ True
980
+ sage: e2 in C
981
+ False
982
+ sage: e2 in D
983
+ True
984
+ """
985
+ if isinstance(elt, (tuple, list)):
986
+ try:
987
+ self(elt, check=True)
988
+ except (ValueError, TypeError):
989
+ return False
990
+ else:
991
+ return True
992
+ elif not isinstance(elt, Constellation_class):
993
+ return False
994
+ return (elt.parent() is self or
995
+ (elt.length() == self._length and
996
+ elt.degree() == self._degree and
997
+ (not self._connected or elt.is_connected())))
998
+
999
+ def _repr_(self):
1000
+ """
1001
+ TESTS::
1002
+
1003
+ sage: Constellations(3,3)._repr_()
1004
+ 'Connected constellations of length 3 and degree 3 on {1, 2, 3}'
1005
+ sage: Constellations(3,3,connected=False)._repr_()
1006
+ 'Constellations of length 3 and degree 3 on {1, 2, 3}'
1007
+ """
1008
+ s = "of length {} and degree {} on {}".format(self._length,
1009
+ self._degree,
1010
+ self._sym.domain())
1011
+ if self._connected:
1012
+ return "Connected constellations " + s
1013
+ else:
1014
+ return "Constellations " + s
1015
+
1016
+ def __iter__(self):
1017
+ """
1018
+ Iterator over all constellations of given degree and length.
1019
+
1020
+ EXAMPLES::
1021
+
1022
+ sage: const = Constellations(3,3); const
1023
+ Connected constellations of length 3 and degree 3 on {1, 2, 3}
1024
+ sage: len([v for v in const])
1025
+ 26
1026
+
1027
+ One can check the first few terms of sequence :oeis:`220754`::
1028
+
1029
+ sage: Constellations(4,1).cardinality()
1030
+ 1
1031
+ sage: Constellations(4,2).cardinality()
1032
+ 7
1033
+ sage: Constellations(4,3).cardinality()
1034
+ 194
1035
+ sage: Constellations(4,4).cardinality() # long time
1036
+ 12858
1037
+ """
1038
+ from itertools import product
1039
+
1040
+ if self._length == 1:
1041
+ if self._degree == 1:
1042
+ yield self([[0]])
1043
+ return
1044
+
1045
+ S = self._sym
1046
+ for p in product(S, repeat=self._length - 1):
1047
+ if self._connected and not perms_are_connected(p, self._degree):
1048
+ continue
1049
+ yield self(list(p) + [None], check=False)
1050
+
1051
+ def random_element(self, mutable=False):
1052
+ r"""
1053
+ Return a random element.
1054
+
1055
+ This is found by trial and rejection, starting from
1056
+ a random list of permutations.
1057
+
1058
+ EXAMPLES::
1059
+
1060
+ sage: const = Constellations(3,3)
1061
+ sage: const.random_element()
1062
+ Constellation of length 3 and degree 3
1063
+ ...
1064
+ ...
1065
+ ...
1066
+ sage: c = const.random_element()
1067
+ sage: c.degree() == 3 and c.length() == 3
1068
+ True
1069
+ """
1070
+ from sage.groups.perm_gps.permgroup import PermutationGroup
1071
+
1072
+ l = self._length
1073
+ d = self._degree
1074
+ Sd = self._sym
1075
+
1076
+ g = [Sd.random_element() for _ in range(l - 1)]
1077
+ G = PermutationGroup(g)
1078
+ while not G.degree() == d or (self._connected and
1079
+ not G.is_transitive()):
1080
+ g = [Sd.random_element() for _ in range(l - 1)]
1081
+ G = PermutationGroup(g)
1082
+
1083
+ return self([sigma.domain() for sigma in g] + [None], mutable=mutable)
1084
+
1085
+ def _element_constructor_(self, *data, **options):
1086
+ r"""
1087
+ Build an element of ``self``.
1088
+
1089
+ EXAMPLES::
1090
+
1091
+ sage: C = Constellations(2,3)
1092
+ sage: C([[2,3,1],[3,1,2]])
1093
+ Constellation of length 2 and degree 3
1094
+ g0 (1,2,3)
1095
+ g1 (1,3,2)
1096
+ sage: C([[3,2,1],[3,2,1]])
1097
+ Traceback (most recent call last):
1098
+ ...
1099
+ ValueError: not connected
1100
+ """
1101
+ if len(data) == 1 and isinstance(data[0], (list, tuple)) and \
1102
+ len(data[0]) == self._length:
1103
+ g = list(data[0])
1104
+ else:
1105
+ g = list(data)
1106
+
1107
+ if len(g) != self._length:
1108
+ raise ValueError("must be a list of length {}".format(self._length))
1109
+
1110
+ if g.count(None) == 0:
1111
+ i = None
1112
+ elif g.count(None) == 1:
1113
+ i = g.index(None)
1114
+ del g[i]
1115
+ else:
1116
+ raise ValueError("at most one permutation can be None")
1117
+
1118
+ g = [self._sym(w) for w in g]
1119
+
1120
+ if i is not None:
1121
+ h = self._sym.one()
1122
+ for p in g[i:]:
1123
+ h *= p
1124
+ for p in g[:i]:
1125
+ h *= p
1126
+ g.insert(i, ~h)
1127
+
1128
+ mutable = options.pop('mutable', False)
1129
+ if options.pop('check', True):
1130
+ c = self.element_class(self, g, self._connected, mutable, True)
1131
+ if c.degree() != self._degree:
1132
+ raise ValueError("degree is not {}".format(self._degree))
1133
+ if c.length() != self._length:
1134
+ raise ValueError("length is not {}".format(self._length))
1135
+ return c
1136
+ else:
1137
+ return self.element_class(self, g, self._connected, mutable, False)
1138
+
1139
+ def _an_element_(self):
1140
+ r"""
1141
+ Return a constellation in ``self``.
1142
+
1143
+ EXAMPLES::
1144
+
1145
+ sage: Constellations(2, 3).an_element()
1146
+ Constellation of length 2 and degree 3
1147
+ g0 (1,3,2)
1148
+ g1 (1,2,3)
1149
+
1150
+ sage: Constellations(3, 5,domain='abcde').an_element()
1151
+ Constellation of length 3 and degree 5
1152
+ g0 ('a','e','d','c','b')
1153
+ g1 ('a','b','c','d','e')
1154
+ g2 ('a')('b')('c')('d')('e')
1155
+
1156
+ sage: Constellations(0, 0).an_element()
1157
+ Constellation of length 0 and degree 0
1158
+
1159
+ sage: Constellations(1, 1).an_element()
1160
+ Constellation of length 1 and degree 1
1161
+ g0 (1)
1162
+
1163
+ sage: Constellations(1, 2).an_element()
1164
+ Traceback (most recent call last):
1165
+ ...
1166
+ EmptySetError
1167
+ """
1168
+ if self.is_empty():
1169
+ from sage.categories.sets_cat import EmptySetError
1170
+ raise EmptySetError
1171
+
1172
+ if self._degree == 0 and self._length == 0:
1173
+ return self([])
1174
+ elif self._length == 1:
1175
+ return self(self._sym.one())
1176
+
1177
+ d = self._degree
1178
+ domain = self._sym.domain().list()
1179
+ if self._connected:
1180
+ g = [[domain[d - 1]] + domain[:d - 1], domain[1:] + [domain[0]]]
1181
+ g += [domain[:]] * (self._length - 2)
1182
+ else:
1183
+ g = [domain[:]] * self._length
1184
+ return self(g)
1185
+
1186
+ def braid_group_action(self):
1187
+ r"""
1188
+ Return a list of graphs that corresponds to the braid group action on
1189
+ ``self`` up to isomorphism.
1190
+
1191
+ OUTPUT: list of graphs
1192
+
1193
+ EXAMPLES::
1194
+
1195
+ sage: C = Constellations(3,3)
1196
+ sage: C.braid_group_action()
1197
+ [Looped multi-digraph on 3 vertices,
1198
+ Looped multi-digraph on 1 vertex,
1199
+ Looped multi-digraph on 3 vertices]
1200
+ """
1201
+ G = []
1202
+ for c in self:
1203
+ c = c.relabel()
1204
+ if any(c in g for g in G):
1205
+ continue
1206
+ G.append(c.braid_group_orbit())
1207
+ return G
1208
+
1209
+ def braid_group_orbits(self):
1210
+ r"""
1211
+ Return the orbits under the action of braid group.
1212
+
1213
+ EXAMPLES::
1214
+
1215
+ sage: C = Constellations(3,3)
1216
+ sage: O = C.braid_group_orbits()
1217
+ sage: len(O)
1218
+ 3
1219
+ sage: [x.profile() for x in O[0]]
1220
+ [([1, 1, 1], [3], [3]), ([3], [1, 1, 1], [3]), ([3], [3], [1, 1, 1])]
1221
+ sage: [x.profile() for x in O[1]]
1222
+ [([3], [3], [3])]
1223
+ sage: [x.profile() for x in O[2]]
1224
+ [([2, 1], [2, 1], [3]), ([2, 1], [3], [2, 1]), ([3], [2, 1], [2, 1])]
1225
+ """
1226
+ return [g.vertices(sort=True) for g in self.braid_group_action()]
1227
+
1228
+
1229
+ class Constellations_p(UniqueRepresentation, Parent):
1230
+ r"""
1231
+ Constellations with fixed profile.
1232
+
1233
+ EXAMPLES::
1234
+
1235
+ sage: C = Constellations([[3,1],[3,1],[2,2]]); C
1236
+ Connected constellations with profile ([3, 1], [3, 1], [2, 2]) on {1, 2, 3, 4}
1237
+ sage: C.cardinality()
1238
+ 24
1239
+ sage: C.first()
1240
+ Constellation of length 3 and degree 4
1241
+ g0 (1)(2,3,4)
1242
+ g1 (1,2,3)(4)
1243
+ g2 (1,2)(3,4)
1244
+ sage: C.last()
1245
+ Constellation of length 3 and degree 4
1246
+ g0 (1,4,3)(2)
1247
+ g1 (1,4,2)(3)
1248
+ g2 (1,2)(3,4)
1249
+
1250
+ Note that the cardinality can also be computed using characters of the
1251
+ symmetric group (Frobenius formula)::
1252
+
1253
+ sage: P = Partitions(4)
1254
+ sage: p1 = Partition([3,1])
1255
+ sage: p2 = Partition([3,1])
1256
+ sage: p3 = Partition([2,2])
1257
+ sage: i1 = P.cardinality() - P.rank(p1) - 1
1258
+ sage: i2 = P.cardinality() - P.rank(p2) - 1
1259
+ sage: i3 = P.cardinality() - P.rank(p3) - 1
1260
+ sage: s = 0
1261
+ sage: for c in SymmetricGroup(4).irreducible_characters():
1262
+ ....: v = c.values()
1263
+ ....: s += v[i1] * v[i2] * v[i3] / v[0]
1264
+ sage: c1 = p1.conjugacy_class_size()
1265
+ sage: c2 = p2.conjugacy_class_size()
1266
+ sage: c3 = p3.conjugacy_class_size()
1267
+ sage: c1 * c2 * c3 / factorial(4)**2 * s
1268
+ 1
1269
+
1270
+ The number obtained above is up to isomorphism. And we can check::
1271
+
1272
+ sage: len(C.isomorphism_representatives())
1273
+ 1
1274
+ """
1275
+
1276
+ def __init__(self, profile, domain=None, connected=True):
1277
+ r"""
1278
+ OPTIONS:
1279
+
1280
+ - ``profile`` -- list of integer partitions of the same integer
1281
+
1282
+ - ``connected`` -- boolean (default: ``True``); whether we consider
1283
+ only connected constellations
1284
+
1285
+ TESTS::
1286
+
1287
+ sage: C = Constellations([(3,1),(3,1),(2,2)])
1288
+ sage: TestSuite(C).run()
1289
+ """
1290
+ l = Integer(len(profile))
1291
+ d = Integer(sum(profile[0]))
1292
+ for p in profile:
1293
+ if sum(p) != d:
1294
+ raise ValueError("all partition in the passport should "
1295
+ "have the same sum.")
1296
+ if domain is None:
1297
+ sym = SymmetricGroup(d)
1298
+ else:
1299
+ sym = SymmetricGroup(domain)
1300
+ if len(sym.domain()) != d:
1301
+ raise ValueError("the size of the domain should be equal to the degree")
1302
+
1303
+ self._cd = Constellations_ld(l, d, sym, connected)
1304
+ self._profile = profile
1305
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
1306
+ Parent.__init__(self, category=FiniteEnumeratedSets())
1307
+
1308
+ def _repr_(self):
1309
+ r"""
1310
+ TESTS::
1311
+
1312
+ sage: Constellations(profile=[[3,2,1],[3,3],[3,3]])
1313
+ Connected constellations with profile ([3, 2, 1], [3, 3], [3, 3]) on {1, 2, 3, 4, 5, 6}
1314
+ """
1315
+ s = "with profile {} on {}".format(self._profile,
1316
+ self._cd._sym.domain())
1317
+ if self._cd._connected:
1318
+ return "Connected constellations " + s
1319
+ return "Constellations " + s
1320
+
1321
+ def isomorphism_representatives(self):
1322
+ r"""
1323
+ Return a set of isomorphism representative of ``self``.
1324
+
1325
+ EXAMPLES::
1326
+
1327
+ sage: C = Constellations([[5], [4,1], [3,2]])
1328
+ sage: C.cardinality()
1329
+ 240
1330
+ sage: ir = sorted(C.isomorphism_representatives())
1331
+ sage: len(ir)
1332
+ 2
1333
+ sage: ir[0]
1334
+ Constellation of length 3 and degree 5
1335
+ g0 (1,2,3,4,5)
1336
+ g1 (1)(2,3,4,5)
1337
+ g2 (1,5,3)(2,4)
1338
+ sage: ir[1]
1339
+ Constellation of length 3 and degree 5
1340
+ g0 (1,2,3,4,5)
1341
+ g1 (1)(2,5,3,4)
1342
+ g2 (1,5)(2,3,4)
1343
+ """
1344
+ result = set()
1345
+ for c in self:
1346
+ cc = c.relabel()
1347
+ if cc not in result:
1348
+ result.add(cc)
1349
+ return result
1350
+
1351
+ def _element_constructor_(self, *data, **options):
1352
+ r"""
1353
+ Build an element of ``self``.
1354
+
1355
+ TESTS::
1356
+
1357
+ sage: C = Constellations([(3,1),(3,1),(2,2)])
1358
+ sage: c = C([(2,3,4),(1,2,3),((1,2),(3,4))]); c
1359
+ Constellation of length 3 and degree 4
1360
+ g0 (1)(2,3,4)
1361
+ g1 (1,2,3)(4)
1362
+ g2 (1,2)(3,4)
1363
+ sage: C([(1,2,3),(3,2,4),None])
1364
+ Traceback (most recent call last):
1365
+ ...
1366
+ ValueError: wrong profile
1367
+ """
1368
+ c = self._cd(*data, **options)
1369
+ if options.get('check', True) and c.profile() != self._profile:
1370
+ raise ValueError("wrong profile")
1371
+ return c
1372
+
1373
+ def __iter__(self):
1374
+ r"""
1375
+ Iterator of the elements in ``self``.
1376
+
1377
+ TESTS::
1378
+
1379
+ sage: C = Constellations([(3,1),(3,1),(2,2)])
1380
+ sage: for c in C: print(c)
1381
+ Constellation of length 3 and degree 4
1382
+ g0 (1)(2,3,4)
1383
+ g1 (1,2,3)(4)
1384
+ g2 (1,2)(3,4)
1385
+ Constellation of length 3 and degree 4
1386
+ g0 (1)(2,3,4)
1387
+ g1 (1,4,2)(3)
1388
+ g2 (1,4)(2,3)
1389
+ ...
1390
+ Constellation of length 3 and degree 4
1391
+ g0 (1,4,3)(2)
1392
+ g1 (1,2,3)(4)
1393
+ g2 (1,4)(2,3)
1394
+ Constellation of length 3 and degree 4
1395
+ g0 (1,4,3)(2)
1396
+ g1 (1,4,2)(3)
1397
+ g2 (1,2)(3,4)
1398
+
1399
+ sage: C = Constellations([(3,1),(3,1),(2,2)], domain='abcd')
1400
+ sage: for c in sorted(C): print(c)
1401
+ Constellation of length 3 and degree 4
1402
+ g0 ('a')('b','c','d')
1403
+ g1 ('a','b','c')('d')
1404
+ g2 ('a','b')('c','d')
1405
+ ...
1406
+ Constellation of length 3 and degree 4
1407
+ g0 ('a','d','c')('b')
1408
+ g1 ('a','d','b')('c')
1409
+ g2 ('a','b')('c','d')
1410
+ """
1411
+ if self._cd._length == 1:
1412
+ if self._cd._degree == 1:
1413
+ yield self([[0]])
1414
+ return
1415
+
1416
+ S = self._cd._sym
1417
+ profile = list(self._profile)[:-1]
1418
+ for p in product(*[S.conjugacy_class(pi) for pi in profile]):
1419
+ if self._cd._connected and not perms_are_connected(p, self._cd._degree):
1420
+ continue
1421
+ c = self._cd(list(p) + [None], check=False)
1422
+ if c.profile() == self._profile:
1423
+ yield c
1424
+
1425
+ # *************************************************************************
1426
+ # auxiliary functions
1427
+ # *************************************************************************
1428
+
1429
+
1430
+ def perm_sym_domain(g):
1431
+ r"""
1432
+ Return the domain of a single permutation (before initialization).
1433
+
1434
+ EXAMPLES::
1435
+
1436
+ sage: from sage.combinat.constellation import perm_sym_domain
1437
+ sage: perm_sym_domain([1,2,3,4])
1438
+ {1, 2, 3, 4}
1439
+ sage: perm_sym_domain(((1,2),(0,4)))
1440
+ {0, 1, 2, 4}
1441
+ sage: sorted(perm_sym_domain('(1,2,0,5)'))
1442
+ [0, 1, 2, 5]
1443
+ """
1444
+ if isinstance(g, (tuple, list)):
1445
+ if isinstance(g[0], tuple):
1446
+ return set().union(*g)
1447
+ else:
1448
+ return set(g)
1449
+ elif isinstance(g, str): # perms given as strings of cycles
1450
+ assert g.startswith('(') and g.endswith(')')
1451
+ domain = set().union(*[a for cyc in g[1:-1].split(')(')
1452
+ for a in cyc.split(',')])
1453
+ if all(s.isdigit() for s in domain):
1454
+ return [int(x) for x in domain]
1455
+ else:
1456
+ return domain
1457
+ elif parent(g) in Groups:
1458
+ return g.domain()
1459
+ else:
1460
+ raise TypeError
1461
+
1462
+
1463
+ def perms_sym_init(g, sym=None):
1464
+ r"""
1465
+ Initialize a list of permutations (in the same symmetric group).
1466
+
1467
+ OUTPUT:
1468
+
1469
+ - ``sym`` -- a symmetric group
1470
+
1471
+ - ``gg`` -- list of permutations
1472
+
1473
+ EXAMPLES::
1474
+
1475
+ sage: from sage.combinat.constellation import perms_sym_init
1476
+ sage: S, g = perms_sym_init([[0,2,1,3], [1,3,2,0]])
1477
+ sage: S.domain()
1478
+ {0, 1, 2, 3}
1479
+ sage: g
1480
+ [(1,2), (0,1,3)]
1481
+
1482
+ sage: S, g = perms_sym_init(['(2,1)', '(0,3)'])
1483
+ sage: S.domain()
1484
+ {0, 1, 2, 3}
1485
+ sage: g
1486
+ [(1,2), (0,3)]
1487
+
1488
+ sage: S, g = perms_sym_init([(1,0), (2,1)])
1489
+ sage: S.domain()
1490
+ {0, 1, 2}
1491
+ sage: g
1492
+ [(0,1), (1,2)]
1493
+
1494
+ sage: S, g = perms_sym_init([((1,0),(2,3)), '(0,1,4)'])
1495
+ sage: S.domain()
1496
+ {0, 1, 2, 3, 4}
1497
+ sage: g
1498
+ [(0,1)(2,3), (0,1,4)]
1499
+ """
1500
+ if g is None or len(g) == 0:
1501
+ if sym is None:
1502
+ sym = SymmetricGroup(0)
1503
+ return sym, [sym([])]
1504
+
1505
+ if sym is None:
1506
+ domain = set().union(*[perm_sym_domain(gg) for gg in g])
1507
+ if all(isinstance(s, (int, Integer)) and s > 0
1508
+ for s in domain):
1509
+ domain = max(domain)
1510
+ else:
1511
+ domain = sorted(domain)
1512
+ sym = SymmetricGroup(domain)
1513
+
1514
+ try:
1515
+ return sym, [sym(u) for u in g]
1516
+ except (ValueError, TypeError):
1517
+ return sym, None
1518
+
1519
+
1520
+ def perms_are_connected(g, n):
1521
+ """
1522
+ Check that the action of the generated group is transitive.
1523
+
1524
+ INPUT:
1525
+
1526
+ - ``g`` -- list of permutations of `[0, n-1]` (in a SymmetricGroup)
1527
+
1528
+ - ``n`` -- integer
1529
+
1530
+ EXAMPLES::
1531
+
1532
+ sage: from sage.combinat.constellation import perms_are_connected
1533
+ sage: S = SymmetricGroup(range(3))
1534
+ sage: perms_are_connected([S([0,1,2]),S([0,2,1])],3)
1535
+ False
1536
+ sage: perms_are_connected([S([0,1,2]),S([1,2,0])],3)
1537
+ True
1538
+ """
1539
+ G = Graph()
1540
+ if g:
1541
+ G.add_vertices(g[0].domain())
1542
+ for p in g:
1543
+ G.add_edges(p.dict().items(), loops=False)
1544
+ return G.is_connected()
1545
+
1546
+
1547
+ def perms_canonical_labels_from(x, y, j0, verbose=False):
1548
+ r"""
1549
+ Return canonical labels for ``x``, ``y`` that starts at ``j0``.
1550
+
1551
+ .. WARNING::
1552
+
1553
+ The group generated by ``x`` and the elements of ``y`` should be
1554
+ transitive.
1555
+
1556
+ INPUT:
1557
+
1558
+ - ``x`` -- list; a permutation of `[0, ..., n]` as a list
1559
+
1560
+ - ``y`` -- list of permutations of `[0, ..., n]` as a list of lists
1561
+
1562
+ - ``j0`` -- an index in [0, ..., n]
1563
+
1564
+ OUTPUT: mapping: a permutation that specify the new labels
1565
+
1566
+ EXAMPLES::
1567
+
1568
+ sage: from sage.combinat.constellation import perms_canonical_labels_from
1569
+ sage: perms_canonical_labels_from([0,1,2],[[1,2,0]], 0)
1570
+ [0, 1, 2]
1571
+ sage: perms_canonical_labels_from([1,0,2], [[2,0,1]], 0)
1572
+ [0, 1, 2]
1573
+ sage: perms_canonical_labels_from([1,0,2], [[2,0,1]], 1)
1574
+ [1, 0, 2]
1575
+ sage: perms_canonical_labels_from([1,0,2], [[2,0,1]], 2)
1576
+ [2, 1, 0]
1577
+ """
1578
+ n = len(x)
1579
+
1580
+ k = 0
1581
+ mapping = [None] * n
1582
+ waiting = [[] for _ in repeat(None, len(y))]
1583
+
1584
+ while k < n:
1585
+ if verbose:
1586
+ print("complete from {}".format(j0))
1587
+ # initialize at j0
1588
+ mapping[j0] = k
1589
+ waiting[0].append(j0)
1590
+ k += 1
1591
+ # complete x cycle from j0
1592
+ j = x[j0]
1593
+ while j != j0:
1594
+ mapping[j] = k
1595
+ waiting[0].append(j)
1596
+ k += 1
1597
+ j = x[j]
1598
+ if verbose:
1599
+ print("completed cycle mapping = {}".format(mapping))
1600
+
1601
+ # find another guy
1602
+ if verbose:
1603
+ print("try to find somebody in {}".format(waiting))
1604
+ l = 0
1605
+ while l < len(waiting):
1606
+ i = 0
1607
+ while i < len(waiting[l]):
1608
+ j1 = waiting[l][i]
1609
+ if mapping[y[l][j1]] is None:
1610
+ break
1611
+ i += 1
1612
+
1613
+ if i == len(waiting[l]): # not found: go further in waiting
1614
+ if l < len(waiting) - 1:
1615
+ waiting[l + 1].extend(waiting[l])
1616
+ waiting[l] = []
1617
+ l += 1
1618
+ i = 0
1619
+
1620
+ else: # found: complete cycle from new guy
1621
+ j0 = y[l][j1]
1622
+ if l < len(waiting) - 1:
1623
+ waiting[l + 1].extend(waiting[l][:i + 1])
1624
+ del waiting[l][:i + 1]
1625
+ break
1626
+
1627
+ return mapping
1628
+
1629
+
1630
+ def perm_invert(p):
1631
+ """
1632
+ Return the inverse of the permutation `p`.
1633
+
1634
+ INPUT:
1635
+
1636
+ - ``p`` -- a permutation of {0,..,n-1} given by a list of values
1637
+
1638
+ OUTPUT: a permutation of {0,..,n-1} given by a list of values
1639
+
1640
+ EXAMPLES::
1641
+
1642
+ sage: from sage.combinat.constellation import perm_invert
1643
+ sage: perm_invert([3,2,0,1])
1644
+ [2, 3, 1, 0]
1645
+ """
1646
+ q = [None] * len(p)
1647
+ for i, j in enumerate(p):
1648
+ q[j] = i
1649
+ return q
1650
+
1651
+
1652
+ def perm_conjugate(p, s):
1653
+ """
1654
+ Return the conjugate of the permutation `p` by the permutation `s`.
1655
+
1656
+ INPUT:
1657
+
1658
+ - ``p``, ``s`` -- two permutations of {0,..,n-1} given by lists of values
1659
+
1660
+ OUTPUT: a permutation of {0,..,n-1} given by a list of values
1661
+
1662
+ EXAMPLES::
1663
+
1664
+ sage: from sage.combinat.constellation import perm_conjugate
1665
+ sage: perm_conjugate([3,1,2,0], [3,2,0,1])
1666
+ [0, 3, 2, 1]
1667
+ """
1668
+ q = [None] * len(p)
1669
+ for i in range(len(p)):
1670
+ q[s[i]] = s[p[i]]
1671
+ return q
1672
+
1673
+
1674
+ def perms_canonical_labels(p, e=None):
1675
+ """
1676
+ Relabel a list with a common conjugation such that two conjugated
1677
+ lists are relabeled the same way.
1678
+
1679
+ INPUT:
1680
+
1681
+ - ``p`` -- list of at least 2 permutations
1682
+
1683
+ - ``e`` -- ``None`` or a list of integer in the domain of the
1684
+ permutations. If provided, then the renumbering algorithm is
1685
+ only performed from the elements of ``e``.
1686
+
1687
+ OUTPUT: a pair made of a list of permutations (as a list of lists) and a
1688
+ list that corresponds to the conjugacy used.
1689
+
1690
+ EXAMPLES::
1691
+
1692
+ sage: from sage.combinat.constellation import perms_canonical_labels
1693
+ sage: l0 = [[2,0,3,1], [3,1,2,0], [0,2,1,3]]
1694
+ sage: l, m = perms_canonical_labels(l0); l
1695
+ [[1, 2, 3, 0], [0, 3, 2, 1], [2, 1, 0, 3]]
1696
+
1697
+ sage: S = SymmetricGroup(range(4))
1698
+ sage: [~S(m) * S(u) * S(m) for u in l0] == list(map(S, l))
1699
+ True
1700
+
1701
+ sage: perms_canonical_labels([])
1702
+ Traceback (most recent call last):
1703
+ ...
1704
+ ValueError: input must have length >= 2
1705
+ """
1706
+ if not len(p) > 1:
1707
+ raise ValueError('input must have length >= 2')
1708
+
1709
+ n = len(p[0])
1710
+
1711
+ c_win = None
1712
+ m_win = list(range(n))
1713
+
1714
+ x = p[0]
1715
+ y = p[1:]
1716
+
1717
+ if e is None:
1718
+ e = list(range(n))
1719
+
1720
+ # get canonical label from i in to_test and compare
1721
+ while e:
1722
+ i = e.pop()
1723
+ m_test = perms_canonical_labels_from(x, y, i)
1724
+ c_test = [perm_conjugate(u, m_test) for u in p]
1725
+ if c_win is None or c_test < c_win:
1726
+ c_win = c_test
1727
+ m_win = m_test
1728
+
1729
+ return c_win, m_win