schubmult 1.1.6__tar.gz → 1.2.0__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.
Files changed (30) hide show
  1. {schubmult-1.1.6 → schubmult-1.2.0}/PKG-INFO +1 -1
  2. schubmult-1.2.0/schubmult/perm_lib.py +530 -0
  3. schubmult-1.2.0/schubmult/schubmult_double/schubmult_double.py +162 -0
  4. schubmult-1.2.0/schubmult/schubmult_py/schubmult_py.py +156 -0
  5. schubmult-1.2.0/schubmult/schubmult_yz/schubmult_yz.py +898 -0
  6. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult.egg-info/PKG-INFO +1 -1
  7. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult.egg-info/SOURCES.txt +1 -2
  8. schubmult-1.2.0/schubmult.egg-info/requires.txt +5 -0
  9. {schubmult-1.1.6 → schubmult-1.2.0}/setup.py +5 -4
  10. schubmult-1.1.6/schubmult/perm_lib.py +0 -242
  11. schubmult-1.1.6/schubmult/schubmult_double/schubmult_double.py +0 -166
  12. schubmult-1.1.6/schubmult/schubmult_py/schubmult_py.py +0 -159
  13. schubmult-1.1.6/schubmult/schubmult_yz/schubmult_yz.py +0 -362
  14. schubmult-1.1.6/schubmult/schubmult_yz/schubmult_yz_test.py +0 -87
  15. schubmult-1.1.6/schubmult.egg-info/requires.txt +0 -4
  16. {schubmult-1.1.6 → schubmult-1.2.0}/LICENSE +0 -0
  17. {schubmult-1.1.6 → schubmult-1.2.0}/README.md +0 -0
  18. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/__init__.py +0 -0
  19. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_double/__init__.py +0 -0
  20. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_double/__main__.py +0 -0
  21. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_py/__init__.py +0 -0
  22. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_py/__main__.py +0 -0
  23. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_py/schubmult_py_bak.py +0 -0
  24. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_py/schubmult_py_parallel.py +0 -0
  25. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_yz/__init__.py +0 -0
  26. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult/schubmult_yz/__main__.py +0 -0
  27. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult.egg-info/dependency_links.txt +0 -0
  28. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult.egg-info/entry_points.txt +0 -0
  29. {schubmult-1.1.6 → schubmult-1.2.0}/schubmult.egg-info/top_level.txt +0 -0
  30. {schubmult-1.1.6 → schubmult-1.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schubmult
3
- Version: 1.1.6
3
+ Version: 1.2.0
4
4
  Summary: Computing Littlewood-Richardson coefficients of Schubert polynomials
5
5
  Home-page: https://github.com/matthematics/schubmult
6
6
  Author: Matt Samuel
@@ -0,0 +1,530 @@
1
+ from symengine import *
2
+ from functools import cache
3
+ from itertools import chain
4
+ from bisect import bisect_left
5
+
6
+ def inv(perm):
7
+ L = len(perm)
8
+ v = [i for i in range(1,L+1)]
9
+ ans = 0
10
+ for i in range(L):
11
+ itr = bisect_left(v, perm[i])
12
+ ans += itr
13
+ v = v[:itr] + v[itr + 1 :]
14
+ return ans
15
+
16
+ def mulperm(perm1,perm2):
17
+ if len(perm1)<len(perm2):
18
+ return [perm1[perm2[i]-1] if perm2[i]<=len(perm1) else perm2[i] for i in range(len(perm2))]
19
+ else:
20
+ return [perm1[perm2[i]-1] for i in range(len(perm2))]+perm1[len(perm2):]
21
+
22
+ def uncode(cd):
23
+ cd2 = list(cd)
24
+ if cd2 == []:
25
+ return [1,2]
26
+ max_required = max([cd2[i]+i for i in range(len(cd2))])
27
+ cd2 += [0 for i in range(len(cd2),max_required)]
28
+ fullperm = [i+1 for i in range(len(cd2)+1)]
29
+ perm = []
30
+ for i in range(len(cd2)):
31
+ perm += [fullperm[cd2[i]]]
32
+ fullperm.pop(cd2[i])
33
+ perm += [fullperm[0]]
34
+ return perm
35
+
36
+
37
+ def code(perm):
38
+ ret = []
39
+ for i in range(len(perm)-1):
40
+ ret += [0]
41
+ for j in range(i+1,len(perm)):
42
+ if perm[i]>perm[j]:
43
+ ret[-1] += 1
44
+ return ret
45
+
46
+ def reversecode(perm):
47
+ ret = []
48
+ for i in range(len(perm)-1,0,-1):
49
+ ret = [0] + ret
50
+ for j in range(i,-1,-1):
51
+ if perm[i]>perm[j]:
52
+ ret[-1] += 1
53
+ return ret
54
+
55
+ def reverseuncode(cd):
56
+ cd2 = list(cd)
57
+ if cd2 == []:
58
+ return [1,2]
59
+ #max_required = max([cd2[i]+i for i in range(len(cd2))])
60
+ #cd2 += [0 for i in range(len(cd2),max_required)]
61
+ fullperm = [i+1 for i in range(len(cd2)+1)]
62
+ perm = []
63
+ for i in range(len(cd2)-1,0,-1):
64
+ perm = [fullperm[cd2[i]]] + perm
65
+ fullperm.pop(cd2[i])
66
+ perm += [fullperm[0]]
67
+ return perm
68
+
69
+ def inverse(perm):
70
+ retperm = [0 for i in range(len(perm))]
71
+ for i in range(len(perm)):
72
+ retperm[perm[i]-1] = i+1
73
+ return retperm
74
+
75
+ def permtrim(perm):
76
+ L = len(perm)
77
+ while L > 2 and perm[-1] == L:
78
+ L = perm.pop() - 1
79
+ return perm
80
+
81
+ def has_bruhat_descent(perm,i,j):
82
+ if perm[i]<perm[j]:
83
+ return False
84
+ for p in range(i+1,j):
85
+ if perm[i]>perm[p] and perm[p]>perm[j]:
86
+ return False
87
+ return True
88
+
89
+ def has_bruhat_ascent(perm,i,j):
90
+ if perm[i]>perm[j]:
91
+ return False
92
+ for p in range(i+1,j):
93
+ if perm[i]<perm[p] and perm[p]<perm[j]:
94
+ return False
95
+ return True
96
+
97
+ def elem_sym_perms(orig_perm,p,k):
98
+ total_list = [(orig_perm,0)]
99
+ up_perm_list = [(orig_perm,1000000000)]
100
+ for pp in range(p):
101
+ perm_list = []
102
+ for up_perm, last in up_perm_list:
103
+ up_perm2 = [*up_perm,len(up_perm)+1]
104
+ if len(up_perm2) < k + 1:
105
+ up_perm2 += [i+1 for i in range(len(up_perm2),k+2)]
106
+ pos_list = [i for i in range(k) if up_perm2[i] < last]
107
+ for j in range(k,len(up_perm2)):
108
+ if up_perm2[j]>=last:
109
+ continue
110
+ for i in pos_list:
111
+ if has_bruhat_ascent(up_perm2,i,j):
112
+ new_perm = [*up_perm2]
113
+ new_perm[i],new_perm[j] = new_perm[j],new_perm[i]
114
+ if new_perm[-1] == len(new_perm):
115
+ new_perm_add = tuple(new_perm[:-1])
116
+ else:
117
+ new_perm_add = tuple(new_perm)
118
+ perm_list += [(new_perm_add,up_perm2[j])]
119
+ total_list+=[(new_perm_add,pp+1)]
120
+ up_perm_list = perm_list
121
+ return total_list
122
+
123
+ # perms and inversion diff
124
+ def kdown_perms(perm,monoperm,p,k):
125
+ inv_m = inv(monoperm)
126
+ inv_p = inv(perm)
127
+ full_perm_list = []
128
+
129
+ if inv(mulperm(list(perm),monoperm)) == inv_m - inv_p:
130
+ full_perm_list+= [(tuple(perm),0,1)]
131
+
132
+ down_perm_list = [(perm,1)]
133
+ if len(perm)<k:
134
+ return full_perm_list
135
+ a2 = k-1
136
+ for pp in range(1,p+1):
137
+ down_perm_list2 = []
138
+ for perm2, s in down_perm_list:
139
+ L = len(perm2)
140
+ if L<k:
141
+ continue
142
+ s2 = -s
143
+ for b in chain(range(k-1),range(k,L)):
144
+ if perm2[b] != perm[b]:
145
+ continue
146
+ if b < a2:
147
+ i,j = b,a2
148
+ else:
149
+ i,j,s2 = a2,b,s
150
+ if has_bruhat_descent(perm2,i,j):
151
+ new_perm = [*perm2]
152
+ new_perm[a2],new_perm[b] = new_perm[b],new_perm[a2]
153
+ permtrim(new_perm)
154
+ down_perm_list2 += [(new_perm,s2)]
155
+ if inv(mulperm(new_perm,monoperm)) == inv_m - inv_p + pp:
156
+ full_perm_list += [(tuple(new_perm),pp,s2)]
157
+ down_perm_list = down_perm_list2
158
+ return full_perm_list
159
+
160
+ def compute_vpathdicts(th,vmu,smpify=False):
161
+ vpathdicts = [{} for index in range(len(th))]
162
+ vpathdicts[-1][tuple(vmu)] = None
163
+ S = sum(th)
164
+ thL = len(th)
165
+ th2 = [*th]
166
+ top = code(inverse(uncode(th)))
167
+ for i in range(thL-1,-1,-1):
168
+ top2 = code(inverse(uncode(top)))
169
+ while top2[-1]==0:
170
+ top2.pop()
171
+ top2.pop()
172
+ top = code(inverse(uncode(top2)))
173
+ monoperm = uncode(top)
174
+ if len(monoperm) < 2:
175
+ monoperm = [1,2]
176
+ k = i+1
177
+ for last_perm in vpathdicts[i]:
178
+ newperms = kdown_perms(last_perm,monoperm,th[i],k)
179
+ vpathdicts[i][last_perm]=newperms
180
+ if i>0:
181
+ for trip in newperms:
182
+ vpathdicts[i-1][trip[0]] = None
183
+ vpathdicts2 = [{} for i in range(len(th))]
184
+ for i in range(len(th)):
185
+ for key,valueset in vpathdicts[i].items():
186
+ for value in valueset:
187
+ key2 = value[0]
188
+ if key2 not in vpathdicts2[i]:
189
+ vpathdicts2[i][key2]=set()
190
+ v2 = value[2]
191
+ if smpify:
192
+ v2 = sympify(v2)
193
+ vpathdicts2[i][key2].add((key,value[1],v2))
194
+ #print(vpathdicts2)
195
+ return vpathdicts2
196
+
197
+
198
+ def theta(perm):
199
+ cd = code(perm)
200
+ for i in range(len(cd)-1,0,-1):
201
+ for j in range(i-1,-1,-1):
202
+ if cd[j] < cd[i]:
203
+ cd[i]+=1
204
+ cd.sort(reverse=True)
205
+ return cd
206
+
207
+ def add_perm_dict(d1,d2):
208
+ for k,v in d2.items():
209
+ d1[k] = d1.get(k,0)+v
210
+ return d1
211
+
212
+ zero = sympify(0)
213
+ one = sympify(1)
214
+
215
+ def elem_sym_poly(p,k,varl1,varl2,xstart=0,ystart=0):
216
+ global zero, one
217
+ if p>k:
218
+ return zero
219
+ if p == 0:
220
+ return one
221
+ if p == 1:
222
+ res = varl1[xstart] - varl2[ystart]
223
+ for i in range(1,k):
224
+ res += varl1[xstart+i] - varl2[ystart+i]
225
+ return res
226
+ if p == k:
227
+ res = (varl1[xstart] - varl2[ystart]) * (varl1[xstart+1] - varl2[ystart])
228
+ for i in range(2,k):
229
+ res *= (varl1[i+xstart] - varl2[ystart])
230
+ return res
231
+ mid = k//2
232
+ xsm = xstart + mid
233
+ ysm = ystart + mid
234
+ kmm = k - mid
235
+ res = elem_sym_poly(p,mid,varl1,varl2,xstart,ystart)+elem_sym_poly(p,kmm,varl1,varl2,xsm,ysm)
236
+ for p2 in range(max(1,p-kmm),min(p,mid+1)):
237
+ res += elem_sym_poly(p2,mid,varl1,varl2,xstart,ystart)*elem_sym_poly(p-p2,kmm,varl1,varl2,xsm,ysm-p2)
238
+ return res
239
+
240
+ @cache
241
+ def call_zvars(v1,v2,k,i):
242
+ v3 = [*v2]+[j for j in range(len(v2)+1,i+1)]
243
+ zvars = [v3[i-1]] + \
244
+ [v3[j] for j in range(len(v1),len(v3)) if v3[j]!=j+1 and j!=i-1] + \
245
+ [v3[j] for j in range(len(v1)) if v1[j]!=v3[j] and j!=i-1]
246
+ return zvars
247
+
248
+ def elem_sym_func(k,i,u1,u2,v1,v2,udiff,vdiff,varl1,varl2):
249
+ global zero, one
250
+ newk = k - udiff
251
+ if newk < vdiff:
252
+ return zero
253
+ if newk == vdiff:
254
+ return one
255
+ yvars = []
256
+ for j in range(min(len(u1),k)):
257
+ if u1[j]==u2[j]:
258
+ yvars += [varl1[u2[j]]]
259
+ for j in range(len(u1),min(k,len(u2))):
260
+ if u2[j]==j+1:
261
+ yvars += [varl1[u2[j]]]
262
+ for j in range(len(u2),k):
263
+ yvars += [varl1[j+1]]
264
+ zvars = [varl2[i] for i in call_zvars(v1,v2,k,i)]
265
+ return elem_sym_poly(newk-vdiff,newk,yvars,zvars)
266
+
267
+ def trimcode(perm):
268
+ cd = code(perm)
269
+ while len(cd)>0 and cd[-1] == 0:
270
+ cd.pop()
271
+ return cd
272
+
273
+ def p_trans(part):
274
+ newpart = []
275
+ if len(part)==0 or part[0]==0:
276
+ return [0]
277
+ for i in range(1,part[0]+1):
278
+ cnt = 0
279
+ for j in range(len(part)):
280
+ if part[j]>=i:
281
+ cnt += 1
282
+ if cnt == 0:
283
+ break
284
+ newpart += [cnt]
285
+ return newpart
286
+
287
+ def cycle(p,q):
288
+ return [i for i in range(1,p)] + [i+1 for i in range(p,p+q)] + [p]
289
+
290
+ def phi1(u):
291
+ c_star = code(inverse(u))
292
+ c_star.pop(0)
293
+ phi_u = inverse(uncode(c_star))
294
+ return phi_u
295
+
296
+ def one_dominates(u,w):
297
+ c_star_u = code(inverse(u))
298
+ c_star_w = code(inverse(w))
299
+
300
+ a = c_star_u[0]
301
+ b = c_star_w[0]
302
+
303
+ for i in range(a,b):
304
+ if i>=len(u)-1:
305
+ return True
306
+ if u[i]>u[i+1]:
307
+ return False
308
+ return True
309
+
310
+ def dominates(u,w):
311
+ u2 = [*u]
312
+ w2 = [*w]
313
+ while u2 != [1,2] and one_dominates(u2,w2):
314
+ u2 = phi1(u2)
315
+ w2 = phi1(w2)
316
+ if u2 == [1,2]:
317
+ return True
318
+ return False
319
+
320
+ def reduce_coeff(u,v,w):
321
+ t_mu_u_t = theta(inverse(u))
322
+ t_mu_v_t = theta(inverse(v))
323
+
324
+ mu_u_inv = uncode(t_mu_u_t)
325
+ mu_v_inv = uncode(t_mu_v_t)
326
+
327
+ t_mu_u = p_trans(t_mu_u_t)
328
+ t_mu_v = p_trans(t_mu_v_t)
329
+
330
+ t_mu_u += [0 for i in range(len(t_mu_u),max(len(t_mu_u),len(t_mu_v)))]
331
+ t_mu_v += [0 for i in range(len(t_mu_v),max(len(t_mu_u),len(t_mu_v)))]
332
+
333
+ t_mu_uv = [t_mu_u[i] + t_mu_v[i] for i in range(len(t_mu_u))]
334
+ t_mu_uv_t = p_trans(t_mu_uv)
335
+
336
+ mu_uv_inv = uncode(t_mu_uv_t)
337
+
338
+ if inv(mulperm(list(w),mu_uv_inv)) != inv(mu_uv_inv) - inv(w):
339
+ return u, v, w
340
+
341
+ umu = mulperm(list(u),mu_u_inv)
342
+ vmu = mulperm(list(v),mu_v_inv)
343
+ wmu = mulperm(list(w),mu_uv_inv)
344
+
345
+ t_mu_w = theta(inverse(wmu))
346
+
347
+ mu_w = uncode(t_mu_w)
348
+
349
+ w_prime = mulperm(wmu,mu_w)
350
+
351
+ if permtrim(list(w)) == permtrim(w_prime):
352
+ return (permtrim(list(u)),permtrim(list(v)),permtrim(list(w)))
353
+
354
+ A = []
355
+ B = []
356
+ indexA = 0
357
+
358
+ while len(t_mu_u_t)>0 and t_mu_u_t[-1] == 0:
359
+ t_mu_u_t.pop()
360
+
361
+ while len(t_mu_v_t)>0 and t_mu_v_t[-1] == 0:
362
+ t_mu_v_t.pop()
363
+
364
+ while len(t_mu_uv_t)>0 and t_mu_uv_t[-1] == 0:
365
+ t_mu_uv_t.pop()
366
+
367
+ for index in range(len(t_mu_uv_t)):
368
+ if indexA<len(t_mu_u_t) and t_mu_uv_t[index] == t_mu_u_t[indexA]:
369
+ A += [index]
370
+ indexA+=1
371
+ else:
372
+ B += [index]
373
+
374
+ mu_w_A = uncode(mu_A(code(mu_w),A))
375
+ mu_w_B = uncode(mu_A(code(mu_w),B))
376
+
377
+ return (permtrim(mulperm(umu,mu_w_A)),permtrim(mulperm(vmu,mu_w_B)),permtrim(w_prime))
378
+
379
+ def mu_A(mu,A):
380
+ mu_t = p_trans(mu)
381
+ mu_A_t = []
382
+ for i in range(len(A)):
383
+ if A[i]<len(mu_t):
384
+ mu_A_t += [mu_t[A[i]]]
385
+ return p_trans(mu_A_t)
386
+
387
+ def reduce_descents(u,v,w):
388
+ u2 = [*u]
389
+ v2 = [*v]
390
+ w2 = [*w]
391
+ found_one = True
392
+ while found_one:
393
+ found_one = False
394
+ 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:
395
+ break
396
+ for i in range(len(w2)-2,-1,-1):
397
+ 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]):
398
+ w2[i], w2[i+1] = w2[i+1], w2[i]
399
+ v2[i], v2[i+1] = v2[i+1], v2[i]
400
+ found_one = True
401
+ 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]):
402
+ w2[i], w2[i+1] = w2[i+1], w2[i]
403
+ u2[i], u2[i+1] = u2[i+1], u2[i]
404
+ found_one = True
405
+ if found_one:
406
+ break
407
+ return permtrim(u2), permtrim(v2), permtrim(w2)
408
+
409
+ def is_reducible(v):
410
+ c03 = code(v)
411
+ found0 = False
412
+ good = True
413
+ for i in range(len(c03)):
414
+ if c03[i] == 0:
415
+ found0 = True
416
+ elif c03[i] != 0 and found0 == True:
417
+ good = False
418
+ break
419
+ return good
420
+
421
+ def try_reduce_v(u, v, w):
422
+ if is_reducible(v):
423
+ return tuple(permtrim([*u])), tuple(permtrim([*v])), tuple(permtrim([*w]))
424
+ u2 = [*u]
425
+ v2 = [*v]
426
+ w2 = [*w]
427
+ cv = code(v2)
428
+ for i in range(len(v2)-2,-1,-1):
429
+ if cv[i] == 0 and i<len(cv)-1 and cv[i+1] != 0:
430
+ if i>=len(u2)-1 or u2[i] < u2[i+1]:
431
+ v2[i], v2[i+1] = v2[i+1], v2[i]
432
+ if i>=len(w2)-1:
433
+ w2 += [j for j in range(len(w2)+1,i+3)]
434
+ w2[i+1], w2[i] = w2[i], w2[i+1]
435
+ if is_reducible(v2):
436
+ return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
437
+ else:
438
+ return try_reduce_v(u2,v2,w2)
439
+ elif i<len(w2)-1 and w2[i]>w2[i+1]:
440
+ u2[i], u2[i+1] = u2[i+1], u2[i]
441
+ v2[i], v2[i+1] = v2[i+1], v2[i]
442
+ return try_reduce_v(u2, v2, w2)
443
+ else:
444
+ return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
445
+ return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
446
+
447
+ def try_reduce_u(u, v, w):
448
+ if one_dominates(u,w):
449
+ return u, v, w
450
+ u2 = [*u]
451
+ v2 = [*v]
452
+ w2 = [*w]
453
+ cu = code(u)
454
+ for i in range(len(u2)-2,-1,-1):
455
+ if cu[i] == 0 and i<len(cu)-1 and cu[i+1] != 0:
456
+ if i>=len(v2)-1 or v2[i] < v2[i+1]:
457
+ u2[i], u2[i+1] = u2[i+1], u2[i]
458
+ if i>len(w2)-1:
459
+ w2 += [j for j in range(len(w2)+1,i+3)]
460
+ w2[i+1], w2[i] = w2[i], w2[i+1]
461
+ if one_dominates(u,w):
462
+ return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
463
+ else:
464
+ return try_reduce_u(u2,v2,w2)
465
+ elif i<len(w2)-1 and w2[i]>w2[i+1]:
466
+ u2[i], u2[i+1] = u2[i+1], u2[i]
467
+ v2[i], v2[i+1] = v2[i+1], v2[i]
468
+ return try_reduce_u(u2, v2, w2)
469
+ else:
470
+ return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
471
+ return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
472
+
473
+ def pull_out_var(vnum,v):
474
+ vn1 = inverse(v)
475
+ th = theta(vn1)
476
+ if th[0]==0:
477
+ return [[[],v]]
478
+ muvn1 = permtrim(uncode(th))
479
+ lm = p_trans(th)
480
+ if vnum>len(lm):
481
+ return [[[],v]]
482
+ lmpop = [*lm]
483
+ k = lmpop.pop(vnum-1)
484
+ inv_v = inv(v)
485
+ vmuvn1 = mulperm(v,muvn1)
486
+ muvn1in1 = permtrim(uncode(lmpop))
487
+ ret_list = []
488
+ vpm_list = [(vmuvn1,k)]
489
+ for p in range(k+1):
490
+ vpm_list2 = []
491
+ for vpm, b in vpm_list:
492
+ vp = permtrim(mulperm(vpm,muvn1in1))
493
+
494
+ pos_list = [i for i in range(k) if ((i<len(vpm) and vmuvn1[i] == vpm[i]) or (i>=len(vpm) and vmuvn1[i] == i+1))]
495
+ if inv(vp)==inv_v-k+p:
496
+ ret_list += [[[vpm[i] for i in pos_list if i<len(vpm)]+[i+1 for i in pos_list if i>=len(vpm) and vmuvn1[i] == i+1],vp]]
497
+ if len(vpm) < k + 1:
498
+ continue
499
+ for j in range(b,len(vpm)):
500
+ for i in pos_list:
501
+ if has_bruhat_descent(vpm,i,j):
502
+ vpm[i],vpm[j] = vpm[j],vpm[i]
503
+ vpm_list2+=[(permtrim([*vpm]),j)]
504
+ vpm[i],vpm[j] = vpm[j],vpm[i]
505
+ vpm_list = vpm_list2
506
+ return ret_list
507
+
508
+ def divdiffable(v,u):
509
+ inv_v = inv(v)
510
+ inv_u = inv(u)
511
+ perm2 = permtrim(mulperm(v,inverse(u)))
512
+ if inv(perm2) != inv_v - inv_u:
513
+ return []
514
+ return perm2
515
+
516
+ def will_formula_work(u,v):
517
+ muv = uncode(theta(v))
518
+ vn1muv = mulperm(inverse(v),muv)
519
+ while True:
520
+ found_one = False
521
+ for i in range(len(vn1muv)-1):
522
+ if vn1muv[i]>vn1muv[i+1]:
523
+ found_one = True
524
+ if i<len(u)-1 and u[i]>u[i+1]:
525
+ return False
526
+ else:
527
+ vn1muv[i],vn1muv[i+1] = vn1muv[i+1],vn1muv[i]
528
+ break
529
+ if not found_one:
530
+ return True
@@ -0,0 +1,162 @@
1
+ from symengine import *
2
+ from functools import cache
3
+ from itertools import chain
4
+ from schubmult.perm_lib import *
5
+ from schubmult.schubmult_yz import schubmult
6
+ import sys
7
+
8
+ n = 100
9
+
10
+ var = symarray('x', n)
11
+ var2 = symarray('y',n)
12
+ var3 = var2
13
+ var_r = symarray('r',n)
14
+
15
+ subs_dict = {}
16
+
17
+ for i in range(1,n):
18
+ sm = var_r[0]
19
+ for j in range(1,i):
20
+ sm += var_r[j]
21
+ subs_dict[var2[i]] = sm
22
+
23
+ def main():
24
+ try:
25
+ perms=[]
26
+ curperm = []
27
+
28
+ pr = True
29
+ ascode = False
30
+ coprod = False
31
+ try:
32
+ for s in sys.argv[1:]:
33
+ if s == "-np" or s == "--no-print":
34
+ pr = False
35
+ continue
36
+ if s == "-code":
37
+ ascode = True
38
+ continue
39
+ if s == "-coprod":
40
+ coprod = True
41
+ continue
42
+ if s == "-":
43
+ perms += [curperm]
44
+ curperm = []
45
+ continue
46
+ curperm += [int(s)]
47
+ except Exception:
48
+ print("Usage: schubmult_double <-np|--no-print> <-code> perm1 - perm2 < - perm 3 ... >")
49
+ print("Alternative usage: schubmult_double <-code> -coprod perm - indexlist")
50
+ exit(1)
51
+
52
+ perms += [curperm]
53
+
54
+ if coprod:
55
+ subs_dict_coprod = {}
56
+ if ascode:
57
+ mperm = tuple(permtrim(uncode(perms[0])))
58
+ else:
59
+ mperm = tuple(permtrim(perms[0]))
60
+
61
+ cd = code(mperm)
62
+ perms[0] = mperm
63
+ pos = perms[1]
64
+
65
+ while cd[-1] == 0:
66
+ cd.pop()
67
+ k = len(pos)
68
+ n = len(perms[0])
69
+ kcd = [pos[i]-i-1 for i in range(len(pos))] + [n+1-k for i in range(k,n)]
70
+ N = len(kcd)
71
+
72
+ for i in range(1,100):
73
+ if i<=N:
74
+ subs_dict_coprod[var[i]] = var2[i]
75
+ else:
76
+ subs_dict_coprod[var[i]] = var2[i-N]
77
+
78
+ kperm = inverse(uncode(kcd))
79
+ coeff_dict = {tuple(kperm): 1}
80
+ coeff_dict = schubmult(coeff_dict,perms[0],var,var2)
81
+
82
+ inv_perm0 = inv(perms[0])
83
+ inv_kperm = inv(kperm)
84
+ inverse_kperm = inverse(kperm)
85
+ if pr:
86
+ coeff_perms = list(coeff_dict.keys())
87
+ coeff_perms.sort(key=lambda x: (inv(x),*x))
88
+
89
+ perm_pairs = []
90
+
91
+ for perm in coeff_perms:
92
+ downperm = mulperm(list(perm),inverse_kperm)
93
+ if inv(downperm) == inv(perm) - inv_kperm:
94
+ flag = True
95
+ for i in range(N):
96
+ if downperm[i] > N:
97
+ flag = False
98
+ break
99
+ if not flag:
100
+ continue
101
+ firstperm = downperm[0:N]
102
+ secondperm = [downperm[i]-N for i in range(N,len(downperm))]
103
+ perm_pairs += [[permtrim(firstperm),permtrim(secondperm)]]
104
+
105
+ if ascode:
106
+ width = max([len(str(trimcode(perm[0]))+" "+str(trimcode(perm[1]))) for perm in perm_pairs])
107
+ else:
108
+ width = max([len(str(perm[0])+" "+str(perm[1])) for perm in perm_pairs])
109
+
110
+ for perm in coeff_perms:
111
+ val = coeff_dict[perm]
112
+ downperm = mulperm(list(perm),inverse_kperm)
113
+ if inv(downperm) == inv(perm) - inv_kperm:
114
+ flag = True
115
+ for i in range(N):
116
+ if downperm[i] > N:
117
+ flag = False
118
+ break
119
+ if not flag:
120
+ continue
121
+ firstperm = downperm[0:N]
122
+ secondperm = [downperm[i]-N for i in range(N,len(downperm))]
123
+ val = sympify(val).subs(subs_dict_coprod)
124
+ val = sympify(val).subs(subs_dict).expand()
125
+ if val != 0:
126
+ if not ascode:
127
+ width2 = width - len(str(permtrim(firstperm))) - len(str(permtrim(secondperm)))
128
+ print(f"{tuple(permtrim(firstperm))}{' ':>{width2}}{tuple(permtrim(secondperm))} {str(val).replace('**','^').replace('*',' ')}")
129
+ else:
130
+ width2 = width - len(str(trimcode(firstperm))) - len(str(trimcode(secondperm)))
131
+ print(f"{trimcode(firstperm)}{' ':>{width2}}{trimcode(secondperm)} {str(val).replace('**','^').replace('*',' ')}")
132
+ else:
133
+ if ascode:
134
+ for i in range(len(perms)):
135
+ perms[i] = uncode(perms[i])
136
+
137
+ coeff_dict = {tuple(permtrim([*perms[0]])): 1}
138
+
139
+ for perm in perms[1:]:
140
+ coeff_dict = schubmult(coeff_dict,tuple(permtrim([*perm])),var2,var2)
141
+
142
+ if pr:
143
+ if ascode:
144
+ width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys()])
145
+ else:
146
+ width = max([len(str(perm)) for perm in coeff_dict.keys()])
147
+
148
+ coeff_perms = list(coeff_dict.keys())
149
+ coeff_perms.sort(key=lambda x: (inv(x),*x))
150
+
151
+ for perm in coeff_perms:
152
+ val = sympify(coeff_dict[perm]).subs(subs_dict).expand()
153
+ if val != 0:
154
+ if ascode:
155
+ print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ')}")
156
+ else:
157
+ print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ')}")
158
+ except BrokenPipeError:
159
+ pass
160
+
161
+ if __name__ == "__main__":
162
+ main()