schubmult 1.3.5__tar.gz → 1.3.7__tar.gz
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-1.3.5 → schubmult-1.3.7}/PKG-INFO +5 -2
- {schubmult-1.3.5 → schubmult-1.3.7}/README.md +4 -1
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/perm_lib.py +39 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q/schubmult_q.py +1 -2
- schubmult-1.3.7/schubmult/schubmult_q_yz/schubmult_q_yz.py +337 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult.egg-info/PKG-INFO +5 -2
- {schubmult-1.3.5 → schubmult-1.3.7}/setup.py +1 -1
- schubmult-1.3.5/schubmult/schubmult_q_yz/schubmult_q_yz.py +0 -206
- {schubmult-1.3.5 → schubmult-1.3.7}/LICENSE +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/__init__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_double/__init__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_double/__main__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_double/schubmult_double.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_py/__init__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_py/__main__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_py/schubmult_py.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q/__init__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q/__main__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q_double/__init__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q_double/__main__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q_double/schubmult_q_double.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q_yz/__init__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_q_yz/__main__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_yz/__init__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_yz/__main__.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult/schubmult_yz/schubmult_yz.py +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult.egg-info/SOURCES.txt +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult.egg-info/dependency_links.txt +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult.egg-info/entry_points.txt +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult.egg-info/requires.txt +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/schubmult.egg-info/top_level.txt +0 -0
- {schubmult-1.3.5 → schubmult-1.3.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: schubmult
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.7
|
4
4
|
Summary: Computing Littlewood-Richardson coefficients of Schubert polynomials
|
5
5
|
Home-page: https://github.com/matthematics/schubmult
|
6
6
|
Author: Matt Samuel
|
@@ -50,7 +50,10 @@ schubmult_double -code -coprod 0 1 2 3 - 2 4
|
|
50
50
|
schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
|
51
51
|
```
|
52
52
|
|
53
|
-
|
53
|
+
Since version 1.3.7, schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
|
54
|
+
```
|
55
|
+
schubmult_q_yz -nil-hecke 6 -code 2 2 --display-positive
|
56
|
+
```
|
54
57
|
|
55
58
|
Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative (which at least is known for schubmult_py, schubmult_q, schubmult_double, and schubmult_q_double) and the problem is in GapP, it is not known to be in #P at this time.
|
56
59
|
|
@@ -37,7 +37,10 @@ schubmult_double -code -coprod 0 1 2 3 - 2 4
|
|
37
37
|
schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
|
38
38
|
```
|
39
39
|
|
40
|
-
|
40
|
+
Since version 1.3.7, schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
|
41
|
+
```
|
42
|
+
schubmult_q_yz -nil-hecke 6 -code 2 2 --display-positive
|
43
|
+
```
|
41
44
|
|
42
45
|
Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative (which at least is known for schubmult_py, schubmult_q, schubmult_double, and schubmult_q_double) and the problem is in GapP, it is not known to be in #P at this time.
|
43
46
|
|
@@ -139,6 +139,19 @@ def elem_sym_perms(orig_perm,p,k):
|
|
139
139
|
up_perm_list = perm_list
|
140
140
|
return total_list
|
141
141
|
|
142
|
+
def strict_theta(u):
|
143
|
+
ret = [*trimcode(u)]
|
144
|
+
did_one = True
|
145
|
+
while did_one:
|
146
|
+
did_one = False
|
147
|
+
for i in range(len(ret)-2,-1,-1):
|
148
|
+
if ret[i+1]!=0 and ret[i] <= ret[i+1]:
|
149
|
+
ret[i], ret[i+1] = ret[i+1] + 1, ret[i]
|
150
|
+
did_one = True
|
151
|
+
break
|
152
|
+
while len(ret)>0 and ret[-1] == 0:
|
153
|
+
ret.pop()
|
154
|
+
return ret
|
142
155
|
|
143
156
|
def elem_sym_perms_q(orig_perm,p,k):
|
144
157
|
total_list = [(orig_perm,0,1)]
|
@@ -168,6 +181,32 @@ def elem_sym_perms_q(orig_perm,p,k):
|
|
168
181
|
#print(f"{total_list=}")
|
169
182
|
return total_list
|
170
183
|
|
184
|
+
def elem_sym_perms_q_op(orig_perm,p,k,n):
|
185
|
+
total_list = [(orig_perm,0,1)]
|
186
|
+
up_perm_list = [(orig_perm,1,k)]
|
187
|
+
for pp in range(p):
|
188
|
+
perm_list = []
|
189
|
+
for up_perm, val, last_j in up_perm_list:
|
190
|
+
up_perm2 = [*up_perm]
|
191
|
+
if len(up_perm) < n :
|
192
|
+
up_perm2 += [i+1 for i in range(len(up_perm2),n)]
|
193
|
+
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])]
|
194
|
+
for j in range(last_j,n):
|
195
|
+
for i in pos_list:
|
196
|
+
ct = count_bruhat(up_perm2,i,j)
|
197
|
+
#print(f"{up_perm2=} {ct=} {i=} {j=} {k=} {pp=}")
|
198
|
+
if ct == -1 or ct == 2*(j-i)-1:
|
199
|
+
new_perm = [*up_perm2]
|
200
|
+
new_perm[i],new_perm[j] = new_perm[j],new_perm[i]
|
201
|
+
new_perm_add = tuple(permtrim(new_perm))
|
202
|
+
new_val = val
|
203
|
+
if ct>0:
|
204
|
+
new_val *= np.prod([q_var[index] for index in range(i+1,j+1)])
|
205
|
+
perm_list += [(new_perm_add,new_val,j)]
|
206
|
+
total_list+=[(new_perm_add,pp+1,new_val)]
|
207
|
+
up_perm_list = perm_list
|
208
|
+
return total_list
|
209
|
+
|
171
210
|
|
172
211
|
# perms and inversion diff
|
173
212
|
def kdown_perms(perm,monoperm,p,k):
|
@@ -21,8 +21,7 @@ for i in range(1,n):
|
|
21
21
|
subs_dict[var2[i]] = sm
|
22
22
|
|
23
23
|
def schubmult(perm_dict,v):
|
24
|
-
|
25
|
-
th = [len(v)-i for i in range(1,len(v)+1)]
|
24
|
+
th = strict_theta(inverse(v))
|
26
25
|
mu = permtrim(uncode(th))
|
27
26
|
vmu = permtrim(mulperm([*v],mu))
|
28
27
|
#print(f"{th=} {mu=} {vmu=}")
|
@@ -0,0 +1,337 @@
|
|
1
|
+
from schubmult.perm_lib import *
|
2
|
+
from schubmult.schubmult_yz import compute_positive_rep, posify
|
3
|
+
from symengine import *
|
4
|
+
import sys
|
5
|
+
|
6
|
+
var2 = symarray("y",100)
|
7
|
+
var3 = symarray("z",100)
|
8
|
+
|
9
|
+
var_x = symarray("x",100)
|
10
|
+
|
11
|
+
def nil_hecke(perm_dict,v,n,var2=var2,var3=var3):
|
12
|
+
th = strict_theta(inverse(v))
|
13
|
+
mu = permtrim(uncode(th))
|
14
|
+
vmu = permtrim(mulperm([*v],mu))
|
15
|
+
inv_vmu = inv(vmu)
|
16
|
+
inv_mu = inv(mu)
|
17
|
+
ret_dict = {}
|
18
|
+
vpaths = [([(vmu,0)],1)]
|
19
|
+
while th[-1] == 0:
|
20
|
+
th.pop()
|
21
|
+
thL = len(th)
|
22
|
+
vpathdicts = compute_vpathdicts(th,vmu,True)
|
23
|
+
for u,val in perm_dict.items():
|
24
|
+
inv_u = inv(u)
|
25
|
+
vpathsums = {u: {(1,2): val}}
|
26
|
+
for index in range(thL):
|
27
|
+
mx_th = 0
|
28
|
+
for vp in vpathdicts[index]:
|
29
|
+
for v2,vdiff,s in vpathdicts[index][vp]:
|
30
|
+
if th[index]-vdiff > mx_th:
|
31
|
+
mx_th = th[index] - vdiff
|
32
|
+
newpathsums = {}
|
33
|
+
for up in vpathsums:
|
34
|
+
inv_up = inv(up)
|
35
|
+
newperms = elem_sym_perms_q_op(up,mx_th,th[index],n)
|
36
|
+
for up2, udiff,mul_val in newperms:
|
37
|
+
if up2 not in newpathsums:
|
38
|
+
newpathsums[up2]={}
|
39
|
+
for v in vpathdicts[index]:
|
40
|
+
sumval = vpathsums[up].get(v,zero)*mul_val
|
41
|
+
if sumval == 0:
|
42
|
+
continue
|
43
|
+
for v2,vdiff,s in vpathdicts[index][v]:
|
44
|
+
#print(f"{code(up2)=} {elem_sym_func_q(th[index],index+1,up,up2,v,v2,udiff,vdiff,var2,var3)=} {mul_val=} {sumval=}")
|
45
|
+
newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s*sumval*elem_sym_func_q(th[index],index+1,up2,up,v,v2,udiff,vdiff,var2,var3)
|
46
|
+
vpathsums = newpathsums
|
47
|
+
toget = tuple(vmu)
|
48
|
+
ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
|
49
|
+
return ret_dict
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
def schubmult(perm_dict,v,var2=var2,var3=var3):
|
54
|
+
th = strict_theta(inverse(v))
|
55
|
+
mu = permtrim(uncode(th))
|
56
|
+
vmu = permtrim(mulperm([*v],mu))
|
57
|
+
inv_vmu = inv(vmu)
|
58
|
+
inv_mu = inv(mu)
|
59
|
+
ret_dict = {}
|
60
|
+
vpaths = [([(vmu,0)],1)]
|
61
|
+
while th[-1] == 0:
|
62
|
+
th.pop()
|
63
|
+
thL = len(th)
|
64
|
+
vpathdicts = compute_vpathdicts(th,vmu,True)
|
65
|
+
for u,val in perm_dict.items():
|
66
|
+
inv_u = inv(u)
|
67
|
+
vpathsums = {u: {(1,2): val}}
|
68
|
+
for index in range(thL):
|
69
|
+
mx_th = 0
|
70
|
+
for vp in vpathdicts[index]:
|
71
|
+
for v2,vdiff,s in vpathdicts[index][vp]:
|
72
|
+
if th[index]-vdiff > mx_th:
|
73
|
+
mx_th = th[index] - vdiff
|
74
|
+
newpathsums = {}
|
75
|
+
for up in vpathsums:
|
76
|
+
inv_up = inv(up)
|
77
|
+
newperms = elem_sym_perms_q(up,min(mx_th,(inv_mu-(inv_up-inv_u))-inv_vmu),th[index])
|
78
|
+
for up2, udiff,mul_val in newperms:
|
79
|
+
if up2 not in newpathsums:
|
80
|
+
newpathsums[up2]={}
|
81
|
+
for v in vpathdicts[index]:
|
82
|
+
sumval = vpathsums[up].get(v,zero)*mul_val
|
83
|
+
if sumval == 0:
|
84
|
+
continue
|
85
|
+
for v2,vdiff,s in vpathdicts[index][v]:
|
86
|
+
#print(f"{code(up2)=} {elem_sym_func_q(th[index],index+1,up,up2,v,v2,udiff,vdiff,var2,var3)=} {mul_val=} {sumval=}")
|
87
|
+
newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s*sumval*elem_sym_func_q(th[index],index+1,up,up2,v,v2,udiff,vdiff,var2,var3)
|
88
|
+
vpathsums = newpathsums
|
89
|
+
toget = tuple(vmu)
|
90
|
+
ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
|
91
|
+
return ret_dict
|
92
|
+
|
93
|
+
q_var2 = q_var.tolist()
|
94
|
+
|
95
|
+
def sum_q_dict(q_dict1,q_dict2):
|
96
|
+
ret = {**q_dict1}
|
97
|
+
for key in q_dict2:
|
98
|
+
ret[key] = ret.get(key,0) + q_dict2[key]
|
99
|
+
return ret
|
100
|
+
|
101
|
+
def mul_q_dict(q_dict1,q_dict2):
|
102
|
+
ret = {}
|
103
|
+
for key1 in q_dict1:
|
104
|
+
for key2 in q_dict2:
|
105
|
+
key3 = key1*key2
|
106
|
+
ret[key3] = ret.get(key3,0) + q_dict1[key1]*q_dict2[key2]
|
107
|
+
return ret
|
108
|
+
|
109
|
+
def factor_out_q_keep_factored(poly):
|
110
|
+
ret = {}
|
111
|
+
if str(poly).find("q") == -1:
|
112
|
+
ret[1] = poly
|
113
|
+
return ret
|
114
|
+
elif poly in q_var2:
|
115
|
+
ret[poly] = 1
|
116
|
+
return ret
|
117
|
+
elif isinstance(poly,Add):
|
118
|
+
ag = poly.args
|
119
|
+
ret = factor_out_q_keep_factored(ag[0])
|
120
|
+
for i in range(1,len(ag)):
|
121
|
+
ret = sum_q_dict(ret,factor_out_q_keep_factored(ag[i]))
|
122
|
+
return ret
|
123
|
+
elif isinstance(poly,Mul):
|
124
|
+
ag = poly.args
|
125
|
+
ret = factor_out_q_keep_factored(ag[0])
|
126
|
+
for i in range(1,len(ag)):
|
127
|
+
ret = mul_q_dict(ret,factor_out_q_keep_factored(ag[i]))
|
128
|
+
return ret
|
129
|
+
elif isinstance(poly,Pow):
|
130
|
+
base = poly.args[0]
|
131
|
+
exponent = int(poly.args[1])
|
132
|
+
#print(f"exponent {exponent}")
|
133
|
+
work_val = factor_out_q_keep_factored(base)
|
134
|
+
ret = {1: 1}
|
135
|
+
while exponent > 0:
|
136
|
+
if exponent % 2 == 1:
|
137
|
+
if ret == {1: 1}:
|
138
|
+
ret = {**work_val}
|
139
|
+
else:
|
140
|
+
ret = mul_q_dict(ret,work_val)
|
141
|
+
exponent -= 1
|
142
|
+
else:
|
143
|
+
work_val = mul_q_dict(work_val,work_val)
|
144
|
+
exponent //= 2
|
145
|
+
return ret
|
146
|
+
return ret
|
147
|
+
|
148
|
+
def factor_out_q(poly):
|
149
|
+
coeff_dict = expand(poly).as_coefficients_dict()
|
150
|
+
ret = {}
|
151
|
+
for key in coeff_dict:
|
152
|
+
coeff = coeff_dict[key]
|
153
|
+
if coeff == 0:
|
154
|
+
continue
|
155
|
+
q_part = 1
|
156
|
+
yz_part = coeff
|
157
|
+
if isinstance(key,Mul):
|
158
|
+
for var_maybe_pow in key.args:
|
159
|
+
if isinstance(var_maybe_pow,Pow):
|
160
|
+
real_var = var_maybe_pow.args[0]
|
161
|
+
if real_var in q_var2:
|
162
|
+
q_part*=var_maybe_pow
|
163
|
+
else:
|
164
|
+
yz_part*=var_maybe_pow
|
165
|
+
else:
|
166
|
+
real_var = var_maybe_pow
|
167
|
+
if real_var in q_var2:
|
168
|
+
q_part*=var_maybe_pow
|
169
|
+
else:
|
170
|
+
yz_part*=var_maybe_pow
|
171
|
+
elif isinstance(key,Pow):
|
172
|
+
real_var = key.args[0]
|
173
|
+
if real_var in q_var2:
|
174
|
+
q_part*=key
|
175
|
+
else:
|
176
|
+
yz_part*=key
|
177
|
+
else:
|
178
|
+
if key in q_var2:
|
179
|
+
q_part *= key
|
180
|
+
else:
|
181
|
+
yz_part*=key
|
182
|
+
|
183
|
+
ret[q_part] = ret.get(q_part,0) + yz_part
|
184
|
+
return ret
|
185
|
+
|
186
|
+
var2_t = tuple(var2.tolist())
|
187
|
+
var3_t = tuple(var3.tolist())
|
188
|
+
|
189
|
+
def print_usage():
|
190
|
+
print("**** schubmult_q_yz ****")
|
191
|
+
print("Purpose: Compute Molev-Sagan coefficients of quantum double Schubert polynomials")
|
192
|
+
print("Usage: schubmult_q_yz <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
|
193
|
+
print(" *** Computes products")
|
194
|
+
print("Alternative usage: schubmult_q_yz -nil-hecke n <-code> <--display-positive> perm")
|
195
|
+
print(" *** Computes nil-Hecke representation of quantum double Schubert polynomial, limiting to the group S_n")
|
196
|
+
|
197
|
+
def main():
|
198
|
+
global var2
|
199
|
+
try:
|
200
|
+
sys.setrecursionlimit(1000000)
|
201
|
+
|
202
|
+
perms=[]
|
203
|
+
curperm = []
|
204
|
+
|
205
|
+
pr = True
|
206
|
+
display_positive = False
|
207
|
+
ascode = False
|
208
|
+
coprod = False
|
209
|
+
nilhecke = False
|
210
|
+
check = True
|
211
|
+
msg = False
|
212
|
+
just_nil = False
|
213
|
+
|
214
|
+
nil_N = 0
|
215
|
+
|
216
|
+
try:
|
217
|
+
for s in sys.argv[1:]:
|
218
|
+
if just_nil:
|
219
|
+
just_nil = False
|
220
|
+
nil_N = int(s)
|
221
|
+
continue
|
222
|
+
if s == "-np" or s == "--no-print":
|
223
|
+
pr = False
|
224
|
+
continue
|
225
|
+
if s == "-nocheck":
|
226
|
+
check = False
|
227
|
+
continue
|
228
|
+
if s == "--display-positive":
|
229
|
+
display_positive = True
|
230
|
+
continue
|
231
|
+
if s == "--optimizer-message":
|
232
|
+
msg = True
|
233
|
+
continue
|
234
|
+
if s == "-nil-hecke":
|
235
|
+
nilhecke = True
|
236
|
+
just_nil = True
|
237
|
+
continue
|
238
|
+
if s == "--version":
|
239
|
+
print(f"Python version {sys.version}")
|
240
|
+
exit(0)
|
241
|
+
if s == "-code":
|
242
|
+
ascode = True
|
243
|
+
continue
|
244
|
+
if s == "--usage" or s == "--help":
|
245
|
+
print_usage()
|
246
|
+
exit(0)
|
247
|
+
if s == "-":
|
248
|
+
perms += [curperm]
|
249
|
+
curperm = []
|
250
|
+
continue
|
251
|
+
curperm += [int(s)]
|
252
|
+
except Exception:
|
253
|
+
print_usage()
|
254
|
+
exit(1)
|
255
|
+
|
256
|
+
perms += [curperm]
|
257
|
+
|
258
|
+
|
259
|
+
if ascode:
|
260
|
+
for i in range(len(perms)):
|
261
|
+
perms[i] = tuple(permtrim(uncode(perms[i])))
|
262
|
+
else:
|
263
|
+
for i in range(len(perms)):
|
264
|
+
perms[i] = tuple(permtrim([*perms[i]]))
|
265
|
+
|
266
|
+
size = 0
|
267
|
+
L = len(perms)
|
268
|
+
|
269
|
+
if nilhecke:
|
270
|
+
coeff_dict = nil_hecke({(1,2): 1},perms[0],nil_N)
|
271
|
+
rep = ("y","x")
|
272
|
+
else:
|
273
|
+
coeff_dict = {perms[0]: 1}
|
274
|
+
for perm in perms[1:]:
|
275
|
+
coeff_dict = schubmult(coeff_dict,perm)
|
276
|
+
rep = ("","")
|
277
|
+
|
278
|
+
if pr:
|
279
|
+
if ascode:
|
280
|
+
width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
|
281
|
+
else:
|
282
|
+
width = max([len(str(perm)) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
|
283
|
+
|
284
|
+
coeff_perms = list(coeff_dict.keys())
|
285
|
+
coeff_perms.sort(key=lambda x: (inv(x),*x))
|
286
|
+
|
287
|
+
for perm in coeff_perms:
|
288
|
+
val = coeff_dict[perm]
|
289
|
+
if expand(val) != 0:
|
290
|
+
notint = False
|
291
|
+
try:
|
292
|
+
int(val)
|
293
|
+
except Exception:
|
294
|
+
notint = True
|
295
|
+
val2 = 0
|
296
|
+
if display_positive:
|
297
|
+
q_dict = factor_out_q_keep_factored(val)
|
298
|
+
for q_part in q_dict:
|
299
|
+
#print(f"{q_part=} {q_dict[q_part]=}")
|
300
|
+
try:
|
301
|
+
val2 += q_part*int(q_dict[q_part])
|
302
|
+
except Exception:
|
303
|
+
try:
|
304
|
+
if len(perms) == 2 and q_part == 1:
|
305
|
+
u = permtrim([*perms[0]])
|
306
|
+
v = permtrim([*perms[1]])
|
307
|
+
val2 += posify(q_dict[q_part],tuple(u),tuple(v),perm,var2_t,var3_t,msg,False)
|
308
|
+
elif len(perms) == 2 and q_part in q_var2:
|
309
|
+
i = q_var2.index(q_part)
|
310
|
+
u = permtrim([*perms[0]])
|
311
|
+
v = permtrim([*perms[1]])
|
312
|
+
#print(f"{u=} {v=} {q_part=} {q_dict[q_part]=}")
|
313
|
+
if i<len(u) and i<len(v) and u[i-1]>u[i] and v[i-1]>v[i]:
|
314
|
+
u[i], u[i-1] = u[i-1], u[i]
|
315
|
+
v[i], v[i-1] = v[i-1], v[i]
|
316
|
+
#print(f"new {u=} {v=}")
|
317
|
+
val2 += q_part*posify(q_dict[q_part],tuple(permtrim(u)),tuple(permtrim(v)),perm,var2_t,var3_t,msg,False)
|
318
|
+
else:
|
319
|
+
val2 += q_part*compute_positive_rep(q_dict[q_part],var2_t,var3_t,msg,False)
|
320
|
+
except Exception as e:
|
321
|
+
print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {coeff_dict.get(perm,0)=}")
|
322
|
+
print(f"Exception: {e}")
|
323
|
+
exit(1)
|
324
|
+
if check and expand(val - val2)!=0:
|
325
|
+
print(f"error: value not equal; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {coeff_dict.get(perm,0)=}")
|
326
|
+
exit(1)
|
327
|
+
val = val2
|
328
|
+
if val!=0:
|
329
|
+
if ascode:
|
330
|
+
print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ').replace(*rep)}")
|
331
|
+
else:
|
332
|
+
print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ').replace(*rep)}")
|
333
|
+
except BrokenPipeError:
|
334
|
+
pass
|
335
|
+
|
336
|
+
if __name__ == "__main__":
|
337
|
+
main()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: schubmult
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.7
|
4
4
|
Summary: Computing Littlewood-Richardson coefficients of Schubert polynomials
|
5
5
|
Home-page: https://github.com/matthematics/schubmult
|
6
6
|
Author: Matt Samuel
|
@@ -50,7 +50,10 @@ schubmult_double -code -coprod 0 1 2 3 - 2 4
|
|
50
50
|
schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
|
51
51
|
```
|
52
52
|
|
53
|
-
|
53
|
+
Since version 1.3.7, schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
|
54
|
+
```
|
55
|
+
schubmult_q_yz -nil-hecke 6 -code 2 2 --display-positive
|
56
|
+
```
|
54
57
|
|
55
58
|
Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative (which at least is known for schubmult_py, schubmult_q, schubmult_double, and schubmult_q_double) and the problem is in GapP, it is not known to be in #P at this time.
|
56
59
|
|
@@ -6,7 +6,7 @@ long_description = (this_directory / "README.md").read_text()
|
|
6
6
|
|
7
7
|
setup(
|
8
8
|
name="schubmult",
|
9
|
-
version="1.3.
|
9
|
+
version="1.3.7",
|
10
10
|
description="Computing Littlewood-Richardson coefficients of Schubert polynomials",
|
11
11
|
long_description=long_description,
|
12
12
|
long_description_content_type='text/markdown',
|
@@ -1,206 +0,0 @@
|
|
1
|
-
from schubmult.perm_lib import *
|
2
|
-
from schubmult.schubmult_yz import compute_positive_rep
|
3
|
-
from symengine import *
|
4
|
-
import sys
|
5
|
-
|
6
|
-
|
7
|
-
#q_var = symarray("q",100)
|
8
|
-
|
9
|
-
var2 = symarray("y",100)
|
10
|
-
var3 = symarray("z",100)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def schubmult(perm_dict,v,var2=var2,var3=var3):
|
18
|
-
th = [len(v)-i for i in range(1,len(v))]
|
19
|
-
mu = permtrim(uncode(th))
|
20
|
-
vmu = permtrim(mulperm([*v],mu))
|
21
|
-
inv_vmu = inv(vmu)
|
22
|
-
inv_mu = inv(mu)
|
23
|
-
ret_dict = {}
|
24
|
-
vpaths = [([(vmu,0)],1)]
|
25
|
-
while th[-1] == 0:
|
26
|
-
th.pop()
|
27
|
-
thL = len(th)
|
28
|
-
vpathdicts = compute_vpathdicts(th,vmu,True)
|
29
|
-
for u,val in perm_dict.items():
|
30
|
-
inv_u = inv(u)
|
31
|
-
vpathsums = {u: {(1,2): val}}
|
32
|
-
for index in range(thL):
|
33
|
-
mx_th = 0
|
34
|
-
for vp in vpathdicts[index]:
|
35
|
-
for v2,vdiff,s in vpathdicts[index][vp]:
|
36
|
-
if th[index]-vdiff > mx_th:
|
37
|
-
mx_th = th[index] - vdiff
|
38
|
-
newpathsums = {}
|
39
|
-
for up in vpathsums:
|
40
|
-
inv_up = inv(up)
|
41
|
-
newperms = elem_sym_perms_q(up,min(mx_th,(inv_mu-(inv_up-inv_u))-inv_vmu),th[index])
|
42
|
-
for up2, udiff,mul_val in newperms:
|
43
|
-
if up2 not in newpathsums:
|
44
|
-
newpathsums[up2]={}
|
45
|
-
for v in vpathdicts[index]:
|
46
|
-
sumval = vpathsums[up].get(v,zero)*mul_val
|
47
|
-
if sumval == 0:
|
48
|
-
continue
|
49
|
-
for v2,vdiff,s in vpathdicts[index][v]:
|
50
|
-
#print(f"{code(up2)=} {elem_sym_func_q(th[index],index+1,up,up2,v,v2,udiff,vdiff,var2,var3)=} {mul_val=} {sumval=}")
|
51
|
-
newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s*sumval*elem_sym_func_q(th[index],index+1,up,up2,v,v2,udiff,vdiff,var2,var3)
|
52
|
-
vpathsums = newpathsums
|
53
|
-
toget = tuple(vmu)
|
54
|
-
ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
|
55
|
-
return ret_dict
|
56
|
-
|
57
|
-
def factor_out_q(poly):
|
58
|
-
coeff_dict = expand(poly).as_coefficients_dict()
|
59
|
-
ret = {}
|
60
|
-
q_var2 = q_var.tolist()
|
61
|
-
for key in coeff_dict:
|
62
|
-
coeff = coeff_dict[key]
|
63
|
-
if coeff == 0:
|
64
|
-
continue
|
65
|
-
q_part = 1
|
66
|
-
yz_part = coeff
|
67
|
-
if isinstance(key,Mul):
|
68
|
-
for var_maybe_pow in key.args:
|
69
|
-
if isinstance(var_maybe_pow,Pow):
|
70
|
-
real_var = var_maybe_pow.args[0]
|
71
|
-
if real_var in q_var2:
|
72
|
-
q_part*=var_maybe_pow
|
73
|
-
else:
|
74
|
-
yz_part*=var_maybe_pow
|
75
|
-
else:
|
76
|
-
real_var = var_maybe_pow
|
77
|
-
if real_var in q_var2:
|
78
|
-
q_part*=var_maybe_pow
|
79
|
-
else:
|
80
|
-
yz_part*=var_maybe_pow
|
81
|
-
elif isinstance(key,Pow):
|
82
|
-
real_var = key.args[0]
|
83
|
-
if real_var in q_var2:
|
84
|
-
q_part*=key
|
85
|
-
else:
|
86
|
-
yz_part*=key
|
87
|
-
else:
|
88
|
-
if key in q_var2:
|
89
|
-
q_part *= key
|
90
|
-
else:
|
91
|
-
yz_part*=key
|
92
|
-
|
93
|
-
ret[q_part] = ret.get(q_part,0) + yz_part
|
94
|
-
return ret
|
95
|
-
|
96
|
-
def main():
|
97
|
-
global var2
|
98
|
-
try:
|
99
|
-
sys.setrecursionlimit(1000000)
|
100
|
-
|
101
|
-
perms=[]
|
102
|
-
curperm = []
|
103
|
-
|
104
|
-
pr = True
|
105
|
-
display_positive = False
|
106
|
-
ascode = False
|
107
|
-
coprod = False
|
108
|
-
check = True
|
109
|
-
msg = False
|
110
|
-
try:
|
111
|
-
for s in sys.argv[1:]:
|
112
|
-
if s == "-np" or s == "--no-print":
|
113
|
-
pr = False
|
114
|
-
continue
|
115
|
-
if s == "-nocheck":
|
116
|
-
check = False
|
117
|
-
continue
|
118
|
-
if s == "--display-positive":
|
119
|
-
display_positive = True
|
120
|
-
continue
|
121
|
-
if s == "--optimizer-message":
|
122
|
-
msg = True
|
123
|
-
continue
|
124
|
-
if s == "--version":
|
125
|
-
print(f"Python version {sys.version}")
|
126
|
-
exit(0)
|
127
|
-
if s == "-code":
|
128
|
-
ascode = True
|
129
|
-
continue
|
130
|
-
if s == "--usage":
|
131
|
-
print("**** schubmult_q_yz ****")
|
132
|
-
print("Purpose: Compute Molev-Sagan coefficients of quantum double Schubert polynomials")
|
133
|
-
print("Usage: schubmult_q_yz <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
|
134
|
-
exit(0)
|
135
|
-
if s == "-":
|
136
|
-
perms += [curperm]
|
137
|
-
curperm = []
|
138
|
-
continue
|
139
|
-
curperm += [int(s)]
|
140
|
-
except Exception:
|
141
|
-
print("**** schubmult_q_yz ****")
|
142
|
-
print("Purpose: Compute Molev-Sagan coefficients of quantum double Schubert polynomials")
|
143
|
-
print("Usage: schubmult_q_yz <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
|
144
|
-
exit(1)
|
145
|
-
|
146
|
-
perms += [curperm]
|
147
|
-
|
148
|
-
|
149
|
-
if ascode:
|
150
|
-
for i in range(len(perms)):
|
151
|
-
perms[i] = tuple(permtrim(uncode(perms[i])))
|
152
|
-
else:
|
153
|
-
for i in range(len(perms)):
|
154
|
-
perms[i] = tuple(permtrim([*perms[i]]))
|
155
|
-
|
156
|
-
size = 0
|
157
|
-
L = len(perms)
|
158
|
-
|
159
|
-
coeff_dict = {perms[0]: 1}
|
160
|
-
for perm in perms[1:]:
|
161
|
-
coeff_dict = schubmult(coeff_dict,perm)
|
162
|
-
|
163
|
-
if pr:
|
164
|
-
if ascode:
|
165
|
-
width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
|
166
|
-
else:
|
167
|
-
width = max([len(str(perm)) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
|
168
|
-
|
169
|
-
coeff_perms = list(coeff_dict.keys())
|
170
|
-
coeff_perms.sort(key=lambda x: (inv(x),*x))
|
171
|
-
|
172
|
-
for perm in coeff_perms:
|
173
|
-
val = coeff_dict[perm]
|
174
|
-
if expand(val) != 0:
|
175
|
-
notint = False
|
176
|
-
try:
|
177
|
-
int(val)
|
178
|
-
except Exception:
|
179
|
-
notint = True
|
180
|
-
val2 = 0
|
181
|
-
if display_positive:
|
182
|
-
q_dict = factor_out_q(val)
|
183
|
-
for q_part in q_dict:
|
184
|
-
#print(f"{q_part=} {q_dict[q_part]=}")
|
185
|
-
try:
|
186
|
-
val2 += q_part*int(q_dict[q_part])
|
187
|
-
except Exception:
|
188
|
-
try:
|
189
|
-
val2 += q_part*compute_positive_rep(q_dict[q_part],var2,var3,msg,False)
|
190
|
-
except TypeError:
|
191
|
-
print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_coeff_dict.get(perm,0)=}")
|
192
|
-
exit(1)
|
193
|
-
if check and expand(val - val2)!=0:
|
194
|
-
print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_coeff_dict.get(perm,0)=}")
|
195
|
-
exit(1)
|
196
|
-
val = val2
|
197
|
-
if val!=0:
|
198
|
-
if ascode:
|
199
|
-
print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ')}")
|
200
|
-
else:
|
201
|
-
print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ')}")
|
202
|
-
except BrokenPipeError:
|
203
|
-
pass
|
204
|
-
|
205
|
-
if __name__ == "__main__":
|
206
|
-
main()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|