schubmult 5.1.0__tar.gz → 5.2.0__tar.gz

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 (498) hide show
  1. schubmult-5.2.0/CHANGELOG.md +481 -0
  2. schubmult-5.2.0/PKG-INFO +234 -0
  3. {schubmult-5.1.0 → schubmult-5.2.0}/README.md +29 -1
  4. schubmult-5.2.0/benchmark_equivcalc.py +164 -0
  5. schubmult-5.2.0/benchmark_qk_kato.py +165 -0
  6. schubmult-5.2.0/benchmark_schubmult.py +218 -0
  7. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/kernel_double.h +39 -15
  8. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/kernel_q_double.h +133 -44
  9. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/kernel_single.h +8 -1
  10. schubmult-5.2.0/cpp/kernel_transition.h +299 -0
  11. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schub_symbolic.h +67 -0
  12. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schubmult_api.h +30 -6
  13. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schubmult_module.cpp +44 -10
  14. {schubmult-5.1.0 → schubmult-5.2.0}/docs/API.md +3527 -312
  15. schubmult-5.2.0/docs/index.md +179 -0
  16. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/README.md +10 -0
  17. schubmult-5.2.0/docs/modules/schubmult/_scripts/grothmult_double.md +50 -0
  18. schubmult-5.2.0/docs/modules/schubmult/_scripts/grothmult_py.md +28 -0
  19. schubmult-5.2.0/docs/modules/schubmult/_scripts/grothmult_q.md +31 -0
  20. schubmult-5.2.0/docs/modules/schubmult/_scripts/grothmult_q_double.md +32 -0
  21. schubmult-5.2.0/docs/modules/schubmult/_scripts/schubmult_double.md +32 -0
  22. schubmult-5.2.0/docs/modules/schubmult/_scripts/schubmult_py.md +29 -0
  23. schubmult-5.2.0/docs/modules/schubmult/_scripts/schubmult_q.md +32 -0
  24. schubmult-5.2.0/docs/modules/schubmult/_scripts/schubmult_q_double.md +37 -0
  25. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/permutation.md +1 -1
  26. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/groth_double.md +108 -1
  27. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/index.md +1 -0
  28. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/positivity.md +10 -0
  29. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/quantum_double.md +7 -1
  30. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/single.md +1 -1
  31. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/base_ring.md +18 -0
  32. schubmult-5.2.0/docs/modules/schubmult/rings/free_algebra/elementary_basis.md +133 -0
  33. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/monomial_slide_basis.md +11 -0
  34. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/schubert_basis.md +2 -2
  35. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/_core.md +0 -10
  36. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/elem_sym_poly_basis.md +22 -0
  37. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/grothendieck_poly_basis.md +1 -1
  38. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/monomial_slide_poly_basis.md +11 -0
  39. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/printing.md +11 -8
  40. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/base_schubert_ring.md +10 -10
  41. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/double_schubert_ring.md +22 -0
  42. schubmult-5.2.0/docs/modules/schubmult/sage/_common.md +144 -0
  43. schubmult-5.2.0/docs/modules/schubmult/sage/_convert.md +81 -0
  44. schubmult-5.2.0/docs/modules/schubmult/sage/double_schubert.md +337 -0
  45. schubmult-5.2.0/docs/modules/schubmult/sage/grothendieck.md +328 -0
  46. schubmult-5.2.0/docs/modules/schubmult/sage/index.md +19 -0
  47. schubmult-5.2.0/docs/modules/schubmult/sage/polynomial_algebra.md +438 -0
  48. schubmult-5.2.0/docs/modules/schubmult/sage/quantum_schubert.md +346 -0
  49. schubmult-5.2.0/docs/modules/schubmult/symbolic/domain.md +49 -0
  50. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/functions.md +29 -0
  51. schubmult-5.2.0/docs/modules/schubmult/symbolic/index.md +15 -0
  52. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/poly/schub_poly.md +22 -14
  53. schubmult-5.2.0/docs/modules/schubmult/utils/_lazy.md +28 -0
  54. schubmult-5.2.0/docs/modules/schubmult/utils/_printable.md +11 -0
  55. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/perm_utils.md +84 -28
  56. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/test_utils.md +14 -0
  57. {schubmult-5.1.0 → schubmult-5.2.0}/mkdocs.yml +10 -0
  58. {schubmult-5.1.0 → schubmult-5.2.0}/pyproject.toml +25 -4
  59. {schubmult-5.1.0 → schubmult-5.2.0}/requirements.txt +1 -1
  60. {schubmult-5.1.0 → schubmult-5.2.0}/src/requirements.txt +1 -1
  61. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/__init__.py +6 -1
  62. schubmult-5.2.0/src/schubmult/_scripts/__init__.py +7 -0
  63. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/_scripts/grothmult_double.py +46 -13
  64. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/_scripts/grothmult_py.py +18 -2
  65. schubmult-5.2.0/src/schubmult/_scripts/grothmult_q.py +114 -0
  66. schubmult-5.2.0/src/schubmult/_scripts/grothmult_q_double.py +114 -0
  67. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/_scripts/schubmult_double.py +37 -30
  68. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/_scripts/schubmult_py.py +23 -5
  69. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/_scripts/schubmult_q.py +26 -3
  70. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/_scripts/schubmult_q_double.py +33 -10
  71. schubmult-5.2.0/src/schubmult/_typing.py +46 -0
  72. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/_version.py +3 -3
  73. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/abc.py +14 -1
  74. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/bpd.py +5 -7
  75. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/crystal_graph.py +1 -1
  76. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/double_forest.py +1 -1
  77. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/hpd.py +20 -12
  78. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/increasing_tableau.py +2 -2
  79. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/mbpd.py +1 -1
  80. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/nilplactic.py +2 -2
  81. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/permutation.py +137 -108
  82. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/plactic.py +2 -2
  83. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/rc_graph.py +59 -29
  84. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/root_tableau.py +7 -7
  85. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/wc_graph.py +41 -19
  86. schubmult-5.2.0/src/schubmult/mult/__init__.py +131 -0
  87. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/_accel.py +33 -6
  88. schubmult-5.2.0/src/schubmult/mult/_shadow.py +78 -0
  89. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/double.py +63 -15
  90. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/groth_double.py +647 -61
  91. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/groth_quantum_double.py +145 -43
  92. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/positivity.py +93 -419
  93. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/quantum_double.py +31 -7
  94. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/single.py +17 -8
  95. schubmult-5.2.0/src/schubmult/mult/transition.py +164 -0
  96. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/base_ring.py +23 -0
  97. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/bounded_rc_factor_algebra.py +2 -4
  98. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/bounded_rc_forest_factor_algebra.py +2 -4
  99. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/bounded_wc_factor_algebra.py +165 -60
  100. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/eg_plactic_ring.py +1 -3
  101. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/eg_ring.py +1 -1
  102. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/grass_tensor_algebra.py +3 -5
  103. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/key_rc_ring.py +2 -2
  104. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/plactic_algebra.py +1 -0
  105. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/rc_schubert_ring.py +2 -4
  106. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/_core.py +0 -3
  107. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/composition_schubert_basis.py +2 -2
  108. schubmult-5.2.0/src/schubmult/rings/free_algebra/elementary_basis.py +177 -0
  109. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/monomial_slide_basis.py +5 -0
  110. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/schubert_basis.py +8 -20
  111. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/nsym.py +2 -0
  112. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/_core.py +0 -8
  113. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/base_polynomial_basis.py +2 -2
  114. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/elem_sym_poly_basis.py +19 -5
  115. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/grothendieck_poly_basis.py +5 -7
  116. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/grove_poly_basis.py +2 -2
  117. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/monomial_basis.py +1 -1
  118. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/monomial_slide_poly_basis.py +7 -1
  119. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/schubert_poly_basis.py +24 -31
  120. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/printing.py +80 -12
  121. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/product_ring.py +1 -2
  122. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/quasisymmetric_functions.py +1 -1
  123. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/base_schubert_ring.py +33 -7
  124. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/beta_coxeter.py +3 -2
  125. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/double_grothendieck_ring.py +11 -8
  126. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/double_schubert_ring.py +37 -1
  127. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/nil_hecke.py +3 -2
  128. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/parabolic_quantum_double_schubert_ring.py +4 -1
  129. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/quantum_double_schubert_ring.py +12 -1
  130. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/schubert_ring.py +3 -1
  131. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/tensor_ring.py +1 -3
  132. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/thompson_algebra.py +3 -3
  133. schubmult-5.2.0/src/schubmult/sage/__init__.py +34 -0
  134. schubmult-5.2.0/src/schubmult/sage/_common.py +451 -0
  135. schubmult-5.2.0/src/schubmult/sage/_convert.py +271 -0
  136. schubmult-5.2.0/src/schubmult/sage/double_schubert.py +332 -0
  137. schubmult-5.2.0/src/schubmult/sage/grothendieck.py +342 -0
  138. schubmult-5.2.0/src/schubmult/sage/polynomial_algebra.py +788 -0
  139. schubmult-5.2.0/src/schubmult/sage/quantum_schubert.py +359 -0
  140. schubmult-5.2.0/src/schubmult/sage/symengine_ring.py +508 -0
  141. schubmult-5.2.0/src/schubmult/symbolic/__init__.py +64 -0
  142. schubmult-5.2.0/src/schubmult/symbolic/domain.py +59 -0
  143. schubmult-5.2.0/src/schubmult/symbolic/functions.py +118 -0
  144. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/poly/schub_poly.py +60 -20
  145. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/poly/variables.py +104 -54
  146. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/_grid_print.py +1 -1
  147. schubmult-5.2.0/src/schubmult/utils/_lazy.py +46 -0
  148. schubmult-5.2.0/src/schubmult/utils/_printable.py +33 -0
  149. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/argparse.py +29 -9
  150. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/parsing.py +1 -1
  151. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/perm_utils.py +122 -49
  152. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/schub_lib.py +1 -1
  153. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/test_utils.py +21 -0
  154. schubmult-5.2.0/src/schubmult.egg-info/PKG-INFO +234 -0
  155. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult.egg-info/SOURCES.txt +39 -5
  156. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult.egg-info/requires.txt +6 -1
  157. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult.egg-info/scm_file_list.json +72 -4
  158. schubmult-5.2.0/src/schubmult.egg-info/scm_version.json +8 -0
  159. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_double.py +60 -0
  160. schubmult-5.2.0/tests/mult/test_groth_double.py +383 -0
  161. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_groth_quantum_double.py +1 -1
  162. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_positivity.py +34 -0
  163. schubmult-5.2.0/tests/mult/test_probabilistic.py +180 -0
  164. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_quantum_double.py +34 -1
  165. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_separated_descents.py +3 -4
  166. schubmult-5.2.0/tests/mult/test_transition.py +95 -0
  167. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_combinatorial.py +65 -1
  168. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_duality.py +58 -12
  169. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_free_algebra.py +49 -36
  170. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_parabolic_quantum_ring.py +17 -0
  171. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_polynomial_algebra.py +115 -3
  172. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_schubert_rings.py +136 -4
  173. schubmult-5.2.0/tests/sage/test_polynomial_algebra.py +257 -0
  174. schubmult-5.2.0/tests/sage/test_sage_rings.py +372 -0
  175. schubmult-5.2.0/tests/scripts/data/schubmult_double/schubmult_double_3_6_1_5_2_4T2_3_5_4_1_6_mixed-var_display-positive.json +50 -0
  176. schubmult-5.2.0/tests/scripts/data/schubmult_double/schubmult_double_code_3_0_3T2_1_0_2_display-positive.json +40 -0
  177. schubmult-5.2.0/tests/scripts/data/schubmult_double/schubmult_double_coprod_3_6_1_5_2_4T2_4_display-positive_mixed-var.json +43 -0
  178. schubmult-5.2.0/tests/scripts/data/schubmult_q_double/schubmult_q_double_code_1_0_3T2_0_2_mixed-var_display-positive.json +42 -0
  179. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_grothmult_q.py +34 -3
  180. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_grothmult_q_double.py +25 -1
  181. {schubmult-5.1.0 → schubmult-5.2.0}/tests/test_api_surface.py +37 -0
  182. schubmult-5.2.0/tests/utils/test_perm_utils.py +92 -0
  183. schubmult-5.2.0/tests/web/test_download_limits.py +160 -0
  184. schubmult-5.1.0/CHANGELOG.md +0 -171
  185. schubmult-5.1.0/PKG-INFO +0 -876
  186. schubmult-5.1.0/docs/index.md +0 -27
  187. schubmult-5.1.0/docs/modules/schubmult/_scripts/grothmult_double.md +0 -23
  188. schubmult-5.1.0/docs/modules/schubmult/_scripts/grothmult_py.md +0 -4
  189. schubmult-5.1.0/docs/modules/schubmult/_scripts/grothmult_q.md +0 -4
  190. schubmult-5.1.0/docs/modules/schubmult/_scripts/grothmult_q_double.md +0 -4
  191. schubmult-5.1.0/docs/modules/schubmult/_scripts/schubmult_double.md +0 -4
  192. schubmult-5.1.0/docs/modules/schubmult/_scripts/schubmult_py.md +0 -4
  193. schubmult-5.1.0/docs/modules/schubmult/_scripts/schubmult_q.md +0 -4
  194. schubmult-5.1.0/docs/modules/schubmult/_scripts/schubmult_q_double.md +0 -4
  195. schubmult-5.1.0/docs/modules/schubmult/rings/free_algebra/elementary_basis.md +0 -76
  196. schubmult-5.1.0/docs/modules/schubmult/symbolic/index.md +0 -13
  197. schubmult-5.1.0/src/schubmult/_scripts/__init__.py +0 -1
  198. schubmult-5.1.0/src/schubmult/_scripts/grothmult_q.py +0 -64
  199. schubmult-5.1.0/src/schubmult/_scripts/grothmult_q_double.py +0 -77
  200. schubmult-5.1.0/src/schubmult/mult/__init__.py +0 -89
  201. schubmult-5.1.0/src/schubmult/rings/free_algebra/elementary_basis.py +0 -81
  202. schubmult-5.1.0/src/schubmult/symbolic/__init__.py +0 -27
  203. schubmult-5.1.0/src/schubmult/symbolic/functions.py +0 -45
  204. schubmult-5.1.0/src/schubmult.egg-info/PKG-INFO +0 -876
  205. schubmult-5.1.0/src/schubmult.egg-info/scm_version.json +0 -8
  206. schubmult-5.1.0/tests/mult/test_groth_double.py +0 -104
  207. schubmult-5.1.0/tests/scripts/data/schubmult_double/schubmult_double_3_7_1_6_2_5_4T2_3_5_4_1_7_6_mixed-var_display-positive.json +0 -54
  208. schubmult-5.1.0/tests/scripts/data/schubmult_double/schubmult_double_code_3_0_5T2_1_0_4_display-positive.json +0 -40
  209. schubmult-5.1.0/tests/scripts/data/schubmult_double/schubmult_double_coprod_3_7_1_6_2_5_4T2_4_6_display-positive_mixed-var.json +0 -47
  210. schubmult-5.1.0/tests/scripts/data/schubmult_q_double/schubmult_q_double_code_2_0_5T3_0_2_mixed-var_display-positive.json +0 -42
  211. {schubmult-5.1.0 → schubmult-5.2.0}/LICENSE +0 -0
  212. {schubmult-5.1.0 → schubmult-5.2.0}/MANIFEST.in +0 -0
  213. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/Makefile +0 -0
  214. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/compare.py +0 -0
  215. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/expr.h +0 -0
  216. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/kernel_double_alt.h +0 -0
  217. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/kernel_q.h +0 -0
  218. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/positivity.h +0 -0
  219. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schub_common.h +0 -0
  220. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schub_quantum.h +0 -0
  221. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schubmult_core.cpp +0 -0
  222. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schubmult_double_core.cpp +0 -0
  223. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schubmult_q_core.cpp +0 -0
  224. {schubmult-5.1.0 → schubmult-5.2.0}/cpp/schubmult_q_double_core.cpp +0 -0
  225. {schubmult-5.1.0 → schubmult-5.2.0}/docs/README.md +0 -0
  226. {schubmult-5.1.0 → schubmult-5.2.0}/docs/generate_docs.py +0 -0
  227. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/_scripts/index.md +0 -0
  228. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/abc.md +0 -0
  229. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/anti_rc_graph.md +0 -0
  230. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/bpd.md +0 -0
  231. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/chute_move_element.md +0 -0
  232. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/crystal_graph.md +0 -0
  233. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/double_forest.md +0 -0
  234. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/hecke_plactic.md +0 -0
  235. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/hpd.md +0 -0
  236. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/increasing_tableau.md +0 -0
  237. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/index.md +0 -0
  238. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/indexed_forests.md +0 -0
  239. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/inversions_tableau.md +0 -0
  240. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/mbpd.md +0 -0
  241. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/nilplactic.md +0 -0
  242. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/pipe_dream.md +0 -0
  243. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/plactic.md +0 -0
  244. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/planar_history.md +0 -0
  245. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/quasi_crystal_graph.md +0 -0
  246. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/rc_graph.md +0 -0
  247. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/root_tableau.md +0 -0
  248. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/schub_poly.md +0 -0
  249. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/schubert_monomial_graph.md +0 -0
  250. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/set_valued_tableau.md +0 -0
  251. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/set_word.md +0 -0
  252. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/combinatorics/wc_graph.md +0 -0
  253. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/index.md +0 -0
  254. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/_accel.md +0 -0
  255. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/double.md +0 -0
  256. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/groth.md +0 -0
  257. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/groth_quantum.md +0 -0
  258. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/groth_quantum_double.md +0 -0
  259. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/quantum.md +0 -0
  260. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/mult/separated_descents.md +0 -0
  261. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/alt_rc_graph_ring.md +0 -0
  262. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/bounded_rc_factor_algebra.md +0 -0
  263. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/bounded_rc_forest_factor_algebra.md +0 -0
  264. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/bounded_wc_factor_algebra.md +0 -0
  265. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/bpd_ring.md +0 -0
  266. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/chute_move_ring.md +0 -0
  267. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/crystal_graph_ring.md +0 -0
  268. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/dual_rc_graph_ring.md +0 -0
  269. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/eg_plactic_ring.md +0 -0
  270. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/eg_ring.md +0 -0
  271. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/forest_invariant_rc_ring.md +0 -0
  272. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/forest_rc_ring.md +0 -0
  273. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/grass_tensor_algebra.md +0 -0
  274. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/grove_wc_ring.md +0 -0
  275. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/hw_rc_ring.md +0 -0
  276. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/index.md +0 -0
  277. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/key_rc_ring.md +0 -0
  278. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/plactic_algebra.md +0 -0
  279. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/qy_rc_graph_ring.md +0 -0
  280. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/rc_graph_ring.md +0 -0
  281. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/rc_schubert_ring.md +0 -0
  282. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/schubert_monomial_ring.md +0 -0
  283. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/schubert_rc_ring.md +0 -0
  284. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/slide_rc_ring.md +0 -0
  285. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/combinatorial/wc_graph_ring.md +0 -0
  286. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/direct_product_ring.md +0 -0
  287. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/_core.md +0 -0
  288. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/composition_schubert_basis.md +0 -0
  289. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/forest_basis.md +0 -0
  290. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/free_algebra_basis.md +0 -0
  291. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/fundamental_slide_basis.md +0 -0
  292. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/glide_basis.md +0 -0
  293. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/grothendieck_basis.md +0 -0
  294. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/grove_basis.md +0 -0
  295. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/index.md +0 -0
  296. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/j_basis.md +0 -0
  297. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/jt_basis.md +0 -0
  298. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/key_basis.md +0 -0
  299. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/lascoux_basis.md +0 -0
  300. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/nelementary_basis.md +0 -0
  301. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/schubert_schur_basis.md +0 -0
  302. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/schur_elementary_basis.md +0 -0
  303. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/separated_descents_basis.md +0 -0
  304. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/word_basis.md +0 -0
  305. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/free_algebra/z_basis.md +0 -0
  306. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/index.md +0 -0
  307. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/nsym.md +0 -0
  308. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/anti_schubert_poly_basis.md +0 -0
  309. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/base_polynomial_basis.md +0 -0
  310. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/composition_schubert_poly_basis.md +0 -0
  311. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/double_forest_poly_basis.md +0 -0
  312. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/forest_poly_basis.md +0 -0
  313. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/fundamental_slide_poly_basis.md +0 -0
  314. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/glide_poly_basis.md +0 -0
  315. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/grove_poly_basis.md +0 -0
  316. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/index.md +0 -0
  317. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/key_poly_basis.md +0 -0
  318. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/lascoux_poly_basis.md +0 -0
  319. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/monomial_basis.md +0 -0
  320. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/polynomial_basis.md +0 -0
  321. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/schubert_poly_basis.md +0 -0
  322. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/polynomial_algebra/sepdesc_poly_basis.md +0 -0
  323. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/product_ring.md +0 -0
  324. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/quasisymmetric_functions.md +0 -0
  325. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/beta_coxeter.md +0 -0
  326. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/chevalley.md +0 -0
  327. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/double_grothendieck_ring.md +0 -0
  328. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/grothendieck_ring.md +0 -0
  329. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/index.md +0 -0
  330. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/nil_hecke.md +0 -0
  331. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/parabolic_quantum_double_schubert_ring.md +0 -0
  332. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/parabolic_quantum_schubert_ring.md +0 -0
  333. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/quantum_double_schubert_ring.md +0 -0
  334. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/quantum_schubert_ring.md +0 -0
  335. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/schubert_ring.md +0 -0
  336. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/schubert/separated_descents.md +0 -0
  337. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/tensor_ring.md +0 -0
  338. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/rings/thompson_algebra.md +0 -0
  339. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/common_polys.md +0 -0
  340. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/poly/index.md +0 -0
  341. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/poly/variables.md +0 -0
  342. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/symmetric_polynomials/complete_sym.md +0 -0
  343. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/symmetric_polynomials/elem_sym.md +0 -0
  344. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/symmetric_polynomials/functions.md +0 -0
  345. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/symmetric_polynomials/index.md +0 -0
  346. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/symbolic/symmetric_polynomials/qelem_sym.md +0 -0
  347. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/_grid_print.md +0 -0
  348. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/_mul_utils.md +0 -0
  349. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/argparse.md +0 -0
  350. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/index.md +0 -0
  351. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/logging.md +0 -0
  352. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/parsing.md +0 -0
  353. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/schub_lib.md +0 -0
  354. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/utils/tuple_utils.md +0 -0
  355. {schubmult-5.1.0 → schubmult-5.2.0}/docs/modules/schubmult/visualization.md +0 -0
  356. {schubmult-5.1.0 → schubmult-5.2.0}/images/algostick.png +0 -0
  357. {schubmult-5.1.0 → schubmult-5.2.0}/images/figure.png +0 -0
  358. {schubmult-5.1.0 → schubmult-5.2.0}/setup.cfg +0 -0
  359. {schubmult-5.1.0 → schubmult-5.2.0}/setup.py +0 -0
  360. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/__init__.py +0 -0
  361. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/anti_rc_graph.py +0 -0
  362. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/chute_move_element.py +0 -0
  363. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/hecke_plactic.py +0 -0
  364. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/indexed_forests.py +0 -0
  365. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/inversions_tableau.py +0 -0
  366. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/pipe_dream.py +0 -0
  367. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/planar_history.py +0 -0
  368. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/quasi_crystal_graph.py +0 -0
  369. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/schub_poly.py +0 -0
  370. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/schubert_monomial_graph.py +0 -0
  371. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/set_valued_tableau.py +0 -0
  372. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/combinatorics/set_word.py +0 -0
  373. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/groth.py +0 -0
  374. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/groth_quantum.py +0 -0
  375. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/quantum.py +0 -0
  376. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/mult/separated_descents.py +0 -0
  377. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/__init__.py +0 -0
  378. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/__init__.py +0 -0
  379. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/alt_rc_graph_ring.py +0 -0
  380. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/bpd_ring.py +0 -0
  381. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/chute_move_ring.py +0 -0
  382. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/crystal_graph_ring.py +0 -0
  383. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/dual_rc_graph_ring.py +0 -0
  384. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/forest_invariant_rc_ring.py +0 -0
  385. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/forest_rc_ring.py +0 -0
  386. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/grove_wc_ring.py +0 -0
  387. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/hw_rc_ring.py +0 -0
  388. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/qy_rc_graph_ring.py +0 -0
  389. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/rc_graph_ring.py +0 -0
  390. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/schubert_monomial_ring.py +0 -0
  391. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/schubert_rc_ring.py +0 -0
  392. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/slide_rc_ring.py +0 -0
  393. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/combinatorial/wc_graph_ring.py +0 -0
  394. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/direct_product_ring.py +0 -0
  395. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/__init__.py +0 -0
  396. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/forest_basis.py +0 -0
  397. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/free_algebra_basis.py +0 -0
  398. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/fundamental_slide_basis.py +0 -0
  399. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/glide_basis.py +0 -0
  400. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/grothendieck_basis.py +0 -0
  401. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/grove_basis.py +0 -0
  402. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/j_basis.py +0 -0
  403. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/jt_basis.py +0 -0
  404. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/key_basis.py +0 -0
  405. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/lascoux_basis.py +0 -0
  406. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/nelementary_basis.py +0 -0
  407. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/schubert_schur_basis.py +0 -0
  408. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/schur_elementary_basis.py +0 -0
  409. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/separated_descents_basis.py +0 -0
  410. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/word_basis.py +0 -0
  411. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/free_algebra/z_basis.py +0 -0
  412. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/__init__.py +0 -0
  413. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/anti_schubert_poly_basis.py +0 -0
  414. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/composition_schubert_poly_basis.py +0 -0
  415. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/double_forest_poly_basis.py +0 -0
  416. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/forest_poly_basis.py +0 -0
  417. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/fundamental_slide_poly_basis.py +0 -0
  418. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/glide_poly_basis.py +0 -0
  419. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/key_poly_basis.py +0 -0
  420. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/lascoux_poly_basis.py +0 -0
  421. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/polynomial_basis.py +0 -0
  422. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/polynomial_algebra/sepdesc_poly_basis.py +0 -0
  423. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/__init__.py +0 -0
  424. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/chevalley.py +0 -0
  425. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/grothendieck_ring.py +0 -0
  426. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/parabolic_quantum_schubert_ring.py +0 -0
  427. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/quantum_schubert_ring.py +0 -0
  428. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/rings/schubert/separated_descents.py +0 -0
  429. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/common_polys.py +0 -0
  430. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/poly/__init__.py +0 -0
  431. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/symmetric_polynomials/__init__.py +0 -0
  432. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/symmetric_polynomials/complete_sym.py +0 -0
  433. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/symmetric_polynomials/elem_sym.py +0 -0
  434. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/symmetric_polynomials/functions.py +0 -0
  435. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/symbolic/symmetric_polynomials/qelem_sym.py +0 -0
  436. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/__init__.py +0 -0
  437. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/_mul_utils.py +0 -0
  438. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/logging.py +0 -0
  439. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/utils/tuple_utils.py +0 -0
  440. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult/visualization.py +0 -0
  441. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult.egg-info/dependency_links.txt +0 -0
  442. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult.egg-info/entry_points.txt +0 -0
  443. {schubmult-5.1.0 → schubmult-5.2.0}/src/schubmult.egg-info/top_level.txt +0 -0
  444. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_anti_rc_graph.py +0 -0
  445. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_bpd.py +0 -0
  446. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_indexed_forests.py +0 -0
  447. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_inversions_tableau.py +0 -0
  448. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_mbpd.py +0 -0
  449. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_nilplactic.py +0 -0
  450. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_permutation_order.py +0 -0
  451. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_pipe_dream.py +0 -0
  452. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_rc_graph.py +0 -0
  453. {schubmult-5.1.0 → schubmult-5.2.0}/tests/combinatorics/test_wc_graph.py +0 -0
  454. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_accel.py +0 -0
  455. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_groth.py +0 -0
  456. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_groth_quantum.py +0 -0
  457. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_quantum.py +0 -0
  458. {schubmult-5.1.0 → schubmult-5.2.0}/tests/mult/test_single.py +0 -0
  459. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_forest_rc_ring.py +0 -0
  460. {schubmult-5.1.0 → schubmult-5.2.0}/tests/rings/test_public_imports.py +0 -0
  461. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/_cmd_line_json.py +0 -0
  462. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_double/grothmult_double_1_3_2T2_1_3_mixed-var.json +0 -0
  463. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_double/grothmult_double_1_3_2T2_1_3_mixed-var_display-positive.json +0 -0
  464. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_double/grothmult_double_2_1_3T2_1_3.json +0 -0
  465. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_double/grothmult_double_code_1_1T0_1T1.json +0 -0
  466. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_double/grothmult_double_code_2_0_1T1_1_mixed-var.json +0 -0
  467. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_double/grothmult_double_display-mode_raw_2_1_4_3T1_3_2_mixed-var.json +0 -0
  468. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_py/grothmult_py_1_3_2T1_3_2T2_1_3.json +0 -0
  469. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_py/grothmult_py_2_1_4_3T1_3_2.json +0 -0
  470. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_py/grothmult_py_3_1_2T2_1_3.json +0 -0
  471. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_py/grothmult_py_code_1_0_1T0_1.json +0 -0
  472. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_py/grothmult_py_display-mode_raw_3_1_2T1_3_2.json +0 -0
  473. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q/grothmult_q_1_3_2T1_3_2T2_1_3.json +0 -0
  474. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q/grothmult_q_2_1T2_1.json +0 -0
  475. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q/grothmult_q_2_3_1T3_1_2.json +0 -0
  476. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q/grothmult_q_code_0_2T1_1.json +0 -0
  477. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q/grothmult_q_code_1_1T2_0.json +0 -0
  478. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q/grothmult_q_display-mode_raw_3_1_2T1_3_2.json +0 -0
  479. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q_double/grothmult_q_double_1_3_2T2_1_3_mixed-var.json +0 -0
  480. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q_double/grothmult_q_double_2_1T2_1.json +0 -0
  481. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q_double/grothmult_q_double_2_1T2_1_mixed-var.json +0 -0
  482. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q_double/grothmult_q_double_code_1_0T1_0T1_0.json +0 -0
  483. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q_double/grothmult_q_double_code_1_1T0_1_mixed-var.json +0 -0
  484. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/grothmult_q_double/grothmult_q_double_display-mode_raw_2_3_1T1_3_2_mixed-var.json +0 -0
  485. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_double/schubmult_double_code_coprod_5_0_1_2T2_3_display-positive.json +0 -0
  486. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_double/schubmult_double_mixed-var_display-positive_coprod_code_1_0_2_0_1T2_4.json +0 -0
  487. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_py/schubmult_py_code_5_0_3_1_2T1_0_3_2_0_5.json +0 -0
  488. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_q/schubmult_q_code_2_0_5T3_0_2.json +0 -0
  489. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_q/schubmult_q_parabolic_2_3_code_1_2T1_3.json +0 -0
  490. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_q_double/schubmult_q_double_code_2_0_5T3_0_2.json +0 -0
  491. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_q_double/schubmult_q_double_code_2_0_5T3_0_2_display-positive.json +0 -0
  492. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/data/schubmult_q_double/schubmult_q_double_parabolic_2_3_code_1_2T1_3_display-positive.json +0 -0
  493. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_grothmult_double.py +0 -0
  494. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_grothmult_py.py +0 -0
  495. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_schubmult_double.py +0 -0
  496. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_schubmult_py.py +0 -0
  497. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_schubmult_q.py +0 -0
  498. {schubmult-5.1.0 → schubmult-5.2.0}/tests/scripts/test_schubmult_q_double.py +0 -0
@@ -0,0 +1,481 @@
1
+ # Changelog
2
+
3
+ ## 5.2.0
4
+
5
+ Final release of 5.2.0, including the changes in 5.2.0b2 and 5.2.0b3.
6
+
7
+ ### Added
8
+
9
+ - **Skew divided differences and the block lift**, after Byung-Hak Hwang, *Coefficient lifting for skew
10
+ divided differences and triple Schubert coefficients* (arXiv:2610.21053). `DoubleSchubertElement.skew_divdiff(w, v)`
11
+ applies Macdonald's skew divided difference $\partial_{w/v}$ (Gao--Xiong normalization, characterized by
12
+ $\partial_w(fg)=\sum_v(\partial_{w/v}f)(\partial_v g)$) to a `DSx`/`Sx` element, using Samuel's identity
13
+ $\partial_{w/v}\mathfrak S_u(x;y)=c^w_{u,v}(y,x)$ so that each basis term is one `schubmult_double` call;
14
+ `schubmult.symbolic.poly.schub_poly.skew_div_diff` applies $\partial_{w/v}$ to an arbitrary polynomial by
15
+ the recurrence $\partial_{s_iw'/v}=\partial_i\partial_{w'/v}+s_i\partial_{w'/s_iv}$.
16
+ `schubmult.utils.perm_utils.block_lift(u, v, w, alpha)` builds the triple
17
+ $(\widetilde u_\alpha,\widetilde v_\alpha,\widetilde w_\alpha)\in S_{n+|\alpha|}$ for which the coefficient
18
+ of $t^\alpha$ in the triple Schubert coefficient $c^w_{u,v}(y,t)$ (`schubmult_double({v: 1}, u, t, y)[w]`)
19
+ is the single coefficient $c^{\widetilde w_\alpha}_{\widetilde u_\alpha,\widetilde v_\alpha}(y,0)$; at
20
+ $y=0$ this realizes every coefficient of $\partial_{w/v}\mathfrak S_u(x)$ (Kirillov's conjecture), and in
21
+ particular every coefficient of $\mathfrak S_u(x)$, as an ordinary structure constant. The identity is
22
+ verified against `schubmult_double` on all of $S_3$ and the paper's running example in the test suite,
23
+ giving the double kernel a rank-mixing consistency check it did not have before.
24
+
25
+ ### Changed
26
+
27
+ - CI tests Python 3.15. The wheel workflow builds CPython 3.10-3.14 wheels; cibuildwheel does not
28
+ yet recognize the CPython 3.15 build selector.
29
+
30
+ ### Fixed
31
+
32
+ - **`posify` / `q_posify` crashed or returned a wrong expression in the one-dominates recursion**
33
+ (`schubmult_q_double --mixed-var --display-positive`, `schubmult.mult.positivity.posify`). When
34
+ $u$ one-dominates $w$, `posify` strips the first row and recurses on $(\phi_1 u, v', \phi_1 w)$
35
+ over the shifted alphabet $y_2, y_3, \ldots$, passed as a plain tuple. Two bugs met there: the
36
+ reduced coefficient was still computed in the unshifted alphabet, so any recursion that bottomed
37
+ out in the integer program returned $c(y_1, y_2, \ldots)$ instead of $c(y_2, y_3, \ldots)$; and
38
+ `compute_positive_rep` used `tuple.index`, which raises on the $z$ variables where
39
+ `GeneratingSet.index` returns `-1`. Hit for instance by $u=2431$, $v=1432$, $w=34512$, where
40
+ `schubmult_q_double 2 4 3 1 - 1 4 3 2 --mixed-var --display-positive` died with a bare
41
+ `Exception`. The reduced coefficient is now computed in the shifted alphabet and
42
+ `compute_positive_rep` accepts plain sequences. `posify` and `q_posify` now reconstruct every
43
+ structure constant on all of $S_4$ (5,558 classical and 11,422 quantum coefficients), and both
44
+ are covered by direct unit tests.
45
+
46
+ ## 5.2.0b2
47
+
48
+ Pre-release of 5.2.0: SageMath integration (`schubmult.sage`), a correctness fix for parabolic
49
+ quantum products with trailing size-1 blocks, and much faster `ElementaryBasis` transitions. Since
50
+ 5.2.0b1: parabolic quantum Grothendieck products, a manifestly positive expansion of double
51
+ Grothendieck polynomials in double Schubert polynomials, a transition + Monk kernel (lrcalc's
52
+ algorithm) with a cost-model hybrid, probabilistic zero testing for the double and quantum double
53
+ kernels, and fast normalization of double Grothendieck coefficients. Pre-releases install with
54
+ `pip install --pre schubmult`; `pip install schubmult` keeps giving 5.1.1 until 5.2.0 is final.
55
+
56
+ ### Added
57
+
58
+ - **Positive expansion of double Grothendieck polynomials in double Schubert polynomials**
59
+ (`schubmult.mult.groth_double.dgroth_to_dschub_positive`). Writes
60
+ $\mathfrak G_v(x;z)=\sum_w a_{v,w}(\beta,z)\,\mathfrak S_w(x;z)$ with every $a_{v,w}$ in
61
+ $\mathbb N[\beta,z]$, as a sum over triples of pipe dreams with no sign and no change of variables:
62
+ the Fomin--Kirillov Cauchy factorization over Demazure products
63
+ $\mathfrak G_v(x;z)=\sum_{u\,\star\,v'=v}\beta^{\ell(u)+\ell(v')-\ell(v)}\mathfrak G_{u^{-1}}(z)\mathfrak G_{v'}(x)$,
64
+ then Lenart's integer expansion of $\mathfrak G_{v'}(x)$ in Schubert polynomials
65
+ (`WCGraph.groth_to_schub`), then $\mathfrak S_{u'}(x)=\sum_{u'=aw}\mathfrak S_a(z)\mathfrak S_w(x;z)$.
66
+ Agrees with the exact divided-difference expansion `dgroth_to_dschub` on all of $S_4$ and samples
67
+ in $S_5$. Also new, and conjectural: `dgroth_positive_phantom_expansion` (the sign-normalized
68
+ staircase phantom expansion in the formal-inverse alphabet, with positivity checked at every step
69
+ and a `ValueError` on failure) and `dgroth_copipe_expansion`, an unsigned reduced-pipe-dream /
70
+ co-pipe-dream formula for the same coefficients, verified against the recurrence for every
71
+ permutation in $S_6$. These are small-rank research routines, not multiplication kernels.
72
+ - **Parabolic quantum Grothendieck products.** `grothmult_q` and `grothmult_q_double` accept
73
+ `--parabolic g1 g2 ...` (block sizes) and return the product in $QK(G/P)$ resp. $QK_T(G/P)$ for the
74
+ partial flag variety $Fl(g_1, g_1+g_2, \ldots; n)$; inputs must be minimal coset representatives.
75
+ Uses Kato's ring homomorphism $QK_T(G/B)\twoheadrightarrow QK_T(G/P)$,
76
+ $\mathcal O^w\mapsto\mathcal O^{[w]_P}$, $Q_j\mapsto 1$ for $j\in P$ (arXiv:1906.09343, Thm 2.19),
77
+ so unlike `schubmult_q --parabolic` there is no Peterson--Woodward comparison term by term. Exposed
78
+ on the web app too.
79
+ - **Transition + Monk kernel and a cost-model hybrid for single Schubert products**
80
+ (`schubmult.mult.transition`). `schubmult_py_transition` multiplies by expanding one factor into
81
+ monomials with the Lascoux--Schützenberger transition recursion (`transition_monomials`) and
82
+ folding them into the other factor one variable at a time by Monk's rule, as a Horner scheme over
83
+ the Schubert basis -- lrcalc's algorithm. Its cost is driven by the number of pipe dreams
84
+ (`pipe_dream_count`), the v-path kernel's by the number of v-paths, and an exhaustive comparison
85
+ over $S_7$ (all 12.7M unordered pairs) and scaling families to $S_{12}$ showed each is faster by
86
+ large factors where the other is slow; `schubmult_py_hybrid` picks between them with a cost model
87
+ fitted on that data. Both have C++ implementations in the extension. `schubmult_py` and `Sx` are
88
+ unchanged; the hybrid is opt-in.
89
+ - **Probabilistic zero testing in the double and quantum double kernels**
90
+ (`schubmult_double --probabilistic`, `schubmult_q_double --probabilistic`;
91
+ `DoubleSchubertPolynomialRing(R, probabilistic=True)` in Sage). The layered DP of
92
+ `schubmult_double` has signed terms that cancel: a state whose partial sum is zero as a polynomial
93
+ but not structurally keeps fanning out, and its leaves are output terms with coefficient zero
94
+ (4187 terms returned for a 246-term answer). Partial sums are now shadowed by exact evaluations
95
+ at random integer points (Schwartz--Zippel; `schubmult.mult._shadow`) and dead states are pruned
96
+ as they arise. `X([4,1,6,5,2,3]) * X([8,1,7,6,2,3,5,4])` in Sage went from 11 s to 0.5 s. The
97
+ quantum double kernel keys its states by $q$-monomial, which alone makes the exact path ~18%
98
+ faster; with `--probabilistic` the benchmark `--code 2 0 5 5 0 5 - 3 0 5 0 3 3` halves again
99
+ (33 s / 2.65 GB -> 14.5 s / 0.84 GB). Exposed on the web app as a checkbox.
100
+ - **Unexpanded coefficients in the Sage rings** (`raw_coefficients=True` on
101
+ `DoubleSchubertPolynomialRing`, `GrothendieckPolynomialRing`, ...). Every native Sage polynomial
102
+ ring stores expanded normal forms, and converting the kernels' factored coefficients through
103
+ libsingular dominated the time of large products. With `raw_coefficients=True` the base ring is
104
+ `schubmult.sage.symengine_ring.SymEngineRing`, whose elements are the kernel's SymEngine
105
+ expressions as is; zero testing is probabilistic (`nonzero_mask`, `is_identically_zero`) and
106
+ printing normalizes all coefficients at once with shared subtrees.
107
+ - **`--simplify` on `grothmult_double`, `grothmult_q_double`** (and `schubmult_double`,
108
+ `schubmult_q_double`): normalize the output coefficients. Slower, but the printed result shrinks
109
+ from tens of thousands of characters per coefficient to something readable.
110
+ - **Web app: download results as a file.** A checkbox emits the full result as a file download
111
+ instead of the text box, with its own limit (`SCHUBMULT_MAX_DOWNLOAD_BYTES`, default 100 MB)
112
+ separate from the display limit (`SCHUBMULT_MAX_OUTPUT_BYTES`, default 1 MB), for users who
113
+ actually want a large product rather than a truncated one.
114
+ - **Baseline type hints** (`schubmult._typing`: `PermLike`, `PermCoeffDict`, `Alphabet`, `Expr`,
115
+ `Coeff`) on `Permutation`, `RCGraph`, `WCGraph`, the Grothendieck kernels and the variable
116
+ machinery, checked with mypy on that subset.
117
+ - **`schubmult.sage`: SageMath integration.** Sage parents built on `CombinatorialFreeModule`
118
+ whose arithmetic is delegated to the schubmult kernels, alongside Sage's own
119
+ `SchubertPolynomialRing`:
120
+ - `DoubleSchubertPolynomialRing(R, alphabet='y')` -- double Schubert polynomials
121
+ $\mathfrak S_w(x; y)$ over `R[y, z]`; a ring in another alphabet
122
+ (`DoubleSchubertPolynomialRing(R, 'z')`) coerces in, so `X(u) * Z(v)` is the mixed product
123
+ $\mathfrak S_u(x;y)\,\mathfrak S_v(x;z)$ expanded in the `y`-basis.
124
+ - `QuantumSchubertPolynomialRing(R, parabolic=None)` and
125
+ `QuantumDoubleSchubertPolynomialRing(R, alphabet='y', parabolic=None)` -- quantum and
126
+ quantum double Schubert polynomials over `R[q]` resp. `R[q, y, z]`; `parabolic=(n_1, ..., n_k)`
127
+ gives the partial flag variety with those block sizes, with an implicit unbounded last block
128
+ (basis permutations may have descents exactly at the recorded boundaries and be increasing
129
+ beyond them; products extend by one new block as needed, never by enlarging a recorded one).
130
+ - `GrothendieckPolynomialRing(R)` and `DoubleGrothendieckPolynomialRing(R, alphabet='y')` --
131
+ $\beta$-Grothendieck polynomials $\mathfrak G^\beta_w(x)$ over `R[beta]` and their double
132
+ versions $\mathfrak G^\beta_w(x; y)$ (with $x \oplus y = x + y + \beta x y$) over the fraction
133
+ field of `R[beta, y, z]`, where the equivariant K-theoretic structure constants live (denominators
134
+ are products of $1 + \beta y_i$). `beta()` returns the deformation parameter; $\beta = 0$
135
+ recovers the (double) Schubert polynomials. Coefficients of the double ring are reduced
136
+ rational functions computed without any symbolic expansion on the schubmult side (a flat
137
+ numerator / atom-power denominator evaluation in the libsingular ring underneath, one gcd per
138
+ coefficient); a triple product of `S_4` elements with 24 terms and numerators of ~10^4 terms
139
+ takes a few seconds.
140
+ - `PolynomialAlgebra(R)` and `PolynomialAlgebra(R, n)` -- the polynomial ring `R[x0, x1, ...]`
141
+ (resp. in `n` variables) as a Sage parent with realizations (like `SymmetricFunctions`), each
142
+ indexed as in the literature: `schubert()` and `grothendieck()` by permutations (`S[3, 1, 2]`);
143
+ `monomial()`, `key()`, `fundamental_slide()`, `monomial_slide()`, `forest()` and the K-theoretic
144
+ `glide()`, `lascoux()`, `grove()` by weak compositions (`k[2, 0, 1]`); and, in `n` variables only,
145
+ `elementary()` -- products of elementary symmetric polynomials `e_a(x0..x_{j-1})`, whose indexing
146
+ depends on `n`. The K-theoretic bases are at `beta = -1`, the classical convention
147
+ (`G[1, 3, 2].expand()` is `x0 + x1 - x0*x1`); `GrothendieckPolynomialRing` and
148
+ `DoubleGrothendieckPolynomialRing` are unaffected and keep `beta` as a variable of their base ring.
149
+ schubmult's own bases work at `beta = 1` and the
150
+ layer converts through the grading (`P^{-1}_a(x) = (-1)^|a| P^{1}_a(-x)`). All bases coerce into one another through the
151
+ monomial basis, products come from the schubmult bases and Schubert kernels, Sage's
152
+ `SchubertPolynomialRing` and `KeyPolynomials` coerce in, and the elements coerce into the (double,
153
+ quantum, Grothendieck) Schubert rings above. schubmult's own `PolynomialAlgebra` is graded by the
154
+ number of variables (keys of different lengths multiply to zero, the structure dual to the free
155
+ algebra); the Sage parents are the plain polynomial ring and pad keys to a common number of
156
+ variables before calling schubmult.
157
+ - All accept lists/`Permutation`s, Sage polynomials (finite or `InfinitePolynomialRing`), and
158
+ elements of `SchubertPolynomialRing`, `KeyPolynomials` and `AtomPolynomials` (whose variables are
159
+ read as `x`, as Sage's Schubert ring does; these also coerce, so `X(w) + k([1])` works).
160
+ `project(n)` drops the classes that vanish in the flag variety of `C^n` (the rings are stable, so
161
+ a product carries every class of the infinite flag variety; e.g. Buch's equivariant quantum
162
+ `Gr(2, 5)` example is `(QD(u) * QD(v)).project(5)` with `parabolic=(2, 3)`).
163
+ `from_symmetric_function(f, n)` expands a symmetric function in `x0..x{n-1}` (a Schur function
164
+ gives the Grassmannian Schubert polynomial with descent at `n`) and `to_symmetric_function(n=None)`
165
+ reads a symmetric element back as a Schur expansion over the coefficient variables (Grassmannian
166
+ double Schubert polynomials are factorial Schur functions). `expand()` lands in
167
+ `R[x0.., y0.., q0..]`, 0-indexed like Sage; `divided_difference(i)` on the double ring.
168
+ Coefficients are converted at the boundary, so nothing SymEngine-flavoured leaks into the Sage API.
169
+ - Sage is **not** a dependency: the subpackage is inert unless imported, and
170
+ `tests/test_api_surface.py::test_package_is_fully_usable_without_sage` runs the whole package
171
+ with Sage imports blocked. Install schubmult into a Sage environment
172
+ (`sage -pip install schubmult`) to use it; CI runs the Sage doctests in a separate job against
173
+ conda-forge Sage.
174
+ - **`strip_zeros(exact=True)` on every ring element.** The kernels leave coefficients as products of
175
+ factors, and in large products a sizeable fraction of them cancel to zero without looking like it
176
+ (7868 -> 3845 terms for a quantum double product in $S_8$). `strip_zeros()` (now on
177
+ `BaseRingElement`, so available in every ring) still only drops literal zeros; `exact=True` also drops
178
+ coefficients that are zero as polynomials, detected by evaluating them at random integer points in
179
+ exact arithmetic with memoized shared subtrees (`schubmult.symbolic.functions.vanish_at_random_points`)
180
+ -- about 0.7x the cost of the product itself, versus ~10x for expanding the coefficients. Products
181
+ are unchanged: stripping stays opt-in.
182
+
183
+ ### Fixed
184
+
185
+ - **Parabolic quantum products with a trailing size-1 block** (`QPSx(2, 3, 1)`,
186
+ `QPSx(2, 3, 1, 1)`, ...). `apply_peterson_woodward` inferred the ambient flag size from the last
187
+ parabolic generator, and a size-1 block contributes none, so the ambient was taken one block
188
+ short: result permutations of length exactly `sum(blocks)` were dropped (for
189
+ $\sigma_{32}\sigma_1$ with blocks `(2,3,1)` the class $\sigma_{42}$ vanished) and the product no
190
+ longer matched the basis polynomials. `apply_peterson_woodward(..., n=)` now takes the ambient
191
+ size explicitly and the parabolic rings pass `sum(blocks)`. `QPSx(2, 3)`, `(2, 3, 1)`,
192
+ `(2, 3, 2)` and `(2, 3, 1, 1)` now all agree, as they should. The CLI (`--parabolic`), which only
193
+ knows generator indices, is unchanged.
194
+ - **`CompositionSchubertPolyBasis` received `(perm, length)` keys.** Transitions landing in a
195
+ Schubert-type basis (from `MonomialBasis`, `GrothendieckPolyBasis`, and `SchubertPolyBasis` itself)
196
+ handed the target the keys of `SchubertPolyBasis` without normalizing them, so
197
+ `PolynomialAlgebra(CompositionSchubertPolyBasis(x)).from_expr(...)` and every `change_basis` into
198
+ that basis produced elements keyed by permutations instead of Lehmer codes, and any transition out
199
+ of the ring then failed. Keys now go through the target basis's `attach_key`.
200
+
201
+ ### Changed
202
+
203
+ - **Double Grothendieck coefficients are normalized in the multiplicative variables.**
204
+ `DoubleGrothendieckElement.simplify()` ran `sympy.cancel` on the raw kernel output; coefficients
205
+ of one product in $K_T(Fl_5)$ reach ~65k characters unexpanded and took 8--58 s each (274 s for
206
+ `DGx([5,1,3,2,4]) * DGx([2,1,5,4,3])`, 56 terms; a 10-product run was 332 s against 0.2 s for
207
+ Buch's EquivCalc). Cancellation is now done in $t_i = 1+\beta y_i$: every coefficient is a Laurent
208
+ polynomial in the $t_i$, the denominator atoms become monomials, a single expansion collects
209
+ everything and the denominator is read off as the monomial of negative exponents. No gcd is
210
+ computed and nothing is expanded in $y$.
211
+ - **`grothmult_double` keeps its result factored as Grothendieck factorial elementary symmetric
212
+ functions.** The kernel now parallels `schubmult_double` directly -- the v-path's layer factors are
213
+ the $K$-theoretic factorial elementaries `groth_elem_sym_poly` / `groth_elem_sym_func`, with the
214
+ Pieri coefficients in closed form (`_tilde_elem_sym_frac`) -- instead of transitioning
215
+ $\mathfrak G_v$ to the double Schubert basis first and applying the Schubert Pieri rule. The
216
+ quantum double kernel iterates its v-paths top-down for the same reason. `BoundedWCFactorAlgebra`'s
217
+ `full_groth_elem` likewise runs the Grothendieck v-path directly, with each layer factor
218
+ $\tilde E_{p,k}(x;0)=G_{1^p}(x_1..x_k)+\beta\,G_{1^{p+1}}(x_1..x_k)$ as a sum of elementary
219
+ Grothendieck WC graphs (`groth_elem_factor`), rather than approximating with Schubert elementaries.
220
+ - **`positivity.py`** lost years-old, misleading comments and picked up a few small optimizations;
221
+ behaviour of `--display-positive` is unchanged.
222
+ - **`ElementaryBasis` <-> `SchubertBasis` transitions are computed blockwise.** Both directions
223
+ go through the finite `(numvars, degree)` block: every elementary product of that degree is
224
+ expanded in the Schubert basis by the Pieri rule (`ElementaryBasis.schubert_block`, cached), which
225
+ is the Schubert -> Elem matrix, and its inverse is Elem -> Schubert. This replaces
226
+ `Sx.from_expr` on staircase-padded monomial-symmetric polynomials and RC-graph enumeration of
227
+ `S_{perm w0}`; e.g. `FA(2) * FA(2, 1)` in the elementary basis went from 25 s to 0.04 s. Results
228
+ are identical on every key checked ($n \le 3$, degree $\le 4$). `ElementaryBasis.degree_keys`
229
+ and `transition_from_schubert` are new; `ElementaryBasis.staircase` is gone.
230
+ - **Test suite runs in ~1 min instead of ~8.** Slow tests were made cheaper without losing
231
+ coverage: exact zero tests of rational-function identities now evaluate at random rational
232
+ points (`schubmult.utils.test_utils.vanishes`) instead of `sympy.cancel` on huge unsimplified
233
+ differences (90 s -> 0.2 s for the double Grothendieck round trip); the heaviest
234
+ `--display-positive` script fixtures were replaced by same-flag, smaller permutations; a few
235
+ ring examples dropped one degree. CI runs `pytest -n auto` (`pytest-xdist`; `pip install -e
236
+ .[test]` locally) and triggers on pull requests into `develop` as well as `main`.
237
+ - **Integration branch renamed `redevelop` -> `develop`.** Feature branches PR into `develop`;
238
+ `main` only receives final releases from `develop` or a `hotfix/*` branch.
239
+ - **Docs deploy only from final release tags.** The docs workflow no longer runs on pushes to
240
+ `main`; it runs on release tags and refuses `.dev`, local (`+...`), and pre-release
241
+ (`a`/`b`/`rc`) versions, so a pre-release tag publishes wheels but leaves the documentation site
242
+ at the last final release.
243
+
244
+ ## 5.1.1
245
+
246
+ Patch release: compatibility with PuLP 4.0.0, a correctness fix for the elementary basis of
247
+ the free algebra, and a much lighter import footprint (SymPy loads only when needed).
248
+
249
+ ### Fixed
250
+
251
+ - **`--display-positive` under PuLP 4.0.0.** PuLP 4.0.0 (released after 5.1.0) broke
252
+ `compute_positive_rep` and `grothmult_double --display-positive` in several ways:
253
+ `expr == <symengine Integer>` now yields a bare `False` instead of a constraint
254
+ (`TypeError: A False object cannot be passed as a constraint`), `pulp.LpStatus` was removed
255
+ and `LpProblem.solve` returns an `LpSolveStats` object, `LpAffineExpression(dict)` can no
256
+ longer form constraints, and variables become unusable once their `LpProblem` is garbage
257
+ collected. Constraints are now built with `int(...)` right-hand sides and `lpSum`, status is
258
+ read via a helper that accepts both APIs, and variable values are read while the problem is
259
+ alive. The code runs on both PuLP 3.3.x and 4.0; the requirement is
260
+ `PuLP[cbc]>=3.3.2, <4` for now so that a resolver does not pull in 4.x untested.
261
+ - **`ElementaryBasis` / `ElemSymPolyBasis` were not dual.** Keys are `(tup, numvars)` with
262
+ `tup[:numvars-1]` the flag part ($e_{a_i}(x_1..x_i)$) and `tup[numvars-1:]` the symmetric
263
+ tail (a sorted product of $e_k(x_1..x_n)$). `ElementaryBasis.transition_schubert` built its
264
+ staircase from the key's own tail length, so `Elem(key)` only annihilated the `E(key')`
265
+ whose tail fit inside that staircase; e.g. $\langle \mathrm{Elem}((0,2),2),\,
266
+ E((0,1,1),2)\rangle = 1$ ($e_2$ against $e_1^2$). The staircase is now padded uniformly to
267
+ the degree, `SchubertBasis.transition_elementary` uses the same staircase and emits
268
+ canonical keys (zeros stripped from the tail, tail sorted, `(0,)` if empty), and the
269
+ `numvars == 1` slicing bug in `transition_schubert` is gone. `Elem -> Schub -> Elem` is
270
+ now the identity and the delta property holds on every canonical key checked
271
+ ($n \le 4$, degree $\le 4$). `SchubertPolyBasis.transition_elementary` emits the same
272
+ canonical keys.
273
+ - `MonomialSlideBasis` / `MonomialSlidePolyBasis` declare each other as `dual_basis()`;
274
+ `GrovePolyBasis` expands through its monomial basis so `expand()` returns a polynomial;
275
+ `GrothendieckPolyBasis` products go through the `grothmult_py` kernel at $\beta = 1$
276
+ instead of the ring-level route. The polynomial-algebra coproduct is the free-algebra
277
+ product's adjoint again for every declared dual pair.
278
+ - `BaseSchubertRing` defines `__hash__` consistent with its `__eq__` (type and generating
279
+ sets), so rings can be dict keys and cache keys; ring *elements* are explicitly unhashable
280
+ (`__hash__ = None`) since they are mutable dicts.
281
+
282
+ ### Changed
283
+
284
+ - **SymPy is imported lazily.** `schubmult.symbolic` exposes SymPy names as
285
+ `schubmult.utils._lazy.LazyAttr` proxies that resolve on first call, attribute access or
286
+ subclassing; the ring-domain protocol (`EXRAW`, `CoercionFailed`, `Ring`, ...) lives in the
287
+ new SymPy-free `schubmult.symbolic.domain`; ring elements print through
288
+ `schubmult.utils._printable.LazyPrintable` instead of subclassing SymPy's `Printable`;
289
+ `schubmult.mult` and the kernels in `schubmult.mult.single` import SymPy/SymEngine only
290
+ inside the functions that need them. `schubmult_py` with integer output never loads SymPy,
291
+ and the CLI sets `OPENBLAS_NUM_THREADS`/`OMP_NUM_THREADS`/`MKL_NUM_THREADS=1` before
292
+ importing numpy. Import time and CLI start-up drop accordingly; no public names moved.
293
+ - Ring elements print as linear text built from SymEngine's `str` (terms sorted by length
294
+ then permutation) instead of SymPy's pretty printer, which took seconds on large double
295
+ Grothendieck coefficients. `_repr_latex_` is disabled for these elements so notebooks show
296
+ the fast form; call `latex(elem)` or `pretty(elem)` explicitly for the SymPy renderings.
297
+ - The PuLP requirement is `PuLP[cbc]>=3.3.2, <4` (was `PuLP>=2.7.0,<4`). `--display-positive`
298
+ builds variables with `LpProblem.add_variable` and solves with `COIN_CMD` using the CBC
299
+ binary from the `[cbc]` extra (`cbcbox`), replacing `LpVariable(...)` and `PULP_CBC_CMD`.
300
+ - Ruff `UP038` is no longer ignored; `isinstance` checks use `X | Y` unions.
301
+
302
+ ### Added
303
+
304
+ - `benchmark_schubmult.py`: timing harness for the `schubmult_*`/`grothmult_*` kernels.
305
+ - `web/`: a small Flask wrapper exposing the CLI scripts through a web form and
306
+ `POST /api/compute`, embeddable via `<iframe>` (see `web/README.md`, `web/DEPLOY.md`).
307
+ - Tests: `tests/rings/test_duality.py` covers `ElementaryBasis` and `MonomialSlideBasis`,
308
+ includes colliding elementary keys, and checks that the free-algebra product is adjoint to
309
+ the polynomial coproduct (and vice versa) for every dual pair; more polynomial-algebra and
310
+ free-algebra basis round-trip tests in `tests/rings/`.
311
+ - CI runs on pushes to `redevelop` as well as `main`.
312
+
313
+ ## 5.1.0
314
+
315
+ Grothendieck products on the command line and in `schubmult.mult`, including the quantum
316
+ and quantum double cases; the multiplication kernels stop expanding coefficients.
317
+
318
+ ### Added
319
+
320
+ - **`grothmult_py`, `grothmult_double`, `grothmult_q`, `grothmult_q_double` command-line
321
+ scripts.** The README and API reference on GitHub have described the Grothendieck CLI
322
+ since 5.0.0 was tagged, but the 5.0.0 release only shipped `grothmult_py` (via the slow
323
+ ring-expansion route) and `grothmult_double`; `grothmult_q` and `grothmult_q_double` did
324
+ not exist. All four are now installed alongside the `schubmult_*` scripts, accept the
325
+ same options (`--code`, `--display-mode`, `--mixed-var`, `--display-positive` for the
326
+ double case), and have script tests with JSON fixtures.
327
+ - **`schubmult.mult.groth.grothmult_py(perm_dict, v, beta)`**: ordinary
328
+ $\beta$-Grothendieck products in the $G$ basis, computed by expanding $G_v$ into Schubert
329
+ polynomials and pushing each through the theta-code v-path layers with the binomial
330
+ closed form `groth_elem_sym_coeff`. Replaces the ring-level `groth_mul_full_with_ring`
331
+ route in `GrothendieckRing`; typical products are orders of magnitude faster.
332
+ - **`schubmult.mult.groth_quantum.grothmult_q`** and
333
+ **`schubmult.mult.groth_quantum_double.grothmult_q_double`**: quantum and quantum double
334
+ $\beta$-Grothendieck products for the Lenart-Maeno quantization $G^q_v = Q(G_v)$, with
335
+ $Q_j = \beta^2 q_j$ so that $\beta = 0$ recovers the quantum double Schubert polynomials
336
+ and $\beta = -1$ the Lenart-Maeno polynomials representing $QK_T(Fl_n)$. The rule is an
337
+ equivariant quantum $K$-Pieri formula over Naito-Sagaki chains in the quantum Bruhat
338
+ graph, assembled Molev-Sagan style. It is **conjectural**: verified symbolically in
339
+ $QK_T(Fl_3)$ and under random specializations in $QK_T(Fl_4)$ against the
340
+ Maeno-Naito-Sagaki presentation, and its specializations ($q = 0$, $\beta = 0$,
341
+ $y = 0$ with $\beta = -1$) are theorems or existing kernels. Also exported:
342
+ `grothmult_q_pieri`, `grothmult_q_double_pieri`, `grothmult_q_double_top`,
343
+ `lm_quantize`, `qgroth_poly`, `quantum_elem_sym`, `quantum_pieri_chains`.
344
+ - `DoubleGrothendieckElement.simplify()` puts the rational coefficients in $y$ and $\beta$
345
+ in normal form (`sympy.cancel`, then `factor`), dropping terms that simplify to zero.
346
+ `BaseRingElement.simplify()` applies `.simplify()` coefficientwise for any ring.
347
+ - `NilHeckeRing.isobaric(..., neg=True)` and `g_isobaric(neg=True)` for the
348
+ $\partial_i(1 - \beta x_{i+1})$ convention.
349
+ - Test coverage for every kernel in `schubmult.mult` (`tests/mult/`), the C++
350
+ acceleration layer (`test_accel.py`), and positivity (`test_positivity.py`).
351
+ - API reference regenerated from docstrings with pydoc-markdown and published with
352
+ MkDocs (`docs/`, `pip install -e ".[docs]"`, GitHub Pages workflow).
353
+
354
+ ### Changed
355
+
356
+ - **Multiplication kernels no longer expand coefficients.** `grothmult_double` and the
357
+ quantum double kernels keep coefficients as structured products and flat fractions
358
+ instead of calling `expand()`/`cancel()` on every term. This is what makes the quantum
359
+ double Grothendieck kernel usable; `grothmult_double` itself is also considerably
360
+ faster. Call `.simplify()` (or `sympy.cancel`) on the result if a normal form is wanted.
361
+ - `BaseRing.from_dict(element)` drops its unused `orig_domain` parameter and builds the
362
+ element in one pass.
363
+ - `NilHeckeRing`/`NilHeckeElement` derive from `BaseRing`/`BaseRingElement`.
364
+
365
+ ### Removed
366
+
367
+ - The research scripts that lived under `src/schubmult/_scripts/` (including the
368
+ `unlinted/` tree and `lr_rule_verify`) are no longer part of the package. Only the eight
369
+ `schubmult_*`/`grothmult_*` CLI entry points remain in `_scripts`.
370
+
371
+ ### Fixed
372
+
373
+ - `grothmult_double` failed at import on Windows (`resource` is POSIX-only; the memory cap
374
+ is now skipped where it is unavailable).
375
+
376
+ ## 5.0.0
377
+
378
+ The multiplication kernels are now compiled C++. This release consolidates the
379
+ 5.0.0b1 and 5.0.0b2 pre-releases.
380
+
381
+ ### Changed
382
+
383
+ - **The Schubert multiplication kernels run in a C++ extension (`schubmult.schubmult_cpp`).**
384
+ `schubmult_py`, `schubmult_double`, `schubmult_q_fast`, `schubmult_q_double_fast`,
385
+ `schubmult_double_from_elems` and `schubmult_double_alt_from_elems` — and therefore
386
+ every ring product built on them — dispatch to ports of the same algorithms in `cpp/`.
387
+ Results are identical to the Python kernels (coefficients are still unexpanded symengine
388
+ expressions); typical products are one to two orders of magnitude faster. The Python
389
+ kernels remain as the fallback for permutations beyond the compiled size limit
390
+ (`MAXN`, default 32). `SCHUBMULT_NO_CPP=1` forces the Python kernels.
391
+ - **Binary wheels for Linux, macOS and Windows** (CPython 3.10–3.14). The extension uses
392
+ only the Python C API — coefficients are handled as `symengine` Python objects — so it
393
+ has no SymEngine C++ dependency and builds from source with any C++17 compiler.
394
+ - Ring products no longer re-scan every coefficient's `free_symbols` when assembling the
395
+ result, and products are computed directly in the ring's variables instead of in generic
396
+ variables followed by a substitution pass.
397
+ - `requires-python` is now `>=3.10` (3.9 was declared but never supported).
398
+ - The PuLP requirement is `PuLP>=2.7.0,<4`. The PuLP 4 pre-releases are a rewrite with an
399
+ incompatible API (no `LpVariable(name=...)`, no bundled CBC) and broke `--display-positive`.
400
+
401
+ ### Added
402
+
403
+ - Standalone C++ command-line tools in `cpp/` (`schubmult_core`, `schubmult_double_core`,
404
+ `schubmult_q_core`, `schubmult_q_double_core`) mirroring the CLI scripts, including
405
+ `--display-positive` for the double kernel (MILP via `cbc`). These are development tools
406
+ built with `make`; they need the SymEngine C++ headers.
407
+
408
+ ### Fixed
409
+
410
+ - The script test fixtures are located relative to the test modules, so the test suite
411
+ runs against a non-editable install.
412
+
413
+ ## 4.2.0
414
+
415
+ ### Fixed
416
+
417
+ - **Parabolic quantum ring constructors were unusable due to a circular import.**
418
+ `schubmult.rings.schubert.schubert_ring` imported `quantum_schubert_ring` at module
419
+ load time, closing a cycle through `parabolic_quantum_double_schubert_ring`. Entering
420
+ the cycle at the parabolic module — as any of `ParabolicQuantumDoubleSchubertRing`,
421
+ `make_parabolic_quantum_basis`, or `make_single_parabolic_quantum_basis` did — raised
422
+
423
+ ```
424
+ ImportError: cannot import name 'ParabolicQuantumDoubleSchubertElement' from
425
+ partially initialized module '...parabolic_quantum_double_schubert_ring'
426
+ ```
427
+
428
+ The import is now deferred to the single call site that needs it. Reported by an
429
+ external smoke test of 4.1.0, which found the bug while trying to compute QH*(P^3);
430
+ that computation is now a regression test.
431
+
432
+ - **Five `dual_basis()` declarations raised instead of returning the dual basis.**
433
+ Each imported the right class name from the wrong module:
434
+ `GrothendieckPolyBasis` looked for `GrothendieckBasis` in `free_algebra.schubert_basis`,
435
+ `GlidePolyBasis` and `LascouxPolyBasis` both looked in `free_algebra.fundamental_slide_basis`,
436
+ and `LascouxBasis` looked for `LascouxPolyBasis` in `polynomial_algebra.key_poly_basis`.
437
+ `GrovePolyBasis` declared no dual at all and inherited the base implementation, which
438
+ returns `None`. Every declared dual pair now round-trips in both directions.
439
+
440
+ ### Added
441
+
442
+ - Grothendieck polynomial multiplication (`schubmult.mult.groth`,
443
+ `schubmult.mult.groth_double`) and a double Grothendieck ring
444
+ (`rings.schubert.double_grothendieck_ring`).
445
+ - Lascoux and glide polynomial bases, in both the free algebra
446
+ (`rings.free_algebra.lascoux_basis`, `glide_basis`) and the polynomial algebra
447
+ (`rings.polynomial_algebra.lascoux_poly_basis`, `glide_poly_basis`).
448
+ - Chevalley/Monk formula module `rings.schubert.chevalley`.
449
+ - Double Grothendieck polynomial separated-descents multiplication (`schubmult.mult.separated_descents`).
450
+ - Weak order operations on `Permutation`: `weak_order_leq`, `weak_order_meet`,
451
+ `weak_order_join`.
452
+ - Verification scripts `groth_lr_rule` and `verify_quantum_triple_positive`.
453
+
454
+ ### Removed
455
+
456
+ - `rings.combinatorial.bounded_double_rc_factor_algebra`, an abandoned line of work
457
+ that could not be imported: it required `DecoratedRCGraph`, which had already been
458
+ commented out of `combinatorics.rc_graph`. Its three classes
459
+ (`BoundedDoubleRCFactorAlgebra`, `BoundedDoubleRCFactorAlgebraElement`,
460
+ `BoundedDoubleRCFactorPrintingTerm`) were advertised by `dir(schubmult)` but raised
461
+ `AttributeError` on access. Nothing referenced them. The unrelated
462
+ `BoundedRCFactorAlgebra` is unaffected.
463
+ - The commented-out `DecoratedRCGraph` class body and its `full_CEM_double` /
464
+ `elem_squash` helpers, which had no live definitions or callers.
465
+
466
+ ### Notes
467
+
468
+ - The free algebra is the dual of the polynomial algebra, so each free algebra basis
469
+ is the dual basis to the correspondingly named polynomial basis. The naming
470
+ convention carries the pairing: `SchubertBasis` / `SchubertPolyBasis`,
471
+ `GrothendieckBasis` / `GrothendieckPolyBasis`, `LascouxBasis` / `LascouxPolyBasis`,
472
+ `GlideBasis` / `GlidePolyBasis`, `GroveBasis` / `GrovePolyBasis`, `KeyBasis` /
473
+ `KeyPolyBasis`, `ForestBasis` / `ForestPolyBasis`, `FundamentalSlideBasis` /
474
+ `FundamentalSlidePolyBasis`, `MonomialSlideBasis` / `MonomialSlidePolyBasis`,
475
+ `CompositionSchubertBasis` / `CompositionSchubertPolyBasis`,
476
+ `SeparatedDescentsBasis` / `SepDescPolyBasis`, `ElementaryBasis` /
477
+ `ElemSymPolyBasis`, and `WordBasis` / `MonomialBasis`. Where a dual is itself
478
+ realized inside the free algebra it is named explicitly: `ForestDual`, `GlideDual`,
479
+ `GroveDual`.
480
+ - The PyPI project description is generated from `README.md`, which documents the
481
+ current (4.x) API. Releases before this one carried a v1.x-era description.