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.
- schubmult/__init__.py +94 -1
- schubmult/perm_lib.py +233 -880
- 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 +17 -15
- schubmult/{sage_integration → sage}/_fast_double_schubert_polynomial_ring.py +142 -220
- schubmult/{sage_integration → sage}/_fast_schubert_polynomial_ring.py +78 -72
- schubmult/sage/_indexing.py +51 -0
- schubmult/schub_lib/__init__.py +51 -0
- schubmult/{schubmult_double/_funcs.py → schub_lib/double.py} +618 -798
- schubmult/{schubmult_q/_funcs.py → schub_lib/quantum.py} +70 -72
- 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} +58 -48
- 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} +40 -11
- 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.3.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 -9
- schubmult/sage_integration/_indexing.py +0 -51
- schubmult/schubmult_double/__init__.py +0 -22
- schubmult/schubmult_double/__main__.py +0 -5
- schubmult/schubmult_double/_script.py +0 -474
- schubmult/schubmult_py/__init__.py +0 -13
- schubmult/schubmult_py/__main__.py +0 -5
- schubmult/schubmult_py/_script.py +0 -96
- schubmult/schubmult_q/__init__.py +0 -13
- schubmult/schubmult_q/__main__.py +0 -5
- schubmult/schubmult_q/_script.py +0 -160
- schubmult/schubmult_q_double/__init__.py +0 -17
- schubmult/schubmult_q_double/__main__.py +0 -5
- schubmult/schubmult_q_double/_funcs.py +0 -540
- schubmult/schubmult_q_double/_script.py +0 -398
- schubmult-2.0.3.dist-info/METADATA +0 -455
- schubmult-2.0.3.dist-info/RECORD +0 -30
- schubmult-2.0.3.dist-info/entry_points.txt +0 -5
- {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/top_level.txt +0 -0
schubmult/perm_lib.py
CHANGED
@@ -1,56 +1,198 @@
|
|
1
|
-
|
2
|
-
from functools import cache
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
import math
|
2
|
+
from functools import cache, cached_property
|
3
|
+
|
4
|
+
import sympy.combinatorics.permutations as spp
|
5
|
+
from symengine import sympify
|
6
|
+
from sympy import Basic, Tuple
|
7
|
+
|
8
|
+
import schubmult.utils.logging as lg
|
9
|
+
from schubmult.utils.perm_utils import cyclic_sort, permtrim_list, sg
|
10
|
+
|
11
|
+
# schubmult.poly_lib.variables import GeneratingSet
|
12
|
+
|
13
|
+
logger = lg.get_logger(__name__)
|
6
14
|
|
7
15
|
zero = sympify(0)
|
8
16
|
n = 100
|
9
17
|
|
10
|
-
|
18
|
+
# TODO: permutations act
|
19
|
+
|
20
|
+
|
21
|
+
class Permutation(Basic):
|
22
|
+
def __new__(cls, perm):
|
23
|
+
return Permutation.__xnew_cached__(cls, tuple(perm))
|
24
|
+
|
25
|
+
print_as_code = False
|
26
|
+
|
27
|
+
@staticmethod
|
28
|
+
@cache
|
29
|
+
def __xnew_cached__(_class, perm):
|
30
|
+
return Permutation.__xnew__(_class, perm)
|
31
|
+
|
32
|
+
@staticmethod
|
33
|
+
def __xnew__(_class, perm):
|
34
|
+
p = tuple(permtrim_list([*perm]))
|
35
|
+
s_perm = spp.Permutation._af_new([i - 1 for i in p])
|
36
|
+
obj = Basic.__new__(_class, Tuple(*perm))
|
37
|
+
obj._s_perm = s_perm
|
38
|
+
obj._perm = p
|
39
|
+
obj._hash_code = hash(p)
|
40
|
+
cd = s_perm.inversion_vector()
|
41
|
+
obj._unique_key = (len(p), sum([cd[i] * math.factorial(len(p) - 1 - i) for i in range(len(cd))]))
|
42
|
+
return obj
|
43
|
+
|
44
|
+
@classmethod
|
45
|
+
def sorting_perm(cls, itera):
|
46
|
+
L = [i + 1 for i in range(len(itera))]
|
47
|
+
L.sort(key=lambda i: itera[i - 1])
|
48
|
+
return Permutation(L)
|
49
|
+
|
50
|
+
def _sympystr(self, printer):
|
51
|
+
if Permutation.print_as_code:
|
52
|
+
return printer.doprint(trimcode(self))
|
53
|
+
return printer.doprint(self._perm)
|
54
|
+
|
55
|
+
def __call__(self, i):
|
56
|
+
"""1-indexed"""
|
57
|
+
return self[i - 1]
|
58
|
+
|
59
|
+
def descents(self, zero_indexed=True):
|
60
|
+
if zero_indexed:
|
61
|
+
return self._s_perm.descents()
|
62
|
+
return {i + 1 for i in self._s_perm.descents()}
|
63
|
+
|
64
|
+
def get_cycles(self):
|
65
|
+
return self.get_cycles_cached()
|
66
|
+
|
67
|
+
@cache
|
68
|
+
def get_cycles_cached(self):
|
69
|
+
return [tuple(cyclic_sort([i + 1 for i in c])) for c in self._s_perm.cyclic_form]
|
70
|
+
|
71
|
+
@property
|
72
|
+
def code(self):
|
73
|
+
return list(self.cached_code())
|
74
|
+
|
75
|
+
@cache
|
76
|
+
def cached_code(self):
|
77
|
+
return self._s_perm.inversion_vector()
|
78
|
+
|
79
|
+
@cached_property
|
80
|
+
def inv(self):
|
81
|
+
return self._s_perm.inversions()
|
82
|
+
|
83
|
+
def swap(self, i, j):
|
84
|
+
new_perm = [*self._perm]
|
85
|
+
# print(f"SWAP {new_perm=}")
|
86
|
+
if i > j:
|
87
|
+
i, j = j, i
|
88
|
+
if j >= len(new_perm):
|
89
|
+
# print(f"SWAP {j}>={new_perm=}")
|
90
|
+
new_perm += list(range(len(new_perm) + 1, j + 2))
|
91
|
+
# print(f"SWAP extended {new_perm=}")
|
92
|
+
new_perm[i], new_perm[j] = new_perm[j], new_perm[i]
|
93
|
+
# print(f"SWAP iddle {new_perm=}")
|
94
|
+
return Permutation(new_perm)
|
95
|
+
|
96
|
+
def __getitem__(self, i):
|
97
|
+
if isinstance(i, slice):
|
98
|
+
return [self[ii] for ii in range(i.start if i.start is not None else 0, i.stop if i.stop is not None else len(self))]
|
99
|
+
if i >= len(self._perm):
|
100
|
+
return i + 1
|
101
|
+
return self._perm[i]
|
102
|
+
|
103
|
+
def __setitem__(self, i, v):
|
104
|
+
raise NotImplementedError
|
105
|
+
|
106
|
+
def __hash__(self):
|
107
|
+
return self._hash_code
|
108
|
+
|
109
|
+
def __mul__(self, other):
|
110
|
+
new_sperm = other._s_perm * self._s_perm
|
111
|
+
new_perm = permtrim_list([new_sperm.array_form[i] + 1 for i in range(new_sperm.size)])
|
112
|
+
return Permutation(new_perm)
|
113
|
+
|
114
|
+
def __iter__(self):
|
115
|
+
yield from self._perm.__iter__()
|
116
|
+
|
117
|
+
def __getslice__(self, i, j):
|
118
|
+
return self._perm[i:j]
|
119
|
+
|
120
|
+
def __str__(self):
|
121
|
+
return str(self._perm)
|
122
|
+
|
123
|
+
def __add__(self, other):
|
124
|
+
if not isinstance(other, list):
|
125
|
+
raise NotImplementedError
|
126
|
+
permlist = [*self._perm, *other]
|
127
|
+
try:
|
128
|
+
return Permutation(permlist)
|
129
|
+
except Exception:
|
130
|
+
return permlist
|
131
|
+
|
132
|
+
def __radd__(self, other):
|
133
|
+
if not isinstance(other, list):
|
134
|
+
raise NotImplementedError
|
135
|
+
permlist = [*other, *self._perm]
|
136
|
+
try:
|
137
|
+
return Permutation(permlist)
|
138
|
+
except Exception:
|
139
|
+
return permlist
|
140
|
+
|
141
|
+
def __eq__(self, other):
|
142
|
+
if isinstance(other, Permutation):
|
143
|
+
# print(f"{other._perm= } {self._perm=} {type(self._perm)=}")
|
144
|
+
# return other._perm == self._perm
|
145
|
+
return other._unique_key == self._unique_key
|
146
|
+
if isinstance(other, list):
|
147
|
+
# print(f"{[*self._perm]= } {other=}")
|
148
|
+
return [*self._perm] == other
|
149
|
+
if isinstance(other, tuple):
|
150
|
+
# print(f"{self._perm=} {other=}")
|
151
|
+
return self._perm == other
|
152
|
+
return False
|
153
|
+
|
154
|
+
def __len__(self):
|
155
|
+
# print("REMOVE THIS")
|
156
|
+
return max(len(self._perm), 2)
|
157
|
+
|
158
|
+
def __invert__(self):
|
159
|
+
new_sperm = ~(self._s_perm)
|
160
|
+
new_perm = [new_sperm.array_form[i] + 1 for i in range(new_sperm.size)]
|
161
|
+
return Permutation(new_perm)
|
11
162
|
|
163
|
+
def __repr__(self):
|
164
|
+
return self.__str__()
|
12
165
|
|
13
|
-
def
|
14
|
-
|
15
|
-
return perm[index]
|
16
|
-
return index + 1
|
166
|
+
def __lt__(self, other):
|
167
|
+
return tuple(self) < tuple(other)
|
17
168
|
|
18
169
|
|
170
|
+
def ensure_perms(func):
|
171
|
+
def wrapper(*args):
|
172
|
+
return func(*[Permutation(arg) if (isinstance(arg, list) or isinstance(arg, tuple)) else arg for arg in args])
|
173
|
+
|
174
|
+
return wrapper
|
175
|
+
|
176
|
+
|
177
|
+
@ensure_perms
|
19
178
|
def inv(perm):
|
20
|
-
|
21
|
-
v = [i for i in range(1, L + 1)]
|
22
|
-
ans = 0
|
23
|
-
for i in range(L):
|
24
|
-
itr = bisect_left(v, perm[i])
|
25
|
-
ans += itr
|
26
|
-
v = v[:itr] + v[itr + 1 :]
|
27
|
-
return ans
|
179
|
+
return perm.inv
|
28
180
|
|
29
181
|
|
182
|
+
@ensure_perms
|
30
183
|
def code(perm):
|
31
|
-
|
32
|
-
ret = []
|
33
|
-
v = [i for i in range(1, L + 1)]
|
34
|
-
for i in range(L - 1):
|
35
|
-
itr = bisect_left(v, perm[i])
|
36
|
-
ret += [itr]
|
37
|
-
v = v[:itr] + v[itr + 1 :]
|
38
|
-
return ret
|
184
|
+
return perm.code
|
39
185
|
|
40
186
|
|
187
|
+
@ensure_perms
|
41
188
|
def mulperm(perm1, perm2):
|
42
|
-
|
43
|
-
return [
|
44
|
-
perm1[perm2[i] - 1] if perm2[i] <= len(perm1) else perm2[i] for i in range(len(perm2))
|
45
|
-
]
|
46
|
-
else:
|
47
|
-
return [perm1[perm2[i] - 1] for i in range(len(perm2))] + perm1[len(perm2) :]
|
189
|
+
return perm1 * perm2
|
48
190
|
|
49
191
|
|
50
192
|
def uncode(cd):
|
51
193
|
cd2 = [*cd]
|
52
194
|
if cd2 == []:
|
53
|
-
return [
|
195
|
+
return Permutation([])
|
54
196
|
max_required = max([cd2[i] + i for i in range(len(cd2))])
|
55
197
|
cd2 += [0 for i in range(len(cd2), max_required)]
|
56
198
|
fullperm = [i + 1 for i in range(len(cd2) + 1)]
|
@@ -58,129 +200,19 @@ def uncode(cd):
|
|
58
200
|
for i in range(len(cd2)):
|
59
201
|
perm += [fullperm.pop(cd2[i])]
|
60
202
|
perm += [fullperm[0]]
|
61
|
-
return perm
|
62
|
-
|
63
|
-
|
64
|
-
def reversecode(perm):
|
65
|
-
ret = []
|
66
|
-
for i in range(len(perm) - 1, 0, -1):
|
67
|
-
ret = [0] + ret
|
68
|
-
for j in range(i, -1, -1):
|
69
|
-
if perm[i] > perm[j]:
|
70
|
-
ret[-1] += 1
|
71
|
-
return ret
|
72
|
-
|
73
|
-
|
74
|
-
def reverseuncode(cd):
|
75
|
-
cd2 = list(cd)
|
76
|
-
if cd2 == []:
|
77
|
-
return [1, 2]
|
78
|
-
# max_required = max([cd2[i]+i for i in range(len(cd2))])
|
79
|
-
# cd2 += [0 for i in range(len(cd2),max_required)]
|
80
|
-
fullperm = [i + 1 for i in range(len(cd2) + 1)]
|
81
|
-
perm = []
|
82
|
-
for i in range(len(cd2) - 1, 0, -1):
|
83
|
-
perm = [fullperm[cd2[i]]] + perm
|
84
|
-
fullperm.pop(cd2[i])
|
85
|
-
perm += [fullperm[0]]
|
86
|
-
return perm
|
203
|
+
return Permutation(perm)
|
87
204
|
|
88
205
|
|
206
|
+
@ensure_perms
|
89
207
|
def inverse(perm):
|
90
|
-
|
91
|
-
for i in range(len(perm)):
|
92
|
-
retperm[perm[i] - 1] = i + 1
|
93
|
-
return retperm
|
208
|
+
return ~perm
|
94
209
|
|
95
210
|
|
96
211
|
def permtrim(perm):
|
97
|
-
|
98
|
-
while L > 2 and perm[-1] == L:
|
99
|
-
L = perm.pop() - 1
|
100
|
-
return perm
|
101
|
-
|
102
|
-
|
103
|
-
def has_bruhat_descent(perm, i, j):
|
104
|
-
if perm[i] < perm[j]:
|
105
|
-
return False
|
106
|
-
for p in range(i + 1, j):
|
107
|
-
if perm[i] > perm[p] and perm[p] > perm[j]:
|
108
|
-
return False
|
109
|
-
return True
|
110
|
-
|
111
|
-
|
112
|
-
def count_bruhat(perm, i, j):
|
113
|
-
up_amount = 0
|
114
|
-
if perm[i] < perm[j]:
|
115
|
-
up_amount = 1
|
116
|
-
else:
|
117
|
-
up_amount = -1
|
118
|
-
for k in range(i + 1, j):
|
119
|
-
if perm[i] < perm[k] and perm[k] < perm[j]:
|
120
|
-
up_amount += 2
|
121
|
-
elif perm[i] > perm[k] and perm[k] > perm[j]:
|
122
|
-
up_amount -= 2
|
123
|
-
return up_amount
|
124
|
-
|
125
|
-
|
126
|
-
def has_bruhat_ascent(perm, i, j):
|
127
|
-
if perm[i] > perm[j]:
|
128
|
-
return False
|
129
|
-
for p in range(i + 1, j):
|
130
|
-
if perm[i] < perm[p] and perm[p] < perm[j]:
|
131
|
-
return False
|
132
|
-
return True
|
133
|
-
|
134
|
-
|
135
|
-
def elem_sym_perms(orig_perm, p, k):
|
136
|
-
total_list = [(orig_perm, 0)]
|
137
|
-
up_perm_list = [(orig_perm, 1000000000)]
|
138
|
-
for pp in range(p):
|
139
|
-
perm_list = []
|
140
|
-
for up_perm, last in up_perm_list:
|
141
|
-
up_perm2 = [*up_perm, len(up_perm) + 1]
|
142
|
-
if len(up_perm2) < k + 1:
|
143
|
-
up_perm2 += [i + 1 for i in range(len(up_perm2), k + 2)]
|
144
|
-
pos_list = [i for i in range(k) if up_perm2[i] < last]
|
145
|
-
for j in range(k, len(up_perm2)):
|
146
|
-
if up_perm2[j] >= last:
|
147
|
-
continue
|
148
|
-
for i in pos_list:
|
149
|
-
if has_bruhat_ascent(up_perm2, i, j):
|
150
|
-
new_perm = [*up_perm2]
|
151
|
-
new_perm[i], new_perm[j] = new_perm[j], new_perm[i]
|
152
|
-
if new_perm[-1] == len(new_perm):
|
153
|
-
new_perm_add = tuple(new_perm[:-1])
|
154
|
-
else:
|
155
|
-
new_perm_add = tuple(new_perm)
|
156
|
-
perm_list += [(new_perm_add, up_perm2[j])]
|
157
|
-
total_list += [(new_perm_add, pp + 1)]
|
158
|
-
up_perm_list = perm_list
|
159
|
-
return total_list
|
160
|
-
|
161
|
-
|
162
|
-
def elem_sym_perms_op(orig_perm, p, k):
|
163
|
-
total_list = [(orig_perm, 0)]
|
164
|
-
up_perm_list = [(orig_perm, k)]
|
165
|
-
for pp in range(p):
|
166
|
-
perm_list = []
|
167
|
-
for up_perm, last in up_perm_list:
|
168
|
-
up_perm2 = [*up_perm]
|
169
|
-
if len(up_perm2) < k + 1:
|
170
|
-
up_perm2 += [i + 1 for i in range(len(up_perm2), k + 2)]
|
171
|
-
pos_list = [i for i in range(k) if getpermval(up_perm2, i) == getpermval(orig_perm, i)]
|
172
|
-
for j in range(last, len(up_perm2)):
|
173
|
-
for i in pos_list:
|
174
|
-
if has_bruhat_descent(up_perm2, i, j):
|
175
|
-
new_perm = [*up_perm2]
|
176
|
-
new_perm[i], new_perm[j] = new_perm[j], new_perm[i]
|
177
|
-
new_perm_add = tuple(permtrim(new_perm))
|
178
|
-
perm_list += [(new_perm_add, j)]
|
179
|
-
total_list += [(new_perm_add, pp + 1)]
|
180
|
-
up_perm_list = perm_list
|
181
|
-
return total_list
|
212
|
+
return Permutation(perm)
|
182
213
|
|
183
214
|
|
215
|
+
@ensure_perms
|
184
216
|
def strict_theta(u):
|
185
217
|
ret = [*trimcode(u)]
|
186
218
|
did_one = True
|
@@ -196,301 +228,20 @@ def strict_theta(u):
|
|
196
228
|
return ret
|
197
229
|
|
198
230
|
|
199
|
-
def elem_sym_perms_q(orig_perm, p, k, q_var=q_var):
|
200
|
-
total_list = [(orig_perm, 0, 1)]
|
201
|
-
up_perm_list = [(orig_perm, 1, 1000)]
|
202
|
-
for pp in range(p):
|
203
|
-
perm_list = []
|
204
|
-
for up_perm, val, last_j in up_perm_list:
|
205
|
-
up_perm2 = [*up_perm, len(up_perm) + 1]
|
206
|
-
if len(up_perm2) < k + 1:
|
207
|
-
up_perm2 += [i + 1 for i in range(len(up_perm2), k + 2)]
|
208
|
-
pos_list = [
|
209
|
-
i
|
210
|
-
for i in range(k)
|
211
|
-
if (i >= len(orig_perm) and up_perm2[i] == i + 1)
|
212
|
-
or (i < len(orig_perm) and up_perm2[i] == orig_perm[i])
|
213
|
-
]
|
214
|
-
for j in range(min(len(up_perm2) - 1, last_j), k - 1, -1):
|
215
|
-
for i in pos_list:
|
216
|
-
ct = count_bruhat(up_perm2, i, j)
|
217
|
-
# print(f"{up_perm2=} {ct=} {i=} {j=} {k=} {pp=}")
|
218
|
-
if ct == 1 or ct == 2 * (i - j) + 1:
|
219
|
-
new_perm = [*up_perm2]
|
220
|
-
new_perm[i], new_perm[j] = new_perm[j], new_perm[i]
|
221
|
-
new_perm_add = tuple(permtrim(new_perm))
|
222
|
-
new_val = val
|
223
|
-
if ct < 0:
|
224
|
-
new_val *= np.prod([q_var[index] for index in range(i + 1, j + 1)])
|
225
|
-
perm_list += [(new_perm_add, new_val, j)]
|
226
|
-
total_list += [(new_perm_add, pp + 1, new_val)]
|
227
|
-
up_perm_list = perm_list
|
228
|
-
return total_list
|
229
|
-
|
230
|
-
|
231
|
-
def elem_sym_perms_q_op(orig_perm, p, k, n, q_var=q_var):
|
232
|
-
total_list = [(orig_perm, 0, 1)]
|
233
|
-
up_perm_list = [(orig_perm, 1, k)]
|
234
|
-
for pp in range(p):
|
235
|
-
perm_list = []
|
236
|
-
for up_perm, val, last_j in up_perm_list:
|
237
|
-
up_perm2 = [*up_perm]
|
238
|
-
if len(up_perm) < n:
|
239
|
-
up_perm2 += [i + 1 for i in range(len(up_perm2), n)]
|
240
|
-
pos_list = [
|
241
|
-
i
|
242
|
-
for i in range(k)
|
243
|
-
if (i >= len(orig_perm) and up_perm2[i] == i + 1)
|
244
|
-
or (i < len(orig_perm) and up_perm2[i] == orig_perm[i])
|
245
|
-
]
|
246
|
-
for j in range(last_j, n):
|
247
|
-
for i in pos_list:
|
248
|
-
ct = count_bruhat(up_perm2, i, j)
|
249
|
-
# print(f"{up_perm2=} {ct=} {i=} {j=} {k=} {pp=}")
|
250
|
-
if ct == -1 or ct == 2 * (j - i) - 1:
|
251
|
-
new_perm = [*up_perm2]
|
252
|
-
new_perm[i], new_perm[j] = new_perm[j], new_perm[i]
|
253
|
-
new_perm_add = tuple(permtrim(new_perm))
|
254
|
-
new_val = val
|
255
|
-
if ct > 0:
|
256
|
-
new_val *= np.prod([q_var[index] for index in range(i + 1, j + 1)])
|
257
|
-
perm_list += [(new_perm_add, new_val, j)]
|
258
|
-
total_list += [(new_perm_add, pp + 1, new_val)]
|
259
|
-
up_perm_list = perm_list
|
260
|
-
return total_list
|
261
|
-
|
262
|
-
|
263
|
-
def q_vector(q_exp, q_var=q_var):
|
264
|
-
qvar_list = q_var.tolist()
|
265
|
-
ret = []
|
266
|
-
|
267
|
-
if q_exp == 1:
|
268
|
-
return ret
|
269
|
-
if q_exp in q_var:
|
270
|
-
i = qvar_list.index(q_exp)
|
271
|
-
ret = [0 for j in range(i - 1)] + [1]
|
272
|
-
return ret
|
273
|
-
if isinstance(q_exp, Pow):
|
274
|
-
qv = q_exp.args[0]
|
275
|
-
expon = int(q_exp.args[1])
|
276
|
-
i = qvar_list.index(qv)
|
277
|
-
ret = [0 for j in range(i - 1)] + [expon]
|
278
|
-
return ret
|
279
|
-
if isinstance(q_exp, Mul):
|
280
|
-
for a in q_exp.args:
|
281
|
-
v1 = q_vector(a)
|
282
|
-
v1 += [0 for i in range(len(v1), len(ret))]
|
283
|
-
ret += [0 for i in range(len(ret), len(v1))]
|
284
|
-
ret = [ret[i] + v1[i] for i in range(len(ret))]
|
285
|
-
return ret
|
286
|
-
|
287
|
-
return None
|
288
|
-
|
289
|
-
|
290
|
-
def omega(i, qv):
|
291
|
-
i = i - 1
|
292
|
-
if len(qv) == 0 or i > len(qv):
|
293
|
-
return 0
|
294
|
-
if i == 0:
|
295
|
-
if len(qv) == 1:
|
296
|
-
return 2 * qv[0]
|
297
|
-
return 2 * qv[0] - qv[1]
|
298
|
-
if i == len(qv):
|
299
|
-
return -qv[-1]
|
300
|
-
if i == len(qv) - 1:
|
301
|
-
return 2 * qv[-1] - qv[-2]
|
302
|
-
return 2 * qv[i] - qv[i - 1] - qv[i + 1]
|
303
|
-
|
304
|
-
|
305
|
-
def sg(i, w):
|
306
|
-
if i >= len(w) - 1 or w[i] < w[i + 1]:
|
307
|
-
return 0
|
308
|
-
return 1
|
309
|
-
|
310
|
-
|
311
|
-
def reduce_q_coeff(u, v, w, qv):
|
312
|
-
for i in range(len(qv)):
|
313
|
-
if sg(i, v) == 1 and sg(i, u) == 0 and sg(i, w) + omega(i + 1, qv) == 1:
|
314
|
-
ret_v = [*v]
|
315
|
-
ret_v[i], ret_v[i + 1] = ret_v[i + 1], ret_v[i]
|
316
|
-
ret_w = [*w] + [j + 1 for j in range(len(w), i + 2)]
|
317
|
-
ret_w[i], ret_w[i + 1] = ret_w[i + 1], ret_w[i]
|
318
|
-
qv_ret = [*qv]
|
319
|
-
if sg(i, w) == 0:
|
320
|
-
qv_ret[i] -= 1
|
321
|
-
return u, tuple(permtrim(ret_v)), tuple(permtrim(ret_w)), qv_ret, True
|
322
|
-
elif sg(i, u) == 1 and sg(i, v) == 0 and sg(i, w) + omega(i + 1, qv) == 1:
|
323
|
-
ret_u = [*u]
|
324
|
-
ret_u[i], ret_u[i + 1] = ret_u[i + 1], ret_u[i]
|
325
|
-
ret_w = [*w] + [j + 1 for j in range(len(w), i + 2)]
|
326
|
-
ret_w[i], ret_w[i + 1] = ret_w[i + 1], ret_w[i]
|
327
|
-
qv_ret = [*qv]
|
328
|
-
if sg(i, w) == 0:
|
329
|
-
qv_ret[i] -= 1
|
330
|
-
return tuple(permtrim(ret_u)), v, tuple(permtrim(ret_w)), qv_ret, True
|
331
|
-
elif sg(i, u) == 1 and sg(i, v) == 1 and sg(i, w) + omega(i + 1, qv) == 2:
|
332
|
-
ret_u = [*u]
|
333
|
-
ret_u[i], ret_u[i + 1] = ret_u[i + 1], ret_u[i]
|
334
|
-
ret_w = [*w] + [j + 1 for j in range(len(w), i + 2)]
|
335
|
-
ret_w[i], ret_w[i + 1] = ret_w[i + 1], ret_w[i]
|
336
|
-
qv_ret = [*qv]
|
337
|
-
if sg(i, w) == 0:
|
338
|
-
qv_ret[i] -= 1
|
339
|
-
return tuple(permtrim(ret_u)), v, tuple(permtrim(ret_w)), qv_ret, True
|
340
|
-
return u, v, w, qv, False
|
341
|
-
|
342
|
-
|
343
|
-
def reduce_q_coeff_u_only(u, v, w, qv):
|
344
|
-
for i in range(len(qv)):
|
345
|
-
if sg(i, u) == 1 and sg(i, v) == 0 and sg(i, w) + omega(i + 1, qv) == 1:
|
346
|
-
ret_u = [*u]
|
347
|
-
ret_u[i], ret_u[i + 1] = ret_u[i + 1], ret_u[i]
|
348
|
-
ret_w = [*w] + [j + 1 for j in range(len(w), i + 2)]
|
349
|
-
ret_w[i], ret_w[i + 1] = ret_w[i + 1], ret_w[i]
|
350
|
-
qv_ret = [*qv]
|
351
|
-
if sg(i, w) == 0:
|
352
|
-
qv_ret[i] -= 1
|
353
|
-
return tuple(permtrim(ret_u)), v, tuple(permtrim(ret_w)), qv_ret, True
|
354
|
-
elif sg(i, u) == 1 and sg(i, v) == 1 and sg(i, w) + omega(i + 1, qv) == 2:
|
355
|
-
ret_u = [*u]
|
356
|
-
ret_u[i], ret_u[i + 1] = ret_u[i + 1], ret_u[i]
|
357
|
-
ret_w = [*w] + [j + 1 for j in range(len(w), i + 2)]
|
358
|
-
ret_w[i], ret_w[i + 1] = ret_w[i + 1], ret_w[i]
|
359
|
-
qv_ret = [*qv]
|
360
|
-
if sg(i, w) == 0:
|
361
|
-
qv_ret[i] -= 1
|
362
|
-
return tuple(permtrim(ret_u)), v, tuple(permtrim(ret_w)), qv_ret, True
|
363
|
-
return u, v, w, qv, False
|
364
|
-
|
365
|
-
|
366
231
|
def longest_element(indices):
|
367
|
-
perm = [1, 2]
|
232
|
+
perm = Permutation([1, 2])
|
368
233
|
did_one = True
|
369
234
|
while did_one:
|
370
235
|
did_one = False
|
371
236
|
for i in range(len(indices)):
|
372
237
|
j = indices[i] - 1
|
373
238
|
if sg(j, perm) == 0:
|
374
|
-
|
375
|
-
perm = perm + [index for index in range(len(perm) + 1, j + 3)]
|
376
|
-
perm[j], perm[j + 1] = perm[j + 1], perm[j]
|
239
|
+
perm = perm.swap(j, j + 1)
|
377
240
|
did_one = True
|
378
241
|
return permtrim(perm)
|
379
242
|
|
380
243
|
|
381
|
-
|
382
|
-
ct = 0
|
383
|
-
i = 0
|
384
|
-
while i < len(arr) and arr[i] < val:
|
385
|
-
i += 1
|
386
|
-
ct += 1
|
387
|
-
return ct
|
388
|
-
|
389
|
-
|
390
|
-
def is_parabolic(w, parabolic_index):
|
391
|
-
for i in parabolic_index:
|
392
|
-
if sg(i - 1, w) == 1:
|
393
|
-
return False
|
394
|
-
return True
|
395
|
-
|
396
|
-
|
397
|
-
def check_blocks(qv, parabolic_index):
|
398
|
-
blocks = []
|
399
|
-
cur_block = []
|
400
|
-
last_val = -1
|
401
|
-
for i in range(len(parabolic_index)):
|
402
|
-
if last_val == -1 or last_val + 1 == parabolic_index[i]:
|
403
|
-
last_val = parabolic_index[i]
|
404
|
-
cur_block += [last_val]
|
405
|
-
else:
|
406
|
-
blocks += [cur_block]
|
407
|
-
cur_block = []
|
408
|
-
for block in blocks:
|
409
|
-
for i in range(len(block)):
|
410
|
-
for j in range(i, len(block)):
|
411
|
-
val = 0
|
412
|
-
for k in range(i, j + 1):
|
413
|
-
val += omega(block[k], qv)
|
414
|
-
if val != 0 and val != -1:
|
415
|
-
return False
|
416
|
-
return True
|
417
|
-
|
418
|
-
|
419
|
-
# perms and inversion diff
|
420
|
-
def kdown_perms(perm, monoperm, p, k):
|
421
|
-
inv_m = inv(monoperm)
|
422
|
-
inv_p = inv(perm)
|
423
|
-
full_perm_list = []
|
424
|
-
|
425
|
-
if inv(mulperm(list(perm), monoperm)) == inv_m - inv_p:
|
426
|
-
full_perm_list += [(tuple(perm), 0, 1)]
|
427
|
-
|
428
|
-
down_perm_list = [(perm, 1)]
|
429
|
-
if len(perm) < k:
|
430
|
-
return full_perm_list
|
431
|
-
a2 = k - 1
|
432
|
-
for pp in range(1, p + 1):
|
433
|
-
down_perm_list2 = []
|
434
|
-
for perm2, s in down_perm_list:
|
435
|
-
L = len(perm2)
|
436
|
-
if L < k:
|
437
|
-
continue
|
438
|
-
s2 = -s
|
439
|
-
for b in chain(range(k - 1), range(k, L)):
|
440
|
-
if perm2[b] != perm[b]:
|
441
|
-
continue
|
442
|
-
if b < a2:
|
443
|
-
i, j = b, a2
|
444
|
-
else:
|
445
|
-
i, j, s2 = a2, b, s
|
446
|
-
if has_bruhat_descent(perm2, i, j):
|
447
|
-
new_perm = [*perm2]
|
448
|
-
new_perm[a2], new_perm[b] = new_perm[b], new_perm[a2]
|
449
|
-
permtrim(new_perm)
|
450
|
-
down_perm_list2 += [(new_perm, s2)]
|
451
|
-
if inv(mulperm(new_perm, monoperm)) == inv_m - inv_p + pp:
|
452
|
-
full_perm_list += [(tuple(new_perm), pp, s2)]
|
453
|
-
down_perm_list = down_perm_list2
|
454
|
-
return full_perm_list
|
455
|
-
|
456
|
-
|
457
|
-
def compute_vpathdicts(th, vmu, smpify=False):
|
458
|
-
vpathdicts = [{} for index in range(len(th))]
|
459
|
-
vpathdicts[-1][tuple(vmu)] = None
|
460
|
-
thL = len(th)
|
461
|
-
|
462
|
-
top = code(inverse(uncode(th)))
|
463
|
-
for i in range(thL - 1, -1, -1):
|
464
|
-
top2 = code(inverse(uncode(top)))
|
465
|
-
while top2[-1] == 0:
|
466
|
-
top2.pop()
|
467
|
-
top2.pop()
|
468
|
-
top = code(inverse(uncode(top2)))
|
469
|
-
monoperm = uncode(top)
|
470
|
-
if len(monoperm) < 2:
|
471
|
-
monoperm = [1, 2]
|
472
|
-
k = i + 1
|
473
|
-
for last_perm in vpathdicts[i]:
|
474
|
-
newperms = kdown_perms(last_perm, monoperm, th[i], k)
|
475
|
-
vpathdicts[i][last_perm] = newperms
|
476
|
-
if i > 0:
|
477
|
-
for trip in newperms:
|
478
|
-
vpathdicts[i - 1][trip[0]] = None
|
479
|
-
vpathdicts2 = [{} for i in range(len(th))]
|
480
|
-
for i in range(len(th)):
|
481
|
-
for key, valueset in vpathdicts[i].items():
|
482
|
-
for value in valueset:
|
483
|
-
key2 = value[0]
|
484
|
-
if key2 not in vpathdicts2[i]:
|
485
|
-
vpathdicts2[i][key2] = set()
|
486
|
-
v2 = value[2]
|
487
|
-
if smpify:
|
488
|
-
v2 = sympify(v2)
|
489
|
-
vpathdicts2[i][key2].add((key, value[1], v2))
|
490
|
-
# print(vpathdicts2)
|
491
|
-
return vpathdicts2
|
492
|
-
|
493
|
-
|
244
|
+
@ensure_perms
|
494
245
|
def theta(perm):
|
495
246
|
cd = code(perm)
|
496
247
|
for i in range(len(cd) - 1, 0, -1):
|
@@ -501,147 +252,30 @@ def theta(perm):
|
|
501
252
|
return cd
|
502
253
|
|
503
254
|
|
504
|
-
|
505
|
-
for k, v in d2.items():
|
506
|
-
d1[k] = d1.get(k, 0) + v
|
507
|
-
return d1
|
508
|
-
|
509
|
-
|
510
|
-
one = sympify(1)
|
511
|
-
|
512
|
-
|
513
|
-
def elem_sym_poly_q(p, k, varl1, varl2, q_var=q_var):
|
514
|
-
if p == 0 and k >= 0:
|
515
|
-
return one
|
516
|
-
if p < 0 or p > k:
|
517
|
-
return zero
|
518
|
-
return (
|
519
|
-
(varl1[k - 1] - varl2[k - p]) * elem_sym_poly_q(p - 1, k - 1, varl1, varl2, q_var)
|
520
|
-
+ elem_sym_poly_q(p, k - 1, varl1, varl2, q_var)
|
521
|
-
+ q_var[k - 1] * elem_sym_poly_q(p - 2, k - 2, varl1, varl2, q_var)
|
522
|
-
)
|
523
|
-
|
524
|
-
|
525
|
-
def elem_sym_poly(p, k, varl1, varl2, xstart=0, ystart=0):
|
526
|
-
global zero, one
|
527
|
-
if p > k:
|
528
|
-
return zero
|
529
|
-
if p == 0:
|
530
|
-
return one
|
531
|
-
if p == 1:
|
532
|
-
res = varl1[xstart] - varl2[ystart]
|
533
|
-
for i in range(1, k):
|
534
|
-
res += varl1[xstart + i] - varl2[ystart + i]
|
535
|
-
return res
|
536
|
-
if p == k:
|
537
|
-
res = (varl1[xstart] - varl2[ystart]) * (varl1[xstart + 1] - varl2[ystart])
|
538
|
-
for i in range(2, k):
|
539
|
-
res *= varl1[i + xstart] - varl2[ystart]
|
540
|
-
return res
|
541
|
-
mid = k // 2
|
542
|
-
xsm = xstart + mid
|
543
|
-
ysm = ystart + mid
|
544
|
-
kmm = k - mid
|
545
|
-
res = elem_sym_poly(p, mid, varl1, varl2, xstart, ystart) + elem_sym_poly(
|
546
|
-
p, kmm, varl1, varl2, xsm, ysm
|
547
|
-
)
|
548
|
-
for p2 in range(max(1, p - kmm), min(p, mid + 1)):
|
549
|
-
res += elem_sym_poly(p2, mid, varl1, varl2, xstart, ystart) * elem_sym_poly(
|
550
|
-
p - p2, kmm, varl1, varl2, xsm, ysm - p2
|
551
|
-
)
|
552
|
-
return res
|
553
|
-
|
554
|
-
|
555
|
-
@cache
|
556
|
-
def call_zvars(v1, v2, k, i):
|
557
|
-
v3 = [*v2] + [j for j in range(len(v2) + 1, i + 1)]
|
558
|
-
zvars = (
|
559
|
-
[v3[i - 1]]
|
560
|
-
+ [v3[j] for j in range(len(v1), len(v3)) if v3[j] != j + 1 and j != i - 1]
|
561
|
-
+ [v3[j] for j in range(len(v1)) if v1[j] != v3[j] and j != i - 1]
|
562
|
-
)
|
563
|
-
return zvars
|
564
|
-
|
565
|
-
|
566
|
-
def elem_sym_func(k, i, u1, u2, v1, v2, udiff, vdiff, varl1, varl2):
|
567
|
-
global zero, one
|
568
|
-
newk = k - udiff
|
569
|
-
if newk < vdiff:
|
570
|
-
return zero
|
571
|
-
if newk == vdiff:
|
572
|
-
return one
|
573
|
-
yvars = []
|
574
|
-
for j in range(min(len(u1), k)):
|
575
|
-
if u1[j] == u2[j]:
|
576
|
-
yvars += [varl1[u2[j]]]
|
577
|
-
for j in range(len(u1), min(k, len(u2))):
|
578
|
-
if u2[j] == j + 1:
|
579
|
-
yvars += [varl1[u2[j]]]
|
580
|
-
for j in range(len(u2), k):
|
581
|
-
yvars += [varl1[j + 1]]
|
582
|
-
zvars = [varl2[i] for i in call_zvars(v1, v2, k, i)]
|
583
|
-
return elem_sym_poly(newk - vdiff, newk, yvars, zvars)
|
584
|
-
|
585
|
-
|
586
|
-
def elem_sym_func_q(k, i, u1, u2, v1, v2, udiff, vdiff, varl1, varl2):
|
587
|
-
global zero, one
|
588
|
-
newk = k - udiff
|
589
|
-
if newk < vdiff:
|
590
|
-
return zero
|
591
|
-
if newk == vdiff:
|
592
|
-
return one
|
593
|
-
yvars = []
|
594
|
-
mlen = max(len(u1), len(u2))
|
595
|
-
u1 = [*u1] + [a + 1 for a in range(len(u1), mlen)]
|
596
|
-
u2 = [*u2] + [a + 1 for a in range(len(u2), mlen)]
|
597
|
-
for j in range(min(len(u1), k)):
|
598
|
-
if u1[j] == u2[j]:
|
599
|
-
yvars += [varl1[u2[j]]]
|
600
|
-
for j in range(len(u1), min(k, len(u2))):
|
601
|
-
if u2[j] == j + 1:
|
602
|
-
yvars += [varl1[u2[j]]]
|
603
|
-
for j in range(len(u2), k):
|
604
|
-
yvars += [varl1[j + 1]]
|
605
|
-
zvars = [varl2[a] for a in call_zvars(v1, v2, k, i)]
|
606
|
-
return elem_sym_poly(newk - vdiff, newk, yvars, zvars)
|
607
|
-
|
608
|
-
|
255
|
+
@ensure_perms
|
609
256
|
def trimcode(perm):
|
610
|
-
cd = code
|
257
|
+
cd = perm.code
|
611
258
|
while len(cd) > 0 and cd[-1] == 0:
|
612
259
|
cd.pop()
|
613
260
|
return cd
|
614
261
|
|
615
262
|
|
616
|
-
def p_trans(part):
|
617
|
-
newpart = []
|
618
|
-
if len(part) == 0 or part[0] == 0:
|
619
|
-
return [0]
|
620
|
-
for i in range(1, part[0] + 1):
|
621
|
-
cnt = 0
|
622
|
-
for j in range(len(part)):
|
623
|
-
if part[j] >= i:
|
624
|
-
cnt += 1
|
625
|
-
if cnt == 0:
|
626
|
-
break
|
627
|
-
newpart += [cnt]
|
628
|
-
return newpart
|
629
|
-
|
630
|
-
|
631
263
|
def cycle(p, q):
|
632
|
-
return
|
264
|
+
return Permutation(list(range(1, p)) + [i + 1 for i in range(p, p + q)] + [p])
|
633
265
|
|
634
266
|
|
267
|
+
@ensure_perms
|
635
268
|
def phi1(u):
|
636
|
-
c_star =
|
269
|
+
c_star = (~u).code
|
637
270
|
c_star.pop(0)
|
638
|
-
|
639
|
-
return
|
271
|
+
# print(f"{uncode(c_star)=}")
|
272
|
+
return ~(uncode(c_star))
|
640
273
|
|
641
274
|
|
275
|
+
@ensure_perms
|
642
276
|
def one_dominates(u, w):
|
643
|
-
c_star_u =
|
644
|
-
c_star_w =
|
277
|
+
c_star_u = (~u).code
|
278
|
+
c_star_w = (~w).code
|
645
279
|
|
646
280
|
a = c_star_u[0]
|
647
281
|
b = c_star_w[0]
|
@@ -655,332 +289,16 @@ def one_dominates(u, w):
|
|
655
289
|
|
656
290
|
|
657
291
|
def dominates(u, w):
|
658
|
-
u2 =
|
659
|
-
w2 =
|
660
|
-
while u2
|
292
|
+
u2 = u
|
293
|
+
w2 = w
|
294
|
+
while inv(u2) > 0 and one_dominates(u2, w2):
|
661
295
|
u2 = phi1(u2)
|
662
296
|
w2 = phi1(w2)
|
663
|
-
if u2 ==
|
297
|
+
if inv(u2) == 0:
|
664
298
|
return True
|
665
299
|
return False
|
666
300
|
|
667
301
|
|
668
|
-
def reduce_coeff(u, v, w):
|
669
|
-
t_mu_u_t = theta(inverse(u))
|
670
|
-
t_mu_v_t = theta(inverse(v))
|
671
|
-
|
672
|
-
mu_u_inv = uncode(t_mu_u_t)
|
673
|
-
mu_v_inv = uncode(t_mu_v_t)
|
674
|
-
|
675
|
-
t_mu_u = p_trans(t_mu_u_t)
|
676
|
-
t_mu_v = p_trans(t_mu_v_t)
|
677
|
-
|
678
|
-
t_mu_u += [0 for i in range(len(t_mu_u), max(len(t_mu_u), len(t_mu_v)))]
|
679
|
-
t_mu_v += [0 for i in range(len(t_mu_v), max(len(t_mu_u), len(t_mu_v)))]
|
680
|
-
|
681
|
-
t_mu_uv = [t_mu_u[i] + t_mu_v[i] for i in range(len(t_mu_u))]
|
682
|
-
t_mu_uv_t = p_trans(t_mu_uv)
|
683
|
-
|
684
|
-
mu_uv_inv = uncode(t_mu_uv_t)
|
685
|
-
|
686
|
-
if inv(mulperm(list(w), mu_uv_inv)) != inv(mu_uv_inv) - inv(w):
|
687
|
-
return u, v, w
|
688
|
-
|
689
|
-
umu = mulperm(list(u), mu_u_inv)
|
690
|
-
vmu = mulperm(list(v), mu_v_inv)
|
691
|
-
wmu = mulperm(list(w), mu_uv_inv)
|
692
|
-
|
693
|
-
t_mu_w = theta(inverse(wmu))
|
694
|
-
|
695
|
-
mu_w = uncode(t_mu_w)
|
696
|
-
|
697
|
-
w_prime = mulperm(wmu, mu_w)
|
698
|
-
|
699
|
-
if permtrim(list(w)) == permtrim(w_prime):
|
700
|
-
return (permtrim(list(u)), permtrim(list(v)), permtrim(list(w)))
|
701
|
-
|
702
|
-
A = []
|
703
|
-
B = []
|
704
|
-
indexA = 0
|
705
|
-
|
706
|
-
while len(t_mu_u_t) > 0 and t_mu_u_t[-1] == 0:
|
707
|
-
t_mu_u_t.pop()
|
708
|
-
|
709
|
-
while len(t_mu_v_t) > 0 and t_mu_v_t[-1] == 0:
|
710
|
-
t_mu_v_t.pop()
|
711
|
-
|
712
|
-
while len(t_mu_uv_t) > 0 and t_mu_uv_t[-1] == 0:
|
713
|
-
t_mu_uv_t.pop()
|
714
|
-
|
715
|
-
for index in range(len(t_mu_uv_t)):
|
716
|
-
if indexA < len(t_mu_u_t) and t_mu_uv_t[index] == t_mu_u_t[indexA]:
|
717
|
-
A += [index]
|
718
|
-
indexA += 1
|
719
|
-
else:
|
720
|
-
B += [index]
|
721
|
-
|
722
|
-
mu_w_A = uncode(mu_A(code(mu_w), A))
|
723
|
-
mu_w_B = uncode(mu_A(code(mu_w), B))
|
724
|
-
|
725
|
-
return (
|
726
|
-
permtrim(mulperm(umu, mu_w_A)),
|
727
|
-
permtrim(mulperm(vmu, mu_w_B)),
|
728
|
-
permtrim(w_prime),
|
729
|
-
)
|
730
|
-
|
731
|
-
|
732
|
-
def mu_A(mu, A):
|
733
|
-
mu_t = p_trans(mu)
|
734
|
-
mu_A_t = []
|
735
|
-
for i in range(len(A)):
|
736
|
-
if A[i] < len(mu_t):
|
737
|
-
mu_A_t += [mu_t[A[i]]]
|
738
|
-
return p_trans(mu_A_t)
|
739
|
-
|
740
|
-
|
741
|
-
def reduce_descents(u, v, w):
|
742
|
-
u2 = [*u]
|
743
|
-
v2 = [*v]
|
744
|
-
w2 = [*w]
|
745
|
-
found_one = True
|
746
|
-
while found_one:
|
747
|
-
found_one = False
|
748
|
-
if (
|
749
|
-
will_formula_work(u2, v2)
|
750
|
-
or will_formula_work(v2, u2)
|
751
|
-
or one_dominates(u2, w2)
|
752
|
-
or is_reducible(v2)
|
753
|
-
or inv(w2) - inv(u2) == 1
|
754
|
-
):
|
755
|
-
break
|
756
|
-
for i in range(len(w2) - 2, -1, -1):
|
757
|
-
if (
|
758
|
-
w2[i] > w2[i + 1]
|
759
|
-
and i < len(v2) - 1
|
760
|
-
and v2[i] > v2[i + 1]
|
761
|
-
and (i >= len(u2) - 1 or u2[i] < u2[i + 1])
|
762
|
-
):
|
763
|
-
w2[i], w2[i + 1] = w2[i + 1], w2[i]
|
764
|
-
v2[i], v2[i + 1] = v2[i + 1], v2[i]
|
765
|
-
found_one = True
|
766
|
-
elif (
|
767
|
-
w2[i] > w2[i + 1]
|
768
|
-
and i < len(u2) - 1
|
769
|
-
and u2[i] > u2[i + 1]
|
770
|
-
and (i >= len(v2) - 1 or v2[i] < v2[i + 1])
|
771
|
-
):
|
772
|
-
w2[i], w2[i + 1] = w2[i + 1], w2[i]
|
773
|
-
u2[i], u2[i + 1] = u2[i + 1], u2[i]
|
774
|
-
found_one = True
|
775
|
-
if found_one:
|
776
|
-
break
|
777
|
-
return permtrim(u2), permtrim(v2), permtrim(w2)
|
778
|
-
|
779
|
-
|
780
|
-
def is_reducible(v):
|
781
|
-
c03 = code(v)
|
782
|
-
found0 = False
|
783
|
-
good = True
|
784
|
-
for i in range(len(c03)):
|
785
|
-
if c03[i] == 0:
|
786
|
-
found0 = True
|
787
|
-
elif c03[i] != 0 and found0:
|
788
|
-
good = False
|
789
|
-
break
|
790
|
-
return good
|
791
|
-
|
792
|
-
|
793
|
-
def try_reduce_v(u, v, w):
|
794
|
-
if is_reducible(v):
|
795
|
-
return tuple(permtrim([*u])), tuple(permtrim([*v])), tuple(permtrim([*w]))
|
796
|
-
u2 = [*u]
|
797
|
-
v2 = [*v]
|
798
|
-
w2 = [*w]
|
799
|
-
cv = code(v2)
|
800
|
-
for i in range(len(v2) - 2, -1, -1):
|
801
|
-
if cv[i] == 0 and i < len(cv) - 1 and cv[i + 1] != 0:
|
802
|
-
if i >= len(u2) - 1 or u2[i] < u2[i + 1]:
|
803
|
-
v2[i], v2[i + 1] = v2[i + 1], v2[i]
|
804
|
-
if i >= len(w2) - 1:
|
805
|
-
w2 += [j for j in range(len(w2) + 1, i + 3)]
|
806
|
-
w2[i + 1], w2[i] = w2[i], w2[i + 1]
|
807
|
-
if is_reducible(v2):
|
808
|
-
return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
|
809
|
-
else:
|
810
|
-
return try_reduce_v(u2, v2, w2)
|
811
|
-
elif i < len(w2) - 1 and w2[i] > w2[i + 1]:
|
812
|
-
u2[i], u2[i + 1] = u2[i + 1], u2[i]
|
813
|
-
v2[i], v2[i + 1] = v2[i + 1], v2[i]
|
814
|
-
return try_reduce_v(u2, v2, w2)
|
815
|
-
else:
|
816
|
-
return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
|
817
|
-
return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
|
818
|
-
|
819
|
-
|
820
|
-
def try_reduce_u(u, v, w):
|
821
|
-
if one_dominates(u, w):
|
822
|
-
return u, v, w
|
823
|
-
u2 = [*u]
|
824
|
-
v2 = [*v]
|
825
|
-
w2 = [*w]
|
826
|
-
cu = code(u)
|
827
|
-
for i in range(len(u2) - 2, -1, -1):
|
828
|
-
if cu[i] == 0 and i < len(cu) - 1 and cu[i + 1] != 0:
|
829
|
-
if i >= len(v2) - 1 or v2[i] < v2[i + 1]:
|
830
|
-
u2[i], u2[i + 1] = u2[i + 1], u2[i]
|
831
|
-
if i > len(w2) - 1:
|
832
|
-
w2 += [j for j in range(len(w2) + 1, i + 3)]
|
833
|
-
w2[i + 1], w2[i] = w2[i], w2[i + 1]
|
834
|
-
if one_dominates(u, w):
|
835
|
-
return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
|
836
|
-
else:
|
837
|
-
return try_reduce_u(u2, v2, w2)
|
838
|
-
elif i < len(w2) - 1 and w2[i] > w2[i + 1]:
|
839
|
-
u2[i], u2[i + 1] = u2[i + 1], u2[i]
|
840
|
-
v2[i], v2[i + 1] = v2[i + 1], v2[i]
|
841
|
-
return try_reduce_u(u2, v2, w2)
|
842
|
-
else:
|
843
|
-
return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
|
844
|
-
return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
|
845
|
-
|
846
|
-
|
847
|
-
def divdiffable(v, u):
|
848
|
-
inv_v = inv(v)
|
849
|
-
inv_u = inv(u)
|
850
|
-
perm2 = permtrim(mulperm(v, inverse(u)))
|
851
|
-
if inv(perm2) != inv_v - inv_u:
|
852
|
-
return []
|
853
|
-
return perm2
|
854
|
-
|
855
|
-
|
856
|
-
def will_formula_work(u, v):
|
857
|
-
muv = uncode(theta(v))
|
858
|
-
vn1muv = mulperm(inverse(v), muv)
|
859
|
-
while True:
|
860
|
-
found_one = False
|
861
|
-
for i in range(len(vn1muv) - 1):
|
862
|
-
if vn1muv[i] > vn1muv[i + 1]:
|
863
|
-
found_one = True
|
864
|
-
if i < len(u) - 1 and u[i] > u[i + 1]:
|
865
|
-
return False
|
866
|
-
else:
|
867
|
-
vn1muv[i], vn1muv[i + 1] = vn1muv[i + 1], vn1muv[i]
|
868
|
-
break
|
869
|
-
if not found_one:
|
870
|
-
return True
|
871
|
-
|
872
|
-
|
873
|
-
def pull_out_var(vnum, v):
|
874
|
-
vup = v + [len(v) + 1]
|
875
|
-
if vnum >= len(v):
|
876
|
-
return [[[], v]]
|
877
|
-
vpm_list = [(vup, 0)]
|
878
|
-
ret_list = []
|
879
|
-
for p in range(len(v) + 1 - vnum):
|
880
|
-
vpm_list2 = []
|
881
|
-
for vpm, b in vpm_list:
|
882
|
-
if vpm[vnum - 1] == len(v) + 1:
|
883
|
-
vpm2 = [*vpm]
|
884
|
-
vpm2.pop(vnum - 1)
|
885
|
-
vp = permtrim(vpm2)
|
886
|
-
ret_list += [
|
887
|
-
[
|
888
|
-
[
|
889
|
-
v[i]
|
890
|
-
for i in range(vnum, len(v))
|
891
|
-
if ((i > len(vp) and v[i] == i) or (i <= len(vp) and v[i] == vp[i - 1]))
|
892
|
-
],
|
893
|
-
vp,
|
894
|
-
]
|
895
|
-
]
|
896
|
-
for j in range(vnum, len(vup)):
|
897
|
-
if vpm[j] <= b:
|
898
|
-
continue
|
899
|
-
for i in range(vnum):
|
900
|
-
if has_bruhat_ascent(vpm, i, j):
|
901
|
-
vpm[i], vpm[j] = vpm[j], vpm[i]
|
902
|
-
vpm_list2 += [([*vpm], vpm[i])]
|
903
|
-
vpm[i], vpm[j] = vpm[j], vpm[i]
|
904
|
-
vpm_list = vpm_list2
|
905
|
-
for vpm, b in vpm_list:
|
906
|
-
if vpm[vnum - 1] == len(v) + 1:
|
907
|
-
vpm2 = [*vpm]
|
908
|
-
vpm2.pop(vnum - 1)
|
909
|
-
vp = permtrim(vpm2)
|
910
|
-
ret_list += [
|
911
|
-
[
|
912
|
-
[
|
913
|
-
v[i]
|
914
|
-
for i in range(vnum, len(v))
|
915
|
-
if ((i > len(vp) and v[i] == i) or (i <= len(vp) and v[i] == vp[i - 1]))
|
916
|
-
],
|
917
|
-
vp,
|
918
|
-
]
|
919
|
-
]
|
920
|
-
return ret_list
|
921
|
-
|
922
|
-
|
923
|
-
def get_cycles(perm):
|
924
|
-
cycle_set = []
|
925
|
-
done_vals = set()
|
926
|
-
for i in range(len(perm)):
|
927
|
-
p = i + 1
|
928
|
-
if perm[i] == p:
|
929
|
-
continue
|
930
|
-
if p in done_vals:
|
931
|
-
continue
|
932
|
-
cycle = []
|
933
|
-
m = -1
|
934
|
-
max_index = -1
|
935
|
-
while p not in done_vals:
|
936
|
-
cycle += [p]
|
937
|
-
done_vals.add(p)
|
938
|
-
if p > m:
|
939
|
-
m = p
|
940
|
-
max_index = len(cycle) - 1
|
941
|
-
p = perm[p - 1]
|
942
|
-
cycle = tuple(cycle[max_index + 1 :] + cycle[: max_index + 1])
|
943
|
-
cycle_set += [cycle]
|
944
|
-
return cycle_set
|
945
|
-
|
946
|
-
|
947
|
-
def double_elem_sym_q(u, p1, p2, k, q_var=q_var):
|
948
|
-
ret_list = {}
|
949
|
-
perms1 = elem_sym_perms_q(u, p1, k, q_var)
|
950
|
-
iu = inverse(u)
|
951
|
-
for perm1, udiff1, mul_val1 in perms1:
|
952
|
-
perms2 = elem_sym_perms_q(perm1, p2, k, q_var)
|
953
|
-
cycles1 = get_cycles(tuple(permtrim(mulperm(iu, [*perm1]))))
|
954
|
-
cycles1_dict = {}
|
955
|
-
for c in cycles1:
|
956
|
-
if c[-1] not in cycles1_dict:
|
957
|
-
cycles1_dict[c[-1]] = []
|
958
|
-
cycles1_dict[c[-1]] += [set(c)]
|
959
|
-
ip1 = inverse(perm1)
|
960
|
-
for perm2, udiff2, mul_val2 in perms2:
|
961
|
-
cycles2 = get_cycles(tuple(permtrim(mulperm(ip1, [*perm2]))))
|
962
|
-
good = True
|
963
|
-
for i in range(len(cycles2)):
|
964
|
-
c2 = cycles2[i]
|
965
|
-
if c2[-1] not in cycles1_dict:
|
966
|
-
continue
|
967
|
-
for c1_s in cycles1_dict[c2[-1]]:
|
968
|
-
for a in range(len(c2) - 2, -1, -1):
|
969
|
-
if c2[a] in c1_s:
|
970
|
-
good = False
|
971
|
-
break
|
972
|
-
if not good:
|
973
|
-
break
|
974
|
-
if not good:
|
975
|
-
break
|
976
|
-
|
977
|
-
if good:
|
978
|
-
if (perm1, udiff1, mul_val1) not in ret_list:
|
979
|
-
ret_list[(perm1, udiff1, mul_val1)] = []
|
980
|
-
ret_list[(perm1, udiff1, mul_val1)] += [(perm2, udiff2, mul_val2)]
|
981
|
-
return ret_list
|
982
|
-
|
983
|
-
|
984
302
|
def medium_theta(perm):
|
985
303
|
cd = code(perm)
|
986
304
|
found_one = True
|
@@ -992,8 +310,43 @@ def medium_theta(perm):
|
|
992
310
|
cd[i], cd[i + 1] = cd[i + 1] + 1, cd[i]
|
993
311
|
break
|
994
312
|
if cd[i] == cd[i + 1] and cd[i] != 0 and i > 0 and cd[i - 1] <= cd[i] + 1:
|
995
|
-
# if cd[i]==cd[i+1] and i>0 and cd[i-1]<=cd[i]+1:
|
996
313
|
cd[i] += 1
|
997
314
|
found_one = True
|
998
315
|
break
|
999
316
|
return cd
|
317
|
+
|
318
|
+
|
319
|
+
def split_perms(perms):
|
320
|
+
perms2 = [perms[0]]
|
321
|
+
for perm in perms[1:]:
|
322
|
+
cd = code(perm)
|
323
|
+
index = -1
|
324
|
+
not_zero = False
|
325
|
+
did = False
|
326
|
+
for i in range(len(cd)):
|
327
|
+
if cd[i] != 0:
|
328
|
+
not_zero = True
|
329
|
+
elif not_zero and cd[i] == 0:
|
330
|
+
not_zero = False
|
331
|
+
index = i
|
332
|
+
num_zeros_to_miss = 0
|
333
|
+
for j in range(index):
|
334
|
+
if cd[j] != 0:
|
335
|
+
num_zeros_to_miss = max(num_zeros_to_miss, cd[j] - (index - 1 - j))
|
336
|
+
num_zeros = 0
|
337
|
+
for j in range(index, len(cd)):
|
338
|
+
if cd[j] != 0:
|
339
|
+
break
|
340
|
+
num_zeros += 1
|
341
|
+
if num_zeros >= num_zeros_to_miss:
|
342
|
+
cd1 = cd[:index]
|
343
|
+
cd2 = [0 for i in range(index)] + cd[index:]
|
344
|
+
perms2 += [
|
345
|
+
uncode(cd1),
|
346
|
+
uncode(cd2),
|
347
|
+
]
|
348
|
+
did = True
|
349
|
+
break
|
350
|
+
if not did:
|
351
|
+
perms2 += [perm]
|
352
|
+
return perms2
|