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,1857 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ r"""
3
+ Combinatorics in Sage
4
+
5
+ This thematic tutorial is a translation by Hugh Thomas of the
6
+ combinatorics chapter written by Nicolas M. Thiéry in the book "Calcul
7
+ Mathématique avec Sage" [CMS2012]_. It covers mainly the treatment in
8
+ ``Sage`` of the following combinatorial problems: enumeration (how
9
+ many elements are there in a set `S`?), listing (generate all the
10
+ elements of `S`, or iterate through them), and random selection
11
+ (choosing an element at random from a set `S` according to a given
12
+ distribution, for example the uniform distribution). These questions
13
+ arise naturally in the calculation of probabilities (what is the
14
+ probability in poker of obtaining a straight or a four-of-a-kind of
15
+ aces?), in statistical physics, and also in computer algebra (the number
16
+ of elements in a finite field), or in the analysis of
17
+ algorithms. Combinatorics covers a much wider domain (partial orders,
18
+ representation theory, …) for which we only give a few pointers
19
+ towards the possibilities offered by ``Sage``.
20
+
21
+ A characteristic of computational combinatorics is the profusion of
22
+ types of objects and sets that one wants to manipulate. It would be
23
+ impossible to describe them all or, a fortiori, to implement them all.
24
+ After some :ref:`section-examples`, this chapter illustrates the
25
+ underlying method: supplying the basic building blocks to describe
26
+ common combinatorial sets :ref:`section-bricks`, tools for combining
27
+ them to construct new examples :ref:`section-constructions`, and
28
+ generic algorithms for solving uniformly a large class of problems
29
+ :ref:`section-generic`.
30
+
31
+ This is a domain in which ``Sage`` has much more extensive capabilities
32
+ than most computer algebra systems, and it is rapidly expanding; at the
33
+ same time, it is still quite new, and has many unnecessary limitations
34
+ and incoherences.
35
+
36
+ .. _section-examples:
37
+
38
+ Initial examples
39
+ ----------------
40
+
41
+ .. _section-examples-poker:
42
+
43
+ Poker and probability
44
+ ~~~~~~~~~~~~~~~~~~~~~
45
+
46
+ We begin by solving a classic problem: enumerating certain combinations
47
+ of cards in the game of poker, in order to deduce their probability.
48
+
49
+ A card in a poker deck is characterized by a suit (hearts, diamonds,
50
+ spades, or clubs) and a value (2, 3, ..., 10, jack, queen, king, ace). The
51
+ game is played with a full deck, which consists of the Cartesian product
52
+ of the set of suits and the set of values:
53
+
54
+ .. MATH:: \operatorname{Cards} = \operatorname{Suits} \times
55
+ \operatorname{Values} = \{ (s, v) \mathrel| s\in
56
+ \operatorname{Suits} \text{ et } v \in \operatorname{Values} \}\,.
57
+
58
+ We construct these examples in ``Sage``::
59
+
60
+ sage: Suits = Set(["Hearts", "Diamonds", "Spades", "Clubs"])
61
+ sage: Values = Set([2, 3, 4, 5, 6, 7, 8, 9, 10,
62
+ ....: "Jack", "Queen", "King", "Ace"])
63
+ sage: Cards = cartesian_product([Values, Suits])
64
+
65
+ There are `4` suits and `13` possible values, and
66
+ therefore `4\times 13=52` cards in the poker deck::
67
+
68
+ sage: Suits.cardinality()
69
+ 4
70
+ sage: Values.cardinality()
71
+ 13
72
+ sage: Cards.cardinality()
73
+ 52
74
+
75
+ Draw a card at random::
76
+
77
+ sage: Cards.random_element() # random
78
+ (6, 'Clubs')
79
+
80
+ Now we can define a set of cards::
81
+
82
+ sage: Set([Cards.random_element(), Cards.random_element()]) # random
83
+ {(2, 'Hearts'), (4, 'Spades')}
84
+
85
+ This problem should eventually disappear: it is planned to change the
86
+ implementation of Cartesian products so that their elements are
87
+ immutable by default.
88
+
89
+ Returning to our main topic, we will be considering a simplified version
90
+ of poker, in which each player directly draws five cards, which form his
91
+ *hand*. The cards are all distinct and the order in which they are drawn
92
+ is irrelevant; a hand is therefore a subset of size `5` of the
93
+ set of cards. To draw a hand at random, we first construct the set of
94
+ all possible hands, and then we ask for a randomly chosen element::
95
+
96
+ sage: Hands = Subsets(Cards, 5)
97
+ sage: Hands.random_element() # random
98
+ {(4, 'Hearts', 4), (9, 'Diamonds'), (8, 'Spades'),
99
+ (9, 'Clubs'), (7, 'Hearts')}
100
+
101
+ The total number of hands is given by the number of subsets of size
102
+ `5` of a set of size `52`, which is given by the
103
+ binomial coefficient `\binom{52}{5}`::
104
+
105
+ sage: binomial(52,5)
106
+ 2598960
107
+
108
+ One can also ignore the method of calculation, and
109
+ simply ask for the size of the set of hands::
110
+
111
+ sage: Hands.cardinality()
112
+ 2598960
113
+
114
+ The strength of a poker hand depends on the particular combination of
115
+ cards present. One such combination is the *flush*; this is a hand all
116
+ of whose cards have the same suit. (In principle, straight flushes
117
+ should be excluded; this will be the goal of an exercise given below.)
118
+ Such a hand is therefore characterized by the choice of five values from
119
+ among the thirteen possibilities, and the choice of one of four suits.
120
+ We will construct the set of all flushes, so as to determine how many
121
+ there are::
122
+
123
+ sage: Flushes = cartesian_product([Subsets(Values, 5), Suits])
124
+ sage: Flushes.cardinality()
125
+ 5148
126
+
127
+
128
+ The probability of obtaining a flush when drawing a hand at random is
129
+ therefore::
130
+
131
+ sage: Flushes.cardinality() / Hands.cardinality()
132
+ 33/16660
133
+
134
+ or about two in a thousand::
135
+
136
+ sage: 1000.0 * Flushes.cardinality() / Hands.cardinality()
137
+ 1.98079231692677
138
+
139
+
140
+ We will now attempt a little numerical simulation. The following
141
+ function tests whether a given hand is a flush or not::
142
+
143
+ sage: def is_flush(hand):
144
+ ....: return len(set(suit for (val, suit) in hand)) == 1
145
+
146
+ We now draw 10000 hands at random, and count the number of flushes
147
+ obtained (this takes about 10 seconds)::
148
+
149
+ sage: n = 10000
150
+ sage: nflush = 0
151
+ sage: for i in range(n): # long time
152
+ ....: hand = Hands.random_element()
153
+ ....: if is_flush(hand):
154
+ ....: nflush += 1
155
+ sage: n, nflush # random
156
+ (10000, 18)
157
+
158
+ .. topic:: Exercises
159
+
160
+ A hand containing four cards of the same value is called a *four
161
+ of a kind*. Construct the set of four of a kind hands (Hint: use
162
+ ``Arrangements`` to choose a pair of distinct values at random,
163
+ then choose a suit for the first value). Calculate the number of
164
+ four of a kind hand, list them, and then determine the probability
165
+ of obtaining a four of a kind when drawing a hand at random.
166
+
167
+ A hand all of whose cards have the same suit, and whose values are
168
+ consecutive, is called a *straight flush* rather than a *flush*.
169
+ Count the number of straight flushes, and then deduce the correct
170
+ probability of obtaining a flush when drawing a hand at random.
171
+
172
+ Calculate the probability of each of the poker hands (see
173
+ :wikipedia:`Poker_hands`), and compare them with the results of
174
+ simulations.
175
+
176
+ .. _section-examples-catalan:
177
+
178
+ Enumeration of trees using generating functions
179
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
180
+
181
+ In this section, we discuss the example of complete binary trees, and
182
+ illustrate in this context many techniques of enumeration in which
183
+ formal power series play a natural role. These techniques are quite
184
+ general, and can be applied whenever the combinatorial objects in
185
+ question admit a recursive definition (grammar) (see
186
+ :ref:`section-generic-species` for an automated treatment). The
187
+ goal is not a formal presentation of these methods; the calculations are
188
+ rigorous, but most of the justifications will be skipped.
189
+
190
+ A *complete binary tree* is either a leaf `\mathrm{L}`, or a
191
+ node to which two complete binary trees are attached (see
192
+ :ref:`figure-examples-catalan-trees`).
193
+
194
+ .. _figure-examples-catalan-trees:
195
+
196
+ .. figure:: ../../media/complete-binary-trees-4.png
197
+ :scale: 150 %
198
+
199
+ Figure: The five complete binary trees with four leaves
200
+
201
+ .. _exo.enumeration.arbres:
202
+
203
+ .. topic:: Exercise: enumeration of binary trees
204
+
205
+ Find by hand all the complete binary trees with `n=1, 2, 3, 4, 5`
206
+ leaves (see :ref:`Exercise: complete binary tree iterator
207
+ <exo-iterators-catalan>` to find them using ``Sage``).
208
+
209
+ Our goal is to determine the number `c_n` of complete binary
210
+ trees with `n` leaves (in this section, except when explicitly
211
+ stated otherwise, “trees” always means complete binary trees). This is a
212
+ typical situation in which one is not only interested in a single set,
213
+ but in a family of sets, typically parameterized by `n\in \NN`.
214
+
215
+ According to the solution of :ref:`Exercise: enumeration of binary trees <exo.enumeration.arbres>`, the first terms are given by
216
+ `c_1,\dots,c_5=1,1,2,5,14`. The simple fact of knowing these few
217
+ numbers is already very valuable. In fact, this permits research in a
218
+ gold mine of information: the `Online Encyclopedia of Integer Sequences
219
+ <http://oeis.org/>`_, commonly called “Sloane”, the name of its principal
220
+ author, which contains more than 190000 sequences of integers::
221
+
222
+ sage: oeis([1,1,2,5,14]) # optional -- internet
223
+ 0: A000108: Catalan numbers: ...
224
+ 1: ...
225
+ 2: ...
226
+
227
+ The result suggests that the trees are counted by one of the most famous
228
+ sequences, the Catalan numbers. Looking through the references supplied
229
+ by the Encyclopedia, we see that this is really the case: the few
230
+ numbers above form a digital fingerprint of our objects, which enable us
231
+ to find, in a few seconds, a precise result from within an abundant
232
+ literature.
233
+
234
+ Our next goal is to recover this result using ``Sage``. Let
235
+ `C_n` be the set of trees with `n` leaves, so that
236
+ `c_n=|C_n|`; by convention, we will define
237
+ `C_0=\emptyset` and `c_0=0`. The set of all trees is
238
+ then the disjoint union of the sets `C_n`:
239
+
240
+ .. MATH:: C=\biguplus_{n\in \mathbb N} C_n\,.
241
+
242
+ Having named the set `C` of all trees, we can translate the
243
+ recursive definition of trees into a set-theoretic equation:
244
+
245
+ .. MATH:: C \quad \approx \quad \{ \mathrm{L} \} \quad \uplus\quad C \times C\,.
246
+
247
+ In words: a tree `t` (which is by definition in `C`) is either a
248
+ leaf (so in `\{\mathrm{L}\}`) or a node to which two trees
249
+ `t_1` and `t_2` have been attached, and which we can
250
+ therefore identify with the pair `(t_1,t_2)` (in the Cartesian
251
+ product `C\times C`).
252
+
253
+ The founding idea of algebraic combinatorics, introduced by Euler in
254
+ a letter to Goldbach of 1751 to treat a similar problem , is to
255
+ manipulate all the numbers `c_n` simultaneously, by encoding them
256
+ as coefficients in a formal power series, called the *generating
257
+ function* of the `c_n`’s:
258
+
259
+ .. MATH:: C(z) = \sum_{n\in \mathbb N} c_n z^n\,,
260
+
261
+ where `z` is a formal variable (which means that we do not
262
+ have to worry about questions of convergence). The beauty of this idea
263
+ is that set-theoretic operations `(A\uplus B`,
264
+ `A\times B)` translate naturally into algebraic operations on
265
+ the corresponding series (`A(z)+B(z)`,
266
+ `A(z)\cdot B(z)`), in such a way that the set-theoretic equation
267
+ satisfied by `C` can be translated directly into an algebraic
268
+ equation satisfied by `C(z)`:
269
+
270
+ .. MATH:: C(z) = z + C(z) \cdot C(z)\,.
271
+
272
+ Now we can solve this equation with ``Sage``. In order to do so, we
273
+ introduce two variables, `C` and `z`, and we define the
274
+ equation::
275
+
276
+ sage: C, z = var('C,z') # needs sage.symbolic
277
+ sage: sys = [ C == z + C*C ] # needs sage.symbolic
278
+
279
+ There are two solutions, which happen to have closed forms::
280
+
281
+ sage: sol = solve(sys, C, solution_dict=True); sol # needs sage.symbolic
282
+ [{C: -1/2*sqrt(-4*z + 1) + 1/2}, {C: 1/2*sqrt(-4*z + 1) + 1/2}]
283
+ sage: s0 = sol[0][C]; s1 = sol[1][C] # needs sage.symbolic
284
+
285
+ and whose Taylor series begin as follows::
286
+
287
+ sage: s0.series(z, 6) # needs sage.symbolic
288
+ 1*z + 1*z^2 + 2*z^3 + 5*z^4 + 14*z^5 + Order(z^6)
289
+ sage: s1.series(z, 6) # needs sage.symbolic
290
+ 1 + (-1)*z + (-1)*z^2 + (-2)*z^3 + (-5)*z^4 + (-14)*z^5
291
+ + Order(z^6)
292
+
293
+ The second solution is clearly aberrant, while the first one gives the
294
+ expected coefficients. Therefore, we set::
295
+
296
+ sage: C = s0 # needs sage.symbolic
297
+
298
+ We can now calculate the next terms::
299
+
300
+ sage: C.series(z, 11) # needs sage.symbolic
301
+ 1*z + 1*z^2 + 2*z^3 + 5*z^4 + 14*z^5 + 42*z^6 +
302
+ 132*z^7 + 429*z^8 + 1430*z^9 + 4862*z^10 + Order(z^11)
303
+
304
+ or calculate, more or less instantaneously, the 100-th coefficient::
305
+
306
+ sage: C.series(z, 101).coefficient(z,100) # needs sage.symbolic
307
+ 227508830794229349661819540395688853956041682601541047340
308
+
309
+ It is unfortunate to have to recalculate everything if at some point we
310
+ wanted the 101-st coefficient. Lazy power series (see
311
+ :mod:`sage.rings.lazy_series_ring`) come into their own here, in that
312
+ one can define them from a system of equations without solving it, and,
313
+ in particular, without needing a closed form for the answer. We begin by
314
+ defining the ring of lazy power series::
315
+
316
+ sage: L.<z> = LazyPowerSeriesRing(QQ)
317
+
318
+ Then we create a “free” power series, which we name, and which we then
319
+ define by a recursive equation::
320
+
321
+ sage: C = L.undefined(valuation=1)
322
+ sage: C.define(z + C * C)
323
+
324
+ ::
325
+
326
+ sage: [C.coefficient(i) for i in range(11)]
327
+ [0, 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
328
+
329
+ At any point, one can ask for any coefficient without having to redefine
330
+ `C`::
331
+
332
+ sage: C.coefficient(100)
333
+ 227508830794229349661819540395688853956041682601541047340
334
+ sage: C.coefficient(200)
335
+ 129013158064429114001222907669676675134349530552728882499810851598901419013348319045534580850847735528275750122188940
336
+
337
+ We now return to the closed form of `C(z)`::
338
+
339
+ sage: z = var('z') # needs sage.symbolic
340
+ sage: C = s0; C # needs sage.symbolic
341
+ -1/2*sqrt(-4*z + 1) + 1/2
342
+
343
+ The `n`-th coefficient in the Taylor series for `C(z)`
344
+ being given by `\frac{1}{n!} C(z)^{(n)}(0)`, we look at the
345
+ successive derivatives `C(z)^{(n)}(z)`::
346
+
347
+ sage: derivative(C, z, 1) # needs sage.symbolic
348
+ 1/sqrt(-4*z + 1)
349
+ sage: derivative(C, z, 2) # needs sage.symbolic
350
+ 2/(-4*z + 1)^(3/2)
351
+ sage: derivative(C, z, 3) # needs sage.symbolic
352
+ 12/(-4*z + 1)^(5/2)
353
+
354
+ This suggests the existence of a simple explicit formula, which we will
355
+ now seek. The following small function returns `d_n=n! \, c_n`::
356
+
357
+ sage: def d(n): return derivative(s0, n).subs(z=0)
358
+
359
+ Taking successive quotients::
360
+
361
+ sage: [ (d(n+1) / d(n)) for n in range(1,17) ] # needs sage.symbolic
362
+ [2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62]
363
+
364
+ we observe that `d_n` satisfies the recurrence relation
365
+ `d_{n+1}=(4n-2)d_n`, from which we deduce that `c_n`
366
+ satisfies the recurrence relation
367
+ `c_{n+1}=\frac{(4n-2)}{n+1}c_n`. Simplifying, we find that
368
+ `c_n` is the `(n-1)`-th Catalan number:
369
+
370
+ .. MATH:: c_n = \operatorname{Catalan}(n-1) = \frac {1}{n} \binom{2(n-1)}{n-1}\,.
371
+
372
+ We check this::
373
+
374
+ sage: n = var('n') # needs sage.symbolic
375
+ sage: c = 1/n*binomial(2*(n-1),n-1) # needs sage.symbolic
376
+ sage: [c.subs(n=k) for k in range(1, 11)] # needs sage.symbolic
377
+ [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
378
+ sage: [catalan_number(k-1) for k in range(1, 11)]
379
+ [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
380
+
381
+ We can now calculate coefficients much further; here we calculate
382
+ `c_{100000}` which has more than `60000` digits::
383
+
384
+ sage: cc = c(n=100000) # needs sage.symbolic
385
+
386
+ This takes a couple of seconds::
387
+
388
+ sage: %time cc = c(100000) # not tested # needs sage.symbolic
389
+ CPU times: user 2.34 s, sys: 0.00 s, total: 2.34 s
390
+ Wall time: 2.34 s
391
+ sage: ZZ(cc).ndigits() # needs sage.symbolic
392
+ 60198
393
+
394
+ The methods which we have used generalize to all recursively defined
395
+ objects: the system of set-theoretic equations can be translated into a
396
+ system of equations on the generating function, which enables the
397
+ recursive calculation of its coefficients. If the set-theoretic
398
+ equations are simple enough (for example, if they only involve Cartesian
399
+ products and disjoint unions), the equation for `C(z)` is
400
+ algebraic. This equation has, in general, no closed-form solution.
401
+ However, using *confinement*, one can deduce a *linear* differential
402
+ equation which `C(z)` satisfies. This differential equation, in
403
+ turn, can be translated into a recurrence relation of fixed length on
404
+ its coefficients `c_n`. In this case, the series is called
405
+ *D-finite*. After the initial calculation of this recurrence relation,
406
+ the calculation of coefficients is very fast. All these steps are purely
407
+ algorithmic, and it is planned to port into ``Sage`` the implementations
408
+ which exist in ``Maple`` (the ``gfun`` and ``combstruct`` packages) or
409
+ ``MuPAD-Combinat`` (the ``decomposableObjects`` library).
410
+
411
+ For the moment, we illustrate this general procedure in the case of
412
+ complete binary trees. The generating function `C(z)` is a
413
+ solution to an algebraic equation `P(z,C(z)) = 0`, where
414
+ `P=P(x,y)` is a polynomial with coefficients in `\QQ`.
415
+ In the present case, `P=y^2-y+x`. We formally differentiate this
416
+ equation with respect to `z`::
417
+
418
+ sage: # needs sage.symbolic
419
+ sage: x, y, z = var('x, y, z')
420
+ sage: P = function('P')(x, y)
421
+ sage: C = function('C')(z)
422
+ sage: equation = P(x=z, y=C) == 0
423
+ sage: diff(equation, z)
424
+ diff(C(z), z)*D[1](P)(z, C(z)) + D[0](P)(z, C(z)) == 0
425
+
426
+ or, in a more readable format,
427
+
428
+ .. MATH:: \frac{d C(z)}{d z} \frac{\partial P}{\partial y} (z, C(z)) + \frac{\partial P}{\partial x}(z,C(z)) = 0
429
+
430
+ From this we deduce:
431
+
432
+ .. MATH:: \frac{d C(z)}{d z} = - \frac{\frac{\partial P}{\partial x}}{\frac{\partial P}{\partial y}}(z, C(z))\,.
433
+
434
+ In the case of complete binary trees, this gives::
435
+
436
+ sage: P = y^2 - y + x # needs sage.symbolic
437
+ sage: Px = diff(P, x); Py = diff(P, y) # needs sage.symbolic
438
+ sage: - Px / Py # needs sage.symbolic
439
+ -1/(2*y - 1)
440
+
441
+ Recall that `P(z, C(z))=0`. Thus, we can calculate this fraction
442
+ mod `P` and, in this way, express the derivative of
443
+ `C(z)` as a *polynomial in* `C(z)` *with coefficients in*
444
+ `\QQ(z)`. In order to achieve this, we construct the quotient
445
+ ring `R= \QQ(x)[y]/ (P)`::
446
+
447
+ sage: Qx = QQ['x'].fraction_field()
448
+ sage: Qxy = Qx['y']
449
+ sage: R = Qxy.quo(P); R # needs sage.symbolic
450
+ Univariate Quotient Polynomial Ring in ybar
451
+ over Fraction Field of Univariate Polynomial Ring in x
452
+ over Rational Field with modulus y^2 - y + x
453
+
454
+ Note: ``ybar`` is the name of the variable `y` in the quotient ring.
455
+
456
+ .. TODO:: add link to some tutorial on quotient rings
457
+
458
+ We continue the calculation of this fraction in `R`::
459
+
460
+ sage: fraction = - R(Px) / R(Py); fraction # needs sage.symbolic
461
+ (1/2/(x - 1/4))*ybar - 1/4/(x - 1/4)
462
+
463
+ .. NOTE::
464
+
465
+ The following variant does not work yet::
466
+
467
+ sage: fraction = R( - Px / Py ); fraction # todo: not implemented
468
+ Traceback (most recent call last):
469
+ ...
470
+ TypeError: denominator must be a unit
471
+
472
+ We lift the result to `\QQ(x)[y]` and then substitute
473
+ `z` and `C(z)` to obtain an expression for
474
+ `\frac{d}{dz}C(z)`::
475
+
476
+ sage: fraction = fraction.lift(); fraction # needs sage.symbolic
477
+ (1/2/(x - 1/4))*y - 1/4/(x - 1/4)
478
+ sage: fraction(x=z, y=C) # needs sage.symbolic
479
+ 2*C(z)/(4*z - 1) - 1/(4*z - 1)
480
+
481
+ or, more legibly,
482
+
483
+ .. MATH:: \frac{\partial C(z)}{\partial z} = \frac{1}{1-4z} -\frac{2}{1-4z}C(z)\,.
484
+
485
+ In this simple case, we can directly deduce from this expression a
486
+ linear differential equation with coefficients in `\QQ[z]`::
487
+
488
+ sage: # needs sage.symbolic
489
+ sage: equadiff = diff(C,z) == fraction(x=z, y=C)
490
+ sage: equadiff
491
+ diff(C(z), z) == 2*C(z)/(4*z - 1) - 1/(4*z - 1)
492
+ sage: equadiff = equadiff.simplify_rational()
493
+ sage: equadiff = equadiff * equadiff.rhs().denominator()
494
+ sage: equadiff = equadiff - equadiff.rhs()
495
+ sage: equadiff
496
+ (4*z - 1)*diff(C(z), z) - 2*C(z) + 1 == 0
497
+
498
+ or, more legibly,
499
+
500
+ .. MATH:: (1-4z) \frac{\partial C(z)}{\partial z} + 2 C(z) - 1 = 0\,.
501
+
502
+ It is trivial to verify this equation on the closed form::
503
+
504
+ sage: Cf = sage.symbolic.function_factory.function('C') # needs sage.symbolic
505
+ sage: equadiff.substitute_function(Cf, s0.function(z)) # needs sage.symbolic
506
+ (4*z - 1)/sqrt(-4*z + 1) + sqrt(-4*z + 1) == 0
507
+ sage: bool(equadiff.substitute_function(Cf, s0.function(z))) # needs sage.symbolic
508
+ True
509
+
510
+ .. On veut non seulement remplacer les occurrences de C(z), mais
511
+ .. aussi de C tout court (par exemple dans D[0](C)). Y-a-t'il mieux
512
+ .. pour retrouver C à partir de C(z)?
513
+ .. Cf. also:
514
+ .. http://ask.sagemath.org/question/541/substitute-expression-instead-of-formal-function
515
+
516
+
517
+ In the general case, one continues to calculate successive derivatives
518
+ of `C(z)`. These derivatives are *confined* in the quotient ring
519
+ `\QQ(z)[C]/(P)` which is of finite dimension `\deg P`
520
+ over `\QQ(z)`. Therefore, one will eventually find a linear
521
+ relation among the first `\deg P` derivatives of `C(z)`.
522
+ Putting it over a single denominator, we obtain a linear
523
+ differential equation of degree `\leq \deg P` with coefficients
524
+ in `\QQ[z]`. By extracting the coefficient of `z^n` in
525
+ the differential equation, we obtain the desired recurrence relation on
526
+ the coefficients; in this case we recover the relation we had already
527
+ found, based on the closed form:
528
+
529
+ .. MATH:: c_{n+1}=\frac{(4n-2)}{n+1}c_n
530
+
531
+ After fixing the correct initial conditions, it becomes possible to
532
+ calculate the coefficients of `C(z)` recursively::
533
+
534
+ sage: def C(n): return 1 if n <= 1 else (4*n-6)/n * C(n-1)
535
+ sage: [ C(i) for i in range(10) ]
536
+ [1, 1, 1, 2, 5, 14, 42, 132, 429, 1430]
537
+
538
+ If `n` is too large for the explicit calculation of
539
+ `c_n`, a sequence asymptotically equivalent to the sequence of
540
+ coefficients `c_n` may be sought. Here again, there are generic
541
+ techniques. The central tool is complex analysis, specifically, the
542
+ study of the generating function around its singularities. In the
543
+ present instance, the singularity is at `z_0=1/4` and one would
544
+ obtain `c_n \sim \frac{4^n}{n^{3/2}\sqrt{\pi}}`.
545
+
546
+ Summary
547
+ ^^^^^^^
548
+
549
+ We see here a general phenomenon of computer algebra: the best *data
550
+ structure* to describe a complicated mathematical object (a real number,
551
+ a sequence, a formal power series, a function, a set) is often an
552
+ equation defining the object (or a system of equations, typically with
553
+ some initial conditions). Attempting to find a closed-form
554
+ solution to this equation is not necessarily of interest: on the one
555
+ hand, such a closed form rarely exists (e.g., the problem of
556
+ solving a polynomial by radicals), and on the other hand, the equation,
557
+ in itself, contains all the necessary information to calculate
558
+ algorithmically the properties of the object under consideration (e.g.,
559
+ a numerical approximation, the initial terms or elements, an asymptotic
560
+ equivalent), or to calculate with the object itself (e.g., performing
561
+ arithmetic on power series). Therefore, instead of solving the equation,
562
+ we look for the equation describing the object which is best suited to
563
+ the problem we want to solve.
564
+
565
+ As we saw in our example, confinement (for example, in a finite
566
+ dimensional vector space) is a fundamental tool for studying such
567
+ equations. This notion of confinement is widely applicable in
568
+ elimination techniques (linear algebra, Gröbner bases, and their
569
+ algebro-differential generalizations). The same tool is central in
570
+ algorithms for automatic summation and automatic verification of
571
+ identities (Gosper’s algorithm, Zeilberger’s algorithm, and their
572
+ generalizations; see also :ref:`Exercise: alternating sign matrices
573
+ <exercise-alternating-sign-matrices>`).
574
+
575
+ .. TODO:: add link to some tutorial on summation
576
+
577
+ All these techniques and their many generalizations are at the heart of
578
+ very active topics of research: automatic combinatorics and analytic
579
+ combinatorics, with major applications in the analysis of algorithms. It is
580
+ likely, and desirable, that they will be progressively implemented in
581
+ ``Sage``.
582
+
583
+ .. _section-bricks:
584
+
585
+ Common enumerated sets
586
+ ----------------------
587
+
588
+ First example: the subsets of a set
589
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
590
+
591
+ Fix a set `E` of size `n` and consider the subsets of
592
+ `E` of size `k`. We know that these subsets are counted
593
+ by the binomial coefficients `\binom n k`. We can therefore
594
+ calculate the number of subsets of size `k=2` of
595
+ `E=\{1,2,3,4\}` with the function ``binomial``::
596
+
597
+ sage: binomial(4, 2)
598
+ 6
599
+
600
+ Alternatively, we can *construct* the set `\mathcal P_2(E)` of
601
+ all the subsets of size `2` of `E`, then ask its
602
+ cardinality::
603
+
604
+ sage: S = Subsets([1,2,3,4], 2)
605
+ sage: S.cardinality()
606
+ 6
607
+
608
+ Once ``S`` has been constructed, we can also obtain the list of its
609
+ elements::
610
+
611
+ sage: S.list()
612
+ [{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}]
613
+
614
+ or select an element at random::
615
+
616
+ sage: S.random_element() # random
617
+ {1, 4}
618
+
619
+ More precisely, the object ``S`` models the set
620
+ `\mathcal P_2(E)` equipped with a fixed order (here,
621
+ lexicographic order). It is therefore possible to ask for its
622
+ `5`-th element, keeping in mind that, as with ``Python`` lists, the first
623
+ element is numbered zero::
624
+
625
+ sage: S.unrank(4)
626
+ {2, 4}
627
+
628
+ As a shortcut, in this setting, one can also use the notation::
629
+
630
+ sage: S[4]
631
+ {2, 4}
632
+
633
+ but this should be used with care because some sets have a
634
+ natural indexing other than by `(0, 1, \dots)`.
635
+
636
+ Conversely, one can calculate the position of an object in this order::
637
+
638
+ sage: s = S([2,4]); s
639
+ {2, 4}
640
+ sage: S.rank(s)
641
+ 4
642
+
643
+ Note that ``S`` is *not* the list of its elements. One can, for example,
644
+ model the set `\mathcal P(\mathcal P(\mathcal P(E)))` and
645
+ calculate its cardinality (`2^{2^{2^4}}`)::
646
+
647
+ sage: E = Set([1,2,3,4])
648
+ sage: S = Subsets(Subsets(Subsets(E))); S
649
+ Subsets of Subsets of Subsets of {1, 2, 3, 4}
650
+ sage: n = S.cardinality(); n
651
+ 2003529930406846464979072351560255750447825475569751419265016973...
652
+
653
+ which is roughly `2\cdot 10^{19728}`::
654
+
655
+ sage: n.ndigits()
656
+ 19729
657
+
658
+ or ask for its `237102124`-th element::
659
+
660
+ sage: S.unrank(237102123) # random print output
661
+ {{{2, 4}, {1, 4}, {}, {1, 3, 4}, {1, 2, 4}, {4}, {2, 3}, {1, 3}, {2}},
662
+ {{1, 3}, {2, 4}, {1, 2, 4}, {}, {3, 4}}}
663
+
664
+ It would be physically impossible to construct explicitly all the
665
+ elements of `S`, as there are many more of them than there are
666
+ particles in the universe (estimated at `10^{82}`).
667
+
668
+ Remark: it would be natural in ``Python`` to use ``len(S)`` to ask for the
669
+ cardinality of ``S``. This is not possible because ``Python`` requires that the
670
+ result of ``len`` be an integer of type ``int``; this could cause
671
+ overflows, and would not permit the return of {Infinity} for infinite
672
+ sets::
673
+
674
+ sage: len(S)
675
+ Traceback (most recent call last):
676
+ ...
677
+ OverflowError: cannot fit 'int' into an index-sized integer
678
+
679
+ Partitions of integers
680
+ ~~~~~~~~~~~~~~~~~~~~~~
681
+
682
+ We now consider another classic problem: given a positive integer
683
+ `n`, in how many ways can it be written in the form of a sum
684
+ `n=i_1+i_2+\dots+i_\ell`, where `i_1,\dots,i_\ell` are
685
+ positive integers? There are two cases to distinguish:
686
+
687
+ - the order of the elements in the sum is not important, in which case
688
+ we call `(i_1,\dots,i_\ell)` a *partition* of `n`;
689
+
690
+ - the order of the elements in the sum is important, in which case we
691
+ call `(i_1,\dots,i_\ell)` a *composition* of `n`.
692
+
693
+ We will begin with the partitions of `n=5`; as before, we begin
694
+ by constructing the set of these partitions::
695
+
696
+ sage: P5 = Partitions(5); P5
697
+ Partitions of the integer 5
698
+
699
+ then we ask for its cardinality::
700
+
701
+ sage: P5.cardinality()
702
+ 7
703
+
704
+ We look at these `7` partitions; the order being irrelevant, the
705
+ entries are ordered, by convention, in decreasing order.
706
+
707
+ ::
708
+
709
+ sage: P5.list()
710
+ [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1],
711
+ [1, 1, 1, 1, 1]]
712
+
713
+ The calculation of the number of partitions uses the Rademacher
714
+ formula (:wikipedia:`Partition_(number_theory)`), implemented in ``C``
715
+ and highly optimized, which makes it very fast::
716
+
717
+ sage: Partitions(100000).cardinality()
718
+ 27493510569775696512677516320986352688173429315980054758203125984302147328114964173055050741660736621590157844774296248940493063070200461792764493033510116079342457190155718943509725312466108452006369558934464248716828789832182345009262853831404597021307130674510624419227311238999702284408609370935531629697851569569892196108480158600569421098519
719
+
720
+ Partitions of integers are combinatorial objects naturally equipped with
721
+ many operations. They are therefore returned as objects that are
722
+ richer than simple lists::
723
+
724
+ sage: P7 = Partitions(7)
725
+ sage: p = P7.unrank(5); p
726
+ [4, 2, 1]
727
+ sage: type(p)
728
+ <class 'sage.combinat.partition.Partitions_n_with_category.element_class'>
729
+
730
+ For example, they can be represented graphically by a Ferrers diagram::
731
+
732
+ sage: print(p.ferrers_diagram())
733
+ ****
734
+ **
735
+ *
736
+
737
+ We leave it to the user to explore by introspection the available
738
+ operations.
739
+
740
+ Note that we can also construct a partition directly by::
741
+
742
+ sage: Partition([4,2,1])
743
+ [4, 2, 1]
744
+
745
+ or::
746
+
747
+ sage: P7([4,2,1])
748
+ [4, 2, 1]
749
+
750
+ If one wants to restrict the possible values of the parts
751
+ `i_1,\dots,i_\ell` of the partition as, for example, when giving
752
+ change, one can use ``WeightedIntegerVectors``. For example, the
753
+ following calculation::
754
+
755
+ sage: WeightedIntegerVectors(8, [2,3,5]).list()
756
+ [[0, 1, 1], [1, 2, 0], [4, 0, 0]]
757
+
758
+ shows that to make 8 dollars using 2, 3, and 5 dollar bills, one can
759
+ use a 3 and a 5 dollar bill, or a 2 and two 3 dollar bills, or four 2
760
+ dollar bills.
761
+
762
+ Compositions of integers are manipulated the same way::
763
+
764
+ sage: C5 = Compositions(5); C5
765
+ Compositions of 5
766
+ sage: C5.cardinality()
767
+ 16
768
+ sage: C5.list()
769
+ [[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 2, 1], [1, 1, 3],
770
+ [1, 2, 1, 1], [1, 2, 2], [1, 3, 1], [1, 4], [2, 1, 1, 1],
771
+ [2, 1, 2], [2, 2, 1], [2, 3], [3, 1, 1], [3, 2], [4, 1], [5]]
772
+
773
+ The number `16` above seems significant and suggests the existence of a
774
+ formula. We look at the number of compositions of `n` ranging
775
+ from `0` to `9`::
776
+
777
+ sage: [Compositions(n).cardinality() for n in range(10)]
778
+ [1, 1, 2, 4, 8, 16, 32, 64, 128, 256]
779
+
780
+ Similarly, if we consider the number of compositions of `5` by
781
+ length, we find a line of Pascal’s triangle::
782
+
783
+ sage: x = var('x') # needs sage.symbolic
784
+ sage: sum(x^len(c) for c in C5) # needs sage.symbolic
785
+ x^5 + 4*x^4 + 6*x^3 + 4*x^2 + x
786
+
787
+ The above example uses a functionality which we have not seen yet:
788
+ ``C5`` being iterable, it can be used like a list in a ``for`` loop or
789
+ a comprehension (:ref:`section-bricks-iterators`).
790
+
791
+ Prove the formulas suggested by the above examples for the number of
792
+ compositions of `n` and the number of compositions of
793
+ `n` of length `k`; investigate by introspection
794
+ whether ``Sage`` uses these formulas for calculating cardinalities.
795
+
796
+ .. _section-bricks-divers:
797
+
798
+ Some other finite enumerated sets
799
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
800
+
801
+ Essentially, the principle is the same for all the finite sets with
802
+ which one wants to do combinatorics in ``Sage``; begin by constructing
803
+ an object which models this set, and then supply appropriate methods,
804
+ following a uniform interface [1]_. We now give a few more typical
805
+ examples.
806
+
807
+ Intervals of integers::
808
+
809
+ sage: C = IntegerRange(3, 21, 2); C
810
+ {3, 5, ..., 19}
811
+ sage: C.cardinality()
812
+ 9
813
+ sage: C.list()
814
+ [3, 5, 7, 9, 11, 13, 15, 17, 19]
815
+
816
+ Permutations::
817
+
818
+ sage: C = Permutations(4); C
819
+ Standard permutations of 4
820
+ sage: C.cardinality()
821
+ 24
822
+ sage: C.list()
823
+ [[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2],
824
+ [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3],
825
+ [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1],
826
+ [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1],
827
+ [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2],
828
+ [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]
829
+
830
+ Set partitions::
831
+
832
+ sage: C = SetPartitions(["a", "b", "c"])
833
+ sage: C # random print output
834
+ Set partitions of {'a', 'c', 'b'}
835
+ sage: C.cardinality()
836
+ 5
837
+ sage: C.list()
838
+ [{{'a', 'b', 'c'}},
839
+ {{'a', 'b'}, {'c'}},
840
+ {{'a', 'c'}, {'b'}},
841
+ {{'a'}, {'b', 'c'}},
842
+ {{'a'}, {'b'}, {'c'}}]
843
+
844
+ Partial orders on a set of `8` elements, up to isomorphism::
845
+
846
+ sage: C = Posets(7); C
847
+ Posets containing 7 elements
848
+ sage: C.cardinality()
849
+ 2045
850
+
851
+ ::
852
+
853
+ sage: C.unrank(20).plot() # needs nauty sage.plot
854
+ Graphics object consisting of ... graphics primitives
855
+
856
+ .. image:: ../../media/a_poset.png
857
+
858
+ One can iterate through all graphs up to isomorphism. For example,
859
+ there are 34 simple graphs with 5 vertices::
860
+
861
+ sage: len(list(graphs(5))) # needs nauty
862
+ 34
863
+
864
+ Here are those with at most `4` edges::
865
+
866
+ sage: up_to_four_edges = list(graphs(5, lambda G: G.size() <= 4))
867
+ sage: pretty_print(*up_to_four_edges)
868
+
869
+ .. image:: ../../media/graphs-5.png
870
+
871
+ However, the *set* ``C`` of these graphs is not yet available in
872
+ ``Sage``; as a result, the following commands are not yet
873
+ implemented::
874
+
875
+ sage: # not implemented
876
+ sage: C = Graphs(5)
877
+ sage: C.cardinality()
878
+ 34
879
+ sage: Graphs(19).cardinality()
880
+ 24637809253125004524383007491432768
881
+ sage: Graphs(19).random_element()
882
+ Graph on 19 vertices
883
+
884
+ What we have seen so far also applies, in principle, to finite algebraic
885
+ structures like the dihedral groups::
886
+
887
+ sage: G = DihedralGroup(4); G
888
+ Dihedral group of order 8 as a permutation group
889
+ sage: G.cardinality()
890
+ 8
891
+ sage: G.list()
892
+ [(), (1,3)(2,4), (1,4,3,2), (1,2,3,4), (2,4), (1,3), (1,4)(2,3), (1,2)(3,4)]
893
+
894
+ or the algebra of `2\times 2` matrices over the finite field
895
+ `\ZZ/2\ZZ`::
896
+
897
+ sage: C = MatrixSpace(GF(2), 2) # needs sage.modules sage.rings.finite_rings
898
+ sage: C.list() # needs sage.modules sage.rings.finite_rings
899
+ [
900
+ [0 0] [1 0] [0 1] [0 0] [0 0] [1 1] [1 0] [1 0] [0 1] [0 1]
901
+ [0 0], [0 0], [0 0], [1 0], [0 1], [0 0], [1 0], [0 1], [1 0], [0 1],
902
+ <BLANKLINE>
903
+ [0 0] [1 1] [1 1] [1 0] [0 1] [1 1]
904
+ [1 1], [1 0], [0 1], [1 1], [1 1], [1 1]
905
+ ]
906
+ sage: C.cardinality() # needs sage.modules sage.rings.finite_rings
907
+ 16
908
+
909
+ .. topic:: Exercise
910
+
911
+ List all the monomials of degree `5` in three variables (see
912
+ ``IntegerVectors``). Manipulate the ordered set partitions
913
+ ``OrderedSetPartitions`` and standard tableaux
914
+ (``StandardTableaux``).
915
+
916
+ .. _exercise-alternating-sign-matrices:
917
+
918
+ .. topic:: Exercise
919
+
920
+ List the alternating sign matrices of size `3`, `4`,
921
+ and `5` (``AlternatingSignMatrices``), and try to guess the
922
+ definition. The discovery and proof of the formula for the
923
+ enumeration of these matrices (see the method ``cardinality``),
924
+ motivated by calculations of determinants in physics, is quite a
925
+ story. In particular, the first proof, given by Zeilberger in 1992
926
+ was automatically produced by a computer program. It was 84 pages long,
927
+ and required nearly a hundred people to verify it.
928
+
929
+ .. topic:: Exercise
930
+
931
+ Calculate by hand the number of vectors in `(\ZZ/2\ZZ)^5`, and
932
+ the number of matrices in `GL_3(\ZZ/2\ZZ)` (that is to say,
933
+ the number of invertible `3\times 3` matrices with
934
+ coefficients in `\ZZ/2\ZZ`). Verify your answer with ``Sage``.
935
+ Generalize to `GL_n(\ZZ/q\ZZ)`.
936
+
937
+ .. _section-bricks-iterators:
938
+
939
+ Set comprehension and iterators
940
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
941
+
942
+ We will now show some of the possibilities offered by ``Python`` for
943
+ constructing (and iterating through) sets, with a notation that is
944
+ flexible and close to usual mathematical usage, and in particular the
945
+ benefits this yields in combinatorics.
946
+
947
+ We begin by constructing the finite set
948
+ `\{i^2\ \|\ i \in \{1,3,7\}\}`::
949
+
950
+ sage: [ i^2 for i in [1, 3, 7] ]
951
+ [1, 9, 49]
952
+
953
+ and then the same set, but with `i` running from `1` to
954
+ `9`::
955
+
956
+ sage: [ i^2 for i in range(1,10) ]
957
+ [1, 4, 9, 16, 25, 36, 49, 64, 81]
958
+
959
+ A construction of this form in ``Python`` is called *set comprehension*.
960
+ A clause can be added to keep only those elements with `i` prime::
961
+
962
+ sage: [ i^2 for i in range(1,10) if is_prime(i) ]
963
+ [4, 9, 25, 49]
964
+
965
+ Combining more than one set comprehension, it is possible to construct
966
+ the set `\{(i,j) \ | \ 1\leq j < i <5\}`::
967
+
968
+ sage: [ (i,j) for i in range(1,6) for j in range(1,i) ]
969
+ [(2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3),
970
+ (5, 1), (5, 2), (5, 3), (5, 4)]
971
+
972
+ or to produce Pascal’s triangle::
973
+
974
+ sage: [[binomial(n,i) for i in range(n+1)] for n in range(10)]
975
+ [[1],
976
+ [1, 1],
977
+ [1, 2, 1],
978
+ [1, 3, 3, 1],
979
+ [1, 4, 6, 4, 1],
980
+ [1, 5, 10, 10, 5, 1],
981
+ [1, 6, 15, 20, 15, 6, 1],
982
+ [1, 7, 21, 35, 35, 21, 7, 1],
983
+ [1, 8, 28, 56, 70, 56, 28, 8, 1],
984
+ [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]]
985
+
986
+ The execution of a set comprehension is accomplished in two steps; first
987
+ an *iterator* is constructed, and then a list is filled with the
988
+ elements successively produced by the iterator. Technically, an
989
+ *iterator* is an object with a method ``next`` which returns a new value
990
+ each time it is called, until it is exhausted. For example, the
991
+ following iterator ``it``::
992
+
993
+ sage: it = (binomial(3, i) for i in range(4))
994
+
995
+ returns successively the binomial coefficients `\binom 3 i` with
996
+ `i=0,1,2,3`::
997
+
998
+ sage: next(it)
999
+ 1
1000
+ sage: next(it)
1001
+ 3
1002
+ sage: next(it)
1003
+ 3
1004
+ sage: next(it)
1005
+ 1
1006
+
1007
+ When the iterator is finally exhausted, an exception is raised::
1008
+
1009
+ sage: next(it)
1010
+ Traceback (most recent call last):
1011
+ ...
1012
+ StopIteration
1013
+
1014
+ More generally, an *iterable* is a ``Python`` object ``L`` (a list,
1015
+ a set, ...) over whose elements it is possible to iterate. Technically,
1016
+ the iterator is constructed by ``iter(L)``. In practice, the commands
1017
+ ``iter`` and ``next`` are used very rarely, since ``for`` loops and list
1018
+ comprehensions provide a much pleasanter syntax::
1019
+
1020
+ sage: for s in Subsets(3):
1021
+ ....: print(s)
1022
+ {}
1023
+ {1}
1024
+ {2}
1025
+ {3}
1026
+ {1, 2}
1027
+ {1, 3}
1028
+ {2, 3}
1029
+ {1, 2, 3}
1030
+
1031
+ ::
1032
+
1033
+ sage: [ s.cardinality() for s in Subsets(3) ]
1034
+ [0, 1, 1, 1, 2, 2, 2, 3]
1035
+
1036
+ What is the point of an iterator? Consider the following example::
1037
+
1038
+ sage: sum( [ binomial(8, i) for i in range(9) ] )
1039
+ 256
1040
+
1041
+ When it is executed, a list of `9` elements is constructed, and
1042
+ then it is passed as an argument to ``sum`` to add them up. If, on the
1043
+ other hand, the iterator is passed directly to ``sum`` (note the absence
1044
+ of square brackets)::
1045
+
1046
+ sage: sum( binomial(8, i) for i in range(9) )
1047
+ 256
1048
+
1049
+ the function ``sum`` receives the iterator directly, and can
1050
+ short-circuit the construction of the intermediate list. If there are a
1051
+ large number of elements, this avoids allocating a large quantity of
1052
+ memory to fill a list which will be immediately destroyed.
1053
+
1054
+ Most functions that take a list of elements as input will also accept
1055
+ an iterator (or an iterable) instead. To begin with, one can obtain the
1056
+ list (or the tuple) of elements of an iterator as follows::
1057
+
1058
+ sage: list(binomial(8, i) for i in range(9))
1059
+ [1, 8, 28, 56, 70, 56, 28, 8, 1]
1060
+ sage: tuple(binomial(8, i) for i in range(9))
1061
+ (1, 8, 28, 56, 70, 56, 28, 8, 1)
1062
+
1063
+ We now consider the functions ``all`` and ``any`` which denote
1064
+ respectively the `n`-ary *and* and *or*::
1065
+
1066
+ sage: all([True, True, True, True])
1067
+ True
1068
+ sage: all([True, False, True, True])
1069
+ False
1070
+ sage: any([False, False, False, False])
1071
+ False
1072
+ sage: any([False, False, True, False])
1073
+ True
1074
+
1075
+ The following example verifies that all primes from `3` to
1076
+ `99` are odd::
1077
+
1078
+ sage: all( is_odd(p) for p in range(3,100) if is_prime(p) )
1079
+ True
1080
+
1081
+ A *Mersenne prime* is a prime of the form `2^p -1`. We verify
1082
+ that, for `p<1000`, if `2^p-1` is prime, then
1083
+ `p` is also prime::
1084
+
1085
+ sage: def mersenne(p): return 2^p -1
1086
+ sage: [ is_prime(p)
1087
+ ....: for p in range(1000) if is_prime(mersenne(p)) ]
1088
+ [True, True, True, True, True, True, True, True, True, True,
1089
+ True, True, True, True]
1090
+
1091
+ Is the converse true?
1092
+
1093
+ .. topic:: Exercise
1094
+
1095
+ Try the two following commands and explain the considerable
1096
+ difference in the length of the calculations::
1097
+
1098
+ sage: all( is_prime(mersenne(p))
1099
+ ....: for p in range(1000) if is_prime(p) )
1100
+ False
1101
+ sage: all( [ is_prime(mersenne(p))
1102
+ ....: for p in range(1000) if is_prime(p)] )
1103
+ False
1104
+
1105
+ We now try to find the smallest counter-example. In order to do this, we
1106
+ use the ``Sage`` function ``exists``::
1107
+
1108
+ sage: exists( (p for p in range(1000) if is_prime(p)),
1109
+ ....: lambda p: not is_prime(mersenne(p)) )
1110
+ (True, 11)
1111
+
1112
+ Alternatively, we could construct an iterator on the counter-examples::
1113
+
1114
+ sage: counter_examples = (p for p in range(1000)
1115
+ ....: if is_prime(p) and not is_prime(mersenne(p)))
1116
+ sage: next(counter_examples)
1117
+ 11
1118
+ sage: next(counter_examples)
1119
+ 23
1120
+
1121
+ .. topic:: Exercise
1122
+
1123
+ What do the following commands do?
1124
+
1125
+ ::
1126
+
1127
+ sage: cubes = [t**3 for t in range(-999,1000)]
1128
+ sage: exists([(x,y) for x in cubes for y in cubes], # long time (3s, 2012)
1129
+ ....: lambda x_y: x_y[0] + x_y[1] == 218)
1130
+ (True, (-125, 343))
1131
+ sage: exists(((x,y) for x in cubes for y in cubes), # long time (2s, 2012)
1132
+ ....: lambda x_y: x_y[0] + x_y[1] == 218)
1133
+ (True, (-125, 343))
1134
+
1135
+ Which of the last two is more economical in terms of time? In terms
1136
+ of memory? By how much?
1137
+
1138
+ .. topic:: Exercise
1139
+
1140
+ Try each of the following commands, and explain its result. If
1141
+ possible, hide the result first and try to guess it before
1142
+ launching the command.
1143
+
1144
+ .. TODO:: hide the results by default
1145
+
1146
+ .. warning:: it will be necessary to interrupt the execution of some of the commands
1147
+
1148
+ ::
1149
+
1150
+ sage: x = var('x') # needs sage.symbolic
1151
+ sage: sum(x^len(s) for s in Subsets(8)) # needs sage.symbolic
1152
+ x^8 + 8*x^7 + 28*x^6 + 56*x^5 + 70*x^4 + 56*x^3 + 28*x^2 + 8*x + 1
1153
+
1154
+ ::
1155
+
1156
+ sage: sum(x^p.length() for p in Permutations(3)) # needs sage.symbolic
1157
+ x^3 + 2*x^2 + 2*x + 1
1158
+
1159
+ ::
1160
+
1161
+ sage: factor(sum(x^p.length() for p in Permutations(3))) # needs sage.symbolic
1162
+ (x^2 + x + 1)*(x + 1)
1163
+
1164
+ ::
1165
+
1166
+ sage: P = Permutations(5)
1167
+ sage: all(p in P for p in P)
1168
+ True
1169
+
1170
+ ::
1171
+
1172
+ sage: for p in GL(2, 2): print(p); print("")
1173
+ [1 0]
1174
+ [0 1]
1175
+ <BLANKLINE>
1176
+ [0 1]
1177
+ [1 0]
1178
+ <BLANKLINE>
1179
+ [0 1]
1180
+ [1 1]
1181
+ <BLANKLINE>
1182
+ [1 1]
1183
+ [0 1]
1184
+ <BLANKLINE>
1185
+ [1 1]
1186
+ [1 0]
1187
+ <BLANKLINE>
1188
+ [1 0]
1189
+ [1 1]
1190
+ <BLANKLINE>
1191
+
1192
+ ::
1193
+
1194
+ sage: for p in Partitions(3): print(p) # not tested
1195
+ [3]
1196
+ [2, 1]
1197
+ [1, 1, 1]
1198
+ ...
1199
+
1200
+ ::
1201
+
1202
+ sage: for p in Partitions(): print(p) # not tested
1203
+ []
1204
+ [1]
1205
+ [2]
1206
+ [1, 1]
1207
+ [3]
1208
+ ...
1209
+
1210
+ ::
1211
+
1212
+ sage: for p in Primes(): print(p) # not tested
1213
+ 2
1214
+ 3
1215
+ 5
1216
+ 7
1217
+ ...
1218
+
1219
+ ::
1220
+
1221
+ sage: exists( Primes(), lambda p: not is_prime(mersenne(p)) )
1222
+ (True, 11)
1223
+
1224
+ ::
1225
+
1226
+ sage: counter_examples = (p for p in Primes()
1227
+ ....: if not is_prime(mersenne(p)))
1228
+ sage: for p in counter_examples: print(p) # not tested
1229
+ 11
1230
+ 23
1231
+ 29
1232
+ 37
1233
+ 41
1234
+ 43
1235
+ 47
1236
+ ...
1237
+
1238
+ Operations on iterators
1239
+ ^^^^^^^^^^^^^^^^^^^^^^^
1240
+
1241
+ ``Python`` provides numerous tools for manipulating iterators; most of them
1242
+ are in the :mod:`itertools` library, which can be imported by::
1243
+
1244
+ sage: import itertools
1245
+
1246
+ We will demonstrate some applications, taking as a starting point the
1247
+ permutations of `3`::
1248
+
1249
+ sage: list(Permutations(3))
1250
+ [[1, 2, 3], [1, 3, 2], [2, 1, 3],
1251
+ [2, 3, 1], [3, 1, 2], [3, 2, 1]]
1252
+
1253
+ We can list the elements of a set by numbering them::
1254
+
1255
+ sage: list(enumerate(Permutations(3)))
1256
+ [(0, [1, 2, 3]), (1, [1, 3, 2]), (2, [2, 1, 3]),
1257
+ (3, [2, 3, 1]), (4, [3, 1, 2]), (5, [3, 2, 1])]
1258
+
1259
+ or select only the elements in positions 2, 3, and 4 (analogue of
1260
+ ``l[1:4]``)::
1261
+
1262
+ sage: import itertools
1263
+ sage: list(itertools.islice(Permutations(3), int(1), int(4)))
1264
+ [[1, 3, 2], [2, 1, 3], [2, 3, 1]]
1265
+
1266
+ To apply a function to all the elements, one can do::
1267
+
1268
+ sage: [z.cycle_type() for z in Permutations(3)]
1269
+ [[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]]
1270
+
1271
+ and similarly to select the elements satisfying a certain condition::
1272
+
1273
+ sage: [z for z in Permutations(3) if z.has_pattern([1,2])]
1274
+ [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2]]
1275
+
1276
+ Implementation of new iterators
1277
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1278
+
1279
+ It is easy to construct new iterators, using the keyword ``yield``
1280
+ instead of ``return`` in a function::
1281
+
1282
+ sage: def f(n):
1283
+ ....: for i in range(n):
1284
+ ....: yield i
1285
+
1286
+ After the ``yield``, execution is not halted, but only suspended, ready
1287
+ to be continued from the same point. The result of the function is
1288
+ therefore an iterator over the successive values returned by ``yield``::
1289
+
1290
+ sage: g = f(4)
1291
+ sage: next(g)
1292
+ 0
1293
+ sage: next(g)
1294
+ 1
1295
+ sage: next(g)
1296
+ 2
1297
+ sage: next(g)
1298
+ 3
1299
+
1300
+ ::
1301
+
1302
+ sage: next(g)
1303
+ Traceback (most recent call last):
1304
+ ...
1305
+ StopIteration
1306
+
1307
+ The function could be used as follows::
1308
+
1309
+ sage: [ x for x in f(5) ]
1310
+ [0, 1, 2, 3, 4]
1311
+
1312
+ This model of computation, called *continuation*, is very useful in
1313
+ combinatorics, especially when combined with recursion. Here is how to
1314
+ generate all words of a given length on a given alphabet::
1315
+
1316
+ sage: def words(alphabet, l):
1317
+ ....: if l == 0:
1318
+ ....: yield []
1319
+ ....: else:
1320
+ ....: for word in words(alphabet, l-1):
1321
+ ....: for l in alphabet:
1322
+ ....: yield word + [l]
1323
+ sage: [ w for w in words(['a','b'], 3) ]
1324
+ [['a', 'a', 'a'], ['a', 'a', 'b'], ['a', 'b', 'a'],
1325
+ ['a', 'b', 'b'], ['b', 'a', 'a'], ['b', 'a', 'b'],
1326
+ ['b', 'b', 'a'], ['b', 'b', 'b']]
1327
+
1328
+ These words can then be counted by::
1329
+
1330
+ sage: sum(1 for w in words(['a','b','c','d'], 10))
1331
+ 1048576
1332
+
1333
+ Counting the words one by one is clearly not an efficient method in this
1334
+ case, since the formula `n^\ell` is also available; note,
1335
+ though, that this is not the stupidest possible approach - it does, at
1336
+ least, avoid constructing the entire list in memory.
1337
+
1338
+ We now consider Dyck words, which are well-parenthesized words in the
1339
+ letters “`(`” and “`)`”. The function below generates
1340
+ all the Dyck words of a given length (where the length is the number of
1341
+ pairs of parentheses), using the recursive definition which says that a
1342
+ Dyck word is either empty or of the form `(w_1)w_2` where
1343
+ `w_1` and `w_2` are Dyck words::
1344
+
1345
+ sage: def dyck_words(l):
1346
+ ....: if l==0:
1347
+ ....: yield ''
1348
+ ....: else:
1349
+ ....: for k in range(l):
1350
+ ....: for w1 in dyck_words(k):
1351
+ ....: for w2 in dyck_words(l-k-1):
1352
+ ....: yield '('+w1+')'+w2
1353
+
1354
+ Here are all the Dyck words of length `4`::
1355
+
1356
+ sage: list(dyck_words(4))
1357
+ ['()()()()', '()()(())', '()(())()', '()(()())', '()((()))',
1358
+ '(())()()', '(())(())', '(()())()', '((()))()', '(()()())',
1359
+ '(()(()))', '((())())', '((()()))', '(((())))']
1360
+
1361
+ Counting them, we recover a well-known sequence::
1362
+
1363
+ sage: [ sum(1 for w in dyck_words(l)) for l in range(10) ]
1364
+ [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
1365
+
1366
+ .. _exo-iterators-catalan:
1367
+
1368
+ .. topic:: Exercise: complete binary tree iterator
1369
+
1370
+ Construct an iterator on the set `C_n` of complete binary
1371
+ trees with `n` leaves
1372
+ (see :ref:`section-examples-catalan`).
1373
+
1374
+ Hint: ``Sage`` 4.8.2 does not yet have a native data structure to
1375
+ represent complete binary trees. One simple way to represent them is
1376
+ to define a formal variable ``Leaf`` for the leaves and a formal
1377
+ 2-ary function ``Node``::
1378
+
1379
+ sage: var('Leaf') # needs sage.symbolic
1380
+ Leaf
1381
+ sage: function('Node', nargs=2) # needs sage.symbolic
1382
+ Node
1383
+
1384
+ The second tree in :ref:`figure-examples-catalan-trees`
1385
+ can be represented by the expression::
1386
+
1387
+ sage: tr = Node(Node(Leaf, Node(Leaf, Leaf)), Leaf) # needs sage.symbolic
1388
+
1389
+ .. _section-constructions:
1390
+
1391
+ Constructions
1392
+ -------------
1393
+
1394
+ We will now see how to construct new sets starting from these building
1395
+ blocks. In fact, we have already begun to do this with the construction
1396
+ of `\mathcal P(\mathcal P(\mathcal P(\{1,2,3,4\})))` in the
1397
+ previous section, and to construct the example of sets of cards in
1398
+ :ref:`section-examples`.
1399
+
1400
+ Consider a large Cartesian product::
1401
+
1402
+ sage: C = cartesian_product([Compositions(8), Permutations(20)]); C
1403
+ The Cartesian product of (Compositions of 8, Standard permutations of 20)
1404
+ sage: C.cardinality()
1405
+ 311411457046609920000
1406
+
1407
+ Clearly, it is impractical to construct the list of all the elements of this
1408
+ Cartesian product! And, in the following example, `H` is equipped with the
1409
+ usual combinatorial operations and also its structure as a product group::
1410
+
1411
+ sage: G = DihedralGroup(4)
1412
+ sage: H = cartesian_product([G,G])
1413
+ sage: H in Groups()
1414
+ True
1415
+ sage: H.an_element()
1416
+ ((1,3), (1,3))
1417
+ sage: t = H([G.gen(0), G.gen(0)])
1418
+ sage: t
1419
+ ((1,2,3,4), (1,2,3,4))
1420
+ sage: t*t
1421
+ ((1,3)(2,4), (1,3)(2,4))
1422
+
1423
+ We now construct the union of two existing disjoint sets::
1424
+
1425
+ sage: C = DisjointUnionEnumeratedSets(
1426
+ ....: [ Compositions(4), Permutations(3)] )
1427
+ sage: C
1428
+ Disjoint union of Family (Compositions of 4,
1429
+ Standard permutations of 3)
1430
+ sage: C.cardinality()
1431
+ 14
1432
+ sage: C.list()
1433
+ [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2],
1434
+ [3, 1], [4], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1],
1435
+ [3, 1, 2], [3, 2, 1]]
1436
+
1437
+ It is also possible to take the union of more than two disjoint sets, or
1438
+ even an infinite number of them. We will now construct the set of all
1439
+ permutations, viewed as the union of the sets `P_n` of
1440
+ permutations of size `n`. We begin by constructing the infinite
1441
+ family `F=(P_n)_{n\in N}`::
1442
+
1443
+ sage: F = Family(NonNegativeIntegers(), Permutations); F
1444
+ Lazy family (<class 'sage.combinat.permutation.Permutations'>(i))_{i in Non negative integers}
1445
+ sage: F.keys()
1446
+ Non negative integers
1447
+ sage: F[1000]
1448
+ Standard permutations of 1000
1449
+
1450
+ Now we can construct the disjoint union `\bigcup_{n\in \NN}P_n`::
1451
+
1452
+ sage: U = DisjointUnionEnumeratedSets(F); U
1453
+ Disjoint union of
1454
+ Lazy family (<class 'sage.combinat.permutation.Permutations'>(i))_{i in Non negative integers}
1455
+
1456
+ It is an infinite set::
1457
+
1458
+ sage: U.cardinality()
1459
+ +Infinity
1460
+
1461
+ which doesn’t prohibit iteration through its elements, though it will be
1462
+ necessary to interrupt it at some point::
1463
+
1464
+ sage: for p in U: # not tested
1465
+ ....: print(p)
1466
+ []
1467
+ [1]
1468
+ [1, 2]
1469
+ [2, 1]
1470
+ [1, 2, 3]
1471
+ [1, 3, 2]
1472
+ [2, 1, 3]
1473
+ [2, 3, 1]
1474
+ [3, 1, 2]
1475
+ ...
1476
+
1477
+ Note: the above set could also have been constructed directly with::
1478
+
1479
+ sage: U = Permutations(); U
1480
+ Standard permutations
1481
+
1482
+ Summary
1483
+ ~~~~~~~
1484
+
1485
+ ``Sage`` provides a library of common enumerated sets, which can be
1486
+ combined by standard constructions, giving a toolbox that is flexible
1487
+ (but which could still be expanded). It is also possible to add new
1488
+ building blocks to ``Sage`` with a few lines (see the code in
1489
+ ``FiniteEnumeratedSets().example()``). This is made possible by the
1490
+ uniformity of the interfaces and the fact that ``Sage`` is based on an
1491
+ object-oriented language. Also, very large or even infinite sets can
1492
+ be manipulated thanks to lazy evaluation strategies (iterators, etc.).
1493
+
1494
+ There is no magic to any of this: under the hood, ``Sage`` applies the
1495
+ usual rules (for example, that the cardinality of `E\times E` is
1496
+ `|E|^2`); the added value comes from the capacity to manipulate
1497
+ complicated constructions. The situation is comparable to ``Sage``’s
1498
+ implementation of differential calculus: ``Sage`` applies the usual
1499
+ rules for differentiation of functions and their compositions, where
1500
+ the added value comes from the possibility of manipulating complicated
1501
+ formulas. In this sense, ``Sage`` implements a *calculus* of finite
1502
+ enumerated sets.
1503
+
1504
+ .. _section-generic:
1505
+
1506
+ Generic algorithms
1507
+ ------------------
1508
+
1509
+ .. _section-generic-integerlistlex:
1510
+
1511
+ Lexicographic generation of lists of integers
1512
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1513
+
1514
+ Among the classic enumerated sets, especially in algebraic
1515
+ combinatorics, a certain number are composed of lists of integers of
1516
+ fixed sum, such as partitions, compositions, or integer vectors. These
1517
+ examples can also have supplementary constraints added to them. Here are
1518
+ some examples. We start with the integer vectors with sum `10`
1519
+ and length `3`, with parts bounded below by `2`,
1520
+ `4` and `2` respectively::
1521
+
1522
+ sage: IntegerVectors(10, 3, min_part=2, max_part=5,
1523
+ ....: inner=[2, 4, 2]).list()
1524
+ [[4, 4, 2], [3, 5, 2], [3, 4, 3], [2, 5, 3], [2, 4, 4]]
1525
+
1526
+ The compositions of `5` with each part at most `3`, and
1527
+ with length `2` or `3`::
1528
+
1529
+ sage: Compositions(5, max_part=3,
1530
+ ....: min_length=2, max_length=3).list()
1531
+ [[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [1, 3, 1],
1532
+ [1, 2, 2], [1, 1, 3]]
1533
+
1534
+ The strictly decreasing partitions of `5`::
1535
+
1536
+ sage: Partitions(5, max_slope=-1).list()
1537
+ [[5], [4, 1], [3, 2]]
1538
+
1539
+ These sets share the same underlying algorithmic structure, implemented
1540
+ in the more general (and slightly more cumbersome) class
1541
+ ``IntegerListsLex``. This class models sets of vectors
1542
+ `(\ell_0,\dots,\ell_k)` of nonnegative integers, with
1543
+ constraints on the sum and the length, and bounds on the parts and on
1544
+ the consecutive differences between the parts. Here are some more
1545
+ examples::
1546
+
1547
+ sage: IntegerListsLex(10, length=3,
1548
+ ....: min_part=2, max_part=5,
1549
+ ....: floor=[2, 4, 2]).list()
1550
+ [[4, 4, 2], [3, 5, 2], [3, 4, 3], [2, 5, 3], [2, 4, 4]]
1551
+
1552
+ sage: IntegerListsLex(5, min_part=1, max_part=3,
1553
+ ....: min_length=2, max_length=3).list()
1554
+ [[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2],
1555
+ [1, 3, 1], [1, 2, 2], [1, 1, 3]]
1556
+
1557
+ sage: IntegerListsLex(5, min_part=1, max_slope=-1).list()
1558
+ [[5], [4, 1], [3, 2]]
1559
+
1560
+ sage: list(Compositions(5, max_length=2))
1561
+ [[5], [4, 1], [3, 2], [2, 3], [1, 4]]
1562
+
1563
+ sage: list(IntegerListsLex(5, max_length=2, min_part=1))
1564
+ [[5], [4, 1], [3, 2], [2, 3], [1, 4]]
1565
+
1566
+ The point of the model of ``IntegerListsLex`` is in the compromise
1567
+ between generality and efficiency. The main algorithm permits
1568
+ iteration through the elements of such a set `S` in reverse
1569
+ lexicographic order with a good complexity in most practical use
1570
+ cases. Roughly speaking, the time needed to iterate through all the
1571
+ elements of `S` is proportional to the number of elements, where the
1572
+ proportion factor is controlled by the length `l` of the longest
1573
+ element of `S`. In addition, the memory usage is also controlled by
1574
+ `l`, which is to say negligible in practice.
1575
+
1576
+ This algorithm is based on a very general principle for traversing a
1577
+ decision tree, called *branch and bound*: at the top level, we run
1578
+ through all the possible choices for `\ell_0`; for each of these
1579
+ choices, we run through all the possible choices for `\ell_1`,
1580
+ and so on. Mathematically speaking, we have put the structure of a
1581
+ prefix tree on the elements of `S`: a node of the tree at depth
1582
+ `k` corresponds to a prefix `\ell_0,\dots,\ell_k` of one
1583
+ (or more) elements of `S` (see :ref:`figure-prefix-tree-partitions`).
1584
+
1585
+ .. _figure-prefix-tree-partitions:
1586
+
1587
+ .. figure:: ../../media/prefix-tree-partitions-5.png
1588
+ :scale: 150%
1589
+
1590
+ Figure: The prefix tree of the partitions of 5.
1591
+
1592
+ The usual problem with this type of approach is to avoid bad decisions
1593
+ which lead to leaving the prefix tree and exploring dead branches;
1594
+ this is particularly problematic because the growth of the number of
1595
+ elements is usually exponential in the depth. It turns out that the
1596
+ constraints listed above are simple enough to be able to reasonably
1597
+ predict when a sequence `\ell_0,\dots,\ell_k` is a prefix of some
1598
+ element `S`. Hence, most dead branches can be pruned.
1599
+
1600
+ .. _section-generic-polytopes:
1601
+
1602
+ Integer points in polytopes
1603
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1604
+
1605
+ Although the algorithm for iteration in ``IntegerListsLex`` is
1606
+ efficient, its counting algorithm is naive: it just iterates over all
1607
+ the elements.
1608
+
1609
+ There is an alternative approach to treating this problem: modelling the
1610
+ desired lists of integers as the set of integer points of a polytope,
1611
+ that is to say, the set of solutions with integer coordinates of a
1612
+ system of linear inequalities. This is a very general context in which
1613
+ there exist advanced counting algorithms (e.g. Barvinok), which are
1614
+ implemented in libraries like ``LattE``. Iteration does not pose a hard problem
1615
+ in principle. However, there are two limitations that justify the
1616
+ existence of ``IntegerListsLex``. The first is theoretical: lattice
1617
+ points in a polytope only allow modelling of problems of a fixed
1618
+ dimension (length). The second is practical: at the moment only the
1619
+ library ``PALP`` has a ``Sage`` interface, and though it offers multiple
1620
+ capabilities for the study of polytopes, in the present application it
1621
+ only produces a list of lattice points, without providing either an
1622
+ iterator or non-naive counting::
1623
+
1624
+ sage: A = random_matrix(ZZ, 6, 3, x=7)
1625
+ sage: L = LatticePolytope(A.rows())
1626
+ sage: L.points() # random # needs palp
1627
+ M(4, 1, 0),
1628
+ M(0, 3, 5),
1629
+ M(2, 2, 3),
1630
+ M(6, 1, 3),
1631
+ M(1, 3, 6),
1632
+ M(6, 2, 3),
1633
+ M(3, 2, 4),
1634
+ M(3, 2, 3),
1635
+ M(4, 2, 4),
1636
+ M(4, 2, 3),
1637
+ M(5, 2, 3)
1638
+ in 3-d lattice M
1639
+ sage: L.npoints() # random # needs palp
1640
+ 11
1641
+
1642
+ This polytope can be visualized in 3D with ``L.plot3d()`` (see
1643
+ :ref:`figure-polytope`).
1644
+
1645
+ .. _figure-polytope:
1646
+
1647
+ .. figure:: ../../media/polytope.png
1648
+ :scale: 75%
1649
+
1650
+ Figure: The polytope `L` and its integer points, in cross-eyed stereographic perspective.
1651
+
1652
+ .. _section-generic-species:
1653
+
1654
+ Species, decomposable combinatorial classes
1655
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1656
+
1657
+ In :ref:`section-examples-catalan`, we showed how to use the recursive
1658
+ definition of binary trees to count them efficiently using generating
1659
+ functions. The techniques we used there are very general, and apply
1660
+ whenever the sets involved can be defined recursively (depending on
1661
+ who you ask, such a set is called a *decomposable combinatorial class*
1662
+ or, roughly speaking, a *combinatorial species*). This includes all
1663
+ the types of trees, but also permutations, compositions, functional
1664
+ graphs, etc.
1665
+
1666
+ Here, we illustrate just a few examples using the ``Sage`` library on
1667
+ combinatorial species::
1668
+
1669
+ sage: from sage.combinat.species.library import *
1670
+ sage: o = var('o') # needs sage.symbolic
1671
+
1672
+ We begin by redefining the complete binary trees; to do so, we stipulate
1673
+ the recurrence relation directly on the sets::
1674
+
1675
+ sage: BT = CombinatorialSpecies(min=1)
1676
+ sage: Leaf = SingletonSpecies()
1677
+ sage: BT.define( Leaf + (BT*BT) )
1678
+
1679
+ Now we can construct the set of trees with five nodes, list them, count
1680
+ them...::
1681
+
1682
+ sage: BT5 = BT.isotypes([o]*5) # needs sage.symbolic
1683
+ sage: BT5.cardinality() # needs sage.symbolic
1684
+ 14
1685
+ sage: BT5.list() # needs sage.symbolic
1686
+ [o*(o*(o*(o*o))), o*(o*((o*o)*o)), o*((o*o)*(o*o)),
1687
+ o*((o*(o*o))*o), o*(((o*o)*o)*o), (o*o)*(o*(o*o)),
1688
+ (o*o)*((o*o)*o), (o*(o*o))*(o*o), ((o*o)*o)*(o*o),
1689
+ (o*(o*(o*o)))*o, (o*((o*o)*o))*o, ((o*o)*(o*o))*o,
1690
+ ((o*(o*o))*o)*o, (((o*o)*o)*o)*o]
1691
+
1692
+ The trees are constructed using a generic recursive structure; the
1693
+ display is therefore not wonderful. To do better, it would be necessary
1694
+ to provide ``Sage`` with a more specialized data structure with the
1695
+ desired display capabilities.
1696
+
1697
+ We recover the generating function for the Catalan numbers::
1698
+
1699
+ sage: g = BT.isotype_generating_series(); g
1700
+ z + z^2 + 2*z^3 + 5*z^4 + 14*z^5 + 42*z^6 + 132*z^7 + O(z^8)
1701
+
1702
+ which is returned in the form of a lazy power series::
1703
+
1704
+ sage: g[100]
1705
+ 227508830794229349661819540395688853956041682601541047340
1706
+
1707
+ We finish with the Fibonacci words, which are binary words without two
1708
+ consecutive “`1`”s. They admit a natural recursive definition::
1709
+
1710
+ sage: Eps = EmptySetSpecies()
1711
+ sage: Z0 = SingletonSpecies()
1712
+ sage: Z1 = Eps*SingletonSpecies()
1713
+ sage: FW = CombinatorialSpecies()
1714
+ sage: FW.define(Eps + Z0*FW + Z1*Eps + Z1*Z0*FW)
1715
+
1716
+ The Fibonacci sequence is easily recognized here, hence the name::
1717
+
1718
+ sage: L = FW.isotype_generating_series()[:15]; L
1719
+ [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
1720
+
1721
+ ::
1722
+
1723
+ sage: oeis(L) # optional -- internet
1724
+ 0: A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1725
+ 1: ...
1726
+ 2: ...
1727
+
1728
+ This is an immediate consequence of the recurrence relation. One can
1729
+ also generate immediately all the Fibonacci words of a given length,
1730
+ with the same limitations resulting from the generic display.
1731
+
1732
+ ::
1733
+
1734
+ sage: FW3 = FW.isotypes([o]*3) # needs sage.symbolic
1735
+ sage: FW3.list() # needs sage.symbolic
1736
+ [o*(o*(o*{})), o*(o*(({}*o)*{})), o*((({}*o)*o)*{}),
1737
+ (({}*o)*o)*(o*{}), (({}*o)*o)*(({}*o)*{})]
1738
+
1739
+ .. _section-generic-isomorphism:
1740
+
1741
+ Graphs up to isomorphism
1742
+ ~~~~~~~~~~~~~~~~~~~~~~~~
1743
+
1744
+ We saw in :ref:`section-bricks-divers` that ``Sage`` could generate
1745
+ graphs and partial orders up to isomorphism. We will now describe the
1746
+ underlying algorithm, which is the same in both cases, and covers a
1747
+ substantially wider class of problems.
1748
+
1749
+ We begin by recalling some notions. A graph `G=(V,E)` is a set
1750
+ `V` of vertices and a set `E` of edges connecting these
1751
+ vertices; an edge is described by a pair `\{u,v\}` of distinct
1752
+ vertices of `V`. Such a graph is called labelled; its vertices
1753
+ are typically numbered by considering `V=\{1,2,3,4,5\}`.
1754
+
1755
+ In many problems, the labels on the vertices play no role. Typically a
1756
+ chemist wants to study all the possible molecules with a given
1757
+ composition, for example the alkanes with `n=8` atoms of carbon
1758
+ and `2n+2=18` atoms of hydrogen. He therefore wants to find all
1759
+ the graphs consisting of `8` vertices with `4` neighbours, and
1760
+ `18` vertices with a single neighbour. The different carbon atoms,
1761
+ however, are all considered to be identical, and the same for
1762
+ the hydrogen atoms. The problem of our chemist is not imaginary; this
1763
+ type of application is actually at the origin of an important part of
1764
+ the research in graph theory on isomorphism problems.
1765
+
1766
+ Working by hand on a small graph it is possible, as in the example of
1767
+ :ref:`section-bricks-divers`, to make a drawing, erase the labels, and
1768
+ “forget” the geometrical information about the location of the
1769
+ vertices in the plane. However, to represent a graph in a computer
1770
+ program, it is necessary to introduce labels on the vertices so as to
1771
+ be able to describe how the edges connect them together. To compensate
1772
+ for the extra information which we have introduced, we then say that
1773
+ two labelled graphs `g_1` and `g_2` are *isomorphic* if there is a
1774
+ bijection from the vertices of `g_1` to those of `g_2`, which maps
1775
+ bijectively the edges of `g_1` to those of `g_2`; an *unlabelled
1776
+ graph* is then an equivalence class of labelled graphs.
1777
+
1778
+ In general, testing if two labelled graphs are isomorphic is expensive.
1779
+ However, the number of graphs, even unlabelled, grows very
1780
+ rapidly. Nonetheless, it is possible to list unlabelled graphs very efficiently
1781
+ considering their number. For example, the program ``Nauty`` can list the
1782
+ `12005168` simple graphs with `10` vertices in
1783
+ `20` seconds.
1784
+
1785
+ As in :ref:`section-generic-integerlistlex`, the general principle
1786
+ of the algorithm is to organize the objects to be enumerated into a tree
1787
+ that one traverses.
1788
+
1789
+ For this, in each equivalence class of labelled graphs (that is to say,
1790
+ for each unlabelled graph) one fixes a convenient canonical
1791
+ representative. The following are the fundamental operations:
1792
+
1793
+ * Testing whether a labelled graph is canonical
1794
+
1795
+ * Calculating the canonical representative of a labelled graph
1796
+
1797
+ These unavoidable operations remain expensive; one therefore tries to
1798
+ minimize the number of calls to them.
1799
+
1800
+ The canonical representatives are chosen in such a way that, for each
1801
+ canonical labelled graph `G`, there is a canonical choice of an edge
1802
+ whose removal produces a canonical graph again, which is called the
1803
+ father of `G`. This property implies that it is possible to organize
1804
+ the set of canonical representatives as a tree: at the root, the graph
1805
+ with no edges; below it, its unique child, the graph with one edge;
1806
+ then the graphs with two edges, and so on. The set of children of a
1807
+ graph `G` can be constructed by *augmentation*, adding an edge in all
1808
+ the possible ways to `G`, and then selecting, from among those graphs,
1809
+ the ones that are still canonical [2]_. Recursively, one obtains all
1810
+ the canonical graphs.
1811
+
1812
+ .. figure:: ../../media/prefix-tree-graphs-4.png
1813
+
1814
+ Figure: The generation tree of simple graphs with `4` vertices.
1815
+
1816
+ In what sense is this algorithm generic? Consider for example planar
1817
+ graphs (graphs which can be drawn in the plane without edges crossing):
1818
+ by removing an edge from a planar graph, one obtains another planar
1819
+ graph; so planar graphs form a subtree of the previous tree. To generate
1820
+ them, exactly the same algorithm can be used,
1821
+ selecting only the children which are planar::
1822
+
1823
+ sage: [len(list(graphs(n, property=lambda G: G.is_planar()))) # needs planarity
1824
+ ....: for n in range(7)]
1825
+ [1, 1, 2, 4, 11, 33, 142]
1826
+
1827
+ In a similar fashion, one can generate any family of graphs closed
1828
+ under deletion of an edge, and in particular any family characterized
1829
+ by a forbidden subgraph. This includes for example forests (graphs
1830
+ without cycles), bipartite graphs (graphs without odd cycles),
1831
+ etc. This can be applied to generate:
1832
+
1833
+ - partial orders, via the bijection with Hasse diagrams which are
1834
+ oriented graphs without cycles and without edges implied by the
1835
+ transitivity of the order relation;
1836
+
1837
+ - lattices (not implemented in ``Sage``), via the bijection with the
1838
+ meet semi-lattice obtained by deleting the maximal vertex; in this
1839
+ case an augmentation by vertices rather than by edges is used.
1840
+
1841
+ REFERENCES:
1842
+
1843
+ .. [CMS2012] Alexandre Casamayou, Nathann Cohen, Guillaume Connan, Thierry
1844
+ Dumont, Laurent Fousse, François Maltey, Matthias Meulien, Marc Mezzarobba,
1845
+ Clément Pernet, Nicolas M. Thiéry, Paul Zimmermann *Calcul Mathématique avec
1846
+ Sage* https://www.sagemath.org/sagebook/french.html
1847
+
1848
+ .. [1]
1849
+ Or at least that should be the case; there are still many corners to
1850
+ clean up.
1851
+
1852
+ .. [2]
1853
+ In practice, an efficient implementation would exploit the symmetries
1854
+ of `G`, i.e., its automorphism group, to reduce the number of
1855
+ children to explore, and to reduce the cost of each test of
1856
+ canonicity.
1857
+ """