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
@@ -1,540 +0,0 @@
1
- # from ._vars import (
2
- # var_y,
3
- # var_x,
4
- # var2,
5
- # var3,
6
- # q_var2,
7
- # )
8
- import schubmult.schubmult_double as norm_yz
9
-
10
- from symengine import Add, Mul, Pow, expand, symarray
11
- from schubmult.perm_lib import (
12
- elem_sym_perms_q,
13
- add_perm_dict,
14
- compute_vpathdicts,
15
- inverse,
16
- strict_theta,
17
- medium_theta,
18
- permtrim,
19
- inv,
20
- mulperm,
21
- uncode,
22
- double_elem_sym_q,
23
- elem_sym_poly_q,
24
- elem_sym_perms_q_op,
25
- elem_sym_func_q,
26
- call_zvars,
27
- )
28
- from functools import cached_property
29
-
30
- class _gvars:
31
- @cached_property
32
- def n(self):
33
- return 100
34
-
35
- # @cached_property
36
- # def fvar(self):
37
- # return 100
38
-
39
- @cached_property
40
- def var1(self):
41
- return tuple(symarray("x", self.n).tolist())
42
-
43
- @cached_property
44
- def var2(self):
45
- return tuple(symarray("y", self.n).tolist())
46
-
47
- @cached_property
48
- def var3(self):
49
- return tuple(symarray("z", self.n).tolist())
50
-
51
- @cached_property
52
- def q_var(self):
53
- return tuple(symarray("q", self.n).tolist())
54
-
55
- @cached_property
56
- def var_r(self):
57
- return symarray("r", 100)
58
-
59
-
60
- _vars = _gvars()
61
-
62
-
63
- def E(p, k, varl=_vars.var2[1:],var_x=_vars.var1):
64
- return elem_sym_poly_q(p, k, var_x[1:], varl)
65
-
66
-
67
- def single_variable(coeff_dict, varnum, var2=_vars.var2, q_var=_vars.q_var):
68
- ret = {}
69
- for u in coeff_dict:
70
- if varnum - 1 < len(u):
71
- ret[u] = ret.get(u, 0) + var2[u[varnum - 1]] * coeff_dict[u]
72
- else:
73
- ret[u] = ret.get(u, 0) + var2[varnum] * coeff_dict[u]
74
- new_perms_k = elem_sym_perms_q(u, 1, varnum, q_var)
75
- new_perms_km1 = []
76
- if varnum > 1:
77
- new_perms_km1 = elem_sym_perms_q(u, 1, varnum - 1, q_var)
78
- for perm, udiff, mul_val in new_perms_k:
79
- if udiff == 1:
80
- ret[perm] = ret.get(perm, 0) + coeff_dict[u] * mul_val
81
- for perm, udiff, mul_val in new_perms_km1:
82
- if udiff == 1:
83
- ret[perm] = ret.get(perm, 0) - coeff_dict[u] * mul_val
84
- return ret
85
-
86
-
87
- def mult_poly(coeff_dict, poly, var_x=_vars.var1, var_y=_vars.var2, q_var=_vars.q_var):
88
- if poly in var_x:
89
- return single_variable(coeff_dict, var_x.index(poly), var_y, q_var)
90
- elif isinstance(poly, Mul):
91
- ret = coeff_dict
92
- for a in poly.args:
93
- ret = mult_poly(ret, a, var_x, var_y, q_var)
94
- return ret
95
- elif isinstance(poly, Pow):
96
- base = poly.args[0]
97
- exponent = int(poly.args[1])
98
- ret = coeff_dict
99
- for i in range(int(exponent)):
100
- ret = mult_poly(ret, base, var_x, var_y, q_var)
101
- return ret
102
- elif isinstance(poly, Add):
103
- ret = {}
104
- for a in poly.args:
105
- ret = add_perm_dict(ret, mult_poly(coeff_dict, a, var_x, var_y, q_var))
106
- return ret
107
- else:
108
- ret = {}
109
- for perm in coeff_dict:
110
- ret[perm] = poly * coeff_dict[perm]
111
- return ret
112
-
113
-
114
- def nil_hecke(perm_dict, v, n, var2=_vars.var2, var3=_vars.var3):
115
- if v == (1, 2):
116
- return perm_dict
117
- th = strict_theta(inverse(v))
118
- mu = permtrim(uncode(th))
119
- vmu = permtrim(mulperm([*v], mu))
120
-
121
- ret_dict = {}
122
- while th[-1] == 0:
123
- th.pop()
124
- thL = len(th)
125
- vpathdicts = compute_vpathdicts(th, vmu, True)
126
- for u, val in perm_dict.items():
127
- vpathsums = {u: {(1, 2): val}}
128
- for index in range(thL):
129
- mx_th = 0
130
- for vp in vpathdicts[index]:
131
- for v2, vdiff, s in vpathdicts[index][vp]:
132
- if th[index] - vdiff > mx_th:
133
- mx_th = th[index] - vdiff
134
- newpathsums = {}
135
- for up in vpathsums:
136
- newperms = elem_sym_perms_q_op(up, mx_th, th[index], n)
137
- for up2, udiff, mul_val in newperms:
138
- if up2 not in newpathsums:
139
- newpathsums[up2] = {}
140
- for v in vpathdicts[index]:
141
- sumval = vpathsums[up].get(v, 0) * mul_val
142
- if sumval == 0:
143
- continue
144
- for v2, vdiff, s in vpathdicts[index][v]:
145
- newpathsums[up2][v2] = newpathsums[up2].get(
146
- v2, 0
147
- ) + s * sumval * elem_sym_func_q(
148
- th[index],
149
- index + 1,
150
- up2,
151
- up,
152
- v,
153
- v2,
154
- udiff,
155
- vdiff,
156
- var2,
157
- var3,
158
- )
159
- vpathsums = newpathsums
160
- toget = tuple(vmu)
161
- ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
162
- return ret_dict
163
-
164
-
165
- def elem_sym_func_q_q(k, i, u1, u2, v1, v2, udiff, vdiff, varl1, varl2, q_var=_vars.q_var):
166
- newk = k - udiff
167
- if newk < vdiff:
168
- return 0
169
- if newk == vdiff:
170
- return 1
171
- yvars = []
172
- mlen = max(len(u1), len(u2))
173
- u1 = [*u1] + [a + 1 for a in range(len(u1), mlen)]
174
- u2 = [*u2] + [a + 1 for a in range(len(u2), mlen)]
175
- for j in range(min(len(u1), k)):
176
- if u1[j] == u2[j]:
177
- yvars += [varl1[u2[j]]]
178
- for j in range(len(u1), min(k, len(u2))):
179
- if u2[j] == j + 1:
180
- yvars += [varl1[u2[j]]]
181
- for j in range(len(u2), k):
182
- yvars += [varl1[j + 1]]
183
- zvars = [varl2[a] for a in call_zvars(v1, v2, k, i)]
184
- return elem_sym_poly_q(newk - vdiff, newk, yvars, zvars, q_var)
185
-
186
-
187
- def schubpoly_quantum(v, var_x=_vars.var1, var_y=_vars.var2, q_var=_vars.q_var, coeff=1):
188
- th = strict_theta(inverse(v))
189
- mu = permtrim(uncode(th))
190
- vmu = permtrim(mulperm([*v], mu))
191
- if len(th) == 0:
192
- return coeff
193
- while th[-1] == 0:
194
- th.pop()
195
- vpathdicts = compute_vpathdicts(th, vmu)
196
- vpathsums = {(1, 2): {(1, 2): coeff}}
197
- inv_mu = inv(mu)
198
- inv_vmu = inv(vmu)
199
- inv_u = 0
200
- ret_dict = {}
201
- for index in range(len(th)):
202
- mx_th = 0
203
- for vp in vpathdicts[index]:
204
- for v2, vdiff, s in vpathdicts[index][vp]:
205
- if th[index] - vdiff > mx_th:
206
- mx_th = th[index] - vdiff
207
- newpathsums = {}
208
- for up in vpathsums:
209
- inv_up = inv(up)
210
- newperms = elem_sym_perms_q(
211
- up, min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu), th[index], q_var
212
- )
213
- for up2, udiff, mul_val in newperms:
214
- if up2 not in newpathsums:
215
- newpathsums[up2] = {}
216
- for v in vpathdicts[index]:
217
- sumval = vpathsums[up].get(v, 0) * mul_val
218
- if sumval == 0:
219
- continue
220
- for v2, vdiff, s in vpathdicts[index][v]:
221
- newpathsums[up2][v2] = newpathsums[up2].get(
222
- v2, 0
223
- ) + s * sumval * elem_sym_func_q_q(
224
- th[index],
225
- index + 1,
226
- up,
227
- up2,
228
- v,
229
- v2,
230
- udiff,
231
- vdiff,
232
- var_x,
233
- var_y,
234
- q_var,
235
- )
236
- vpathsums = newpathsums
237
- toget = tuple(vmu)
238
- ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
239
- return ret_dict[(1, 2)]
240
-
241
-
242
- def schubmult(perm_dict, v, var2=_vars.var2, var3=_vars.var3, q_var=_vars.q_var):
243
- if v == (1, 2):
244
- return perm_dict
245
- th = strict_theta(inverse(v))
246
- mu = permtrim(uncode(th))
247
- vmu = permtrim(mulperm([*v], mu))
248
- inv_vmu = inv(vmu)
249
- inv_mu = inv(mu)
250
- ret_dict = {}
251
- if len(th) == 0:
252
- return perm_dict
253
- while th[-1] == 0:
254
- th.pop()
255
- thL = len(th)
256
- vpathdicts = compute_vpathdicts(th, vmu, True)
257
- for u, val in perm_dict.items():
258
- inv_u = inv(u)
259
- vpathsums = {u: {(1, 2): val}}
260
- for index in range(thL):
261
- mx_th = 0
262
- for vp in vpathdicts[index]:
263
- for v2, vdiff, s in vpathdicts[index][vp]:
264
- if th[index] - vdiff > mx_th:
265
- mx_th = th[index] - vdiff
266
- newpathsums = {}
267
- for up in vpathsums:
268
- inv_up = inv(up)
269
- newperms = elem_sym_perms_q(
270
- up,
271
- min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu),
272
- th[index],
273
- q_var,
274
- )
275
- for up2, udiff, mul_val in newperms:
276
- if up2 not in newpathsums:
277
- newpathsums[up2] = {}
278
- for v in vpathdicts[index]:
279
- sumval = vpathsums[up].get(v, 0) * mul_val
280
- if sumval == 0:
281
- continue
282
- for v2, vdiff, s in vpathdicts[index][v]:
283
- newpathsums[up2][v2] = newpathsums[up2].get(
284
- v2, 0
285
- ) + s * sumval * elem_sym_func_q(
286
- th[index],
287
- index + 1,
288
- up,
289
- up2,
290
- v,
291
- v2,
292
- udiff,
293
- vdiff,
294
- var2,
295
- var3,
296
- )
297
- vpathsums = newpathsums
298
- toget = tuple(vmu)
299
- ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
300
- return ret_dict
301
-
302
-
303
- def schubmult_db(perm_dict, v, var2=_vars.var2, var3=_vars.var3, q_var=_vars.q_var):
304
- if v == (1, 2):
305
- return perm_dict
306
- th = medium_theta(inverse(v))
307
- if len(th) == 0:
308
- return perm_dict
309
- while th[-1] == 0:
310
- th.pop()
311
- mu = permtrim(uncode(th))
312
- vmu = permtrim(mulperm([*v], mu))
313
- inv_vmu = inv(vmu)
314
- inv_mu = inv(mu)
315
- ret_dict = {}
316
-
317
- thL = len(th)
318
- vpathdicts = compute_vpathdicts(th, vmu, True)
319
- for u, val in perm_dict.items():
320
- inv_u = inv(u)
321
- vpathsums = {u: {(1, 2): val}}
322
- for index in range(thL):
323
- if index > 0 and th[index - 1] == th[index]:
324
- continue
325
- mx_th = 0
326
- for vp in vpathdicts[index]:
327
- for v2, vdiff, s in vpathdicts[index][vp]:
328
- if th[index] - vdiff > mx_th:
329
- mx_th = th[index] - vdiff
330
- if index < len(th) - 1 and th[index] == th[index + 1]:
331
- mx_th1 = 0
332
- for vp in vpathdicts[index + 1]:
333
- for v2, vdiff, s in vpathdicts[index + 1][vp]:
334
- if th[index + 1] - vdiff > mx_th1:
335
- mx_th1 = th[index + 1] - vdiff
336
- newpathsums = {}
337
- for up in vpathsums:
338
- newpathsums0 = {}
339
- inv_up = inv(up)
340
- newperms = double_elem_sym_q(up, mx_th, mx_th1, th[index], q_var)
341
- for v in vpathdicts[index]:
342
- sumval = vpathsums[up].get(v, 0)
343
- if sumval == 0:
344
- continue
345
- for v2, vdiff2, s2 in vpathdicts[index][v]:
346
- for up1, udiff1, mul_val1 in newperms:
347
- esim1 = (
348
- elem_sym_func_q(
349
- th[index],
350
- index + 1,
351
- up,
352
- up1,
353
- v,
354
- v2,
355
- udiff1,
356
- vdiff2,
357
- var2,
358
- var3,
359
- )
360
- * mul_val1
361
- * s2
362
- )
363
- mulfac = sumval * esim1
364
- if (up1, udiff1, mul_val1) not in newpathsums0:
365
- newpathsums0[(up1, udiff1, mul_val1)] = {}
366
- # newpathsums0[(up1, udiff1, mul_val1
367
- newpathsums0[(up1, udiff1, mul_val1)][v2] = (
368
- newpathsums0[(up1, udiff1, mul_val1)].get(v2, 0) + mulfac
369
- )
370
-
371
- for up1, udiff1, mul_val1 in newpathsums0:
372
- for v in vpathdicts[index + 1]:
373
- sumval = newpathsums0[(up1, udiff1, mul_val1)].get(v, 0)
374
- if sumval == 0:
375
- continue
376
- for v2, vdiff2, s2 in vpathdicts[index + 1][v]:
377
- for up2, udiff2, mul_val2 in newperms[(up1, udiff1, mul_val1)]:
378
- esim1 = (
379
- elem_sym_func_q(
380
- th[index + 1],
381
- index + 2,
382
- up1,
383
- up2,
384
- v,
385
- v2,
386
- udiff2,
387
- vdiff2,
388
- var2,
389
- var3,
390
- )
391
- * mul_val2
392
- * s2
393
- )
394
- mulfac = sumval * esim1
395
- if up2 not in newpathsums:
396
- newpathsums[up2] = {}
397
- newpathsums[up2][v2] = newpathsums[up2].get(v2, 0) + mulfac
398
- else:
399
- newpathsums = {}
400
- for up in vpathsums:
401
- inv_up = inv(up)
402
- newperms = elem_sym_perms_q(
403
- up,
404
- min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu),
405
- th[index],
406
- q_var,
407
- )
408
- for up2, udiff, mul_val in newperms:
409
- if up2 not in newpathsums:
410
- newpathsums[up2] = {}
411
- for v in vpathdicts[index]:
412
- sumval = vpathsums[up].get(v, 0) * mul_val
413
- if sumval == 0:
414
- continue
415
- for v2, vdiff, s in vpathdicts[index][v]:
416
- newpathsums[up2][v2] = newpathsums[up2].get(
417
- v2, 0
418
- ) + s * sumval * elem_sym_func_q(
419
- th[index],
420
- index + 1,
421
- up,
422
- up2,
423
- v,
424
- v2,
425
- udiff,
426
- vdiff,
427
- var2,
428
- var3,
429
- )
430
- vpathsums = newpathsums
431
- toget = tuple(vmu)
432
- ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
433
- return ret_dict
434
-
435
-
436
- def div_diff(v, w, var2=_vars.var2, var3=_vars.var3):
437
- coeff_dict = {v: 1}
438
- coeff_dict = norm_yz.schubmult_down(coeff_dict, w, var2, var3)
439
- return coeff_dict.get((1, 2), 0)
440
-
441
-
442
- def sum_q_dict(q_dict1, q_dict2):
443
- ret = {**q_dict1}
444
- for key in q_dict2:
445
- ret[key] = ret.get(key, 0) + q_dict2[key]
446
- return ret
447
-
448
-
449
- def mul_q_dict(q_dict1, q_dict2):
450
- ret = {}
451
- for key1 in q_dict1:
452
- for key2 in q_dict2:
453
- key3 = key1 * key2
454
- ret[key3] = ret.get(key3, 0) + q_dict1[key1] * q_dict2[key2]
455
- return ret
456
-
457
-
458
- def factor_out_q_keep_factored(poly):
459
- ret = {}
460
- if str(poly).find("q") == -1:
461
- ret[1] = poly
462
- return ret
463
- elif poly in _vars.q_var:
464
- ret[poly] = 1
465
- return ret
466
- elif isinstance(poly, Add):
467
- ag = poly.args
468
- ret = factor_out_q_keep_factored(ag[0])
469
- for i in range(1, len(ag)):
470
- ret = sum_q_dict(ret, factor_out_q_keep_factored(ag[i]))
471
- return ret
472
- elif isinstance(poly, Mul):
473
- ag = poly.args
474
- ret = factor_out_q_keep_factored(ag[0])
475
- for i in range(1, len(ag)):
476
- ret = mul_q_dict(ret, factor_out_q_keep_factored(ag[i]))
477
- return ret
478
- elif isinstance(poly, Pow):
479
- base = poly.args[0]
480
- exponent = int(poly.args[1])
481
-
482
- ret = factor_out_q_keep_factored(base)
483
- ret0 = dict(ret)
484
- for i in range(exponent - 1):
485
- ret = mul_q_dict(ret, ret0)
486
-
487
- # print(f"exponent {exponent}")
488
- # work_val = factor_out_q_keep_factored(base)
489
- # ret = {1: 1}
490
- # while exponent > 0:
491
- # if exponent % 2 == 1:
492
- # if ret == {1: 1}:
493
- # ret = {**work_val}
494
- # else:
495
- # ret = mul_q_dict(ret,work_val)
496
- # exponent -= 1
497
- # else:
498
- # work_val = mul_q_dict(work_val,work_val)
499
- # exponent //= 2
500
- return ret
501
- return ret
502
-
503
-
504
- def factor_out_q(poly):
505
- coeff_dict = expand(poly).as_coefficients_dict()
506
- ret = {}
507
- for key in coeff_dict:
508
- coeff = coeff_dict[key]
509
- if coeff == 0:
510
- continue
511
- q_part = 1
512
- yz_part = coeff
513
- if isinstance(key, Mul):
514
- for var_maybe_pow in key.args:
515
- if isinstance(var_maybe_pow, Pow):
516
- real_var = var_maybe_pow.args[0]
517
- if real_var in _vars.q_var:
518
- q_part *= var_maybe_pow
519
- else:
520
- yz_part *= var_maybe_pow
521
- else:
522
- real_var = var_maybe_pow
523
- if real_var in _vars.q_var:
524
- q_part *= var_maybe_pow
525
- else:
526
- yz_part *= var_maybe_pow
527
- elif isinstance(key, Pow):
528
- real_var = key.args[0]
529
- if real_var in _vars.q_var:
530
- q_part *= key
531
- else:
532
- yz_part *= key
533
- else:
534
- if key in _vars.q_var:
535
- q_part *= key
536
- else:
537
- yz_part *= key
538
-
539
- ret[q_part] = ret.get(q_part, 0) + yz_part
540
- return ret