schubmult 2.0.3__py3-none-any.whl → 3.0.0__py3-none-any.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 (59) hide show
  1. schubmult/__init__.py +94 -1
  2. schubmult/perm_lib.py +233 -880
  3. schubmult/poly_lib/__init__.py +31 -0
  4. schubmult/poly_lib/poly_lib.py +244 -0
  5. schubmult/poly_lib/schub_poly.py +148 -0
  6. schubmult/poly_lib/variables.py +204 -0
  7. schubmult/rings/__init__.py +17 -0
  8. schubmult/rings/_quantum_schubert_polynomial_ring.py +788 -0
  9. schubmult/rings/_schubert_polynomial_ring.py +1006 -0
  10. schubmult/rings/_tensor_schub_ring.py +128 -0
  11. schubmult/rings/_utils.py +55 -0
  12. schubmult/{sage_integration → sage}/__init__.py +17 -15
  13. schubmult/{sage_integration → sage}/_fast_double_schubert_polynomial_ring.py +142 -220
  14. schubmult/{sage_integration → sage}/_fast_schubert_polynomial_ring.py +78 -72
  15. schubmult/sage/_indexing.py +51 -0
  16. schubmult/schub_lib/__init__.py +51 -0
  17. schubmult/{schubmult_double/_funcs.py → schub_lib/double.py} +618 -798
  18. schubmult/{schubmult_q/_funcs.py → schub_lib/quantum.py} +70 -72
  19. schubmult/schub_lib/quantum_double.py +954 -0
  20. schubmult/schub_lib/schub_lib.py +659 -0
  21. schubmult/{schubmult_py/_funcs.py → schub_lib/single.py} +58 -48
  22. schubmult/schub_lib/tests/__init__.py +0 -0
  23. schubmult/schub_lib/tests/legacy_perm_lib.py +946 -0
  24. schubmult/schub_lib/tests/test_vs_old.py +109 -0
  25. schubmult/scripts/__init__.py +0 -0
  26. schubmult/scripts/schubmult_double.py +378 -0
  27. schubmult/scripts/schubmult_py.py +84 -0
  28. schubmult/scripts/schubmult_q.py +109 -0
  29. schubmult/scripts/schubmult_q_double.py +207 -0
  30. schubmult/utils/__init__.py +0 -0
  31. schubmult/{_base_argparse.py → utils/argparse.py} +40 -11
  32. schubmult/utils/logging.py +16 -0
  33. schubmult/utils/parsing.py +20 -0
  34. schubmult/utils/perm_utils.py +135 -0
  35. schubmult/utils/test_utils.py +65 -0
  36. schubmult-3.0.0.dist-info/METADATA +1234 -0
  37. schubmult-3.0.0.dist-info/RECORD +41 -0
  38. {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/WHEEL +1 -1
  39. schubmult-3.0.0.dist-info/entry_points.txt +5 -0
  40. schubmult/_tests.py +0 -9
  41. schubmult/sage_integration/_indexing.py +0 -51
  42. schubmult/schubmult_double/__init__.py +0 -22
  43. schubmult/schubmult_double/__main__.py +0 -5
  44. schubmult/schubmult_double/_script.py +0 -474
  45. schubmult/schubmult_py/__init__.py +0 -13
  46. schubmult/schubmult_py/__main__.py +0 -5
  47. schubmult/schubmult_py/_script.py +0 -96
  48. schubmult/schubmult_q/__init__.py +0 -13
  49. schubmult/schubmult_q/__main__.py +0 -5
  50. schubmult/schubmult_q/_script.py +0 -160
  51. schubmult/schubmult_q_double/__init__.py +0 -17
  52. schubmult/schubmult_q_double/__main__.py +0 -5
  53. schubmult/schubmult_q_double/_funcs.py +0 -540
  54. schubmult/schubmult_q_double/_script.py +0 -398
  55. schubmult-2.0.3.dist-info/METADATA +0 -455
  56. schubmult-2.0.3.dist-info/RECORD +0 -30
  57. schubmult-2.0.3.dist-info/entry_points.txt +0 -5
  58. {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/licenses/LICENSE +0 -0
  59. {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/top_level.txt +0 -0
@@ -1,35 +1,37 @@
1
+ from functools import cache
2
+
3
+ import symengine as syme
1
4
  from sage.all import * # noqa: F403
2
- from sage.categories.graded_bialgebras_with_basis import GradedBialgebrasWithBasis
5
+ from sage.categories.cartesian_product import cartesian_product
3
6
  from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis
7
+ from sage.categories.graded_bialgebras_with_basis import GradedBialgebrasWithBasis
8
+ from sage.combinat.composition import (
9
+ Composition,
10
+ Compositions,
11
+ )
4
12
  from sage.combinat.free_module import CombinatorialFreeModule
5
- from sage.categories.cartesian_product import cartesian_product
6
- from sage.combinat.permutation import Permutations, Permutation, from_lehmer_code
13
+ from sage.combinat.permutation import Permutation, Permutations
7
14
  from sage.misc.cachefunc import cached_method
15
+ from sage.misc.parser import Parser
16
+ from sage.rings.polynomial.flatten import FlatteningMorphism
8
17
  from sage.rings.polynomial.multi_polynomial import MPolynomial
9
18
  from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_base
10
19
  from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
11
- from sage.rings.polynomial.flatten import FlatteningMorphism
12
- from sage.combinat.composition import (
13
- Compositions,
14
- Composition,
15
- )
20
+ from sympy import sympify
21
+
22
+ import schubmult.perm_lib as pl
16
23
 
17
24
  # from . import (
18
25
  # FastSchubertPolynomialRing_base,
19
26
  # FastSchubertPolynomialRing,
20
27
  # FastSchubertPolynomial,
21
- # )
22
- import schubmult.sage_integration._fast_schubert_polynomial_ring as bork
23
- from ._indexing import _coerce_index
24
-
25
- from functools import cache
26
- import schubmult.schubmult_q_double as qyz
27
- import schubmult.schubmult_double as yz
28
- from sympy import sympify
29
- import symengine as syme
28
+ # )as
29
+ import schubmult.sage._fast_schubert_polynomial_ring as bork
30
+ import schubmult.schub_lib.double as yz
31
+ import schubmult.schub_lib.quantum_double as qyz
30
32
  from schubmult.perm_lib import permtrim
31
33
 
32
- from sage.misc.parser import Parser
34
+ from ._indexing import _coerce_index
33
35
 
34
36
 
35
37
  def FastDoubleSchubertPolynomialRing(
@@ -38,12 +40,13 @@ def FastDoubleSchubertPolynomialRing(
38
40
  base_variable_name: str,
39
41
  coeff_variable_names: str | tuple[str],
40
42
  *,
41
- indices: tuple[int] = tuple([1]),
43
+ indices: tuple[int] = (1,),
42
44
  code_display: bool = False,
43
45
  q_varname: str = "q",
44
46
  is_quantum: bool = False,
45
47
  ):
46
- """Wrapper function to return a double Schubert polynomial Ring
48
+ """
49
+ Wrapper function to return a double Schubert polynomial Ring
47
50
 
48
51
  Calls the _xbasis class to return a double or quantum double Schubert
49
52
  polynomial ring with the indicated base ring, number of variables,
@@ -58,7 +61,7 @@ def FastDoubleSchubertPolynomialRing(
58
61
  X([2, 4, 3, 1]) + X([2, 1, 4, 3], "z")
59
62
  ```
60
63
 
61
- Args:
64
+ Args:
62
65
  R (sage ring): The base ring
63
66
  num_vars (int): Cardinality of the sets of variables
64
67
  base_variable_name (str): Base variable name
@@ -68,8 +71,9 @@ def FastDoubleSchubertPolynomialRing(
68
71
  q_varname (str, optional): Variable name of the q-ring. Defaults to "q".
69
72
  is_quantum (bool, optional): Whether or not the ring is quantum. Defaults to False.
70
73
 
71
- Returns:
74
+ Returns:
72
75
  FastDoubleSchubertPolynomialRing_xbasis: Basis element generator of the ring
76
+
73
77
  """
74
78
  QR = None
75
79
  if is_quantum:
@@ -96,7 +100,8 @@ def FastQuantumDoubleSchubertPolynomialRing(
96
100
  code_display=False,
97
101
  q_varname="q",
98
102
  ):
99
- """Quantum double Schubert ring generator
103
+ """
104
+ Quantum double Schubert ring generator
100
105
 
101
106
  Wraps FastDoubleSchubertPolynomialRing(), omitting indices and setting
102
107
  is_quantum to True.
@@ -111,6 +116,7 @@ def FastQuantumDoubleSchubertPolynomialRing(
111
116
 
112
117
  Returns:
113
118
  FastDoubleSchubertPolynomialRing_xbasis: Basis element generator of the quantum ring
119
+
114
120
  """
115
121
  return FastDoubleSchubertPolynomialRing(
116
122
  R,
@@ -118,7 +124,7 @@ def FastQuantumDoubleSchubertPolynomialRing(
118
124
  base_variable_name,
119
125
  coeff_variable_names,
120
126
  code_display=code_display,
121
- indices=tuple([1]),
127
+ indices=(1,),
122
128
  is_quantum=True,
123
129
  q_varname=q_varname,
124
130
  )
@@ -133,8 +139,7 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
133
139
  def q_varname(self):
134
140
  if not self.parent().is_quantum:
135
141
  return None
136
- else:
137
- return self.parent()._q_varname
142
+ return self.parent()._q_varname
138
143
 
139
144
  @property
140
145
  def base_polynomial_ring(self):
@@ -148,35 +153,34 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
148
153
  def q_ring(self):
149
154
  if not self.parent()._quantum:
150
155
  return None
151
- else:
152
- return self.parent()._q_ring
156
+ return self.parent()._q_ring
153
157
 
158
+ # can speed this up
154
159
  def expand(self):
155
160
  if self.parent()._quantum:
156
161
  return sum(
157
162
  [
158
163
  qyz.schubpoly_quantum(
159
- tuple(_coerce_index(k[0], self.parent()._ascode, False)),
164
+ pl.Permutation(_coerce_index(k[0], self.parent()._ascode, False)),
160
165
  self.parent()._base_polynomial_ring.gens(),
161
166
  self.parent()._coeff_polynomial_rings[k[1]].gens(),
162
167
  self.parent()._q_ring.gens(),
163
168
  v,
164
169
  )
165
170
  for k, v in self.monomial_coefficients().items()
166
- ]
167
- )
168
- else:
169
- return sum(
170
- [
171
- yz.schubmult(
172
- {(1, 2): v},
173
- tuple(_coerce_index(k[0], self.parent()._ascode, False)),
174
- self.parent()._base_polynomial_ring.gens(),
175
- self.parent()._coeff_polynomial_rings[k[1]].gens(),
176
- ).get((1, 2), 0)
177
- for k, v in self.monomial_coefficients().items()
178
- ]
171
+ ],
179
172
  )
173
+ return sum(
174
+ [
175
+ yz.schubmult_double(
176
+ {pl.Permutation([]): v},
177
+ pl.Permutation(_coerce_index(k[0], self.parent()._ascode, False)),
178
+ self.parent()._base_polynomial_ring.gens(),
179
+ self.parent()._coeff_polynomial_rings[k[1]].gens(),
180
+ ).get(pl.Permutation([]), 0)
181
+ for k, v in self.monomial_coefficients().items()
182
+ ],
183
+ )
180
184
 
181
185
  def __eq__(self, other):
182
186
  ss = self.parent().one() * self
@@ -202,7 +206,7 @@ def _double_schub_parser(passed):
202
206
  fdict = {}
203
207
  vardict = {}
204
208
  fdict[passed._sc_rep] = passed._element_constructor_
205
- if passed._quantum:
209
+ if passed._quantum:
206
210
  QSRing = bork.FastSchubertPolynomialRing(
207
211
  passed._base_polynomial_ring.base_ring(),
208
212
  len(passed._base_polynomial_ring.gens()),
@@ -211,31 +215,31 @@ def _double_schub_parser(passed):
211
215
  code_display=passed._ascode,
212
216
  q_varname=passed._q_varname,
213
217
  )
214
- fdict[QSRing._sc_rep] = QSRing._element_constructor_
218
+ fdict[QSRing._sc_rep] = QSRing._element_constructor_
215
219
  SRing = bork.FastSchubertPolynomialRing(
216
- passed._base_polynomial_ring.base_ring().base_ring(),
217
- len(passed._base_polynomial_ring.gens()),
218
- passed._base_varname,
219
- is_quantum=False,
220
- code_display=passed._ascode,
221
- )
220
+ passed._base_polynomial_ring.base_ring().base_ring(),
221
+ len(passed._base_polynomial_ring.gens()),
222
+ passed._base_varname,
223
+ is_quantum=False,
224
+ code_display=passed._ascode,
225
+ )
222
226
  DRing = FastDoubleSchubertPolynomialRing(
223
- passed._base_polynomial_ring.base_ring().base_ring(),
224
- len(passed._base_polynomial_ring.gens()),
225
- passed._base_varname,
226
- coeff_variable_names=tuple(passed._varlist),
227
- )
227
+ passed._base_polynomial_ring.base_ring().base_ring(),
228
+ len(passed._base_polynomial_ring.gens()),
229
+ passed._base_varname,
230
+ coeff_variable_names=tuple(passed._varlist),
231
+ )
228
232
  fdict[DRing._sc_rep] = DRing._element_constructor_
229
- fdict[SRing._sc_rep] = SRing._element_constructor_
233
+ fdict[SRing._sc_rep] = SRing._element_constructor_
230
234
  for g in passed._base_polynomial_ring.gens():
231
- vardict[str(g)] = g
235
+ vardict[str(g)] = g
232
236
  return Parser(make_function=fdict, make_var=vardict)
233
237
 
234
238
 
235
239
  class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
236
240
  Element = FastDoubleSchubertPolynomial_class
237
241
 
238
- #def inject_variables:
242
+ # def inject_variables:
239
243
 
240
244
  def parser(self):
241
245
  if self._parser is None:
@@ -266,21 +270,22 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
266
270
  if isinstance(coeff_variable_names, tuple):
267
271
  self._mixed = True
268
272
  self._varlist = [*coeff_variable_names]
269
- self._coeff_polynomial_rings = {
270
- name: PolynomialRing(R if not quantum else QR, num_vars, name)
271
- for name in self._varlist
272
- }
273
+ self._coeff_polynomial_rings = {name: PolynomialRing(R if not quantum else QR, num_vars, name) for name in self._varlist}
273
274
 
274
275
  self._coeff_polynomial_ring = R if not quantum else QR
275
276
  for name, CR in self._coeff_polynomial_rings.items():
276
277
  self._coeff_polynomial_ring = PolynomialRing(
277
- self._coeff_polynomial_ring, num_vars, name
278
+ self._coeff_polynomial_ring,
279
+ num_vars,
280
+ name,
278
281
  )
279
282
  self._coeff_polynomial_ring = FlatteningMorphism(self._coeff_polynomial_ring).codomain()
280
283
  else:
281
284
  self._varlist = [coeff_variable_names]
282
285
  self._coeff_polynomial_ring = PolynomialRing(
283
- R if not quantum else QR, num_vars, coeff_variable_names
286
+ R if not quantum else QR,
287
+ num_vars,
288
+ coeff_variable_names,
284
289
  )
285
290
  self._coeff_polynomial_rings = {}
286
291
  self._coeff_polynomial_rings[coeff_variable_names] = self._coeff_polynomial_ring
@@ -293,18 +298,26 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
293
298
  self._ascode = True
294
299
 
295
300
  self._base_polynomial_ring = PolynomialRing(
296
- self._coeff_polynomial_ring, num_vars, base_variable_name
301
+ self._coeff_polynomial_ring,
302
+ num_vars,
303
+ base_variable_name,
297
304
  )
298
305
 
299
306
  self._index_wrapper = cartesian_product([index_set, self._varlist])
300
- cat = (
301
- GradedAlgebrasWithBasis(self._coeff_polynomial_ring).Commutative()
302
- if quantum
303
- else GradedBialgebrasWithBasis(self._coeff_polynomial_ring).Commutative()
304
- )
307
+ cat = GradedAlgebrasWithBasis(self._coeff_polynomial_ring).Commutative() if quantum else GradedBialgebrasWithBasis(self._coeff_polynomial_ring).Commutative()
305
308
 
306
309
  self._sc_rep = f"{'Q' if quantum else ''}DS{base_variable_name}"
307
310
 
311
+ # [('bracket', None),
312
+ # ('iterate_key', False),
313
+ # ('latex_bracket', False), ('latex_names', None),
314
+ # ('latex_prefix', None), ('latex_scalar_mult', None),
315
+ # ('names', None), ('prefix', 'x'),
316
+ # ('scalar_mult', '*'),
317
+ # ('sorting_key', <function ...<lambda> at ...>),
318
+ # ('sorting_reverse', False), ('string_quotes', True),
319
+ # ('tensor_symbol', None)]
320
+
308
321
  CombinatorialFreeModule.__init__(
309
322
  self,
310
323
  self._coeff_polynomial_ring,
@@ -312,6 +325,7 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
312
325
  category=cat,
313
326
  prefix=self._sc_rep,
314
327
  )
328
+ # print_options
315
329
  self._populate_coercion_lists_()
316
330
  self._parser = None
317
331
 
@@ -326,91 +340,64 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
326
340
  def set_coproduct_indices(self, indices):
327
341
  self._splitter = indices
328
342
 
329
- def _element_constructor_(self, *x):
330
- if len(x) == 1:
331
- x = x[0]
332
- elif len(x) > 2:
333
- raise ValueError("Bad index for element")
334
-
343
+ def _element_constructor_(self, x, vname=None):
335
344
  if isinstance(x, str):
336
345
  return self.parser().parse(x)
337
- elif (
338
- isinstance(x, list)
339
- or isinstance(x, tuple)
340
- or isinstance(x, Permutation)
341
- or isinstance(x, Composition)
342
- ):
343
- # checking the input to avoid symmetrica crashing Sage, see trac 12924
344
- if x in self._index_wrapper:
345
- elem = self._from_dict({self._index_wrapper((x[0], x[1])): self.base_ring().one()})
346
- else:
347
- elem = self._from_dict(
348
- {
349
- self._index_wrapper(
350
- (
351
- _coerce_index(x, self._ascode, self._ascode),
352
- self._varlist[0],
353
- )
354
- ): self.base_ring().one()
355
- }
356
- )
346
+ if (x, vname) in self._index_wrapper:
347
+ elem = self._from_dict({self._index_wrapper((x, vname)): self.base_ring().one()})
348
+ elif isinstance(x, list) or isinstance(x, tuple) or isinstance(x, Permutation) or isinstance(x, Composition) or isinstance(x, pl.Permutation):
349
+ elem = self._from_dict(
350
+ {
351
+ self._index_wrapper(
352
+ (
353
+ _coerce_index(x, self._ascode, self._ascode),
354
+ self._varlist[0] if vname is None else vname,
355
+ ),
356
+ ): self.base_ring().one(),
357
+ },
358
+ )
357
359
  elif isinstance(x, FastDoubleSchubertPolynomial):
358
- if (
359
- x.base_varname == self._base_varname
360
- and (self._quantum == x.parent()._quantum)
361
- and (not self._quantum or x.q_varname == self._q_varname)
362
- ):
360
+ if x.base_varname == self._base_varname and (self._quantum == x.parent()._quantum) and (not self._quantum or x.q_varname == self._q_varname):
363
361
  elem = self._from_dict(
364
- {
365
- (_coerce_index(k[0], x.parent()._ascode, self._ascode), k[1]): v
366
- for k, v in x.monomial_coefficients().items()
367
- }
362
+ {(_coerce_index(k[0], x.parent()._ascode, self._ascode), k[1]): v for k, v in x.monomial_coefficients().items()},
368
363
  )
369
364
  else:
370
365
  return self(x.expand())
371
366
  elif isinstance(x, bork.FastSchubertPolynomial):
372
- if (
373
- x.base_varname == self._base_varname
374
- and x.q_varname == self._q_varname
375
- and (self._quantum == x.parent()._quantum)
376
- and (not self._quantum or x.q_varname == self._q_varname)
377
- ):
367
+ if x.base_varname == self._base_varname and x.q_varname == self._q_varname and (self._quantum == x.parent()._quantum) and (not self._quantum or x.q_varname == self._q_varname):
378
368
  elem_dict = {}
379
369
 
380
370
  for k, v in x.monomial_coefficients().items():
381
371
  if self._quantum:
382
- res = qyz.schubmult_db(
383
- {(1, 2): self._coeff_polynomial_ring(v)},
384
- tuple(_coerce_index(k, x.parent()._ascode, False)),
372
+ res = qyz.schubmult_q_double_fast(
373
+ {pl.Permutation([]): self._coeff_polynomial_ring(v)},
374
+ pl.Permutation(list(_coerce_index(k, x.parent()._ascode, False))),
385
375
  self._coeff_polynomial_rings[self._varlist[0]].gens(),
386
376
  [
387
377
  0
388
378
  for i in range(
389
- len(self._coeff_polynomial_rings[self._varlist[0]].gens())
379
+ len(self._coeff_polynomial_rings[self._varlist[0]].gens()),
390
380
  )
391
381
  ],
392
382
  self._q_ring.gens(),
393
383
  )
394
384
  else:
395
- res = yz.schubmult(
396
- {(1, 2): self._coeff_polynomial_ring(v)},
397
- tuple(_coerce_index(k, x.parent()._ascode, False)),
385
+ res = yz.schubmult_double(
386
+ {pl.Permutation([]): self._coeff_polynomial_ring(v)},
387
+ pl.Permutation(list(_coerce_index(k, x.parent()._ascode, False))),
398
388
  self._coeff_polynomial_rings[self._varlist[0]].gens(),
399
389
  [
400
390
  0
401
391
  for i in range(
402
- len(self._coeff_polynomial_rings[self._varlist[0]].gens())
392
+ len(self._coeff_polynomial_rings[self._varlist[0]].gens()),
403
393
  )
404
394
  ],
405
395
  )
406
396
  for k0, c0 in res.items():
407
- elem_dict[(_coerce_index(k0, False, self._ascode), self._varlist[0])] = (
408
- elem_dict.get(
409
- (_coerce_index(k0, False, self._ascode), self._varlist[0]),
410
- self._coeff_polynomial_ring.zero(),
411
- )
412
- + self._coeff_polynomial_ring(c0)
413
- )
397
+ elem_dict[(_coerce_index(k0, False, self._ascode), self._varlist[0])] = elem_dict.get(
398
+ (_coerce_index(k0, False, self._ascode), self._varlist[0]),
399
+ self._coeff_polynomial_ring.zero(),
400
+ ) + self._coeff_polynomial_ring(c0)
414
401
  elem = self._from_dict(elem_dict)
415
402
  else:
416
403
  elem = self(x.expand())
@@ -421,25 +408,19 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
421
408
  sympy_floff = sympify(str(x))
422
409
  val = syme.sympify(sympy_floff)
423
410
  if self._quantum:
424
- result = qyz.mult_poly(
425
- {(1, 2): 1},
411
+ result = qyz.mult_poly_q_double(
412
+ {pl.Permutation([]): 1},
426
413
  val,
427
414
  [syme.Symbol(str(g)) for g in self._base_polynomial_ring.gens()],
428
- [
429
- syme.Symbol(str(g))
430
- for g in self._coeff_polynomial_rings[self._varlist[0]].gens()
431
- ],
415
+ [syme.Symbol(str(g)) for g in self._coeff_polynomial_rings[self._varlist[0]].gens()],
432
416
  [syme.Symbol(str(g)) for g in self._q_ring.gens()],
433
417
  )
434
418
  else:
435
- result = yz.mult_poly(
436
- {(1, 2): 1},
419
+ result = yz.mult_poly_double(
420
+ {pl.Permutation([]): 1},
437
421
  val,
438
422
  [syme.Symbol(str(g)) for g in self._base_polynomial_ring.gens()],
439
- [
440
- syme.Symbol(str(g))
441
- for g in self._coeff_polynomial_rings[self._varlist[0]].gens()
442
- ],
423
+ [syme.Symbol(str(g)) for g in self._coeff_polynomial_rings[self._varlist[0]].gens()],
443
424
  )
444
425
  elem = self._from_dict(
445
426
  {
@@ -448,7 +429,7 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
448
429
  self._varlist[0],
449
430
  ): self._coeff_polynomial_ring(str(v))
450
431
  for k, v in result.items()
451
- }
432
+ },
452
433
  )
453
434
  else:
454
435
  raise TypeError
@@ -458,43 +439,33 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
458
439
  def some_elements(self):
459
440
  return [
460
441
  self.one(),
461
- self(_coerce_index([1], False, self._ascode))
462
- + 2 * self(_coerce_index([2, 1], False, self._ascode)),
463
- self(_coerce_index([4, 2, 1, 3], False, self._ascode))
464
- - self(_coerce_index([3, 2, 1], False, self._ascode)),
442
+ self(_coerce_index([1], False, self._ascode)) + 2 * self(_coerce_index([2, 1], False, self._ascode)),
443
+ self(_coerce_index([4, 2, 1, 3], False, self._ascode)) - self(_coerce_index([3, 2, 1], False, self._ascode)),
465
444
  ]
466
445
 
467
446
  def product_on_basis(self, left, right):
468
- le = tuple(left[0])
469
- ri = tuple(right[0])
470
- var_y = [
471
- self._coeff_polynomial_ring(g) for g in self._coeff_polynomial_rings[left[1]].gens()
472
- ]
473
- var_z = [
474
- self._coeff_polynomial_ring(g) for g in self._coeff_polynomial_rings[right[1]].gens()
475
- ]
447
+ le = _coerce_index(left[0], self._ascode, False)
448
+ ri = _coerce_index(right[0], self._ascode, False)
449
+ var_y = [syme.sympify(str(g)) for g in self._coeff_polynomial_rings[left[1]].gens()]
450
+ var_z = [syme.sympify(str(g)) for g in self._coeff_polynomial_rings[right[1]].gens()]
476
451
  if self._quantum:
477
- result = qyz.schubmult_db(
478
- {tuple(_coerce_index(le, self._ascode, False)): 1},
479
- tuple(_coerce_index(ri, self._ascode, False)),
452
+ result = qyz.schubmult_q_double_fast(
453
+ {pl.Permutation(le): 1},
454
+ pl.Permutation(ri),
480
455
  var_y,
481
456
  var_z,
482
- self._q_ring.gens(),
457
+ [syme.sympify(str(g)) for g in self._q_ring.gens()],
483
458
  )
484
459
  else:
485
- result = yz.schubmult(
486
- {tuple(_coerce_index(le, self._ascode, False)): 1},
487
- tuple(_coerce_index(ri, self._ascode, False)),
460
+ result = yz.schubmult_double(
461
+ {pl.Permutation(le): 1},
462
+ pl.Permutation(ri),
488
463
  var_y,
489
464
  var_z,
490
465
  )
491
466
  result = {k: v for k, v in result.items() if v != 0}
492
467
  return sum(
493
- [
494
- self._coeff_polynomial_ring(v)
495
- * self((_coerce_index(k, False, self._ascode), left[1]))
496
- for k, v in result.items()
497
- ]
468
+ [self._coeff_polynomial_ring(str(v)) * self(_coerce_index(k, False, self._ascode), left[1]) for k, v in result.items()],
498
469
  )
499
470
 
500
471
  def _coerce_map_from_(self, S):
@@ -513,70 +484,21 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
513
484
  raise NotImplementedError("Quantum double Schubert polynomials have no coproduct")
514
485
  indices = self._splitter
515
486
  indices = sorted(indices)
516
- subs_dict_coprod = {}
517
- mperm = indm[0]
518
- mperm = _coerce_index(mperm, self._ascode, False)
519
487
  RR = self._coeff_polynomial_rings[indm[1]]
520
- RBase = self._coeff_polynomial_rings[self._varlist[0]]
521
- k = len(indices)
522
- n = len(mperm)
523
- kcd = [indices[i] - i - 1 for i in range(len(indices))] + [n + 1 - k for i in range(k, n)]
524
- max_required = max([kcd[i] + i for i in range(len(kcd))])
525
- kcd2 = kcd + [0 for i in range(len(kcd), max_required)] + [0]
526
- N = len(kcd)
527
- kperm = from_lehmer_code(kcd2).inverse()
528
- # r = [sum(self.base_ring()._first_ngens(j)) for j in range(100)]
529
- vn = [f"soible_{i}" for i in range(N * 2 + 1)]
530
- TR = PolynomialRing(self.base_ring(), N * 2 + 1, vn)
531
-
532
- for i in range(N * 2 + 1):
533
- if i <= N:
534
- subs_dict_coprod[TR.gens()[i]] = self._coeff_polynomial_ring(RR.gens()[i])
535
- else:
536
- subs_dict_coprod[TR.gens()[i]] = self._coeff_polynomial_ring(RBase.gens()[i - N])
537
-
538
- coeff_dict = {tuple(kperm): 1}
539
- coeff_dict = yz.schubmult(
540
- coeff_dict,
541
- tuple(mperm),
542
- list(TR.gens()),
543
- RR.gens(),
544
- )
488
+ TR = self._coeff_polynomial_rings[self._varlist[0]]
545
489
 
546
- inv_kperm = kperm.number_of_inversions()
547
- inverse_kperm = kperm.inverse()
490
+ coeff_dict = yz.schub_coprod_double(permtrim(indm[0]), indices, [syme.sympify(str(g)) for g in TR.gens()], [syme.sympify(str(g)) for g in RR.gens()])
548
491
  total_sum = 0
549
- for perm, val in coeff_dict.items():
550
- pperm = Permutation(list(perm))
551
- downperm = pperm.left_action_product(inverse_kperm)
552
- if downperm.number_of_inversions() == pperm.number_of_inversions() - inv_kperm:
553
- flag = True
554
- for i in range(N):
555
- if downperm[i] > N:
556
- flag = False
557
- break
558
- if not flag:
559
- continue
560
- firstperm = Permutation(permtrim(list(downperm[0:N])))
561
- secondperm = Permutation(
562
- permtrim([downperm[i] - N for i in range(N, len(downperm))])
563
- )
564
- val = TR(val).subs(subs_dict_coprod)
565
- total_sum += self._coeff_polynomial_ring(val) * self(
566
- (_coerce_index(firstperm, False, self._ascode), indm[1])
567
- ).tensor(
568
- self(
569
- (
570
- _coerce_index(secondperm, False, self._ascode),
571
- self._varlist[0],
572
- )
573
- )
574
- )
492
+ for (fp, sp), val in coeff_dict.items():
493
+ firstperm = Permutation(list(fp))
494
+ secondperm = Permutation(list(sp))
495
+ # val = syme.sympify(val).subs(subs_dict_coprod)
496
+ total_sum += self._coeff_polynomial_ring(val) * self(_coerce_index(firstperm, False, self._ascode), indm[1]).tensor(self(_coerce_index(secondperm, False, self._ascode), self._varlist[0]))
575
497
  return total_sum
576
498
 
577
499
  def _repr_(self):
578
500
  return (
579
- f"Ring of {'quantum' if self._quantum else ''} double Schubert polynomials in {self._base_varname}{',' + self._q_varname if self._quantum else ''} with {len(self._base_polynomial_ring.gens())} variables with"
501
+ f"Ring of {'quantum' if self._quantum else ''} double Schubert polynomials in {self._base_varname}{',' + self._q_varname if self._quantum else ''} with {len(self._base_polynomial_ring.gens())} variables with" # noqa: E501
580
502
  f" coefficient variables {','.join(self._varlist)} over the ring {self._coeff_polynomial_ring.base_ring()} indexed by {'the Lehmer code' if self._ascode else 'permutations'}"
581
503
  )
582
504