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,659 @@
|
|
1
|
+
from functools import cache
|
2
|
+
from itertools import chain
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from symengine import sympify
|
6
|
+
|
7
|
+
import schubmult.poly_lib.variables as spl
|
8
|
+
from schubmult.perm_lib import (
|
9
|
+
Permutation,
|
10
|
+
code,
|
11
|
+
ensure_perms,
|
12
|
+
inv,
|
13
|
+
inverse,
|
14
|
+
one_dominates,
|
15
|
+
permtrim,
|
16
|
+
theta,
|
17
|
+
uncode,
|
18
|
+
)
|
19
|
+
from schubmult.utils.perm_utils import (
|
20
|
+
count_bruhat,
|
21
|
+
get_cycles,
|
22
|
+
getpermval,
|
23
|
+
has_bruhat_ascent,
|
24
|
+
has_bruhat_descent,
|
25
|
+
mu_A,
|
26
|
+
omega,
|
27
|
+
p_trans,
|
28
|
+
sg,
|
29
|
+
)
|
30
|
+
|
31
|
+
q_var = spl.GeneratingSet("q")
|
32
|
+
|
33
|
+
|
34
|
+
# def double_elem_sym_q(u, p1, p2, k, q_var=q_var):
|
35
|
+
# ret_list = {}
|
36
|
+
# perms1 = elem_sym_perms_q(u, p1, k, q_var)
|
37
|
+
# iu = inverse(u)
|
38
|
+
# for perm1, udiff1, mul_val1 in perms1:
|
39
|
+
# perms2 = elem_sym_perms_q(perm1, p2, k, q_var)
|
40
|
+
# cycles1 = get_cycles(tuple(permtrim(mulperm(iu, [*perm1]))))
|
41
|
+
# cycles1_dict = {}
|
42
|
+
# for c in cycles1:
|
43
|
+
# if c[-1] not in cycles1_dict:
|
44
|
+
# cycles1_dict[c[-1]] = []
|
45
|
+
# cycles1_dict[c[-1]] += [set(c)]
|
46
|
+
# ip1 = inverse(perm1)
|
47
|
+
# for perm2, udiff2, mul_val2 in perms2:
|
48
|
+
# cycles2 = get_cycles(tuple(permtrim(mulperm(ip1, [*perm2]))))
|
49
|
+
# good = True
|
50
|
+
# for i in range(len(cycles2)):
|
51
|
+
# c2 = cycles2[i]
|
52
|
+
# if c2[-1] not in cycles1_dict:
|
53
|
+
# continue
|
54
|
+
# for c1_s in cycles1_dict[c2[-1]]:
|
55
|
+
# for a in range(len(c2) - 2, -1, -1):
|
56
|
+
# if c2[a] in c1_s:
|
57
|
+
# good = False
|
58
|
+
# break
|
59
|
+
# if not good:
|
60
|
+
# break
|
61
|
+
# if not good:
|
62
|
+
# break
|
63
|
+
|
64
|
+
# if good:
|
65
|
+
# # print(f"{(perm1, udiff1, mul_val1)=}")
|
66
|
+
# if (perm1, udiff1, mul_val1) not in ret_list:
|
67
|
+
# ret_list[(perm1, udiff1, mul_val1)] = []
|
68
|
+
# ret_list[(perm1, udiff1, mul_val1)] += [(perm2, udiff2, mul_val2)]
|
69
|
+
# return ret_list
|
70
|
+
|
71
|
+
|
72
|
+
def double_elem_sym_q(u, p1, p2, k, q_var=q_var):
|
73
|
+
ret_list = {}
|
74
|
+
perms1 = elem_sym_perms_q(u, p1, k, q_var)
|
75
|
+
iu = ~u
|
76
|
+
for perm1, udiff1, mul_val1 in perms1:
|
77
|
+
perms2 = elem_sym_perms_q(perm1, p2, k, q_var)
|
78
|
+
cycles1 = get_cycles(iu*perm1)
|
79
|
+
cycles1_dict = {}
|
80
|
+
for c in cycles1:
|
81
|
+
if c[-1] not in cycles1_dict:
|
82
|
+
cycles1_dict[c[-1]] = []
|
83
|
+
cycles1_dict[c[-1]] += [set(c)]
|
84
|
+
ip1 = inverse(perm1)
|
85
|
+
for perm2, udiff2, mul_val2 in perms2:
|
86
|
+
cycles2 = get_cycles(ip1*perm2)
|
87
|
+
good = True
|
88
|
+
for i in range(len(cycles2)):
|
89
|
+
c2 = cycles2[i]
|
90
|
+
if c2[-1] not in cycles1_dict:
|
91
|
+
continue
|
92
|
+
for c1_s in cycles1_dict[c2[-1]]:
|
93
|
+
for a in range(len(c2) - 2, -1, -1):
|
94
|
+
if c2[a] in c1_s:
|
95
|
+
good = False
|
96
|
+
break
|
97
|
+
if not good:
|
98
|
+
break
|
99
|
+
if not good:
|
100
|
+
break
|
101
|
+
|
102
|
+
if good:
|
103
|
+
if (perm1, udiff1, mul_val1) not in ret_list:
|
104
|
+
ret_list[(perm1, udiff1, mul_val1)] = []
|
105
|
+
ret_list[(perm1, udiff1, mul_val1)] += [(perm2, udiff2, mul_val2)]
|
106
|
+
return ret_list
|
107
|
+
|
108
|
+
|
109
|
+
def will_formula_work(u, v):
|
110
|
+
u, v = Permutation(u), Permutation(v)
|
111
|
+
muv = uncode(theta(v))
|
112
|
+
vn1muv = (~v) * muv
|
113
|
+
while inv(vn1muv)>0:
|
114
|
+
found_one = False
|
115
|
+
for i in range(len(vn1muv) - 1):
|
116
|
+
if vn1muv[i] > vn1muv[i + 1]:
|
117
|
+
found_one = True
|
118
|
+
if i < len(u) - 1 and u[i] > u[i + 1]:
|
119
|
+
return False
|
120
|
+
# vn1muv[i], vn1muv[i + 1] = vn1muv[i + 1], vn1muv[i]
|
121
|
+
vn1muv = vn1muv.swap(i, i + 1)
|
122
|
+
break
|
123
|
+
if found_one:
|
124
|
+
return False
|
125
|
+
return True
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
def try_reduce_u(u, v, w):
|
130
|
+
if one_dominates(u, w):
|
131
|
+
return u, v, w
|
132
|
+
u2 = u
|
133
|
+
v2 = v
|
134
|
+
w2 = w
|
135
|
+
cu = code(u)
|
136
|
+
for i in range(len(u2) - 2, -1, -1):
|
137
|
+
if cu[i] == 0 and i < len(cu) - 1 and cu[i + 1] != 0:
|
138
|
+
if i >= len(v2) - 1 or v2[i] < v2[i + 1]:
|
139
|
+
# u2[i], u2[i + 1] = u2[i + 1], u2[i]
|
140
|
+
# if i > len(w2) - 1:
|
141
|
+
# w2 += list(range(len(w2) + 1, i + 3))
|
142
|
+
# w2[i + 1], w2[i] = w2[i], w2[i + 1]
|
143
|
+
u2 = u2.swap(i, i + 1)
|
144
|
+
w2 = w2.swap(i, i + 1)
|
145
|
+
if one_dominates(u2, w):
|
146
|
+
# return Permutation(u2), Permutation(v2), Permutation(w2)
|
147
|
+
return u2, v2, w2
|
148
|
+
return try_reduce_u(u2, v2, w2)
|
149
|
+
if i < len(w2) - 1 and w2[i] > w2[i + 1]:
|
150
|
+
# ERROR?
|
151
|
+
# u2[i], u2[i + 1] = u2[i + 1], u2[i]
|
152
|
+
# v2[i], v2[i + 1] = v2[i + 1], v2[i]
|
153
|
+
u2 = u2.swap(i, i + 1)
|
154
|
+
v2 = v2.swap(i, i + 1)
|
155
|
+
return try_reduce_u(u2, v2, w2)
|
156
|
+
# return Permutation(u2), Permutation(v2), Permutation(w2)
|
157
|
+
return u2, v2, w2
|
158
|
+
# return Permutation(u2), Permutation(v2), Permutation(w2)
|
159
|
+
return u2, v2, w2
|
160
|
+
|
161
|
+
|
162
|
+
def reduce_descents(u, v, w):
|
163
|
+
found_one = True
|
164
|
+
u2 = Permutation(u)
|
165
|
+
v2 = Permutation(v)
|
166
|
+
w2 = Permutation(w)
|
167
|
+
while found_one:
|
168
|
+
found_one = False
|
169
|
+
if will_formula_work(u2, v2) or will_formula_work(v2, u2) or one_dominates(u2, w2) or is_reducible(v2) or inv(w2) - inv(u2) == 1:
|
170
|
+
break
|
171
|
+
for i in range(len(w2) - 2, -1, -1):
|
172
|
+
if w2[i] > w2[i + 1] and i < len(v2) - 1 and v2[i] > v2[i + 1] and (i >= len(u2) - 1 or u2[i] < u2[i + 1]):
|
173
|
+
w2 = w2.swap(i, i + 1)
|
174
|
+
v2 = v2.swap(i, i + 1)
|
175
|
+
found_one = True
|
176
|
+
elif w2[i] > w2[i + 1] and i < len(u2) - 1 and u2[i] > u2[i + 1] and (i >= len(v2) - 1 or v2[i] < v2[i + 1]):
|
177
|
+
w2 = w2.swap(i, i + 1)
|
178
|
+
u2 = u2.swap(i, i + 1)
|
179
|
+
found_one = True
|
180
|
+
if found_one:
|
181
|
+
break
|
182
|
+
# return Permutation(u2), Permutation(v2), Permutation(w2)
|
183
|
+
return u2, v2, w2
|
184
|
+
|
185
|
+
|
186
|
+
def is_reducible(v):
|
187
|
+
c03 = code(v)
|
188
|
+
found0 = False
|
189
|
+
good = True
|
190
|
+
for i in range(len(c03)):
|
191
|
+
if c03[i] == 0:
|
192
|
+
found0 = True
|
193
|
+
elif c03[i] != 0 and found0:
|
194
|
+
good = False
|
195
|
+
break
|
196
|
+
return good
|
197
|
+
|
198
|
+
|
199
|
+
# @ensure_perms
|
200
|
+
def try_reduce_v(u, v, w):
|
201
|
+
if is_reducible(v):
|
202
|
+
return u, v, w
|
203
|
+
u2 = u
|
204
|
+
v2 = v
|
205
|
+
w2 = w
|
206
|
+
cv = code(v2)
|
207
|
+
for i in range(len(v2) - 2, -1, -1):
|
208
|
+
if cv[i] == 0 and i < len(cv) - 1 and cv[i + 1] != 0:
|
209
|
+
if i >= len(u2) - 1 or u2[i] < u2[i + 1]:
|
210
|
+
# v2[i], v2[i + 1] = v2[i + 1], v2[i]
|
211
|
+
v2 = v2.swap(i, i + 1)
|
212
|
+
# if i >= len(w2) - 1:
|
213
|
+
# w2 += list(range(len(w2) + 1, i + 3))
|
214
|
+
# w2[i + 1], w2[i] = w2[i], w2[i + 1]
|
215
|
+
w2 = w2.swap(i, i + 1)
|
216
|
+
if is_reducible(v2):
|
217
|
+
return Permutation(u2), Permutation(v2), Permutation(w2)
|
218
|
+
return try_reduce_v(u2, v2, w2)
|
219
|
+
if i < len(w2) - 1 and w2[i] > w2[i + 1]:
|
220
|
+
# u2[i], u2[i + 1] = u2[i + 1], u2[i]
|
221
|
+
# v2[i], v2[i + 1] = v2[i + 1], v2[i]
|
222
|
+
u2 = u2.swap(i, i + 1)
|
223
|
+
v2 = v2.swap(i, i + 1)
|
224
|
+
return try_reduce_v(u2, v2, w2)
|
225
|
+
# return Permutation(u2), Permutation(v2), Permutation(w2)
|
226
|
+
return u2, v2, w2
|
227
|
+
return u2, v2, w2
|
228
|
+
|
229
|
+
|
230
|
+
def reduce_coeff(u, v, w):
|
231
|
+
t_mu_u_t = theta(inverse(u))
|
232
|
+
t_mu_v_t = theta(inverse(v))
|
233
|
+
|
234
|
+
mu_u_inv = uncode(t_mu_u_t)
|
235
|
+
mu_v_inv = uncode(t_mu_v_t)
|
236
|
+
|
237
|
+
t_mu_u = p_trans(t_mu_u_t)
|
238
|
+
t_mu_v = p_trans(t_mu_v_t)
|
239
|
+
|
240
|
+
t_mu_u += [0 for i in range(len(t_mu_u), max(len(t_mu_u), len(t_mu_v)))]
|
241
|
+
t_mu_v += [0 for i in range(len(t_mu_v), max(len(t_mu_u), len(t_mu_v)))]
|
242
|
+
|
243
|
+
t_mu_uv = [t_mu_u[i] + t_mu_v[i] for i in range(len(t_mu_u))]
|
244
|
+
t_mu_uv_t = p_trans(t_mu_uv)
|
245
|
+
|
246
|
+
mu_uv_inv = uncode(t_mu_uv_t)
|
247
|
+
|
248
|
+
if inv(w * mu_uv_inv) != inv(mu_uv_inv) - inv(w):
|
249
|
+
return u, v, w
|
250
|
+
|
251
|
+
# umu = mulperm(list(u), mu_u_inv)
|
252
|
+
# vmu = mulperm(list(v), mu_v_inv)
|
253
|
+
# wmu = mulperm(list(w), mu_uv_inv)
|
254
|
+
umu = u * mu_u_inv
|
255
|
+
vmu = v * mu_v_inv
|
256
|
+
wmu = w * mu_uv_inv
|
257
|
+
|
258
|
+
t_mu_w = theta(inverse(wmu))
|
259
|
+
|
260
|
+
mu_w = uncode(t_mu_w)
|
261
|
+
|
262
|
+
w_prime = wmu * mu_w
|
263
|
+
|
264
|
+
if w == w_prime:
|
265
|
+
return u, v, w
|
266
|
+
# if permtrim(list(w)) == permtrim(w_prime):
|
267
|
+
# return (permtrim(list(u)), permtrim(list(v)), permtrim(list(w)))
|
268
|
+
|
269
|
+
A = []
|
270
|
+
B = []
|
271
|
+
indexA = 0
|
272
|
+
|
273
|
+
while len(t_mu_u_t) > 0 and t_mu_u_t[-1] == 0:
|
274
|
+
t_mu_u_t.pop()
|
275
|
+
|
276
|
+
while len(t_mu_v_t) > 0 and t_mu_v_t[-1] == 0:
|
277
|
+
t_mu_v_t.pop()
|
278
|
+
|
279
|
+
while len(t_mu_uv_t) > 0 and t_mu_uv_t[-1] == 0:
|
280
|
+
t_mu_uv_t.pop()
|
281
|
+
|
282
|
+
for index in range(len(t_mu_uv_t)):
|
283
|
+
if indexA < len(t_mu_u_t) and t_mu_uv_t[index] == t_mu_u_t[indexA]:
|
284
|
+
A += [index]
|
285
|
+
indexA += 1
|
286
|
+
else:
|
287
|
+
B += [index]
|
288
|
+
|
289
|
+
mu_w_A = uncode(mu_A(code(mu_w), A))
|
290
|
+
mu_w_B = uncode(mu_A(code(mu_w), B))
|
291
|
+
|
292
|
+
return (umu * mu_w_A, vmu * mu_w_B, w_prime)
|
293
|
+
|
294
|
+
|
295
|
+
def pull_out_var(vnum, v):
|
296
|
+
v = Permutation(v)
|
297
|
+
vup = v
|
298
|
+
if vnum >= len(v):
|
299
|
+
return [[[], v]]
|
300
|
+
vpm_list = [(vup, 0)]
|
301
|
+
ret_list = []
|
302
|
+
for p in range(len(v) + 1 - vnum):
|
303
|
+
vpm_list2 = []
|
304
|
+
for vpm, b in vpm_list:
|
305
|
+
if vpm[vnum - 1] == len(v) + 1:
|
306
|
+
vpm2 = [*vpm]
|
307
|
+
vpm2.pop(vnum - 1)
|
308
|
+
vp = permtrim(vpm2)
|
309
|
+
ret_list += [
|
310
|
+
[
|
311
|
+
[v[i] for i in range(vnum, len(v)) if ((i > len(vp) and v[i] == i) or (i <= len(vp) and v[i] == vp[i - 1]))],
|
312
|
+
vp,
|
313
|
+
],
|
314
|
+
]
|
315
|
+
for j in range(vnum, len(vup) + 2):
|
316
|
+
if vpm[j] <= b:
|
317
|
+
continue
|
318
|
+
for i in range(vnum):
|
319
|
+
if has_bruhat_ascent(vpm, i, j):
|
320
|
+
vpm_list2 += [(vpm.swap(i, j), vpm[j])]
|
321
|
+
vpm_list = vpm_list2
|
322
|
+
for vpm, b in vpm_list:
|
323
|
+
if vpm[vnum - 1] == len(v) + 1:
|
324
|
+
vpm2 = [*vpm]
|
325
|
+
vpm2.pop(vnum - 1)
|
326
|
+
vp = permtrim(vpm2)
|
327
|
+
ret_list += [
|
328
|
+
[
|
329
|
+
[v[i] for i in range(vnum, len(v)) if ((i > len(vp) and v[i] == i) or (i <= len(vp) and v[i] == vp[i - 1]))],
|
330
|
+
vp,
|
331
|
+
],
|
332
|
+
]
|
333
|
+
return ret_list
|
334
|
+
|
335
|
+
|
336
|
+
@ensure_perms
|
337
|
+
def divdiffable(v, u):
|
338
|
+
inv_v = inv(v)
|
339
|
+
inv_u = inv(u)
|
340
|
+
perm2 = v * (~u)
|
341
|
+
if inv(perm2) != inv_v - inv_u:
|
342
|
+
return []
|
343
|
+
return perm2
|
344
|
+
|
345
|
+
|
346
|
+
# perms and inversion diff
|
347
|
+
def kdown_perms(perm, monoperm, p, k):
|
348
|
+
perm = Permutation(perm)
|
349
|
+
monoperm = Permutation(monoperm)
|
350
|
+
inv_m = inv(monoperm)
|
351
|
+
inv_p = inv(perm)
|
352
|
+
full_perm_list = []
|
353
|
+
# perm = Permutation(perm)
|
354
|
+
# print(f"{perm=} {monoperm=} {inv_m=} {inv_p=} {perm*monoperm=}")
|
355
|
+
if inv(perm * monoperm) == inv_m - inv_p:
|
356
|
+
full_perm_list += [(perm, 0, 1)]
|
357
|
+
|
358
|
+
down_perm_list = [(perm, 1)]
|
359
|
+
if len(perm) < k:
|
360
|
+
return full_perm_list
|
361
|
+
a2 = k - 1
|
362
|
+
for pp in range(1, p + 1):
|
363
|
+
down_perm_list2 = []
|
364
|
+
for perm2, s in down_perm_list:
|
365
|
+
L = len(perm2)
|
366
|
+
# print(f"{perm2=} {L=}")
|
367
|
+
if k > L:
|
368
|
+
continue
|
369
|
+
s2 = -s
|
370
|
+
for b in chain(range(k - 1), range(k, L)):
|
371
|
+
if perm2[b] != perm[b]:
|
372
|
+
continue
|
373
|
+
if b < a2:
|
374
|
+
i, j = b, a2
|
375
|
+
else:
|
376
|
+
i, j, s2 = a2, b, s
|
377
|
+
# print(f"{perm2=} {i=} {j=}")
|
378
|
+
if has_bruhat_descent(perm2, i, j):
|
379
|
+
# print(f"YEAH BABY {perm2=} {i=} {j=}")
|
380
|
+
new_perm = perm2.swap(i, j)
|
381
|
+
# print(f"{new_perm=}")
|
382
|
+
down_perm_list2 += [(new_perm, s2)]
|
383
|
+
if inv(new_perm * monoperm) == inv_m - inv_p + pp:
|
384
|
+
full_perm_list += [(new_perm, pp, s2)]
|
385
|
+
# else:
|
386
|
+
# # print(f"NO BABY {perm2=} {i=} {j=}")
|
387
|
+
down_perm_list = down_perm_list2
|
388
|
+
return full_perm_list
|
389
|
+
|
390
|
+
@cache
|
391
|
+
def compute_vpathdicts_cached(th, vmu, smpify):
|
392
|
+
vpathdicts = [{} for index in range(len(th))]
|
393
|
+
vpathdicts[-1][vmu] = None
|
394
|
+
thL = len(th)
|
395
|
+
|
396
|
+
top = code(~Permutation(uncode(th)))
|
397
|
+
for i in range(thL - 1, -1, -1):
|
398
|
+
top2 = code(~Permutation(uncode(top)))
|
399
|
+
while top2[-1] == 0:
|
400
|
+
top2.pop()
|
401
|
+
top2.pop()
|
402
|
+
top = code(~Permutation(uncode(top2)))
|
403
|
+
# print(f"{top=}")
|
404
|
+
monoperm = Permutation(uncode(top))
|
405
|
+
# print(f"{monoperm=}")
|
406
|
+
k = i + 1
|
407
|
+
for last_perm in vpathdicts[i]:
|
408
|
+
newperms = kdown_perms(last_perm, monoperm, th[i], k)
|
409
|
+
vpathdicts[i][last_perm] = newperms
|
410
|
+
if i > 0:
|
411
|
+
for trip in newperms:
|
412
|
+
vpathdicts[i - 1][trip[0]] = None
|
413
|
+
vpathdicts2 = [{} for i in range(len(th))]
|
414
|
+
for i in range(len(th)):
|
415
|
+
for key, valueset in vpathdicts[i].items():
|
416
|
+
for value in valueset:
|
417
|
+
key2 = value[0]
|
418
|
+
if key2 not in vpathdicts2[i]:
|
419
|
+
vpathdicts2[i][key2] = set()
|
420
|
+
v2 = value[2]
|
421
|
+
if smpify:
|
422
|
+
v2 = sympify(v2)
|
423
|
+
vpathdicts2[i][key2].add((key, value[1], v2))
|
424
|
+
return vpathdicts2
|
425
|
+
|
426
|
+
def compute_vpathdicts(th, vmu, smpify=False):
|
427
|
+
return compute_vpathdicts_cached(tuple(th), vmu, smpify)
|
428
|
+
|
429
|
+
|
430
|
+
def check_blocks(qv, parabolic_index):
|
431
|
+
blocks = []
|
432
|
+
cur_block = []
|
433
|
+
last_val = -1
|
434
|
+
for i in range(len(parabolic_index)):
|
435
|
+
if last_val + 1 != parabolic_index[i] and i != 0:
|
436
|
+
blocks += [cur_block]
|
437
|
+
cur_block = []
|
438
|
+
last_val = parabolic_index[i]
|
439
|
+
cur_block += [last_val]
|
440
|
+
if len(cur_block) != 0:
|
441
|
+
blocks += [cur_block]
|
442
|
+
# print(f"{parabolic_index=}")
|
443
|
+
# print(f"{blocks=}")
|
444
|
+
for block in blocks:
|
445
|
+
for i in range(len(block)):
|
446
|
+
for j in range(i, len(block)):
|
447
|
+
val = 0
|
448
|
+
for k in range(i, j + 1):
|
449
|
+
val += omega(block[k], qv)
|
450
|
+
if val != 0 and val != -1:
|
451
|
+
return False
|
452
|
+
return True
|
453
|
+
|
454
|
+
|
455
|
+
def reduce_q_coeff(u, v, w, qv):
|
456
|
+
for i in range(len(qv)):
|
457
|
+
if sg(i, v) == 1 and sg(i, u) == 0 and sg(i, w) + omega(i + 1, qv) == 1:
|
458
|
+
ret_v = v.swap(i, i + 1)
|
459
|
+
ret_w = w.swap(i, i + 1)
|
460
|
+
qv_ret = [*qv]
|
461
|
+
if sg(i, w) == 0:
|
462
|
+
qv_ret[i] -= 1
|
463
|
+
return u, ret_v, ret_w, qv_ret, True
|
464
|
+
if (sg(i, u) == 1 and sg(i, v) == 0 and sg(i, w) + omega(i + 1, qv) == 1) or (sg(i, u) == 1 and sg(i, v) == 1 and sg(i, w) + omega(i + 1, qv) == 2):
|
465
|
+
ret_u = u.swap(i, i + 1)
|
466
|
+
ret_w = w.swap(i, i + 1)
|
467
|
+
qv_ret = [*qv]
|
468
|
+
if sg(i, w) == 0:
|
469
|
+
qv_ret[i] -= 1
|
470
|
+
return ret_u, v, ret_w, qv_ret, True
|
471
|
+
return u, v, w, qv, False
|
472
|
+
|
473
|
+
|
474
|
+
def reduce_q_coeff_u_only(u, v, w, qv):
|
475
|
+
for i in range(len(qv)):
|
476
|
+
if (sg(i, u) == 1 and sg(i, v) == 0 and sg(i, w) + omega(i + 1, qv) == 1) or (sg(i, u) == 1 and sg(i, v) == 1 and sg(i, w) + omega(i + 1, qv) == 2):
|
477
|
+
# ret_u = [*u]
|
478
|
+
# ret_u[i], ret_u[i + 1] = ret_u[i + 1], ret_u[i]
|
479
|
+
ret_u = u.swap(i, i + 1)
|
480
|
+
# ret_w = [*w] + [j + 1 for j in range(len(w), i + 2)]
|
481
|
+
# ret_w[i], ret_w[i + 1] = ret_w[i + 1], ret_w[i]
|
482
|
+
ret_w = w.swap(i, i + 1)
|
483
|
+
qv_ret = [*qv]
|
484
|
+
if sg(i, w) == 0:
|
485
|
+
qv_ret[i] -= 1
|
486
|
+
return ret_u, v, ret_w, qv_ret, True
|
487
|
+
return u, v, w, qv, False
|
488
|
+
|
489
|
+
|
490
|
+
# def elem_sym_perms_q(orig_perm, p, k, q_var=q_var):
|
491
|
+
# total_list = [(orig_perm, 0, 1)]
|
492
|
+
# up_perm_list = [(orig_perm, 1, 1000)]
|
493
|
+
# for pp in range(p):
|
494
|
+
# perm_list = []
|
495
|
+
# for up_perm, val, last_j in up_perm_list:
|
496
|
+
# up_perm2 = [*up_perm, len(up_perm) + 1]
|
497
|
+
# if len(up_perm2) < k + 1:
|
498
|
+
# up_perm2 += [i + 1 for i in range(len(up_perm2), k + 2)]
|
499
|
+
# pos_list = [i for i in range(k) if (i >= len(orig_perm) and up_perm2[i] == i + 1) or (i < len(orig_perm) and up_perm2[i] == orig_perm[i])]
|
500
|
+
# for j in range(min(len(up_perm2) - 1, last_j), k - 1, -1):
|
501
|
+
# for i in pos_list:
|
502
|
+
# ct = count_bruhat(up_perm2, i, j)
|
503
|
+
# # print(f"{up_perm2=} {ct=} {i=} {j=} {k=} {pp=}")
|
504
|
+
# if ct == 1 or ct == 2 * (i - j) + 1:
|
505
|
+
# new_perm = [*up_perm2]
|
506
|
+
# new_perm[i], new_perm[j] = new_perm[j], new_perm[i]
|
507
|
+
# new_perm_add = tuple(permtrim(new_perm))
|
508
|
+
# new_val = val
|
509
|
+
# if ct < 0:
|
510
|
+
# new_val *= np.prod([q_var[index] for index in range(i + 1, j + 1)])
|
511
|
+
# perm_list += [(new_perm_add, new_val, j)]
|
512
|
+
# total_list += [(new_perm_add, pp + 1, new_val)]
|
513
|
+
# up_perm_list = perm_list
|
514
|
+
# return total_list
|
515
|
+
|
516
|
+
|
517
|
+
def elem_sym_perms_q(orig_perm, p, k, q_var=q_var):
|
518
|
+
total_list = [(orig_perm, 0, 1)]
|
519
|
+
up_perm_list = [(orig_perm, 1, 1000)]
|
520
|
+
for pp in range(p):
|
521
|
+
perm_list = []
|
522
|
+
for up_perm, val, last_j in up_perm_list:
|
523
|
+
pos_list = [i for i in range(k) if up_perm[i] == orig_perm[i]]
|
524
|
+
# print(f"{pos_list=} {up_perm=} {orig_perm=} {k=}", file=sys.stderr)
|
525
|
+
for j in range(min(max(k + 1, len(up_perm)), last_j), k - 1, -1):
|
526
|
+
for i in pos_list:
|
527
|
+
ct = count_bruhat(up_perm, i, j)
|
528
|
+
if ct == 1 or ct == 2 * (i - j) + 1:
|
529
|
+
new_perm_add = up_perm.swap(i, j)
|
530
|
+
# print(f"{new_perm_add=}")
|
531
|
+
new_val = val
|
532
|
+
if ct < 0:
|
533
|
+
new_val *= np.prod([q_var[index] for index in range(i + 1, j + 1)])
|
534
|
+
perm_list += [(new_perm_add, new_val, j)]
|
535
|
+
total_list += [(new_perm_add, pp + 1, new_val)]
|
536
|
+
up_perm_list = perm_list
|
537
|
+
return total_list
|
538
|
+
|
539
|
+
|
540
|
+
@ensure_perms
|
541
|
+
def elem_sym_perms_q_op(orig_perm, p, k, n, q_var=q_var):
|
542
|
+
total_list = [(orig_perm, 0, 1)]
|
543
|
+
up_perm_list = [(orig_perm, 1, k)]
|
544
|
+
for pp in range(p):
|
545
|
+
perm_list = []
|
546
|
+
for up_perm, val, last_j in up_perm_list:
|
547
|
+
up_perm2 = [*up_perm]
|
548
|
+
if len(up_perm) < n:
|
549
|
+
up_perm2 += [i + 1 for i in range(len(up_perm2), n)]
|
550
|
+
pos_list = [i for i in range(k) if (i >= len(orig_perm) and up_perm2[i] == i + 1) or (i < len(orig_perm) and up_perm2[i] == orig_perm[i])]
|
551
|
+
for j in range(last_j, n):
|
552
|
+
for i in pos_list:
|
553
|
+
ct = count_bruhat(up_perm2, i, j)
|
554
|
+
# print(f"{up_perm2=} {ct=} {i=} {j=} {k=} {pp=}")
|
555
|
+
if ct == -1 or ct == 2 * (j - i) - 1:
|
556
|
+
new_perm = [*up_perm2]
|
557
|
+
new_perm[i], new_perm[j] = new_perm[j], new_perm[i]
|
558
|
+
new_perm_add = Permutation(new_perm)
|
559
|
+
new_val = val
|
560
|
+
if ct > 0:
|
561
|
+
new_val *= np.prod([q_var[index] for index in range(i + 1, j + 1)])
|
562
|
+
perm_list += [(new_perm_add, new_val, j)]
|
563
|
+
total_list += [(new_perm_add, pp + 1, new_val)]
|
564
|
+
up_perm_list = perm_list
|
565
|
+
return total_list
|
566
|
+
|
567
|
+
|
568
|
+
def elem_sym_perms(orig_perm, p, k):
|
569
|
+
orig_perm = Permutation(orig_perm)
|
570
|
+
total_list = [(orig_perm, 0)]
|
571
|
+
up_perm_list = [(orig_perm, 1000000000)]
|
572
|
+
for pp in range(p):
|
573
|
+
perm_list = []
|
574
|
+
for up_perm, last in up_perm_list:
|
575
|
+
pos_list = [i for i in range(k) if up_perm[i] < last]
|
576
|
+
for j in range(k, max(k + 2, len(up_perm) + 1)):
|
577
|
+
if up_perm[j] >= last:
|
578
|
+
continue
|
579
|
+
for i in pos_list:
|
580
|
+
if has_bruhat_ascent(up_perm, i, j):
|
581
|
+
new_perm_add = up_perm.swap(i, j)
|
582
|
+
perm_list += [(new_perm_add, up_perm[j])]
|
583
|
+
total_list += [(new_perm_add, pp + 1)]
|
584
|
+
up_perm_list = perm_list
|
585
|
+
return total_list
|
586
|
+
|
587
|
+
|
588
|
+
def elem_sym_perms_op(orig_perm, p, k):
|
589
|
+
total_list = [(orig_perm, 0)]
|
590
|
+
up_perm_list = [(orig_perm, k)]
|
591
|
+
for pp in range(p):
|
592
|
+
perm_list = []
|
593
|
+
for up_perm, last in up_perm_list:
|
594
|
+
up_perm2 = [*up_perm]
|
595
|
+
if len(up_perm2) < k + 1:
|
596
|
+
up_perm2 += [i + 1 for i in range(len(up_perm2), k + 2)]
|
597
|
+
pos_list = [i for i in range(k) if getpermval(up_perm2, i) == getpermval(orig_perm, i)]
|
598
|
+
for j in range(last, len(up_perm2)):
|
599
|
+
for i in pos_list:
|
600
|
+
if has_bruhat_descent(up_perm2, i, j):
|
601
|
+
new_perm_add = up_perm.swap(i, j)
|
602
|
+
perm_list += [(new_perm_add, j)]
|
603
|
+
total_list += [(new_perm_add, pp + 1)]
|
604
|
+
up_perm_list = perm_list
|
605
|
+
return total_list
|
606
|
+
|
607
|
+
|
608
|
+
def is_split_two(u, v, w):
|
609
|
+
if inv(w) - inv(u) != 2:
|
610
|
+
return False, []
|
611
|
+
diff_perm = (~v) * w
|
612
|
+
identity = [i + 1 for i in range(len(diff_perm))]
|
613
|
+
cycles = []
|
614
|
+
for i in range(len(identity)):
|
615
|
+
if diff_perm[i] != identity[i]:
|
616
|
+
cycle0 = set()
|
617
|
+
cycle = {i + 1}
|
618
|
+
last = i
|
619
|
+
while len(cycle0) != len(cycle):
|
620
|
+
cycle0 = cycle
|
621
|
+
last = diff_perm[last] - 1
|
622
|
+
cycle.add(last + 1)
|
623
|
+
if len(cycle) > 1 and cycle not in cycles:
|
624
|
+
cycles += [cycle]
|
625
|
+
if len(cycles) > 2:
|
626
|
+
break
|
627
|
+
if len(cycles) == 2:
|
628
|
+
return True, cycles
|
629
|
+
return False, []
|
630
|
+
|
631
|
+
|
632
|
+
def is_coeff_irreducible(u, v, w):
|
633
|
+
return (
|
634
|
+
not will_formula_work(u, v)
|
635
|
+
and not will_formula_work(v, u)
|
636
|
+
and not one_dominates(u, w)
|
637
|
+
and not is_reducible(v)
|
638
|
+
and inv(w) - inv(u) > 1
|
639
|
+
and not is_split_two(u, v, w)[0]
|
640
|
+
and len([i for i in code(v) if i != 0]) > 1
|
641
|
+
)
|
642
|
+
|
643
|
+
|
644
|
+
def is_hook(cd):
|
645
|
+
started = False
|
646
|
+
done = False
|
647
|
+
found_zero_after = False
|
648
|
+
for i in range(len(cd)):
|
649
|
+
if (done or found_zero_after) and cd[i] != 0:
|
650
|
+
return False
|
651
|
+
if cd[i] == 1 and not started:
|
652
|
+
started = True
|
653
|
+
if cd[i] > 1:
|
654
|
+
done = True
|
655
|
+
if started and cd[i] == 0:
|
656
|
+
found_zero_after = True
|
657
|
+
if started or done:
|
658
|
+
return True
|
659
|
+
return False
|