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