schubmult 2.0.4__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.
- schubmult/__init__.py +94 -1
- schubmult/perm_lib.py +232 -819
- schubmult/poly_lib/__init__.py +31 -0
- schubmult/poly_lib/poly_lib.py +244 -0
- schubmult/poly_lib/schub_poly.py +148 -0
- schubmult/poly_lib/variables.py +204 -0
- schubmult/rings/__init__.py +17 -0
- schubmult/rings/_quantum_schubert_polynomial_ring.py +788 -0
- schubmult/rings/_schubert_polynomial_ring.py +1006 -0
- schubmult/rings/_tensor_schub_ring.py +128 -0
- schubmult/rings/_utils.py +55 -0
- schubmult/{sage_integration → sage}/__init__.py +4 -1
- schubmult/{sage_integration → sage}/_fast_double_schubert_polynomial_ring.py +67 -109
- schubmult/{sage_integration → sage}/_fast_schubert_polynomial_ring.py +33 -28
- schubmult/{sage_integration → sage}/_indexing.py +9 -5
- schubmult/schub_lib/__init__.py +51 -0
- schubmult/{schubmult_double/_funcs.py → schub_lib/double.py} +532 -596
- schubmult/{schubmult_q/_funcs.py → schub_lib/quantum.py} +54 -53
- schubmult/schub_lib/quantum_double.py +954 -0
- schubmult/schub_lib/schub_lib.py +659 -0
- schubmult/{schubmult_py/_funcs.py → schub_lib/single.py} +45 -35
- schubmult/schub_lib/tests/__init__.py +0 -0
- schubmult/schub_lib/tests/legacy_perm_lib.py +946 -0
- schubmult/schub_lib/tests/test_vs_old.py +109 -0
- schubmult/scripts/__init__.py +0 -0
- schubmult/scripts/schubmult_double.py +378 -0
- schubmult/scripts/schubmult_py.py +84 -0
- schubmult/scripts/schubmult_q.py +109 -0
- schubmult/scripts/schubmult_q_double.py +207 -0
- schubmult/utils/__init__.py +0 -0
- schubmult/{_base_argparse.py → utils/argparse.py} +29 -5
- schubmult/utils/logging.py +16 -0
- schubmult/utils/parsing.py +20 -0
- schubmult/utils/perm_utils.py +135 -0
- schubmult/utils/test_utils.py +65 -0
- schubmult-3.0.0.dist-info/METADATA +1234 -0
- schubmult-3.0.0.dist-info/RECORD +41 -0
- {schubmult-2.0.4.dist-info → schubmult-3.0.0.dist-info}/WHEEL +1 -1
- schubmult-3.0.0.dist-info/entry_points.txt +5 -0
- schubmult/_tests.py +0 -24
- schubmult/schubmult_double/__init__.py +0 -12
- schubmult/schubmult_double/__main__.py +0 -6
- schubmult/schubmult_double/_script.py +0 -474
- schubmult/schubmult_py/__init__.py +0 -12
- schubmult/schubmult_py/__main__.py +0 -6
- schubmult/schubmult_py/_script.py +0 -97
- schubmult/schubmult_q/__init__.py +0 -8
- schubmult/schubmult_q/__main__.py +0 -6
- schubmult/schubmult_q/_script.py +0 -166
- schubmult/schubmult_q_double/__init__.py +0 -10
- schubmult/schubmult_q_double/__main__.py +0 -6
- schubmult/schubmult_q_double/_funcs.py +0 -540
- schubmult/schubmult_q_double/_script.py +0 -396
- schubmult-2.0.4.dist-info/METADATA +0 -542
- schubmult-2.0.4.dist-info/RECORD +0 -30
- schubmult-2.0.4.dist-info/entry_points.txt +0 -5
- {schubmult-2.0.4.dist-info → schubmult-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {schubmult-2.0.4.dist-info → schubmult-3.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
from functools import cache
|
2
|
+
|
3
|
+
import symengine
|
4
|
+
from symengine import expand
|
5
|
+
from sympy import Add, Basic, Dict, Expr, Mul, sympify
|
6
|
+
|
7
|
+
import schubmult.perm_lib as pl
|
8
|
+
|
9
|
+
|
10
|
+
def _tensor_product_of_dicts(d1, d2):
|
11
|
+
ret_dict = {}
|
12
|
+
for k1, v1 in d1.items():
|
13
|
+
this_dict = {}
|
14
|
+
for k2, v2 in d2.items():
|
15
|
+
this_dict[(k1, k2)] = v1 * v2
|
16
|
+
ret_dict = pl.add_perm_dict(ret_dict, this_dict)
|
17
|
+
return Dict(ret_dict)
|
18
|
+
|
19
|
+
|
20
|
+
class TensorBasisElement(Expr):
|
21
|
+
is_commutative = False
|
22
|
+
|
23
|
+
def __new__(cls, k1, k2, basis, tensor_symbol=" # "):
|
24
|
+
obj = Expr.__new__(cls, k1, k2, basis)
|
25
|
+
obj._elem1 = basis.basis1._from_dict({k1: 1})
|
26
|
+
obj._elem2 = basis.basis2._from_dict({k2: 1})
|
27
|
+
obj._tensor_symbol = tensor_symbol
|
28
|
+
return obj
|
29
|
+
|
30
|
+
def _sympystr(self, printer):
|
31
|
+
return f"{printer.doprint(self._elem1)}{self._tensor_symbol}{printer.doprint(self._elem2)}"
|
32
|
+
|
33
|
+
|
34
|
+
class TensorAlgebraElement(Expr):
|
35
|
+
# tensor ring
|
36
|
+
def __new__(cls, _dict, basis):
|
37
|
+
return TensorAlgebraElement.__xnew_cached__(cls, Dict(_dict), basis)
|
38
|
+
|
39
|
+
@staticmethod
|
40
|
+
def __xnew__(_class, _dict, basis):
|
41
|
+
_dict = Dict({k: v for k, v in _dict.items() if expand(v) != 0})
|
42
|
+
return Expr.__new__(_class, _dict, basis)
|
43
|
+
|
44
|
+
@property
|
45
|
+
def coeff_dict(self):
|
46
|
+
return self.args[0]
|
47
|
+
|
48
|
+
@staticmethod
|
49
|
+
@cache
|
50
|
+
def __xnew_cached__(_class, _dict, basis):
|
51
|
+
return TensorAlgebraElement.__xnew__(_class, _dict, basis)
|
52
|
+
|
53
|
+
@property
|
54
|
+
def basis(self):
|
55
|
+
return self.args[1]
|
56
|
+
|
57
|
+
def __mul__(self, other):
|
58
|
+
ret_dict = {}
|
59
|
+
for k1, v1 in self.coeff_dict.items():
|
60
|
+
for k2, v2 in other.coeff_dict.items():
|
61
|
+
dict1 = self.basis.basis1._from_dict({k1[0]: v1 * v2}) * self.basis.basis1._from_dict({k2[0]: 1})
|
62
|
+
dict2 = self.basis.basis2._from_dict({k1[1]: 1}) * self.basis.basis2._from_dict({k2[1]: 1})
|
63
|
+
ret_dict = pl.add_perm_dict(ret_dict, _tensor_product_of_dicts(dict1.coeff_dict, dict2.coeff_dict))
|
64
|
+
return self.basis._from_dict(ret_dict)
|
65
|
+
|
66
|
+
def __add__(self, other):
|
67
|
+
return self.basis._from_dict(pl.add_perm_dict(self.coeff_dict, other.coeff_dict))
|
68
|
+
|
69
|
+
def __sub__(self, other):
|
70
|
+
return self.basis._from_dict(pl.add_perm_dict(self.coeff_dict, {k: -v for k, v in other.coeff_dict.items()}))
|
71
|
+
|
72
|
+
@cache
|
73
|
+
def cached_sympystr(self, printer):
|
74
|
+
ret_list = [Mul(v, TensorBasisElement(k[0], k[1], self.basis)) for k, v in self.coeff_dict.items()]
|
75
|
+
return printer.doprint(Add(*ret_list))
|
76
|
+
|
77
|
+
def _sympystr(self, printer):
|
78
|
+
return self.cached_sympystr(printer)
|
79
|
+
|
80
|
+
def expand(self, **_):
|
81
|
+
return sympify(
|
82
|
+
symengine.Add(
|
83
|
+
*[v * symengine.sympify(self.basis.basis1._from_dict({k[0]: 1}).expand()) * symengine.sympify(self.basis.basis2._from_dict({k[1]: 1}).expand()) for k, v in self.coeff_dict.items()],
|
84
|
+
),
|
85
|
+
)
|
86
|
+
|
87
|
+
|
88
|
+
class TensorAlgebraBasis(Basic):
|
89
|
+
# tensor ring
|
90
|
+
def __new__(cls, basis1, basis2):
|
91
|
+
return TensorAlgebraBasis.__xnew_cached__(cls, basis1, basis2)
|
92
|
+
|
93
|
+
@staticmethod
|
94
|
+
def __xnew__(_class, basis1, basis2):
|
95
|
+
return Basic.__new__(_class, basis1, basis2)
|
96
|
+
|
97
|
+
@property
|
98
|
+
def basis1(self):
|
99
|
+
return self.args[0]
|
100
|
+
|
101
|
+
@property
|
102
|
+
def basis2(self):
|
103
|
+
return self.args[1]
|
104
|
+
|
105
|
+
@property
|
106
|
+
def coeff_dict(self):
|
107
|
+
return self.args[0]
|
108
|
+
|
109
|
+
def _from_dict(self, _dict):
|
110
|
+
return TensorAlgebraElement(_dict, self)
|
111
|
+
|
112
|
+
@staticmethod
|
113
|
+
@cache
|
114
|
+
def __xnew_cached__(_class, basis1, basis2):
|
115
|
+
return TensorAlgebraBasis.__xnew__(_class, basis1, basis2)
|
116
|
+
|
117
|
+
def call2(self, *args):
|
118
|
+
def calla(*a):
|
119
|
+
return TensorAlgebraElement._from_dict(_tensor_product_of_dicts(self.basis1(*args).coeff_dict, self.basis2(*a).coeff_dict))
|
120
|
+
|
121
|
+
return calla
|
122
|
+
|
123
|
+
def __call__(self, *args):
|
124
|
+
return self.call2(args)
|
125
|
+
|
126
|
+
|
127
|
+
# def TensorAlgebra_basis(Basic):
|
128
|
+
# pass
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from functools import cache
|
2
|
+
|
3
|
+
from symengine import sympify
|
4
|
+
|
5
|
+
from schubmult.poly_lib.variables import GeneratingSet
|
6
|
+
|
7
|
+
NoneVar = 1e10
|
8
|
+
ZeroVar = 0
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
@cache
|
15
|
+
def poly_ring(v: str):
|
16
|
+
if v == ZeroVar:
|
17
|
+
return tuple([sympify(0) for i in range(100)])
|
18
|
+
if v == NoneVar:
|
19
|
+
return tuple([sympify(0) for i in range(100)])
|
20
|
+
return GeneratingSet(str(v))
|
21
|
+
|
22
|
+
# def _schubifyit(func):
|
23
|
+
# @wraps(func)
|
24
|
+
# def wrapper(f, g):
|
25
|
+
# g = _sympify(g)
|
26
|
+
# if isinstance(g, Poly):
|
27
|
+
# return func(f, g)
|
28
|
+
# elif isinstance(g, Integer):
|
29
|
+
# g = f.from_expr(g, *f.gens, domain=f.domain)
|
30
|
+
# return func(f, g)
|
31
|
+
# elif isinstance(g, Expr):
|
32
|
+
# try:
|
33
|
+
# g = f.from_expr(g, *f.gens)
|
34
|
+
# except PolynomialError:
|
35
|
+
# if g.is_Matrix:
|
36
|
+
# return NotImplemented
|
37
|
+
# expr_method = getattr(f.as_expr(), func.__name__)
|
38
|
+
# result = expr_method(g)
|
39
|
+
# if result is not NotImplemented:
|
40
|
+
# sympy_deprecation_warning(
|
41
|
+
# """
|
42
|
+
# Mixing Poly with non-polynomial expressions in binary
|
43
|
+
# operations is deprecated. Either explicitly convert
|
44
|
+
# the non-Poly operand to a Poly with as_poly() or
|
45
|
+
# convert the Poly to an Expr with as_expr().
|
46
|
+
# """,
|
47
|
+
# deprecated_since_version="1.6",
|
48
|
+
# active_deprecations_target="deprecated-poly-nonpoly-binary-operations",
|
49
|
+
# )
|
50
|
+
# return result
|
51
|
+
# else:
|
52
|
+
# return func(f, g)
|
53
|
+
# else:
|
54
|
+
# return NotImplemented
|
55
|
+
# return wrapper
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
try:
|
2
|
+
import sage # noqa: F401
|
3
|
+
except ImportError:
|
4
|
+
raise ImportError("SageMath is not installed. Please install SageMath to use this module.")
|
2
5
|
|
3
6
|
from ._fast_double_schubert_polynomial_ring import (
|
4
7
|
FastDoubleSchubertPolynomial,
|
@@ -10,7 +10,7 @@ from sage.combinat.composition import (
|
|
10
10
|
Compositions,
|
11
11
|
)
|
12
12
|
from sage.combinat.free_module import CombinatorialFreeModule
|
13
|
-
from sage.combinat.permutation import Permutation, Permutations
|
13
|
+
from sage.combinat.permutation import Permutation, Permutations
|
14
14
|
from sage.misc.cachefunc import cached_method
|
15
15
|
from sage.misc.parser import Parser
|
16
16
|
from sage.rings.polynomial.flatten import FlatteningMorphism
|
@@ -19,14 +19,16 @@ from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_base
|
|
19
19
|
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
20
20
|
from sympy import sympify
|
21
21
|
|
22
|
+
import schubmult.perm_lib as pl
|
23
|
+
|
22
24
|
# from . import (
|
23
25
|
# FastSchubertPolynomialRing_base,
|
24
26
|
# FastSchubertPolynomialRing,
|
25
27
|
# FastSchubertPolynomial,
|
26
|
-
# )
|
27
|
-
import schubmult.
|
28
|
-
import schubmult.
|
29
|
-
import schubmult.
|
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
34
|
from ._indexing import _coerce_index
|
@@ -153,12 +155,13 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
|
|
153
155
|
return None
|
154
156
|
return self.parent()._q_ring
|
155
157
|
|
158
|
+
# can speed this up
|
156
159
|
def expand(self):
|
157
160
|
if self.parent()._quantum:
|
158
161
|
return sum(
|
159
162
|
[
|
160
163
|
qyz.schubpoly_quantum(
|
161
|
-
|
164
|
+
pl.Permutation(_coerce_index(k[0], self.parent()._ascode, False)),
|
162
165
|
self.parent()._base_polynomial_ring.gens(),
|
163
166
|
self.parent()._coeff_polynomial_rings[k[1]].gens(),
|
164
167
|
self.parent()._q_ring.gens(),
|
@@ -169,12 +172,12 @@ class FastDoubleSchubertPolynomial_class(CombinatorialFreeModule.Element):
|
|
169
172
|
)
|
170
173
|
return sum(
|
171
174
|
[
|
172
|
-
yz.
|
173
|
-
{(
|
174
|
-
|
175
|
+
yz.schubmult_double(
|
176
|
+
{pl.Permutation([]): v},
|
177
|
+
pl.Permutation(_coerce_index(k[0], self.parent()._ascode, False)),
|
175
178
|
self.parent()._base_polynomial_ring.gens(),
|
176
179
|
self.parent()._coeff_polynomial_rings[k[1]].gens(),
|
177
|
-
).get((
|
180
|
+
).get(pl.Permutation([]), 0)
|
178
181
|
for k, v in self.monomial_coefficients().items()
|
179
182
|
],
|
180
183
|
)
|
@@ -305,6 +308,16 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
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,29 +340,22 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
326
340
|
def set_coproduct_indices(self, indices):
|
327
341
|
self._splitter = indices
|
328
342
|
|
329
|
-
def _element_constructor_(self,
|
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
|
-
if
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
},
|
351
|
-
)
|
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
|
+
)
|
352
359
|
elif isinstance(x, FastDoubleSchubertPolynomial):
|
353
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):
|
354
361
|
elem = self._from_dict(
|
@@ -362,9 +369,9 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
362
369
|
|
363
370
|
for k, v in x.monomial_coefficients().items():
|
364
371
|
if self._quantum:
|
365
|
-
res = qyz.
|
366
|
-
{(
|
367
|
-
|
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))),
|
368
375
|
self._coeff_polynomial_rings[self._varlist[0]].gens(),
|
369
376
|
[
|
370
377
|
0
|
@@ -375,9 +382,9 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
375
382
|
self._q_ring.gens(),
|
376
383
|
)
|
377
384
|
else:
|
378
|
-
res = yz.
|
379
|
-
{(
|
380
|
-
|
385
|
+
res = yz.schubmult_double(
|
386
|
+
{pl.Permutation([]): self._coeff_polynomial_ring(v)},
|
387
|
+
pl.Permutation(list(_coerce_index(k, x.parent()._ascode, False))),
|
381
388
|
self._coeff_polynomial_rings[self._varlist[0]].gens(),
|
382
389
|
[
|
383
390
|
0
|
@@ -401,16 +408,16 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
401
408
|
sympy_floff = sympify(str(x))
|
402
409
|
val = syme.sympify(sympy_floff)
|
403
410
|
if self._quantum:
|
404
|
-
result = qyz.
|
405
|
-
{(
|
411
|
+
result = qyz.mult_poly_q_double(
|
412
|
+
{pl.Permutation([]): 1},
|
406
413
|
val,
|
407
414
|
[syme.Symbol(str(g)) for g in self._base_polynomial_ring.gens()],
|
408
415
|
[syme.Symbol(str(g)) for g in self._coeff_polynomial_rings[self._varlist[0]].gens()],
|
409
416
|
[syme.Symbol(str(g)) for g in self._q_ring.gens()],
|
410
417
|
)
|
411
418
|
else:
|
412
|
-
result = yz.
|
413
|
-
{(
|
419
|
+
result = yz.mult_poly_double(
|
420
|
+
{pl.Permutation([]): 1},
|
414
421
|
val,
|
415
422
|
[syme.Symbol(str(g)) for g in self._base_polynomial_ring.gens()],
|
416
423
|
[syme.Symbol(str(g)) for g in self._coeff_polynomial_rings[self._varlist[0]].gens()],
|
@@ -437,28 +444,28 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
437
444
|
]
|
438
445
|
|
439
446
|
def product_on_basis(self, left, right):
|
440
|
-
le =
|
441
|
-
ri =
|
442
|
-
var_y = [
|
443
|
-
var_z = [
|
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()]
|
444
451
|
if self._quantum:
|
445
|
-
result = qyz.
|
446
|
-
{
|
447
|
-
|
452
|
+
result = qyz.schubmult_q_double_fast(
|
453
|
+
{pl.Permutation(le): 1},
|
454
|
+
pl.Permutation(ri),
|
448
455
|
var_y,
|
449
456
|
var_z,
|
450
|
-
self._q_ring.gens(),
|
457
|
+
[syme.sympify(str(g)) for g in self._q_ring.gens()],
|
451
458
|
)
|
452
459
|
else:
|
453
|
-
result = yz.
|
454
|
-
{
|
455
|
-
|
460
|
+
result = yz.schubmult_double(
|
461
|
+
{pl.Permutation(le): 1},
|
462
|
+
pl.Permutation(ri),
|
456
463
|
var_y,
|
457
464
|
var_z,
|
458
465
|
)
|
459
466
|
result = {k: v for k, v in result.items() if v != 0}
|
460
467
|
return sum(
|
461
|
-
[self._coeff_polynomial_ring(v) * self(
|
468
|
+
[self._coeff_polynomial_ring(str(v)) * self(_coerce_index(k, False, self._ascode), left[1]) for k, v in result.items()],
|
462
469
|
)
|
463
470
|
|
464
471
|
def _coerce_map_from_(self, S):
|
@@ -477,65 +484,16 @@ class FastDoubleSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
477
484
|
raise NotImplementedError("Quantum double Schubert polynomials have no coproduct")
|
478
485
|
indices = self._splitter
|
479
486
|
indices = sorted(indices)
|
480
|
-
subs_dict_coprod = {}
|
481
|
-
mperm = indm[0]
|
482
|
-
mperm = _coerce_index(mperm, self._ascode, False)
|
483
487
|
RR = self._coeff_polynomial_rings[indm[1]]
|
484
|
-
|
485
|
-
k = len(indices)
|
486
|
-
n = len(mperm)
|
487
|
-
kcd = [indices[i] - i - 1 for i in range(len(indices))] + [n + 1 - k for i in range(k, n)]
|
488
|
-
max_required = max([kcd[i] + i for i in range(len(kcd))])
|
489
|
-
kcd2 = kcd + [0 for i in range(len(kcd), max_required)] + [0]
|
490
|
-
N = len(kcd)
|
491
|
-
kperm = from_lehmer_code(kcd2).inverse()
|
492
|
-
# r = [sum(self.base_ring()._first_ngens(j)) for j in range(100)]
|
493
|
-
vn = [f"soible_{i}" for i in range(N * 2 + 1)]
|
494
|
-
TR = PolynomialRing(self.base_ring(), N * 2 + 1, vn)
|
495
|
-
|
496
|
-
for i in range(N * 2 + 1):
|
497
|
-
if i <= N:
|
498
|
-
subs_dict_coprod[TR.gens()[i]] = self._coeff_polynomial_ring(RR.gens()[i])
|
499
|
-
else:
|
500
|
-
subs_dict_coprod[TR.gens()[i]] = self._coeff_polynomial_ring(RBase.gens()[i - N])
|
501
|
-
|
502
|
-
coeff_dict = {tuple(kperm): 1}
|
503
|
-
coeff_dict = yz.schubmult(
|
504
|
-
coeff_dict,
|
505
|
-
tuple(mperm),
|
506
|
-
list(TR.gens()),
|
507
|
-
RR.gens(),
|
508
|
-
)
|
488
|
+
TR = self._coeff_polynomial_rings[self._varlist[0]]
|
509
489
|
|
510
|
-
|
511
|
-
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()])
|
512
491
|
total_sum = 0
|
513
|
-
for
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
for i in range(N):
|
519
|
-
if downperm[i] > N:
|
520
|
-
flag = False
|
521
|
-
break
|
522
|
-
if not flag:
|
523
|
-
continue
|
524
|
-
firstperm = Permutation(permtrim(list(downperm[0:N])))
|
525
|
-
secondperm = Permutation(
|
526
|
-
permtrim([downperm[i] - N for i in range(N, len(downperm))]),
|
527
|
-
)
|
528
|
-
val = TR(val).subs(subs_dict_coprod)
|
529
|
-
total_sum += self._coeff_polynomial_ring(val) * self(
|
530
|
-
(_coerce_index(firstperm, False, self._ascode), indm[1]),
|
531
|
-
).tensor(
|
532
|
-
self(
|
533
|
-
(
|
534
|
-
_coerce_index(secondperm, False, self._ascode),
|
535
|
-
self._varlist[0],
|
536
|
-
),
|
537
|
-
),
|
538
|
-
)
|
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]))
|
539
497
|
return total_sum
|
540
498
|
|
541
499
|
def _repr_(self):
|
@@ -17,11 +17,12 @@ from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_base
|
|
17
17
|
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
18
18
|
from sympy import sympify
|
19
19
|
|
20
|
-
import schubmult.
|
21
|
-
import schubmult.
|
22
|
-
import schubmult.
|
23
|
-
import schubmult.
|
24
|
-
import schubmult.
|
20
|
+
import schubmult.perm_lib as pl
|
21
|
+
import schubmult.sage._fast_double_schubert_polynomial_ring as bork
|
22
|
+
import schubmult.schub_lib.double as yz
|
23
|
+
import schubmult.schub_lib.quantum as sq
|
24
|
+
import schubmult.schub_lib.quantum_double as qyz
|
25
|
+
import schubmult.schub_lib.single as py
|
25
26
|
from schubmult.perm_lib import permtrim
|
26
27
|
|
27
28
|
from ._indexing import _coerce_index
|
@@ -143,7 +144,7 @@ class FastSchubertPolynomial_class(CombinatorialFreeModule.Element):
|
|
143
144
|
[
|
144
145
|
self.parent()._polynomial_ring(
|
145
146
|
qyz.schubpoly_quantum(
|
146
|
-
|
147
|
+
pl.Permutation(_coerce_index(k, self.parent()._ascode, False)),
|
147
148
|
self.parent()._polynomial_ring.gens(),
|
148
149
|
[0 for i in range(100)],
|
149
150
|
self.parent()._q_ring.gens(),
|
@@ -156,17 +157,24 @@ class FastSchubertPolynomial_class(CombinatorialFreeModule.Element):
|
|
156
157
|
return sum(
|
157
158
|
[
|
158
159
|
self.parent()._polynomial_ring(
|
159
|
-
yz.
|
160
|
-
{(
|
161
|
-
|
160
|
+
yz.schubmult_double(
|
161
|
+
{pl.Permutation([]): v},
|
162
|
+
pl.Permutation(_coerce_index(k, self.parent()._ascode, False)),
|
162
163
|
self.parent()._polynomial_ring.gens(),
|
163
164
|
[0 for i in range(100)],
|
164
|
-
).get((
|
165
|
+
).get(pl.Permutation([]), 0),
|
165
166
|
)
|
166
167
|
for k, v in self.monomial_coefficients().items()
|
167
168
|
],
|
168
169
|
)
|
169
170
|
|
171
|
+
# PDB STEP WHEN LATEX CALLED
|
172
|
+
# def _latex_(self):
|
173
|
+
# rep = "\\mathfrak{S}"
|
174
|
+
# if self.is_quantum:
|
175
|
+
# rep+=f"^{'{'}{self.q_varname}{'}'}"
|
176
|
+
# rep+="_{"+str(()"
|
177
|
+
|
170
178
|
|
171
179
|
@cache
|
172
180
|
def _single_schub_parser(passed):
|
@@ -265,12 +273,7 @@ class FastSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
265
273
|
def _element_constructor_(self, x):
|
266
274
|
if isinstance(x, str):
|
267
275
|
return self.parser().parse(x)
|
268
|
-
if (
|
269
|
-
isinstance(x, list)
|
270
|
-
or isinstance(x, tuple)
|
271
|
-
or isinstance(x, Composition)
|
272
|
-
or isinstance(x, Permutation)
|
273
|
-
):
|
276
|
+
if isinstance(x, (list, tuple, Composition, Permutation, pl.Permutation)):
|
274
277
|
# checking the input to avoid symmetrica crashing Sage, see trac 12924
|
275
278
|
elem = self._from_dict(
|
276
279
|
{_coerce_index(x, self._ascode, self._ascode): self.base_ring().one()},
|
@@ -296,15 +299,15 @@ class FastSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
296
299
|
sympy_floff = sympify(str(x))
|
297
300
|
val = syme.sympify(sympy_floff)
|
298
301
|
if self._quantum:
|
299
|
-
result = sq.
|
300
|
-
{(
|
302
|
+
result = sq.mult_poly_q(
|
303
|
+
{pl.Permutation([]): 1},
|
301
304
|
val,
|
302
305
|
[syme.Symbol(str(g)) for g in self._polynomial_ring.gens()],
|
303
306
|
[syme.Symbol(str(g)) for g in self._q_ring.gens()],
|
304
307
|
)
|
305
308
|
else:
|
306
|
-
result = py.
|
307
|
-
{(
|
309
|
+
result = py.mult_poly_py(
|
310
|
+
{pl.Permutation([]): 1},
|
308
311
|
val,
|
309
312
|
[syme.Symbol(str(g)) for g in self._polynomial_ring.gens()],
|
310
313
|
)
|
@@ -334,17 +337,17 @@ class FastSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
334
337
|
return sum(
|
335
338
|
[
|
336
339
|
self.base_ring()(str(v)) * self(_coerce_index(k, False, self._ascode))
|
337
|
-
for k, v in sq.
|
338
|
-
{
|
339
|
-
|
340
|
-
|
340
|
+
for k, v in sq.schubmult_q_fast(
|
341
|
+
{pl.Permutation(_coerce_index(left, self._ascode, False)): 1},
|
342
|
+
pl.Permutation(_coerce_index(right, self._ascode, False)),
|
343
|
+
[syme.sympify(str(g)) for g in self._q_ring.gens()],
|
341
344
|
).items()
|
342
345
|
],
|
343
346
|
)
|
344
347
|
return sum(
|
345
348
|
[
|
346
349
|
self.base_ring()(v) * self(_coerce_index(k, False, self._ascode))
|
347
|
-
for k, v in py.
|
350
|
+
for k, v in py.schubmult_py(
|
348
351
|
{tuple(_coerce_index(left, self._ascode, False)): 1},
|
349
352
|
tuple(_coerce_index(right, self._ascode, False)),
|
350
353
|
).items()
|
@@ -365,7 +368,7 @@ class FastSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
365
368
|
N = len(kcd)
|
366
369
|
kperm = from_lehmer_code(kcd2).inverse()
|
367
370
|
coeff_dict = {tuple(kperm): 1}
|
368
|
-
coeff_dict = py.
|
371
|
+
coeff_dict = py.schubmult_py(coeff_dict, tuple(mperm))
|
369
372
|
|
370
373
|
inv_kperm = kperm.number_of_inversions()
|
371
374
|
inverse_kperm = kperm.inverse()
|
@@ -390,9 +393,11 @@ class FastSchubertPolynomialRing_xbasis(CombinatorialFreeModule):
|
|
390
393
|
).tensor(self(_coerce_index(secondperm, False, self._ascode)))
|
391
394
|
return total_sum
|
392
395
|
|
396
|
+
def _latex_(self, S):
|
397
|
+
return f"Boobfucker {S}"
|
393
398
|
|
394
|
-
def _repr_(self):
|
395
|
-
|
399
|
+
def _repr_(self):
|
400
|
+
return f"Ring of Schubert polynomials in {self._base_varname} with {len(self._polynomial_ring.gens())} variables over {self._q_ring.base_ring()}"
|
396
401
|
|
397
402
|
|
398
403
|
FastSchubertPolynomial = FastSchubertPolynomial_class
|
@@ -1,21 +1,24 @@
|
|
1
1
|
from sage.combinat.composition import Composition
|
2
2
|
from sage.combinat.permutation import Permutation
|
3
3
|
|
4
|
+
import schubmult.perm_lib as pl
|
4
5
|
from schubmult.perm_lib import permtrim, trimcode, uncode
|
5
6
|
|
6
7
|
|
7
8
|
def _coerce_index(indexed_obj, is_comp, should_be_comp):
|
8
9
|
if is_comp == should_be_comp:
|
9
|
-
if isinstance(indexed_obj, list
|
10
|
+
if isinstance(indexed_obj, (list, tuple, pl.Permutation)):
|
10
11
|
if is_comp:
|
11
12
|
return Composition(trimcode(permtrim(uncode(list(indexed_obj)))))
|
12
|
-
return Permutation(permtrim(list(indexed_obj)))
|
13
|
+
return Permutation(list(permtrim(list(indexed_obj))))
|
13
14
|
if not is_comp:
|
14
15
|
if isinstance(indexed_obj, Permutation):
|
15
16
|
return indexed_obj.remove_extra_fixed_points()
|
17
|
+
if isinstance(indexed_obj, pl.Permutation):
|
18
|
+
return Permutation(list(indexed_obj))
|
16
19
|
if isinstance(indexed_obj, dict):
|
17
20
|
{
|
18
|
-
Permutation(permtrim(list(k)))
|
21
|
+
Permutation(list(permtrim(list(k)))): v
|
19
22
|
for k, v in indexed_obj.items()
|
20
23
|
}
|
21
24
|
elif is_comp:
|
@@ -24,11 +27,11 @@ def _coerce_index(indexed_obj, is_comp, should_be_comp):
|
|
24
27
|
or isinstance(indexed_obj, tuple)
|
25
28
|
or isinstance(indexed_obj, Composition)
|
26
29
|
):
|
27
|
-
return Permutation(permtrim(uncode(list(indexed_obj))))
|
30
|
+
return Permutation(list(permtrim(uncode(list(indexed_obj)))))
|
28
31
|
|
29
32
|
if isinstance(indexed_obj, dict): # keys are comps
|
30
33
|
return {
|
31
|
-
Permutation(permtrim(uncode(list(k))))
|
34
|
+
Permutation(list(permtrim(uncode(list(k))))): v
|
32
35
|
for k, v in indexed_obj.items()
|
33
36
|
}
|
34
37
|
else:
|
@@ -36,6 +39,7 @@ def _coerce_index(indexed_obj, is_comp, should_be_comp):
|
|
36
39
|
isinstance(indexed_obj, list)
|
37
40
|
or isinstance(indexed_obj, tuple)
|
38
41
|
or isinstance(indexed_obj, Permutation)
|
42
|
+
or isinstance(indexed_obj, pl.Permutation)
|
39
43
|
):
|
40
44
|
return Composition(trimcode(list(indexed_obj)))
|
41
45
|
|