schubmult 2.0.2__py3-none-any.whl → 2.0.4__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 (40) hide show
  1. schubmult/__init__.py +1 -1
  2. schubmult/_base_argparse.py +42 -8
  3. schubmult/_tests.py +24 -0
  4. schubmult/perm_lib.py +52 -112
  5. schubmult/sage_integration/__init__.py +13 -13
  6. schubmult/sage_integration/_fast_double_schubert_polynomial_ring.py +139 -118
  7. schubmult/sage_integration/_fast_schubert_polynomial_ring.py +88 -49
  8. schubmult/sage_integration/_indexing.py +35 -32
  9. schubmult/schubmult_double/__init__.py +6 -12
  10. schubmult/schubmult_double/__main__.py +2 -1
  11. schubmult/schubmult_double/_funcs.py +245 -281
  12. schubmult/schubmult_double/_script.py +128 -70
  13. schubmult/schubmult_py/__init__.py +5 -3
  14. schubmult/schubmult_py/__main__.py +2 -1
  15. schubmult/schubmult_py/_funcs.py +68 -23
  16. schubmult/schubmult_py/_script.py +40 -58
  17. schubmult/schubmult_q/__init__.py +3 -7
  18. schubmult/schubmult_q/__main__.py +2 -1
  19. schubmult/schubmult_q/_funcs.py +41 -60
  20. schubmult/schubmult_q/_script.py +39 -30
  21. schubmult/schubmult_q_double/__init__.py +5 -11
  22. schubmult/schubmult_q_double/__main__.py +2 -1
  23. schubmult/schubmult_q_double/_funcs.py +99 -66
  24. schubmult/schubmult_q_double/_script.py +209 -150
  25. schubmult-2.0.4.dist-info/METADATA +542 -0
  26. schubmult-2.0.4.dist-info/RECORD +30 -0
  27. {schubmult-2.0.2.dist-info → schubmult-2.0.4.dist-info}/WHEEL +1 -1
  28. schubmult-2.0.4.dist-info/entry_points.txt +5 -0
  29. {schubmult-2.0.2.dist-info → schubmult-2.0.4.dist-info}/top_level.txt +0 -1
  30. schubmult/schubmult_double/_vars.py +0 -18
  31. schubmult/schubmult_py/_vars.py +0 -3
  32. schubmult/schubmult_q/_vars.py +0 -18
  33. schubmult/schubmult_q_double/_vars.py +0 -21
  34. schubmult-2.0.2.dist-info/METADATA +0 -455
  35. schubmult-2.0.2.dist-info/RECORD +0 -36
  36. schubmult-2.0.2.dist-info/entry_points.txt +0 -5
  37. tests/__init__.py +0 -0
  38. tests/test_fast_double_schubert.py +0 -145
  39. tests/test_fast_schubert.py +0 -38
  40. {schubmult-2.0.2.dist-info → schubmult-2.0.4.dist-info}/licenses/LICENSE +0 -0
@@ -1,29 +1,35 @@
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, from_lehmer_code
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
- )
16
- from . import (
17
- FastSchubertPolynomialRing_base,
18
- FastSchubertPolynomial,
19
- )
20
- from ._indexing import _coerce_index
21
-
20
+ from sympy import sympify
22
21
 
23
- import schubmult.schubmult_q_double as qyz
22
+ # from . import (
23
+ # FastSchubertPolynomialRing_base,
24
+ # FastSchubertPolynomialRing,
25
+ # FastSchubertPolynomial,
26
+ # )
27
+ import schubmult.sage_integration._fast_schubert_polynomial_ring as bork
24
28
  import schubmult.schubmult_double as yz
25
- from sympy import sympify
26
- import symengine as syme
29
+ import schubmult.schubmult_q_double as qyz
30
+ from schubmult.perm_lib import permtrim
31
+
32
+ from ._indexing import _coerce_index
27
33
 
28
34
 
29
35
  def FastDoubleSchubertPolynomialRing(
@@ -32,12 +38,13 @@ def FastDoubleSchubertPolynomialRing(
32
38
  base_variable_name: str,
33
39
  coeff_variable_names: str | tuple[str],
34
40
  *,
35
- indices: tuple[int] = tuple([1]),
41
+ indices: tuple[int] = (1,),
36
42
  code_display: bool = False,
37
43
  q_varname: str = "q",
38
44
  is_quantum: bool = False,
39
45
  ):
40
- """Wrapper function to return a double Schubert polynomial Ring
46
+ """
47
+ Wrapper function to return a double Schubert polynomial Ring
41
48
 
42
49
  Calls the _xbasis class to return a double or quantum double Schubert
43
50
  polynomial ring with the indicated base ring, number of variables,
@@ -52,7 +59,7 @@ def FastDoubleSchubertPolynomialRing(
52
59
  X([2, 4, 3, 1]) + X([2, 1, 4, 3], "z")
53
60
  ```
54
61
 
55
- Args:
62
+ Args:
56
63
  R (sage ring): The base ring
57
64
  num_vars (int): Cardinality of the sets of variables
58
65
  base_variable_name (str): Base variable name
@@ -62,8 +69,9 @@ def FastDoubleSchubertPolynomialRing(
62
69
  q_varname (str, optional): Variable name of the q-ring. Defaults to "q".
63
70
  is_quantum (bool, optional): Whether or not the ring is quantum. Defaults to False.
64
71
 
65
- Returns:
72
+ Returns:
66
73
  FastDoubleSchubertPolynomialRing_xbasis: Basis element generator of the ring
74
+
67
75
  """
68
76
  QR = None
69
77
  if is_quantum:
@@ -90,7 +98,8 @@ def FastQuantumDoubleSchubertPolynomialRing(
90
98
  code_display=False,
91
99
  q_varname="q",
92
100
  ):
93
- """Quantum double Schubert ring generator
101
+ """
102
+ Quantum double Schubert ring generator
94
103
 
95
104
  Wraps FastDoubleSchubertPolynomialRing(), omitting indices and setting
96
105
  is_quantum to True.
@@ -105,6 +114,7 @@ def FastQuantumDoubleSchubertPolynomialRing(
105
114
 
106
115
  Returns:
107
116
  FastDoubleSchubertPolynomialRing_xbasis: Basis element generator of the quantum ring
117
+
108
118
  """
109
119
  return FastDoubleSchubertPolynomialRing(
110
120
  R,
@@ -112,7 +122,7 @@ def FastQuantumDoubleSchubertPolynomialRing(
112
122
  base_variable_name,
113
123
  coeff_variable_names,
114
124
  code_display=code_display,
115
- indices=tuple([1]),
125
+ indices=(1,),
116
126
  is_quantum=True,
117
127
  q_varname=q_varname,
118
128
  )
@@ -127,8 +137,7 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
127
137
  def q_varname(self):
128
138
  if not self.parent().is_quantum:
129
139
  return None
130
- else:
131
- return self.parent()._q_varname
140
+ return self.parent()._q_varname
132
141
 
133
142
  @property
134
143
  def base_polynomial_ring(self):
@@ -142,8 +151,7 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
142
151
  def q_ring(self):
143
152
  if not self.parent()._quantum:
144
153
  return None
145
- else:
146
- return self.parent()._q_ring
154
+ return self.parent()._q_ring
147
155
 
148
156
  def expand(self):
149
157
  if self.parent()._quantum:
@@ -157,20 +165,19 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
157
165
  v,
158
166
  )
159
167
  for k, v in self.monomial_coefficients().items()
160
- ]
161
- )
162
- else:
163
- return sum(
164
- [
165
- yz.schubmult(
166
- {(1, 2): v},
167
- tuple(_coerce_index(k[0], self.parent()._ascode, False)),
168
- self.parent()._base_polynomial_ring.gens(),
169
- self.parent()._coeff_polynomial_rings[k[1]].gens(),
170
- ).get((1, 2), 0)
171
- for k, v in self.monomial_coefficients().items()
172
- ]
168
+ ],
173
169
  )
170
+ return sum(
171
+ [
172
+ yz.schubmult(
173
+ {(1, 2): v},
174
+ tuple(_coerce_index(k[0], self.parent()._ascode, False)),
175
+ self.parent()._base_polynomial_ring.gens(),
176
+ self.parent()._coeff_polynomial_rings[k[1]].gens(),
177
+ ).get((1, 2), 0)
178
+ for k, v in self.monomial_coefficients().items()
179
+ ],
180
+ )
174
181
 
175
182
  def __eq__(self, other):
176
183
  ss = self.parent().one() * self
@@ -191,9 +198,51 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
191
198
  return self.map_coefficients(lambda foi: RR(foi.subs(subs_dict)))
192
199
 
193
200
 
201
+ @cache
202
+ def _double_schub_parser(passed):
203
+ fdict = {}
204
+ vardict = {}
205
+ fdict[passed._sc_rep] = passed._element_constructor_
206
+ if passed._quantum:
207
+ QSRing = bork.FastSchubertPolynomialRing(
208
+ passed._base_polynomial_ring.base_ring(),
209
+ len(passed._base_polynomial_ring.gens()),
210
+ passed._base_varname,
211
+ is_quantum=True,
212
+ code_display=passed._ascode,
213
+ q_varname=passed._q_varname,
214
+ )
215
+ fdict[QSRing._sc_rep] = QSRing._element_constructor_
216
+ SRing = bork.FastSchubertPolynomialRing(
217
+ passed._base_polynomial_ring.base_ring().base_ring(),
218
+ len(passed._base_polynomial_ring.gens()),
219
+ passed._base_varname,
220
+ is_quantum=False,
221
+ code_display=passed._ascode,
222
+ )
223
+ DRing = FastDoubleSchubertPolynomialRing(
224
+ passed._base_polynomial_ring.base_ring().base_ring(),
225
+ len(passed._base_polynomial_ring.gens()),
226
+ passed._base_varname,
227
+ coeff_variable_names=tuple(passed._varlist),
228
+ )
229
+ fdict[DRing._sc_rep] = DRing._element_constructor_
230
+ fdict[SRing._sc_rep] = SRing._element_constructor_
231
+ for g in passed._base_polynomial_ring.gens():
232
+ vardict[str(g)] = g
233
+ return Parser(make_function=fdict, make_var=vardict)
234
+
235
+
194
236
  class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
195
237
  Element = FastDoubleSchubertPolynomial_class
196
238
 
239
+ # def inject_variables:
240
+
241
+ def parser(self):
242
+ if self._parser is None:
243
+ self._parser = _double_schub_parser(self)
244
+ return self._parser
245
+
197
246
  def __init__(
198
247
  self,
199
248
  R,
@@ -218,21 +267,22 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
218
267
  if isinstance(coeff_variable_names, tuple):
219
268
  self._mixed = True
220
269
  self._varlist = [*coeff_variable_names]
221
- self._coeff_polynomial_rings = {
222
- name: PolynomialRing(R if not quantum else QR, num_vars, name)
223
- for name in self._varlist
224
- }
270
+ self._coeff_polynomial_rings = {name: PolynomialRing(R if not quantum else QR, num_vars, name) for name in self._varlist}
225
271
 
226
272
  self._coeff_polynomial_ring = R if not quantum else QR
227
273
  for name, CR in self._coeff_polynomial_rings.items():
228
274
  self._coeff_polynomial_ring = PolynomialRing(
229
- self._coeff_polynomial_ring, num_vars, name
275
+ self._coeff_polynomial_ring,
276
+ num_vars,
277
+ name,
230
278
  )
231
279
  self._coeff_polynomial_ring = FlatteningMorphism(self._coeff_polynomial_ring).codomain()
232
280
  else:
233
281
  self._varlist = [coeff_variable_names]
234
282
  self._coeff_polynomial_ring = PolynomialRing(
235
- R if not quantum else QR, num_vars, coeff_variable_names
283
+ R if not quantum else QR,
284
+ num_vars,
285
+ coeff_variable_names,
236
286
  )
237
287
  self._coeff_polynomial_rings = {}
238
288
  self._coeff_polynomial_rings[coeff_variable_names] = self._coeff_polynomial_ring
@@ -245,24 +295,25 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
245
295
  self._ascode = True
246
296
 
247
297
  self._base_polynomial_ring = PolynomialRing(
248
- self._coeff_polynomial_ring, num_vars, base_variable_name
298
+ self._coeff_polynomial_ring,
299
+ num_vars,
300
+ base_variable_name,
249
301
  )
250
302
 
251
303
  self._index_wrapper = cartesian_product([index_set, self._varlist])
252
- cat = (
253
- GradedAlgebrasWithBasis(self._coeff_polynomial_ring).Commutative()
254
- if quantum
255
- else GradedBialgebrasWithBasis(self._coeff_polynomial_ring).Commutative()
256
- )
304
+ cat = GradedAlgebrasWithBasis(self._coeff_polynomial_ring).Commutative() if quantum else GradedBialgebrasWithBasis(self._coeff_polynomial_ring).Commutative()
305
+
306
+ self._sc_rep = f"{'Q' if quantum else ''}DS{base_variable_name}"
257
307
 
258
308
  CombinatorialFreeModule.__init__(
259
309
  self,
260
310
  self._coeff_polynomial_ring,
261
311
  self._index_wrapper,
262
312
  category=cat,
263
- prefix=f"{'Q' if quantum else ''}S{base_variable_name}",
313
+ prefix=self._sc_rep,
264
314
  )
265
315
  self._populate_coercion_lists_()
316
+ self._parser = None
266
317
 
267
318
  @cached_method
268
319
  def one_basis(self):
@@ -281,12 +332,9 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
281
332
  elif len(x) > 2:
282
333
  raise ValueError("Bad index for element")
283
334
 
284
- if (
285
- isinstance(x, list)
286
- or isinstance(x, tuple)
287
- or isinstance(x, Permutation)
288
- or isinstance(x, Composition)
289
- ):
335
+ if isinstance(x, str):
336
+ return self.parser().parse(x)
337
+ if isinstance(x, list) or isinstance(x, tuple) or isinstance(x, Permutation) or isinstance(x, Composition):
290
338
  # checking the input to avoid symmetrica crashing Sage, see trac 12924
291
339
  if x in self._index_wrapper:
292
340
  elem = self._from_dict({self._index_wrapper((x[0], x[1])): self.base_ring().one()})
@@ -297,31 +345,19 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
297
345
  (
298
346
  _coerce_index(x, self._ascode, self._ascode),
299
347
  self._varlist[0],
300
- )
301
- ): self.base_ring().one()
302
- }
348
+ ),
349
+ ): self.base_ring().one(),
350
+ },
303
351
  )
304
352
  elif isinstance(x, FastDoubleSchubertPolynomial):
305
- if (
306
- x.base_varname == self._base_varname
307
- and (self._quantum == x.parent()._quantum)
308
- and (not self._quantum or x.q_varname == self._q_varname)
309
- ):
353
+ if x.base_varname == self._base_varname and (self._quantum == x.parent()._quantum) and (not self._quantum or x.q_varname == self._q_varname):
310
354
  elem = self._from_dict(
311
- {
312
- (_coerce_index(k[0], x.parent()._ascode, self._ascode), k[1]): v
313
- for k, v in x.monomial_coefficients().items()
314
- }
355
+ {(_coerce_index(k[0], x.parent()._ascode, self._ascode), k[1]): v for k, v in x.monomial_coefficients().items()},
315
356
  )
316
357
  else:
317
358
  return self(x.expand())
318
- elif isinstance(x, FastSchubertPolynomial):
319
- if (
320
- x.base_varname == self._base_varname
321
- and x.q_varname == self._q_varname
322
- and (self._quantum == x.parent()._quantum)
323
- and (not self._quantum or x.q_varname == self._q_varname)
324
- ):
359
+ elif isinstance(x, bork.FastSchubertPolynomial):
360
+ 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):
325
361
  elem_dict = {}
326
362
 
327
363
  for k, v in x.monomial_coefficients().items():
@@ -333,7 +369,7 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
333
369
  [
334
370
  0
335
371
  for i in range(
336
- len(self._coeff_polynomial_rings[self._varlist[0]].gens())
372
+ len(self._coeff_polynomial_rings[self._varlist[0]].gens()),
337
373
  )
338
374
  ],
339
375
  self._q_ring.gens(),
@@ -346,18 +382,15 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
346
382
  [
347
383
  0
348
384
  for i in range(
349
- len(self._coeff_polynomial_rings[self._varlist[0]].gens())
385
+ len(self._coeff_polynomial_rings[self._varlist[0]].gens()),
350
386
  )
351
387
  ],
352
388
  )
353
389
  for k0, c0 in res.items():
354
- elem_dict[(_coerce_index(k0, False, self._ascode), self._varlist[0])] = (
355
- elem_dict.get(
356
- (_coerce_index(k0, False, self._ascode), self._varlist[0]),
357
- self._coeff_polynomial_ring.zero(),
358
- )
359
- + self._coeff_polynomial_ring(c0)
360
- )
390
+ elem_dict[(_coerce_index(k0, False, self._ascode), self._varlist[0])] = elem_dict.get(
391
+ (_coerce_index(k0, False, self._ascode), self._varlist[0]),
392
+ self._coeff_polynomial_ring.zero(),
393
+ ) + self._coeff_polynomial_ring(c0)
361
394
  elem = self._from_dict(elem_dict)
362
395
  else:
363
396
  elem = self(x.expand())
@@ -372,10 +405,7 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
372
405
  {(1, 2): 1},
373
406
  val,
374
407
  [syme.Symbol(str(g)) for g in self._base_polynomial_ring.gens()],
375
- [
376
- syme.Symbol(str(g))
377
- for g in self._coeff_polynomial_rings[self._varlist[0]].gens()
378
- ],
408
+ [syme.Symbol(str(g)) for g in self._coeff_polynomial_rings[self._varlist[0]].gens()],
379
409
  [syme.Symbol(str(g)) for g in self._q_ring.gens()],
380
410
  )
381
411
  else:
@@ -383,10 +413,7 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
383
413
  {(1, 2): 1},
384
414
  val,
385
415
  [syme.Symbol(str(g)) for g in self._base_polynomial_ring.gens()],
386
- [
387
- syme.Symbol(str(g))
388
- for g in self._coeff_polynomial_rings[self._varlist[0]].gens()
389
- ],
416
+ [syme.Symbol(str(g)) for g in self._coeff_polynomial_rings[self._varlist[0]].gens()],
390
417
  )
391
418
  elem = self._from_dict(
392
419
  {
@@ -395,7 +422,7 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
395
422
  self._varlist[0],
396
423
  ): self._coeff_polynomial_ring(str(v))
397
424
  for k, v in result.items()
398
- }
425
+ },
399
426
  )
400
427
  else:
401
428
  raise TypeError
@@ -405,21 +432,15 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
405
432
  def some_elements(self):
406
433
  return [
407
434
  self.one(),
408
- self(_coerce_index([1], False, self._ascode))
409
- + 2 * self(_coerce_index([2, 1], False, self._ascode)),
410
- self(_coerce_index([4, 2, 1, 3], False, self._ascode))
411
- - self(_coerce_index([3, 2, 1], False, self._ascode)),
435
+ self(_coerce_index([1], False, self._ascode)) + 2 * self(_coerce_index([2, 1], False, self._ascode)),
436
+ self(_coerce_index([4, 2, 1, 3], False, self._ascode)) - self(_coerce_index([3, 2, 1], False, self._ascode)),
412
437
  ]
413
438
 
414
439
  def product_on_basis(self, left, right):
415
440
  le = tuple(left[0])
416
441
  ri = tuple(right[0])
417
- var_y = [
418
- self._coeff_polynomial_ring(g) for g in self._coeff_polynomial_rings[left[1]].gens()
419
- ]
420
- var_z = [
421
- self._coeff_polynomial_ring(g) for g in self._coeff_polynomial_rings[right[1]].gens()
422
- ]
442
+ var_y = [self._coeff_polynomial_ring(g) for g in self._coeff_polynomial_rings[left[1]].gens()]
443
+ var_z = [self._coeff_polynomial_ring(g) for g in self._coeff_polynomial_rings[right[1]].gens()]
423
444
  if self._quantum:
424
445
  result = qyz.schubmult_db(
425
446
  {tuple(_coerce_index(le, self._ascode, False)): 1},
@@ -437,20 +458,18 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
437
458
  )
438
459
  result = {k: v for k, v in result.items() if v != 0}
439
460
  return sum(
440
- [
441
- self._coeff_polynomial_ring(v)
442
- * self((_coerce_index(k, False, self._ascode), left[1]))
443
- for k, v in result.items()
444
- ]
461
+ [self._coeff_polynomial_ring(v) * self((_coerce_index(k, False, self._ascode), left[1])) for k, v in result.items()],
445
462
  )
446
463
 
447
464
  def _coerce_map_from_(self, S):
448
465
  if isinstance(S, MPolynomialRing_base):
449
466
  return True
450
- if isinstance(S, FastSchubertPolynomialRing_base):
467
+ if isinstance(S, bork.FastSchubertPolynomialRing_base):
451
468
  return True
452
469
  if isinstance(S, FastDoubleSchubertPolynomialRing_base):
453
470
  return True
471
+ if isinstance(S, str):
472
+ return True
454
473
  return super().has_coerce_map_from(S)
455
474
 
456
475
  def coproduct_on_basis(self, indm):
@@ -502,24 +521,26 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
502
521
  break
503
522
  if not flag:
504
523
  continue
505
- firstperm = Permutation(list(downperm[0:N]))
506
- secondperm = Permutation([downperm[i] - N for i in range(N, len(downperm))])
524
+ firstperm = Permutation(permtrim(list(downperm[0:N])))
525
+ secondperm = Permutation(
526
+ permtrim([downperm[i] - N for i in range(N, len(downperm))]),
527
+ )
507
528
  val = TR(val).subs(subs_dict_coprod)
508
529
  total_sum += self._coeff_polynomial_ring(val) * self(
509
- (_coerce_index(firstperm, False, self._ascode), indm[1])
530
+ (_coerce_index(firstperm, False, self._ascode), indm[1]),
510
531
  ).tensor(
511
532
  self(
512
533
  (
513
534
  _coerce_index(secondperm, False, self._ascode),
514
535
  self._varlist[0],
515
- )
516
- )
536
+ ),
537
+ ),
517
538
  )
518
539
  return total_sum
519
540
 
520
541
  def _repr_(self):
521
542
  return (
522
- 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"
543
+ 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
523
544
  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'}"
524
545
  )
525
546