passagemath-combinat 10.6.1__cp312-cp312-musllinux_1_2_aarch64.whl → 10.8.1a1__cp312-cp312-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. passagemath_combinat/__init__.py +3 -0
  2. {passagemath_combinat-10.6.1.dist-info → passagemath_combinat-10.8.1a1.dist-info}/METADATA +17 -20
  3. {passagemath_combinat-10.6.1.dist-info → passagemath_combinat-10.8.1a1.dist-info}/RECORD +220 -218
  4. {passagemath_combinat-10.6.1.dist-info → passagemath_combinat-10.8.1a1.dist-info}/WHEEL +1 -1
  5. passagemath_combinat-10.8.1a1.dist-info/top_level.txt +3 -0
  6. sage/algebras/affine_nil_temperley_lieb.py +3 -3
  7. sage/algebras/all.py +0 -1
  8. sage/algebras/askey_wilson.py +1 -1
  9. sage/algebras/associated_graded.py +2 -2
  10. sage/algebras/cellular_basis.py +3 -6
  11. sage/algebras/cluster_algebra.py +2 -3
  12. sage/algebras/down_up_algebra.py +6 -6
  13. sage/algebras/free_algebra.py +3 -32
  14. sage/algebras/free_algebra_element.py +21 -25
  15. sage/algebras/free_algebra_quotient_element.py +9 -38
  16. sage/algebras/free_zinbiel_algebra.py +4 -3
  17. sage/algebras/hall_algebra.py +2 -2
  18. sage/algebras/hecke_algebras/ariki_koike_algebra.py +8 -8
  19. sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +2 -2
  20. sage/algebras/hecke_algebras/cubic_hecke_algebra.py +11 -14
  21. sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1 -1
  22. sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +5 -5
  23. sage/algebras/iwahori_hecke_algebra.py +59 -57
  24. sage/algebras/jordan_algebra.py +97 -89
  25. sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +6 -6
  26. sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +14 -12
  27. sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +6 -6
  28. sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +4 -4
  29. sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +13 -13
  30. sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +8 -6
  31. sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +7 -5
  32. sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +7 -7
  33. sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +6 -5
  34. sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +12 -11
  35. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +3 -3
  36. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +3 -3
  37. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +11 -11
  38. sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +3 -3
  39. sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +8 -7
  40. sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +9 -8
  41. sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +6 -5
  42. sage/algebras/nil_coxeter_algebra.py +4 -4
  43. sage/algebras/q_commuting_polynomials.py +6 -6
  44. sage/algebras/q_system.py +3 -3
  45. sage/algebras/quantum_clifford.py +8 -8
  46. sage/algebras/quantum_groups/fock_space.py +48 -8
  47. sage/algebras/quantum_groups/quantum_group_gap.py +5 -7
  48. sage/algebras/quantum_matrix_coordinate_algebra.py +7 -7
  49. sage/algebras/quantum_oscillator.py +3 -3
  50. sage/algebras/quaternion_algebra_element.py +5 -3
  51. sage/algebras/schur_algebra.py +3 -3
  52. sage/algebras/shuffle_algebra.py +5 -8
  53. sage/algebras/splitting_algebra.py +129 -85
  54. sage/algebras/tensor_algebra.py +7 -7
  55. sage/algebras/yangian.py +16 -15
  56. sage/algebras/yokonuma_hecke_algebra.py +13 -11
  57. sage/combinat/all.py +9 -0
  58. sage/combinat/all__sagemath_combinat.py +1 -0
  59. sage/combinat/alternating_sign_matrix.py +36 -29
  60. sage/combinat/baxter_permutations.py +32 -12
  61. sage/combinat/bijectionist.py +13 -17
  62. sage/combinat/chas/fsym.py +6 -6
  63. sage/combinat/chas/wqsym.py +23 -29
  64. sage/combinat/colored_permutations.py +9 -11
  65. sage/combinat/colored_permutations_representations.py +13 -12
  66. sage/combinat/composition_tableau.py +2 -2
  67. sage/combinat/constellation.py +57 -30
  68. sage/combinat/crystals/affine_factorization.py +5 -4
  69. sage/combinat/crystals/alcove_path.py +2 -2
  70. sage/combinat/crystals/fully_commutative_stable_grothendieck.py +3 -2
  71. sage/combinat/crystals/infinity_crystals.py +18 -18
  72. sage/combinat/crystals/kac_modules.py +1 -1
  73. sage/combinat/crystals/kirillov_reshetikhin.py +2 -2
  74. sage/combinat/crystals/letters.cpython-312-aarch64-linux-musl.so +0 -0
  75. sage/combinat/crystals/littelmann_path.py +1 -1
  76. sage/combinat/crystals/pbw_datum.cpython-312-aarch64-linux-musl.so +0 -0
  77. sage/combinat/crystals/pbw_datum.pyx +3 -2
  78. sage/combinat/crystals/spins.cpython-312-aarch64-linux-musl.so +0 -0
  79. sage/combinat/crystals/tensor_product.py +7 -5
  80. sage/combinat/crystals/tensor_product_element.cpython-312-aarch64-linux-musl.so +0 -0
  81. sage/combinat/debruijn_sequence.cpython-312-aarch64-linux-musl.so +0 -0
  82. sage/combinat/debruijn_sequence.pyx +1 -2
  83. sage/combinat/degree_sequences.cpython-312-aarch64-linux-musl.so +0 -0
  84. sage/combinat/degree_sequences.pyx +241 -188
  85. sage/combinat/derangements.py +28 -22
  86. sage/combinat/diagram_algebras.py +12 -14
  87. sage/combinat/dyck_word.py +15 -14
  88. sage/combinat/e_one_star.py +1 -1
  89. sage/combinat/expnums.cpython-312-aarch64-linux-musl.so +0 -0
  90. sage/combinat/fast_vector_partitions.cpython-312-aarch64-linux-musl.so +0 -0
  91. sage/combinat/fqsym.py +13 -19
  92. sage/combinat/free_dendriform_algebra.py +2 -2
  93. sage/combinat/free_prelie_algebra.py +2 -2
  94. sage/combinat/fully_commutative_elements.py +8 -8
  95. sage/combinat/fully_packed_loop.py +9 -9
  96. sage/combinat/gelfand_tsetlin_patterns.py +4 -5
  97. sage/combinat/gray_codes.py +3 -4
  98. sage/combinat/grossman_larson_algebras.py +2 -2
  99. sage/combinat/growth.py +13 -13
  100. sage/combinat/hall_polynomial.py +1 -1
  101. sage/combinat/hillman_grassl.py +1 -1
  102. sage/combinat/integer_matrices.py +5 -7
  103. sage/combinat/k_tableau.py +8 -7
  104. sage/combinat/kazhdan_lusztig.py +3 -3
  105. sage/combinat/key_polynomial.py +845 -298
  106. sage/combinat/knutson_tao_puzzles.py +11 -13
  107. sage/combinat/matrices/hadamard_matrix.py +1 -1
  108. sage/combinat/matrices/latin.py +75 -92
  109. sage/combinat/misc.py +3 -3
  110. sage/combinat/multiset_partition_into_sets_ordered.py +27 -10
  111. sage/combinat/ncsf_qsym/generic_basis_code.py +5 -5
  112. sage/combinat/ncsf_qsym/ncsf.py +6 -5
  113. sage/combinat/ncsf_qsym/qsym.py +9 -17
  114. sage/combinat/ncsym/ncsym.py +8 -12
  115. sage/combinat/nu_dyck_word.py +1 -1
  116. sage/combinat/parallelogram_polyomino.py +3 -5
  117. sage/combinat/parking_functions.py +6 -5
  118. sage/combinat/partition_algebra.py +22 -57
  119. sage/combinat/partition_kleshchev.py +4 -4
  120. sage/combinat/partition_tuple.py +12 -10
  121. sage/combinat/plane_partition.py +10 -13
  122. sage/combinat/positive_integer_semigroup_test.py +17 -0
  123. sage/combinat/q_bernoulli.cpython-312-aarch64-linux-musl.so +0 -0
  124. sage/combinat/quickref.py +2 -2
  125. sage/combinat/recognizable_series.py +2 -2
  126. sage/combinat/regular_sequence.py +7 -7
  127. sage/combinat/regular_sequence_bounded.py +15 -21
  128. sage/combinat/restricted_growth.py +3 -3
  129. sage/combinat/ribbon.py +3 -3
  130. sage/combinat/rigged_configurations/bijection.py +3 -3
  131. sage/combinat/rigged_configurations/rigged_partition.cpython-312-aarch64-linux-musl.so +0 -0
  132. sage/combinat/rsk.py +2 -0
  133. sage/combinat/schubert_polynomial.py +11 -2
  134. sage/combinat/set_partition.py +3 -7
  135. sage/combinat/set_partition_iterator.cpython-312-aarch64-linux-musl.so +0 -0
  136. sage/combinat/set_partition_iterator.pyx +0 -1
  137. sage/combinat/set_partition_ordered.py +2 -2
  138. sage/combinat/sf/classical.py +1 -1
  139. sage/combinat/sf/dual.py +4 -8
  140. sage/combinat/sf/elementary.py +13 -7
  141. sage/combinat/sf/hall_littlewood.py +10 -8
  142. sage/combinat/sf/homogeneous.py +6 -3
  143. sage/combinat/sf/jack.py +11 -9
  144. sage/combinat/sf/llt.py +4 -5
  145. sage/combinat/sf/macdonald.py +10 -11
  146. sage/combinat/sf/monomial.py +6 -0
  147. sage/combinat/sf/ns_macdonald.py +92 -51
  148. sage/combinat/sf/powersum.py +9 -14
  149. sage/combinat/sf/schur.py +6 -0
  150. sage/combinat/sf/sf.py +21 -19
  151. sage/combinat/sf/sfa.py +13 -64
  152. sage/combinat/shifted_primed_tableau.py +5 -7
  153. sage/combinat/shuffle.py +1 -1
  154. sage/combinat/sine_gordon.py +18 -38
  155. sage/combinat/skew_partition.py +9 -12
  156. sage/combinat/skew_tableau.py +2 -7
  157. sage/combinat/sloane_functions.py +1 -1
  158. sage/combinat/species/all.py +67 -2
  159. sage/combinat/species/characteristic_species.py +3 -0
  160. sage/combinat/species/composition_species.py +3 -0
  161. sage/combinat/species/cycle_species.py +4 -0
  162. sage/combinat/species/empty_species.py +3 -0
  163. sage/combinat/species/functorial_composition_species.py +3 -0
  164. sage/combinat/species/generating_series.py +3 -0
  165. sage/combinat/species/library.py +3 -0
  166. sage/combinat/species/linear_order_species.py +3 -0
  167. sage/combinat/species/partition_species.py +3 -0
  168. sage/combinat/species/permutation_species.py +4 -0
  169. sage/combinat/species/product_species.py +3 -0
  170. sage/combinat/species/recursive_species.py +3 -0
  171. sage/combinat/species/set_species.py +3 -0
  172. sage/combinat/species/species.py +13 -7
  173. sage/combinat/species/structure.py +8 -9
  174. sage/combinat/species/subset_species.py +3 -0
  175. sage/combinat/species/sum_species.py +3 -0
  176. sage/combinat/subword.py +4 -1
  177. sage/combinat/subword_complex.py +7 -7
  178. sage/combinat/subword_complex_c.cpython-312-aarch64-linux-musl.so +0 -0
  179. sage/combinat/superpartition.py +1 -1
  180. sage/combinat/symmetric_group_algebra.py +9 -9
  181. sage/combinat/symmetric_group_representations.py +5 -5
  182. sage/combinat/t_sequences.py +4 -4
  183. sage/combinat/tableau.py +3 -4
  184. sage/combinat/tableau_tuple.py +2 -2
  185. sage/combinat/tiling.py +39 -42
  186. sage/combinat/triangles_FHM.py +38 -15
  187. sage/combinat/tutorial.py +2 -2
  188. sage/combinat/vector_partition.py +43 -31
  189. sage/combinat/words/abstract_word.py +4 -4
  190. sage/combinat/words/alphabet.py +12 -12
  191. sage/combinat/words/finite_word.py +25 -229
  192. sage/combinat/words/infinite_word.py +1 -1
  193. sage/combinat/words/morphic.py +13 -13
  194. sage/combinat/words/morphism.py +3 -12
  195. sage/combinat/words/paths.py +16 -17
  196. sage/combinat/words/word.py +60 -35
  197. sage/combinat/words/word_char.cpython-312-aarch64-linux-musl.so +0 -0
  198. sage/combinat/words/word_char.pyx +46 -7
  199. sage/combinat/words/word_datatypes.cpython-312-aarch64-linux-musl.so +0 -0
  200. sage/combinat/words/word_generators.py +39 -38
  201. sage/databases/findstat.py +72 -31
  202. sage/databases/oeis.py +125 -25
  203. sage/databases/sloane.py +14 -8
  204. sage/games/sudoku_backtrack.cpython-312-aarch64-linux-musl.so +0 -0
  205. sage/groups/indexed_free_group.py +3 -4
  206. sage/libs/symmetrica/symmetrica.cpython-312-aarch64-linux-musl.so +0 -0
  207. sage/libs/symmetrica/symmetrica.pxi +1 -0
  208. sage/monoids/automatic_semigroup.py +1 -3
  209. sage/monoids/free_abelian_monoid.py +7 -33
  210. sage/monoids/free_abelian_monoid_element.cpython-312-aarch64-linux-musl.so +0 -0
  211. sage/monoids/free_monoid.py +8 -40
  212. sage/monoids/free_monoid_element.py +1 -9
  213. sage/monoids/string_monoid.py +5 -2
  214. sage/monoids/string_monoid_element.py +12 -66
  215. sage/rings/all__sagemath_combinat.py +7 -0
  216. sage/sat/solvers/__init__.py +3 -4
  217. sage/sat/solvers/cryptominisat.py +2 -3
  218. sage/sat/solvers/picosat.py +2 -3
  219. sage/sat/solvers/sat_lp.py +2 -2
  220. sage/sat/solvers/satsolver.cpython-312-aarch64-linux-musl.so +0 -0
  221. passagemath_combinat-10.6.1.dist-info/top_level.txt +0 -2
@@ -200,6 +200,7 @@ AUTHORS:
200
200
  # https://www.gnu.org/licenses/
201
201
  # ****************************************************************************
202
202
  from sage.misc.lazy_list import lazy_list
203
+ from sage.misc.lazy_attribute import lazy_attribute
203
204
  from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
204
205
  from sage.structure.element import Element
205
206
  from sage.structure.parent import Parent
@@ -633,7 +634,7 @@ def _data_from_iterable(iterable, mapping=False, domain=None,
633
634
  pre_data = [(elts, vals)]
634
635
 
635
636
  # pre_data is a list of all elements of the iterator accessed so
636
- # far, for each of its elements and also the remainder ot the
637
+ # far, for each of its elements and also the remainder of the
637
638
  # iterator, each element is either a pair ``(object, value)`` or
638
639
  # a pair ``(objects, values)``
639
640
  elts, vals = pre_data[0]
@@ -732,16 +733,15 @@ def _data_from_data(data, max_values):
732
733
  [0, 0, 1, 1, 2, 2, 1, 0, 0, 0, 1, 1, 1, 2, 3])]
733
734
  """
734
735
  query = []
735
- total = min(max_values, FINDSTAT_MAX_VALUES)
736
736
  iterator = iter(data)
737
- while total > 0:
737
+ while max_values > 0:
738
738
  try:
739
739
  elts, vals = next(iterator)
740
740
  except StopIteration:
741
741
  break
742
- if total >= len(elts):
742
+ if max_values >= len(elts):
743
743
  query.append((elts, vals))
744
- total -= len(elts)
744
+ max_values -= len(elts)
745
745
  else:
746
746
  break # assuming that the next pair is even larger
747
747
 
@@ -1019,12 +1019,12 @@ def findstat(query=None, values=None, distribution=None, domain=None,
1019
1019
  sage: findstat("Permutations", lambda x: 1, depth='x') # optional -- internet
1020
1020
  Traceback (most recent call last):
1021
1021
  ...
1022
- ValueError: E021: Depth should be a nonnegative integer at most 9, but is x.
1022
+ ValueError: E021: Depth should be a non-negative integer at most 9, but is x.
1023
1023
 
1024
1024
  sage: findstat("Permutations", lambda x: 1, depth=100) # optional -- internet
1025
1025
  Traceback (most recent call last):
1026
1026
  ...
1027
- ValueError: E021: Depth should be a nonnegative integer at most 9, but is 100.
1027
+ ValueError: E021: Depth should be a non-negative integer at most 9, but is 100.
1028
1028
 
1029
1029
  sage: S = Permutation
1030
1030
  sage: findstat([(S([1,2]), 1), ([S([1,3,2]), S([1,2])], [2,3])]) # optional -- internet
@@ -1788,10 +1788,10 @@ class FindStatFunction(SageObject):
1788
1788
  EXAMPLES::
1789
1789
 
1790
1790
  sage: q = findstat([(d, randint(1,1000)) for d in DyckWords(4)]) # optional -- internet
1791
- sage: q.set_sage_code("def statistic(x):\n return randint(1, 1000)") # optional -- internet
1791
+ sage: q.set_sage_code("def statistic(x):\n return randint(1, 1000)") # optional -- internet
1792
1792
  sage: print(q.sage_code()) # optional -- internet
1793
1793
  def statistic(x):
1794
- return randint(1,1000)
1794
+ return randint(1, 1000)
1795
1795
  """
1796
1796
  if value != self.sage_code():
1797
1797
  self._modified = True
@@ -1820,9 +1820,22 @@ class FindStatCombinatorialStatistic(SageObject):
1820
1820
  sage: FindStatCombinatorialStatistic()
1821
1821
  <sage.databases.findstat.FindStatCombinatorialStatistic object at 0x...>
1822
1822
  """
1823
- self._first_terms_cache = None
1824
1823
  self._first_terms_raw_cache = None
1825
1824
 
1825
+ @lazy_attribute
1826
+ def _first_terms_cache(self):
1827
+ """
1828
+ Return the first terms of the (compound) statistic as a
1829
+ dictionary.
1830
+
1831
+ EXAMPLES::
1832
+
1833
+ sage: findstat(41)._first_terms_cache[PerfectMatching([(1,6),(2,5),(3,4)])] # optional -- internet
1834
+ 3
1835
+ """
1836
+ # this indirectly initializes self._first_terms_raw_cache
1837
+ return dict(self._fetch_first_terms())
1838
+
1826
1839
  def first_terms(self):
1827
1840
  r"""
1828
1841
  Return the first terms of the (compound) statistic as a
@@ -1840,10 +1853,6 @@ class FindStatCombinatorialStatistic(SageObject):
1840
1853
  sage: findstat(41).first_terms()[PerfectMatching([(1,6),(2,5),(3,4)])] # optional -- internet
1841
1854
  3
1842
1855
  """
1843
- # initialize self._first_terms_cache and
1844
- # self._first_terms_raw_cache on first call
1845
- if self._first_terms_cache is None:
1846
- self._first_terms_cache = self._fetch_first_terms()
1847
1856
  # a shallow copy suffices - tuples are immutable
1848
1857
  return dict(self._first_terms_cache)
1849
1858
 
@@ -1946,7 +1955,7 @@ class FindStatCombinatorialStatistic(SageObject):
1946
1955
  domain = self.domain()
1947
1956
  levels_with_sizes = domain.levels_with_sizes()
1948
1957
  total = 0
1949
- for elt, val in self.first_terms().items():
1958
+ for elt, val in self._first_terms_cache.items():
1950
1959
  if total == max_values:
1951
1960
  break
1952
1961
  lvl = domain.element_level(elt)
@@ -2155,7 +2164,7 @@ class FindStatStatistic(Element,
2155
2164
  sage: q(graphs.PetersenGraph().copy(immutable=True)) # optional -- internet
2156
2165
  2
2157
2166
  """
2158
- val = self.first_terms().get(elt, None)
2167
+ val = self._first_terms_cache.get(elt, None)
2159
2168
  if val is None:
2160
2169
  return FindStatFunction.__call__(self, elt)
2161
2170
  return val
@@ -2269,12 +2278,22 @@ class FindStatStatistic(Element,
2269
2278
  [(1, 4), (2, 3)] => 3
2270
2279
  sage: s.reset() # optional -- internet
2271
2280
  """
2272
- to_str = self.domain().to_string()
2281
+ domain = self.domain()
2282
+ from_str = domain.from_string()
2283
+ to_str = domain.to_string()
2284
+
2285
+ def to_domain(elt):
2286
+ if domain.is_element(elt):
2287
+ return elt
2288
+ if not isinstance(elt, str):
2289
+ elt = str(elt)
2290
+ return from_str(elt)
2291
+
2273
2292
  new = [(to_str(obj), value) for obj, value in values]
2274
2293
  if sorted(new) != sorted(self.first_terms_str()):
2275
2294
  self._modified = True
2276
2295
  self._first_terms_raw_cache = new
2277
- self._first_terms_cache = values
2296
+ self._first_terms_cache = {to_domain(elt): v for elt, v in values}
2278
2297
 
2279
2298
  def code(self):
2280
2299
  r"""
@@ -2586,6 +2605,7 @@ class FindStatStatisticQuery(FindStatStatistic):
2586
2605
  self._known_terms = data
2587
2606
  else:
2588
2607
  self._known_terms = known_terms
2608
+ self._known_terms_number = 0
2589
2609
  self._values_of = None
2590
2610
  self._distribution_of = None
2591
2611
  self._depth = depth
@@ -2649,9 +2669,26 @@ class FindStatStatisticQuery(FindStatStatistic):
2649
2669
  function=function)
2650
2670
  Element.__init__(self, FindStatStatistics()) # this is not completely correct, but it works
2651
2671
 
2672
+ @lazy_attribute
2673
+ def _first_terms_cache(self):
2674
+ """
2675
+ Return the pairs of the known terms which contain
2676
+ singletons, as a dictionary.
2677
+
2678
+ EXAMPLES::
2679
+
2680
+ sage: PM = PerfectMatchings
2681
+ sage: l = [(PM(2*n), [m.number_of_nestings() for m in PM(2*n)]) for n in range(5)]
2682
+ sage: r = findstat(l, depth=0) # optional -- internet
2683
+ sage: r._first_terms_cache # optional -- internet
2684
+ {}
2685
+ """
2686
+ return dict()
2687
+
2652
2688
  def first_terms(self, max_values=FINDSTAT_MAX_SUBMISSION_VALUES):
2653
2689
  """
2654
- Return the pairs of the known terms which contain singletons as a dictionary.
2690
+ Return the pairs of the known terms which contain
2691
+ singletons, as a dictionary.
2655
2692
 
2656
2693
  EXAMPLES::
2657
2694
 
@@ -2662,10 +2699,14 @@ class FindStatStatisticQuery(FindStatStatistic):
2662
2699
  1: St000042 (quality [99, 100])
2663
2700
  sage: r.first_terms() # optional -- internet
2664
2701
  {[]: 0, [(1, 2)]: 0}
2702
+
2665
2703
  """
2666
- return dict(itertools.islice(((objs[0], vals[0])
2667
- for objs, vals in self._known_terms
2668
- if len(vals) == 1), max_values))
2704
+ new_terms = self._known_terms[self._known_terms_number:max_values]
2705
+ self._first_terms_cache.update((objs[0], vals[0])
2706
+ for objs, vals in new_terms
2707
+ if len(vals) == 1)
2708
+ self._known_terms_number = max(max_values, self._known_terms_number)
2709
+ return dict(self._first_terms_cache)
2669
2710
 
2670
2711
  def _first_terms_raw(self, max_values):
2671
2712
  """
@@ -2804,7 +2845,7 @@ class FindStatCompoundStatistic(Element, FindStatCombinatorialStatistic):
2804
2845
  FindStatCombinatorialStatistic.__init__(self)
2805
2846
  Element.__init__(self, FindStatStatistics()) # this is not completely correct, but it works
2806
2847
 
2807
- def _fetch_first_terms_raw(self):
2848
+ def _fetch_first_terms_raw(self) -> list:
2808
2849
  r"""
2809
2850
  Return the first terms of the compound statistic, as ``(string,
2810
2851
  value)`` pairs, fetched from FindStat.
@@ -2819,7 +2860,7 @@ class FindStatCompoundStatistic(Element, FindStatCombinatorialStatistic):
2819
2860
  """
2820
2861
  fields = "Values"
2821
2862
  url = FINDSTAT_API_STATISTICS + self.id_str() + "?fields=" + fields
2822
- if len(self._maps):
2863
+ if self._maps:
2823
2864
  values = _get_json(url)["included"]["CompoundStatistics"][self.id_str()]["Values"]
2824
2865
  else:
2825
2866
  values = _get_json(url)["included"]["Statistics"][self.id_str()]["Values"]
@@ -2853,7 +2894,7 @@ class FindStatCompoundStatistic(Element, FindStatCombinatorialStatistic):
2853
2894
  """
2854
2895
  return self.statistic()(self.compound_map()(elt))
2855
2896
 
2856
- def id_str(self):
2897
+ def id_str(self) -> str:
2857
2898
  """
2858
2899
  Return the padded identifier of the compound statistic.
2859
2900
 
@@ -2864,7 +2905,7 @@ class FindStatCompoundStatistic(Element, FindStatCombinatorialStatistic):
2864
2905
  """
2865
2906
  return self._id
2866
2907
 
2867
- def _repr_(self):
2908
+ def _repr_(self) -> str:
2868
2909
  """
2869
2910
  Return a string representation of the compound statistic.
2870
2911
 
@@ -3823,7 +3864,7 @@ class FindStatCompoundMap(Element, FindStatCombinatorialMap):
3823
3864
  Mp00099: bounce path: Dyck paths -> Dyck paths
3824
3865
  """
3825
3866
  for mp in self:
3826
- mp.info()
3867
+ mp.info()
3827
3868
 
3828
3869
 
3829
3870
  class FindStatMatchingMap(FindStatCompoundMap):
@@ -4524,7 +4565,7 @@ _SupportedFindStatCollections = {
4524
4565
  _SupportedFindStatCollection(lambda x: BinaryTree(str(x)),
4525
4566
  str,
4526
4567
  BinaryTrees,
4527
- lambda x: x.node_number(),
4568
+ lambda x: x.number_of_nodes(),
4528
4569
  lambda x: isinstance(x, BinaryTree)),
4529
4570
  "Cores":
4530
4571
  _SupportedFindStatCollection(lambda x: Core(*literal_eval(x)),
@@ -4557,9 +4598,9 @@ _SupportedFindStatCollections = {
4557
4598
  _SupportedFindStatCollection(lambda x: (lambda E, V: Graph([list(range(V)),
4558
4599
  lambda i,j: (i,j) in E or (j,i) in E],
4559
4600
  immutable=True))(*literal_eval(x)),
4560
- lambda X: str((X.edges(labels=False, sort=True), X.num_verts())),
4601
+ lambda X: str((X.edges(labels=False, sort=True), X.n_vertices())),
4561
4602
  lambda x: (g.copy(immutable=True) for g in graphs(x, copy=False)),
4562
- lambda x: x.num_verts(),
4603
+ lambda x: x.n_vertices(),
4563
4604
  lambda x: isinstance(x, Graph)),
4564
4605
  "IntegerPartitions":
4565
4606
  _SupportedFindStatCollection(lambda x: Partition(literal_eval(x)),
@@ -4577,7 +4618,7 @@ _SupportedFindStatCollections = {
4577
4618
  _SupportedFindStatCollection(lambda x: OrderedTree(literal_eval(x)),
4578
4619
  str,
4579
4620
  OrderedTrees,
4580
- lambda x: x.node_number(),
4621
+ lambda x: x.number_of_nodes(),
4581
4622
  lambda x: isinstance(x, OrderedTree)),
4582
4623
  "ParkingFunctions":
4583
4624
  _SupportedFindStatCollection(lambda x: ParkingFunction(literal_eval(x)),
sage/databases/oeis.py CHANGED
@@ -134,7 +134,6 @@ AUTHORS:
134
134
 
135
135
  import re
136
136
  from collections import defaultdict
137
- from ssl import create_default_context as default_context
138
137
  from urllib.parse import urlencode
139
138
  # ****************************************************************************
140
139
  # Copyright (C) 2012 Thierry Monteil <sage!lma.metelu.net>
@@ -148,7 +147,6 @@ from urllib.request import urlopen, Request
148
147
 
149
148
  from sage.version import version
150
149
  from sage.cpython.string import bytes_to_str
151
- from sage.misc.cachefunc import cached_method
152
150
  from sage.misc.flatten import flatten
153
151
  from sage.misc.html import HtmlFragment
154
152
  from sage.misc.temporary_file import tmp_filename
@@ -156,13 +154,16 @@ from sage.misc.unknown import Unknown
156
154
  from sage.misc.verbose import verbose
157
155
  from sage.repl.preparse import preparse
158
156
  from sage.rings.integer import Integer
157
+ from sage.rings.integer_ring import ZZ
158
+ from sage.rings.infinity import infinity
159
+ from sage.structure.global_options import GlobalOptions
159
160
  from sage.structure.sage_object import SageObject
160
161
  from sage.structure.unique_representation import UniqueRepresentation
161
162
 
162
163
  oeis_url = 'https://oeis.org/'
163
164
 
164
165
 
165
- def _fetch(url):
166
+ def _fetch(url) -> str:
166
167
  r"""
167
168
  Fetch the given ``url``.
168
169
 
@@ -186,7 +187,7 @@ def _fetch(url):
186
187
  raise OSError("%s\nerror fetching %s" % (msg, url))
187
188
 
188
189
 
189
- def _urls(html_string):
190
+ def _urls(html_string) -> list[str]:
190
191
  r"""
191
192
  Return the list of URLs contained in ``html_string``.
192
193
 
@@ -219,7 +220,7 @@ def _urls(html_string):
219
220
  return urls
220
221
 
221
222
 
222
- def to_tuple(string):
223
+ def to_tuple(string: str) -> tuple:
223
224
  """
224
225
  Convert a string to a tuple of integers.
225
226
 
@@ -247,15 +248,17 @@ class OEIS:
247
248
  - a list representing a sequence of integers.
248
249
  - a string, representing a text search.
249
250
 
250
- - ``max_results`` -- (integer, default: 30) the maximum number of
251
+ - ``max_results`` -- integer (default: 3); the maximum number of
251
252
  results to return, they are sorted according to their relevance. In
252
253
  any cases, the OEIS website will never provide more than 100 results.
253
254
 
254
- - ``first_result`` -- (integer, default: 0) allow to skip the
255
+ - ``first_result`` -- integer (default: 0); allow to skip the
255
256
  ``first_result`` first results in the search, to go further.
256
257
  This is useful if you are looking for a sequence that may appear
257
258
  after the 100 first found sequences.
258
259
 
260
+ ``max_results`` can also be set using :meth:`options`.
261
+
259
262
  OUTPUT:
260
263
 
261
264
  - if ``query`` is an integer or an OEIS ID (e.g. 'A000045'), returns
@@ -362,8 +365,7 @@ class OEIS:
362
365
  sage: oeis('A000045') # optional -- internet
363
366
  A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
364
367
  """
365
-
366
- def __call__(self, query, max_results=3, first_result=0):
368
+ def __call__(self, query, max_results=None, first_result=0):
367
369
  r"""
368
370
  See the documentation of :class:`OEIS`.
369
371
 
@@ -384,6 +386,46 @@ class OEIS:
384
386
  elif isinstance(query, (list, tuple)):
385
387
  return self.find_by_subsequence(query, max_results, first_result)
386
388
 
389
+ class options(GlobalOptions):
390
+ r"""
391
+ Set and display the options for the OEIS.
392
+
393
+ If no parameters are set, then the function returns a copy of
394
+ the options dictionary.
395
+
396
+ The ``options`` can be accessed as using
397
+ :class:`oeis.options`.
398
+
399
+ @OPTIONS@
400
+
401
+ EXAMPLES::
402
+
403
+ sage: oeis.options
404
+ Current options for OEIS
405
+ - fetch_b_file: False
406
+ - max_results: 3
407
+
408
+ sage: oeis.options.max_results = 5
409
+ sage: oeis('beaver') # optional -- internet
410
+ 0: A...: ...eaver...
411
+ 1: A...: ...eaver...
412
+ 2: A...: ...eaver...
413
+ 3: A...: ...eaver...
414
+ 4: A...: ...eaver...
415
+
416
+ sage: oeis.options._reset()
417
+ sage: oeis.options.max_results
418
+ 3
419
+ """
420
+ NAME = 'OEIS'
421
+ module = 'sage.databases.oeis'
422
+ max_results = dict(default=3,
423
+ description='the maximum number of results to return',
424
+ checker=lambda x: x in ZZ and x > 0)
425
+ fetch_b_file = dict(default=False,
426
+ description='whether to fetch terms from the b-file by default',
427
+ checker=lambda x: isinstance(x, bool))
428
+
387
429
  def __repr__(self) -> str:
388
430
  r"""
389
431
  Return the representation of ``self``.
@@ -441,7 +483,7 @@ class OEIS:
441
483
  sequence._raw = entry
442
484
  return sequence
443
485
 
444
- def find_by_description(self, description, max_results=3, first_result=0):
486
+ def find_by_description(self, description, max_results=None, first_result=0):
445
487
  r"""
446
488
  Search for OEIS sequences corresponding to the description.
447
489
 
@@ -449,11 +491,11 @@ class OEIS:
449
491
 
450
492
  - ``description`` -- string; the description the searched sequences
451
493
 
452
- - ``max_results`` -- (integer, default: 3) the maximum number of results
494
+ - ``max_results`` -- integer (default: 3); the maximum number of results
453
495
  we want. In any case, the on-line encyclopedia will not return more
454
496
  than 100 results.
455
497
 
456
- - ``first_result`` -- (integer, default: 0) allow to skip the
498
+ - ``first_result`` -- integer (default: 0); allow to skip the
457
499
  ``first_result`` first results in the search, to go further.
458
500
  This is useful if you are looking for a sequence that may appear
459
501
  after the 100 first found sequences.
@@ -484,7 +526,19 @@ class OEIS:
484
526
  1: A...: ...eaver...
485
527
  2: A...: ...eaver...
486
528
  3: A...: ...eaver...
529
+
530
+ Alternatively, we can also set the global option `max_results`::
531
+
532
+ sage: oeis.options.max_results = 5
533
+ sage: oeis('beaver') # optional -- internet
534
+ 0: A...: ...eaver...
535
+ 1: A...: ...eaver...
536
+ 2: A...: ...eaver...
537
+ 3: A...: ...eaver...
538
+ 4: A...: ...eaver...
487
539
  """
540
+ if max_results is None:
541
+ max_results = self.options['max_results']
488
542
  options = {'q': description,
489
543
  'n': str(max_results),
490
544
  'fmt': 'text',
@@ -494,7 +548,7 @@ class OEIS:
494
548
  T = [self.find_by_entry(entry=s) for s in sequence_list]
495
549
  return FancyTuple([s for s in T if not s.is_dead()])
496
550
 
497
- def find_by_subsequence(self, subsequence, max_results=3, first_result=0):
551
+ def find_by_subsequence(self, subsequence, max_results=None, first_result=0):
498
552
  r"""
499
553
  Search for OEIS sequences containing the given subsequence.
500
554
 
@@ -690,7 +744,7 @@ class OEISSequence(SageObject, UniqueRepresentation):
690
744
 
691
745
  def online_update(self):
692
746
  r"""
693
- Fetch the online OEIS to update the informations about this sequence.
747
+ Fetch the sequence from the OEIS.
694
748
 
695
749
  TESTS::
696
750
 
@@ -1206,15 +1260,17 @@ class OEISSequence(SageObject, UniqueRepresentation):
1206
1260
  else:
1207
1261
  return Unknown
1208
1262
 
1209
- @cached_method
1210
1263
  def first_terms(self, number=None):
1211
1264
  r"""
1265
+ Return the first few terms of the sequence.
1212
1266
 
1213
1267
  INPUT:
1214
1268
 
1215
- - ``number`` -- integer or ``None`` (default); the number of
1216
- terms returned (if less than the number of available terms). When set
1217
- to ``None``, returns all the known terms.
1269
+ - ``number`` -- integer, ``infinity`` or ``None`` (default);
1270
+ the number of terms returned. When set to ``None``,
1271
+ returns all the known terms. When set to an integer larger
1272
+ than the number of terms in the internal format, or to
1273
+ ``infinity``, the b-file is fetched.
1218
1274
 
1219
1275
  OUTPUT: tuple of integers
1220
1276
 
@@ -1238,9 +1294,54 @@ class OEISSequence(SageObject, UniqueRepresentation):
1238
1294
  (1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
1239
1295
  sage: s.first_terms(5)
1240
1296
  (1, 1, 1, 1, 2)
1297
+
1298
+ sage: len(oeis(45).first_terms()) # optional -- internet
1299
+ 41
1300
+ sage: len(oeis(45).first_terms(oo)) # optional -- internet
1301
+ 2001
1302
+
1303
+ sage: len(oeis(1).first_terms()) # optional -- internet
1304
+ 94
1305
+
1306
+ sage: oeis.options.fetch_b_file = True
1307
+ sage: len(oeis(1).first_terms()) # optional -- internet
1308
+ 2048
1309
+ sage: oeis.options._reset()
1241
1310
  """
1242
- fields = ['S', 'T', 'U']
1243
- return to_tuple(" ".join(flatten([self._field(a) for a in fields])))[:number]
1311
+ def fetch_b_file():
1312
+ url = oeis_url + f"b{self.id(format='int')}.txt"
1313
+ terms = _fetch(url)
1314
+ first_terms = tuple()
1315
+ check = None
1316
+ for term in terms.split('\n'):
1317
+ if not term or term[0] == '#':
1318
+ continue
1319
+ k, v = (Integer(e) for e in term.strip().split())
1320
+ if check is not None and k != check + 1:
1321
+ raise ValueError(f"malformed b-file {url}: key {check} followed by {k}")
1322
+ check = k
1323
+ first_terms += (v,)
1324
+ self._first_terms = True, first_terms
1325
+
1326
+ if ((number is infinity or oeis.options['fetch_b_file'])
1327
+ and self is not oeis._imaginary_sequence()): # all other sequences have a b-file
1328
+ # self._first_terms is a pair (all?, first_terms)
1329
+ if not hasattr(self, "_first_terms") or not self._first_terms[0]:
1330
+ fetch_b_file()
1331
+ return self._first_terms[1]
1332
+
1333
+ if not hasattr(self, "_first_terms"):
1334
+ fields = ['S', 'T', 'U']
1335
+ first_terms = to_tuple(" ".join(flatten([self._field(a) for a in fields])))
1336
+ self._first_terms = (False, first_terms)
1337
+
1338
+ if number is None:
1339
+ return self._first_terms[1]
1340
+
1341
+ if number > len(self._first_terms[1]) and not self._first_terms[0]:
1342
+ fetch_b_file()
1343
+
1344
+ return self._first_terms[1][:number]
1244
1345
 
1245
1346
  def _repr_(self):
1246
1347
  r"""
@@ -1756,8 +1857,7 @@ class OEISSequence(SageObject, UniqueRepresentation):
1756
1857
  https://oeis.org/A012345
1757
1858
  <BLANKLINE>
1758
1859
  AUTHOR
1759
- Patrick Demichel (patrick.demichel(AT)hp.com)
1760
- <BLANKLINE>
1860
+ ...
1761
1861
 
1762
1862
  TESTS::
1763
1863
 
@@ -1931,7 +2031,7 @@ class OEISSequence(SageObject, UniqueRepresentation):
1931
2031
  return sorted(table)
1932
2032
  return sorted(prog for la, prog in table if la == language)
1933
2033
 
1934
- def test_compile_sage_code(self):
2034
+ def check_compile_sage_code(self):
1935
2035
  """
1936
2036
  Try to compile the extracted sage code, if there is any.
1937
2037
 
@@ -1947,13 +2047,13 @@ class OEISSequence(SageObject, UniqueRepresentation):
1947
2047
  One correct sequence::
1948
2048
 
1949
2049
  sage: s = oeis.find_by_id('A027642') # optional -- internet
1950
- sage: s.test_compile_sage_code() # optional -- internet
2050
+ sage: s.check_compile_sage_code() # optional -- internet
1951
2051
  True
1952
2052
 
1953
2053
  One dead sequence::
1954
2054
 
1955
2055
  sage: s = oeis.find_by_id('A000154') # optional -- internet
1956
- sage: s.test_compile_sage_code() # optional -- internet
2056
+ sage: s.check_compile_sage_code() # optional -- internet
1957
2057
  True
1958
2058
  """
1959
2059
  if self.is_dead():
sage/databases/sloane.py CHANGED
@@ -1,4 +1,5 @@
1
1
  # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sloane_database
2
3
  """
3
4
  Local copy of the On-Line Encyclopedia of Integer Sequences
4
5
 
@@ -12,21 +13,21 @@ To look up a sequence, type
12
13
 
13
14
  ::
14
15
 
15
- sage: SloaneEncyclopedia[60843] # optional - sloane_database
16
+ sage: SloaneEncyclopedia[60843]
16
17
  [1, 6, 21, 107, 47176870]
17
18
 
18
19
  To get the name of a sequence, type
19
20
 
20
21
  ::
21
22
 
22
- sage: SloaneEncyclopedia.sequence_name(1) # optional - sloane_database
23
+ sage: SloaneEncyclopedia.sequence_name(1)
23
24
  'Number of groups of order n.'
24
25
 
25
26
  To search locally for a particular subsequence, type
26
27
 
27
28
  ::
28
29
 
29
- sage: SloaneEncyclopedia.find([1,2,3,4,5], 1) # optional - sloane_database
30
+ sage: SloaneEncyclopedia.find([1,2,3,4,5], 1)
30
31
  [(15, [1, 2, 3, 4, 5, 7, 7, 8, 9, 11, 11, 13, 13, 16, 16, 16, 17, 19, 19, 23, 23, 23, 23, 25, 25, 27, 27, 29, 29, 31, 31, 32, 37, 37, 37, 37, 37, 41, 41, 41, 41, 43, 43, 47, 47, 47, 47, 49, 49, 53, 53, 53, 53, 59, 59, 59, 59, 59, 59, 61, 61, 64, 64, 64, 67, 67, 67, 71, 71, 71, 71, 73])]
31
32
 
32
33
  The default maximum number of results is 30, but to return up to
@@ -34,7 +35,7 @@ The default maximum number of results is 30, but to return up to
34
35
 
35
36
  ::
36
37
 
37
- sage: SloaneEncyclopedia.find([1,2,3,4,5], 100) # optional - sloane_database
38
+ sage: SloaneEncyclopedia.find([1,2,3,4,5], 100)
38
39
  [(15, [1, 2, 3, 4, 5, 7, 7, 8, 9, 11, 11, ...
39
40
 
40
41
  Results in either case are of the form [ (number, list) ].
@@ -88,7 +89,7 @@ from urllib.request import urlretrieve
88
89
  import ssl
89
90
 
90
91
  from sage.misc.verbose import verbose
91
- from sage.env import SAGE_SHARE
92
+ from sage.env import DOT_SAGE, sage_data_paths
92
93
  from sage.rings.integer_ring import ZZ
93
94
 
94
95
 
@@ -102,7 +103,12 @@ class SloaneEncyclopediaClass:
102
103
  """
103
104
  Initialize the database but do not load any of the data.
104
105
  """
105
- self.__path__ = os.path.join(SAGE_SHARE, 'sloane')
106
+ self.__path__ = os.path.join(DOT_SAGE, 'db', 'sloane')
107
+ for path in sage_data_paths('sloane'):
108
+ file_oeis = os.path.join(path, 'sloane-oeis.bz2')
109
+ file_names = os.path.join(path, 'sloane-names.bz2')
110
+ if os.path.exists(file_oeis) and os.path.exists(file_names):
111
+ self.__path__ = path
106
112
  self.__file__ = os.path.join(self.__path__, 'sloane-oeis.bz2')
107
113
  self.__file_names__ = os.path.join(self.__path__, 'sloane-names.bz2')
108
114
  self.__loaded__ = False
@@ -156,7 +162,7 @@ class SloaneEncyclopediaClass:
156
162
 
157
163
  EXAMPLES::
158
164
 
159
- sage: SloaneEncyclopedia.is_installed() # optional - sloane_database
165
+ sage: SloaneEncyclopedia.is_installed()
160
166
  True
161
167
  """
162
168
  return os.path.exists(self.__file__) and os.path.exists(self.__file_names__)
@@ -334,7 +340,7 @@ class SloaneEncyclopediaClass:
334
340
 
335
341
  EXAMPLES::
336
342
 
337
- sage: SloaneEncyclopedia.sequence_name(1) # optional - sloane_database
343
+ sage: SloaneEncyclopedia.sequence_name(1)
338
344
  'Number of groups of order n.'
339
345
  """
340
346
  self.load()
@@ -281,7 +281,7 @@ class IndexedFreeGroup(IndexedGroup, Group):
281
281
  return self.__class__(self.parent(),
282
282
  tuple((x[0], -x[1]) for x in reversed(self._monomial)))
283
283
 
284
- def to_word_list(self):
284
+ def to_word_list(self) -> list[tuple]:
285
285
  """
286
286
  Return ``self`` as a word represented as a list whose entries
287
287
  are the pairs ``(i, s)`` where ``i`` is the index and ``s`` is
@@ -295,9 +295,8 @@ class IndexedFreeGroup(IndexedGroup, Group):
295
295
  sage: x.to_word_list()
296
296
  [(0, 1), (1, 1), (1, 1), (4, 1), (0, -1)]
297
297
  """
298
- sign = lambda x: 1 if x > 0 else -1 # It is never 0
299
- return [ (k, sign(e)) for k,e in self._sorted_items()
300
- for dummy in range(abs(e))]
298
+ return [(k, 1 if e > 0 else -1) for k, e in self._sorted_items()
299
+ for dummy in range(abs(e))]
301
300
 
302
301
 
303
302
  class IndexedFreeAbelianGroup(IndexedGroup, AbelianGroup):
@@ -527,6 +527,7 @@ def test_integer(object x):
527
527
 
528
528
  EXAMPLES::
529
529
 
530
+ sage: import sage.libs.symmetrica.all
530
531
  sage: from sage.libs.symmetrica.symmetrica import test_integer
531
532
  sage: test_integer(1)
532
533
  1