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.
Files changed (59) hide show
  1. schubmult/__init__.py +94 -1
  2. schubmult/perm_lib.py +233 -880
  3. schubmult/poly_lib/__init__.py +31 -0
  4. schubmult/poly_lib/poly_lib.py +244 -0
  5. schubmult/poly_lib/schub_poly.py +148 -0
  6. schubmult/poly_lib/variables.py +204 -0
  7. schubmult/rings/__init__.py +17 -0
  8. schubmult/rings/_quantum_schubert_polynomial_ring.py +788 -0
  9. schubmult/rings/_schubert_polynomial_ring.py +1006 -0
  10. schubmult/rings/_tensor_schub_ring.py +128 -0
  11. schubmult/rings/_utils.py +55 -0
  12. schubmult/{sage_integration → sage}/__init__.py +17 -15
  13. schubmult/{sage_integration → sage}/_fast_double_schubert_polynomial_ring.py +142 -220
  14. schubmult/{sage_integration → sage}/_fast_schubert_polynomial_ring.py +78 -72
  15. schubmult/sage/_indexing.py +51 -0
  16. schubmult/schub_lib/__init__.py +51 -0
  17. schubmult/{schubmult_double/_funcs.py → schub_lib/double.py} +618 -798
  18. schubmult/{schubmult_q/_funcs.py → schub_lib/quantum.py} +70 -72
  19. schubmult/schub_lib/quantum_double.py +954 -0
  20. schubmult/schub_lib/schub_lib.py +659 -0
  21. schubmult/{schubmult_py/_funcs.py → schub_lib/single.py} +58 -48
  22. schubmult/schub_lib/tests/__init__.py +0 -0
  23. schubmult/schub_lib/tests/legacy_perm_lib.py +946 -0
  24. schubmult/schub_lib/tests/test_vs_old.py +109 -0
  25. schubmult/scripts/__init__.py +0 -0
  26. schubmult/scripts/schubmult_double.py +378 -0
  27. schubmult/scripts/schubmult_py.py +84 -0
  28. schubmult/scripts/schubmult_q.py +109 -0
  29. schubmult/scripts/schubmult_q_double.py +207 -0
  30. schubmult/utils/__init__.py +0 -0
  31. schubmult/{_base_argparse.py → utils/argparse.py} +40 -11
  32. schubmult/utils/logging.py +16 -0
  33. schubmult/utils/parsing.py +20 -0
  34. schubmult/utils/perm_utils.py +135 -0
  35. schubmult/utils/test_utils.py +65 -0
  36. schubmult-3.0.0.dist-info/METADATA +1234 -0
  37. schubmult-3.0.0.dist-info/RECORD +41 -0
  38. {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/WHEEL +1 -1
  39. schubmult-3.0.0.dist-info/entry_points.txt +5 -0
  40. schubmult/_tests.py +0 -9
  41. schubmult/sage_integration/_indexing.py +0 -51
  42. schubmult/schubmult_double/__init__.py +0 -22
  43. schubmult/schubmult_double/__main__.py +0 -5
  44. schubmult/schubmult_double/_script.py +0 -474
  45. schubmult/schubmult_py/__init__.py +0 -13
  46. schubmult/schubmult_py/__main__.py +0 -5
  47. schubmult/schubmult_py/_script.py +0 -96
  48. schubmult/schubmult_q/__init__.py +0 -13
  49. schubmult/schubmult_q/__main__.py +0 -5
  50. schubmult/schubmult_q/_script.py +0 -160
  51. schubmult/schubmult_q_double/__init__.py +0 -17
  52. schubmult/schubmult_q_double/__main__.py +0 -5
  53. schubmult/schubmult_q_double/_funcs.py +0 -540
  54. schubmult/schubmult_q_double/_script.py +0 -398
  55. schubmult-2.0.3.dist-info/METADATA +0 -455
  56. schubmult-2.0.3.dist-info/RECORD +0 -30
  57. schubmult-2.0.3.dist-info/entry_points.txt +0 -5
  58. {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/licenses/LICENSE +0 -0
  59. {schubmult-2.0.3.dist-info → schubmult-3.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,109 @@
1
+ import schubmult.poly_lib.variables as schub_vars
2
+ import schubmult.schub_lib.schub_lib as schub_lib
3
+ import schubmult.perm_lib as pl
4
+ import schubmult.schub_lib.tests.legacy_perm_lib as opl
5
+ q_var = schub_vars.GeneratingSet("q")
6
+
7
+
8
+
9
+ def test_double_elem_sym_q():
10
+ ret_list = {}
11
+ ret_list_N = {}
12
+ u= tuple([7,5,1,6,4,2,3])
13
+ u_N = pl.Permutation(u)
14
+ p1 = 3
15
+ p2 = 5
16
+ k = 6
17
+
18
+ perms1 = opl.elem_sym_perms_q(u, p1, k, q_var)
19
+ perms1_N = schub_lib.elem_sym_perms_q(u_N, p1, k, q_var)
20
+ iu = opl.inverse(u)
21
+ iu_N = ~u_N
22
+ for perm1, udiff1, mul_val1 in perms1:
23
+ perm1_N = pl.Permutation(perm1)
24
+ assert (perm1_N, udiff1, mul_val1) in perms1_N, f"Permutation {perm1} not found in new result"
25
+ perms2 = opl.elem_sym_perms_q(perm1, p2, k, q_var)
26
+ perms2_N = schub_lib.elem_sym_perms_q(perm1_N, p2, k, q_var)
27
+ cycles1 = opl.get_cycles(opl.mulperm([*iu],[*perm1]))
28
+ cycles1_N = (iu_N*perm1_N).get_cycles()
29
+ assert cycles1 == cycles1_N
30
+ cycles1_dict = {}
31
+ for c in cycles1:
32
+ if c[-1] not in cycles1_dict:
33
+ cycles1_dict[c[-1]] = []
34
+ cycles1_dict[c[-1]] += [set(c)]
35
+ ip1 = opl.inverse(perm1)
36
+ ip1_N = ~perm1_N
37
+ assert ip1 == list(ip1_N)
38
+ for perm2, udiff2, mul_val2 in perms2:
39
+ perm2_N = pl.Permutation(perm2)
40
+ assert (perm2_N, udiff2, mul_val2) in perms2_N, f"Permutation {perm2} not found in new result"
41
+ cycles2 = opl.get_cycles(opl.mulperm([*ip1],[*perm2]))
42
+ cycles2_N = (ip1_N*perm2_N).get_cycles()
43
+ assert cycles2 == cycles2_N
44
+ good = True
45
+ for i in range(len(cycles2)):
46
+ c2 = cycles2[i]
47
+ if c2[-1] not in cycles1_dict:
48
+ continue
49
+ for c1_s in cycles1_dict[c2[-1]]:
50
+ for a in range(len(c2) - 2, -1, -1):
51
+ if c2[a] in c1_s:
52
+ good = False
53
+ break
54
+ if not good:
55
+ break
56
+ if not good:
57
+ break
58
+
59
+ if good:
60
+ if (perm1, udiff1, mul_val1) not in ret_list:
61
+ ret_list[(perm1, udiff1, mul_val1)] = []
62
+ ret_list[(perm1, udiff1, mul_val1)] += [(perm2, udiff2, mul_val2)]
63
+ return ret_list
64
+
65
+
66
+
67
+ def test_elem_sym_q():
68
+ # Test the function with a sample permutation
69
+ old_perm = tuple([5,1,4,2,3])
70
+ orig_perm = pl.Permutation(old_perm)
71
+ p = 3
72
+ k = 5
73
+ result_old = opl.elem_sym_perms_q(old_perm, p, k)
74
+ result_new = schub_lib.elem_sym_perms_q(orig_perm, p, k)
75
+ assert len(result_old) == len(result_new), "Length of results do not match"
76
+ for i in range(len(result_old)):
77
+ # print(f"{result_old[i]=} {result_new[i]=}")
78
+ assert pl.Permutation(result_old[i][0]) == result_new[i][0], f"Permutation mismatch at index {i}"
79
+ assert result_old[i][2] == result_new[i][2], f"Value mismatch at index {i}"
80
+ # def double_elem_sym_q(u, p1, p2, k, q_var=q_var):
81
+ old_perm = tuple([7,5,1,6,4,2,3])
82
+ orig_perm = pl.Permutation(old_perm)
83
+ p1 = 3
84
+ p2 = 5
85
+ k = 6
86
+ result_old = opl.double_elem_sym_q(old_perm, p1, p2, k)
87
+ result_new = schub_lib.double_elem_sym_q(orig_perm, p1, p2, k)
88
+ assert len(result_old) == len(result_new), "Length of results do not match"
89
+ print("OLD")
90
+ print("\n".join([str((str(b),str(result_old[b]))) for b in result_old]))
91
+ print("NEW")
92
+ print("\n".join([str((str(b),str(result_new[b]))) for b in result_new]))
93
+ for k, v in result_old.items():
94
+ k2 = (pl.Permutation(k[0]),k[1],k[2])
95
+ assert k2 in result_new, f"Key {k2} not found in new result"
96
+ v2 = result_new[k2]
97
+ v = sorted(v)
98
+ v2 = sorted(v2)
99
+ assert len(v) == len(v2)
100
+ for i in range(len(v)):
101
+ assert pl.Permutation(v[i][0]) == v2[i][0]
102
+ assert v[i][2] == v2[i][2]
103
+
104
+ #double_elem_sym_q
105
+ # assert pl.Permutation(result_old[i][1]) == result_new[i][1], f"Value mismatch at index {i}"
106
+ # assert pl.Permutation(result_old[i][2]) == result_new[i][2], f"Last j mismatch at index {i}"
107
+ # Print the result
108
+ # for perm, val, last_j in result:
109
+ # # print(f"Permutation: {perm}, Value: {val}, Last j: {last_j}")
File without changes
@@ -0,0 +1,378 @@
1
+ import sys
2
+ from functools import cached_property
3
+
4
+ import sympy
5
+ from symengine import expand, sympify
6
+
7
+ from schubmult import GeneratingSet, Permutation, efficient_subs, mult_poly_double, permtrim, posify, schub_coprod_double, schubmult_double, theta, uncode
8
+ from schubmult.perm_lib import split_perms
9
+ from schubmult.schub_lib.schub_lib import will_formula_work
10
+ from schubmult.utils.argparse import schub_argparse
11
+ from schubmult.utils.logging import get_logger
12
+ from schubmult.utils.perm_utils import (
13
+ add_perm_dict,
14
+ mu_A,
15
+ )
16
+
17
+ logger = get_logger(__name__)
18
+
19
+
20
+ class _gvars:
21
+ @cached_property
22
+ def n(self):
23
+ return 100
24
+
25
+ @cached_property
26
+ def var1(self):
27
+ return GeneratingSet("x")
28
+
29
+ @cached_property
30
+ def var2(self):
31
+ return GeneratingSet("y")
32
+
33
+ @cached_property
34
+ def var3(self):
35
+ return GeneratingSet("z")
36
+
37
+ @cached_property
38
+ def var_r(self):
39
+ return GeneratingSet("r")
40
+
41
+
42
+ _vars = _gvars()
43
+
44
+
45
+ def _display(val):
46
+ print(val)
47
+
48
+
49
+ subs_dict = {}
50
+ for i in range(1, 100):
51
+ sm = _vars.var2[1]
52
+ for j in range(1, i):
53
+ sm += _vars.var_r[j]
54
+ subs_dict[_vars.var2[i]] = sm
55
+
56
+
57
+ def sv_posify(val):
58
+ # this has just y's, we want to rearrange
59
+ # can we do this without an optimization
60
+ val = sympify(sympy.simplify(val.subs(subs_dict)))
61
+ bingle_dict = {}
62
+ for i in range(1, len(_vars.var_r) - 1):
63
+ bingle_dict[_vars.var_r[i]] = _vars.var2[i + 1] - _vars.var2[i] # sympy.Add(*[_vars.var2[i+1], - _vars.var2[i]],evaluate=False)
64
+ # oh bay does that bar bangled banber bet bave space buckets of cheese
65
+ # val = sympy.simplify(val)
66
+ return val.xreplace(bingle_dict)
67
+
68
+
69
+ def pre_posify(perms, perm, val, check, check_val, same, down, var2, var3, msg):
70
+ try:
71
+ return int(val)
72
+ except Exception:
73
+ if same:
74
+ val = sv_posify(val) # efficient_subs(sympify(val), subs_dict).expand() # expand(sympify(val).xreplace(subs_dict))
75
+ else:
76
+ if not down:
77
+ val = posify(
78
+ val,
79
+ perms[0],
80
+ perms[1],
81
+ perm,
82
+ var2,
83
+ var3,
84
+ msg,
85
+ )
86
+ else:
87
+ val = posify(
88
+ val,
89
+ perm,
90
+ perms[1],
91
+ perms[0],
92
+ var2,
93
+ var3,
94
+ msg,
95
+ )
96
+ # except Exception:
97
+ # _display(
98
+ # f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_val=}",
99
+ # )
100
+ # exit(1)
101
+ # if check and expand(val - check_coeff_dict.get(perm, 0)) != 0:
102
+ if check and expand(val - check_val) != 0:
103
+ _display(
104
+ f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_val=}",
105
+ )
106
+ # logger.debug("Yep it's here")
107
+ exit(1)
108
+ return val
109
+
110
+
111
+ def flip_symbol_signs(val):
112
+ subs_dict = {}
113
+ for s in val.free_symbols:
114
+ if _vars.var2.index(s) != -1 or _vars.var3.index(s) != -1:
115
+ subs_dict[s] = -s
116
+ return efficient_subs(val, subs_dict)
117
+
118
+
119
+ def _display_full(
120
+ coeff_dict,
121
+ args,
122
+ formatter,
123
+ var2,
124
+ var3,
125
+ check=True,
126
+ ):
127
+ subs_dict2 = {}
128
+ for i in range(1, 100):
129
+ sm = var2[1]
130
+ for j in range(1, i):
131
+ sm += _vars.var_r[j]
132
+ subs_dict2[var2[i]] = sm
133
+ raw_result_dict = {}
134
+ perms = args.perms
135
+ ascode = args.ascode
136
+ Permutation.print_as_code = ascode
137
+ coprod = args.coprod
138
+ msg = args.msg
139
+ same = args.same
140
+ display_positive = args.display_positive
141
+ perms[0] = Permutation(perms[0])
142
+ pos = list(perms[1])
143
+ pos2 = []
144
+ last_descent = -1
145
+ poso = []
146
+ for i in range(len(perms[0]) - 1):
147
+ if perms[0][i] > perms[0][i + 1]:
148
+ last_descent = i + 1
149
+ for i in range(1, last_descent + 1):
150
+ if i not in pos:
151
+ pos2 += [i - 1]
152
+ else:
153
+ poso += [i - 1]
154
+
155
+ mu_W = uncode(theta(~perms[0]))
156
+
157
+ the_top_perm = perms[0] * mu_W
158
+
159
+ muA = uncode(mu_A(mu_W.code, poso))
160
+ muB = uncode(mu_A(mu_W.code, pos2))
161
+
162
+ coeff_perms = list(coeff_dict.keys())
163
+ if coprod:
164
+ perm_pairs = coeff_perms
165
+ width = max([len(sympy.sstr(perm[0]) + " " + sympy.sstr(perm[1])) for perm in perm_pairs])
166
+
167
+ for firstperm, secondperm in perm_pairs:
168
+ val = coeff_dict[(firstperm, secondperm)]
169
+ if same and display_positive:
170
+ val = sv_posify(val) # efficient_subs(sympify(val), subs_dict2).expand()
171
+ if val != 0:
172
+ if display_positive and not same:
173
+ if val != 0:
174
+ try:
175
+ val = int(expand(val))
176
+ except Exception as e: # noqa: F841
177
+ val2 = posify(
178
+ flip_symbol_signs(val),
179
+ firstperm * muA,
180
+ secondperm * muB,
181
+ the_top_perm,
182
+ var2,
183
+ var3,
184
+ msg,
185
+ False,
186
+ )
187
+ val2 = flip_symbol_signs(val2)
188
+ if check and expand(val - val2) != 0:
189
+ _display(
190
+ f"error; write to schubmult@gmail.com with the case {perms=}\n{sympy.sstr(firstperm)=} {sympy.sstr(secondperm)=}\n{val2=}\n{val=}",
191
+ )
192
+ _display(f"{firstperm*muA=} {secondperm*muB=} {the_top_perm=}")
193
+ exit(1)
194
+ val = val2
195
+ else:
196
+ val = 0
197
+ if val != 0:
198
+ width2 = width - len(sympy.sstr(permtrim(firstperm))) - len(sympy.sstr(permtrim(secondperm)))
199
+ raw_result_dict[(permtrim(firstperm), Permutation(secondperm))] = val
200
+ if formatter:
201
+ _display(
202
+ f"{sympy.sstr(permtrim(firstperm))}{' ':>{width2}}{sympy.sstr(Permutation(secondperm))} {formatter(val)}",
203
+ )
204
+ else:
205
+ width = max([len(sympy.sstr(perm)) for perm in coeff_dict.keys()])
206
+
207
+ coeff_perms = list(coeff_dict.keys())
208
+ coeff_perms.sort(key=lambda x: (x.inv, *x))
209
+
210
+ for perm in coeff_perms:
211
+ val = coeff_dict[perm]
212
+ # if val != 0:
213
+ if val != 0:
214
+ raw_result_dict[perm] = val
215
+ if formatter:
216
+ _display(f"{sympy.sstr(perm)!s:>{width}} {formatter(val)}")
217
+ return raw_result_dict
218
+
219
+
220
+ def main(argv=None):
221
+ if argv is None:
222
+ argv = sys.argv
223
+
224
+ try:
225
+ var2 = GeneratingSet("y")
226
+ var3 = GeneratingSet("z")
227
+ sys.setrecursionlimit(1000000)
228
+
229
+ # TEMP
230
+ sympy.init_printing()
231
+
232
+ args, formatter = schub_argparse(
233
+ "schubmult_double",
234
+ "Compute coefficients of products of double Schubert polynomials in the same or different sets of coefficient variables",
235
+ argv=argv[1:],
236
+ yz=True,
237
+ )
238
+
239
+ mult = args.mult
240
+ mulstring = args.mulstring
241
+
242
+ perms = args.perms
243
+
244
+ ascode = args.ascode
245
+ coprod = args.coprod
246
+ same = args.same
247
+ msg = args.msg
248
+ down = args.down
249
+ check = args.check
250
+ display_positive = args.display_positive
251
+ pr = args.pr
252
+ # debug = args.debug
253
+
254
+ # logger.log(logging.DEBUG, f"main boing 1 {var2=}{var3=}{same=}")
255
+ if same:
256
+ var3 = var2
257
+ # logger.log(logging.DEBUG, f"main boing 2 {var2=}{var3=}{same=}")
258
+ posified = False
259
+ if coprod:
260
+ if ascode:
261
+ perms[0] = uncode(perms[0])
262
+ pos = [*perms[1]]
263
+ pos.sort()
264
+ mperm = Permutation(perms[0])
265
+
266
+ coeff_dict = schub_coprod_double(mperm, pos, var2, var3)
267
+
268
+ if pr or formatter is None:
269
+ # logger.log(logging.DEBUG, f"main {var2=}{var3=}{same=}")
270
+ raw_result_dict = _display_full(
271
+ coeff_dict,
272
+ args,
273
+ formatter,
274
+ var2=var2,
275
+ var3=var3,
276
+ )
277
+ if formatter is None:
278
+ return raw_result_dict
279
+ else:
280
+ if ascode:
281
+ for i in range(len(perms)):
282
+ perms[i] = uncode(perms[i])
283
+ else:
284
+ for i in range(len(perms)):
285
+ if len(perms[i]) < 2 and (len(perms[i]) == 0 or perms[i][0] == 1):
286
+ perms[i] = Permutation([])
287
+ perms[i] = Permutation(perms[i])
288
+
289
+ size = 0
290
+ orig_perms = [*perms]
291
+ while len(perms) != size:
292
+ size = len(perms)
293
+ perms = split_perms(perms)
294
+
295
+ coeff_dict = {perms[0]: 1}
296
+ check_coeff_dict = {perms[0]: 1}
297
+
298
+ # if mult:
299
+ # for v in var2:
300
+ # ()[str(v)] = v
301
+ # for v in var3:
302
+ # globals()[str(v)] = v
303
+ # for v in _vars.var1:
304
+ # globals()[str(v)] = v
305
+
306
+ # if down:
307
+ # for perm in orig_perms[1:]:
308
+ # check_coeff_dict = schubmult_down(check_coeff_dict, perm, var2, var3)
309
+ # if mult:
310
+ # mul_exp = eval(mulstring)
311
+ # check_coeff_dict = mult_poly_down(check_coeff_dict, mul_exp)
312
+ # else:
313
+ for perm in orig_perms[1:]:
314
+ check_coeff_dict = schubmult_double(check_coeff_dict, perm, var2, var3)
315
+ # coeff_dict = check_coeff_dict
316
+ if mult:
317
+ mul_exp = eval(mulstring)
318
+ check_coeff_dict = mult_poly_double(check_coeff_dict, mul_exp)
319
+ # preprocess positivity
320
+ if display_positive and len(perms) == 2 and will_formula_work(perms[0], perms[1]) and not mult and not down and not same:
321
+ coeff_dict = {}
322
+ th = theta(perms[1])
323
+ muv = uncode(th)
324
+ muvn1v = (~muv) * perms[1]
325
+ coeff_dict2 = {perms[0]: 1}
326
+ coeff_dict2 = schubmult_double(coeff_dict2, muv, var2, var3)
327
+ for perm, val in coeff_dict2.items():
328
+ w = perm * muvn1v
329
+ if w.inv + muvn1v.inv == perm.inv:
330
+ coeff_dict[Permutation(w)] = val
331
+ posified = True
332
+
333
+ if display_positive and len(perms) > 2 and not mult and not same:
334
+ coeff_dict2 = dict(coeff_dict)
335
+ for perm in perms[1:]:
336
+ coeff_dict3 = {}
337
+ for u in coeff_dict2:
338
+ coeff_dict4 = {u: 1}
339
+ coeff_dict4 = schubmult_double(coeff_dict4, perm, var2, var3)
340
+ for w in coeff_dict4:
341
+ coeff_dict4[w] = coeff_dict2[u] * posify(
342
+ coeff_dict4[w],
343
+ u,
344
+ perm,
345
+ w,
346
+ var2,
347
+ var3,
348
+ msg,
349
+ )
350
+ coeff_dict3 = add_perm_dict(coeff_dict4, coeff_dict3)
351
+ coeff_dict2 = coeff_dict3
352
+ coeff_dict = coeff_dict2
353
+ posified = True
354
+ elif not posified:
355
+ coeff_dict = check_coeff_dict
356
+
357
+ if not posified and display_positive:
358
+ # print(f"{coeff_dict=}")
359
+ coeff_dict = {k: pre_posify(perms, k, v, check, check_coeff_dict.get(k, 0), same, down, var2, var3, msg) for k, v in coeff_dict.items()}
360
+
361
+ if pr or formatter is None:
362
+ raw_result_dict = _display_full(
363
+ coeff_dict,
364
+ args,
365
+ formatter,
366
+ var2,
367
+ var3,
368
+ )
369
+
370
+ if formatter is None:
371
+ return raw_result_dict
372
+ except BrokenPipeError:
373
+ pass
374
+ return 0
375
+
376
+
377
+ if __name__ == "__main__":
378
+ sys.exit(main(sys.argv))
@@ -0,0 +1,84 @@
1
+ import sys
2
+
3
+ import sympy
4
+ from symengine import sympify
5
+
6
+ from schubmult import Permutation, mult_poly_py, permtrim, schub_coprod_py, schubmult_py, theta, uncode
7
+ from schubmult.utils.argparse import schub_argparse
8
+
9
+
10
+ def main(argv=None):
11
+ if argv is None:
12
+ argv = sys.argv
13
+ try:
14
+ args, formatter = schub_argparse(
15
+ "schubmult_py",
16
+ "Compute products of ordinary Schubert polynomials",
17
+ argv=argv[1:],
18
+ )
19
+
20
+ mult = args.mult
21
+ mulstring = args.mulstring
22
+
23
+ perms = args.perms
24
+
25
+ for perm in perms:
26
+ try:
27
+ for i in range(len(perm)):
28
+ perm[i] = int(perm[i])
29
+ except Exception as e:
30
+ print("Permutations must have integer values")
31
+ raise e
32
+
33
+ ascode = args.ascode
34
+ Permutation.print_as_code = ascode
35
+ pr = args.pr
36
+ coprod = args.coprod
37
+ raw_result_dict = {}
38
+ if coprod:
39
+ if ascode:
40
+ perms[0] = uncode(perms[0])
41
+ pos = [*perms[1]]
42
+ pos.sort()
43
+ mperm = Permutation(perms[0])
44
+
45
+ coeff_dict = schub_coprod_py(mperm, pos)
46
+
47
+ if pr or formatter is None:
48
+ for firstperm, secondperm in coeff_dict:
49
+ val = coeff_dict[(firstperm, secondperm)]
50
+ if val != 0:
51
+ if formatter is None:
52
+ raw_result_dict[(firstperm, secondperm)] = val
53
+ else:
54
+ print(f"{val} {sympy.sstr(firstperm)} {sympy.sstr(secondperm)}")
55
+ else:
56
+ if ascode:
57
+ for i in range(len(perms)):
58
+ perms[i] = permtrim(uncode(perms[i]))
59
+ else:
60
+ perms = [permtrim(perm) for perm in perms]
61
+ perms.sort(reverse=True, key=lambda x: sum(theta(~x)) - x.inv)
62
+
63
+ coeff_dict = {permtrim([*perms[0]]): 1}
64
+
65
+ for perm in perms[1:]:
66
+ coeff_dict = schubmult_py(coeff_dict, Permutation(perm))
67
+ if mult:
68
+ mul_exp = sympify(mulstring)
69
+ coeff_dict = mult_poly_py(coeff_dict, mul_exp)
70
+
71
+ if pr or formatter is None:
72
+ for perm, val in coeff_dict.items():
73
+ if val != 0:
74
+ raw_result_dict[perm] = val
75
+ if formatter:
76
+ print(f"{val} {sympy.sstr(perm)}")
77
+ if formatter is None:
78
+ return raw_result_dict
79
+ except BrokenPipeError:
80
+ pass
81
+
82
+
83
+ if __name__ == "__main__":
84
+ sys.exit(main(sys.argv))
@@ -0,0 +1,109 @@
1
+ import sys
2
+
3
+ import sympy
4
+ from symengine import sympify
5
+
6
+ from schubmult import GeneratingSet, Permutation, apply_peterson_woodward, schubmult_q, schubmult_q_fast, uncode
7
+ from schubmult.utils.argparse import schub_argparse
8
+
9
+ q_var = GeneratingSet("q")
10
+
11
+
12
+ def _display_full(coeff_dict, args, formatter):
13
+ raw_result_dict = {}
14
+ ascode = args.ascode
15
+ Permutation.print_as_code = ascode
16
+ parabolic_index = []
17
+ start = 0
18
+ for i in range(len(args.parabolic)):
19
+ end = start + int(args.parabolic[i])
20
+ parabolic_index += list(range(start + 1, end))
21
+ start = end
22
+ parabolic = len(parabolic_index) != 0
23
+
24
+ if parabolic:
25
+ coeff_dict = apply_peterson_woodward(coeff_dict, parabolic_index)
26
+
27
+ coeff_perms = list(coeff_dict.keys())
28
+ coeff_perms.sort(key=lambda x: (x.inv, *x))
29
+
30
+ for perm in coeff_perms:
31
+ val = sympify(coeff_dict[perm]).expand()
32
+ if val != 0:
33
+ raw_result_dict[perm] = val
34
+ if formatter:
35
+ print(f"{sympy.sstr(perm)!s} {formatter(val)}")
36
+ return raw_result_dict
37
+
38
+
39
+ def main(argv=None):
40
+ if argv is None:
41
+ argv = sys.argv
42
+ try:
43
+ args, formatter = schub_argparse(
44
+ "schubmult_q",
45
+ "Compute products of quantum Schubert polynomials",
46
+ argv=argv[1:],
47
+ quantum=True,
48
+ )
49
+
50
+ perms = args.perms
51
+
52
+ for perm in perms:
53
+ try:
54
+ for i in range(len(perm)):
55
+ perm[i] = int(perm[i])
56
+ except Exception as e:
57
+ print("Permutations must have integer values")
58
+ raise e
59
+
60
+ ascode = args.ascode
61
+ pr = args.pr
62
+ parabolic_index = [int(s) for s in args.parabolic]
63
+ parabolic = len(parabolic_index) != 0
64
+ slow = args.slow
65
+
66
+ if parabolic and len(perms) != 2:
67
+ print("Only two permutations supported for parabolic.")
68
+ exit(1)
69
+
70
+ if ascode:
71
+ for i in range(len(perms)):
72
+ perms[i] = uncode(perms[i])
73
+ else:
74
+ perms = [Permutation(perm) for perm in perms]
75
+
76
+ # if parabolic:
77
+ # for i in range(len(parabolic_index)):
78
+ # index = parabolic_index[i] - 1
79
+ # if sg(index, perms[0]) == 1 or sg(index, perms[1]) == 1:
80
+ # print(
81
+ # "Parabolic given but elements are not minimal length coset representatives.",
82
+ # )
83
+ # exit(1)
84
+
85
+ coeff_dict = {perms[0]: 1}
86
+
87
+ if not slow:
88
+ for perm in perms[1:]:
89
+ coeff_dict = schubmult_q_fast(coeff_dict, perm)
90
+ else:
91
+ for perm in perms[1:]:
92
+ coeff_dict = schubmult_q(coeff_dict, perm)
93
+
94
+ # if mult:
95
+ # mul_exp = sympify(mulstring)
96
+ # coeff_dict = mult_poly(coeff_dict, mul_exp)
97
+
98
+ if pr or formatter is None:
99
+ raw_result_dict = _display_full(coeff_dict, args, formatter)
100
+ if formatter is None:
101
+ return raw_result_dict
102
+ except BrokenPipeError:
103
+ pass
104
+
105
+
106
+ if __name__ == "__main__":
107
+ import sys
108
+
109
+ sys.exit(main(sys.argv))