schubmult 2.0.4__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 (58) hide show
  1. schubmult/__init__.py +94 -1
  2. schubmult/perm_lib.py +232 -819
  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 +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.0.dist-info/METADATA +1234 -0
  37. schubmult-3.0.0.dist-info/RECORD +41 -0
  38. {schubmult-2.0.4.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 -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.0.dist-info}/licenses/LICENSE +0 -0
  58. {schubmult-2.0.4.dist-info → schubmult-3.0.0.dist-info}/top_level.txt +0 -0
@@ -8,45 +8,42 @@ import sympy
8
8
  from cachetools import cached
9
9
  from cachetools.keys import hashkey
10
10
  from sortedcontainers import SortedList
11
- from symengine import Add, Integer, Mul, Pow, expand, symarray, sympify
11
+ from symengine import Add, Integer, Mul, Pow, sympify
12
12
 
13
13
  from schubmult.perm_lib import (
14
- add_perm_dict,
14
+ Permutation,
15
15
  code,
16
- compute_vpathdicts,
17
16
  cycle,
18
- divdiffable,
19
17
  dominates,
20
- elem_sym_func,
21
- elem_sym_perms,
22
- elem_sym_perms_op,
23
- elem_sym_poly,
24
18
  inv,
25
- inverse,
26
- is_reducible,
27
- mulperm,
28
19
  one_dominates,
29
- permtrim,
30
20
  phi1,
21
+ theta,
22
+ uncode,
23
+ )
24
+ from schubmult.poly_lib.poly_lib import efficient_subs, elem_sym_func, elem_sym_poly, expand
25
+ from schubmult.poly_lib.schub_poly import schubpoly
26
+ from schubmult.poly_lib.variables import CustomGeneratingSet, GeneratingSet, GeneratingSet_base
27
+ from schubmult.schub_lib.schub_lib import (
28
+ compute_vpathdicts,
29
+ divdiffable,
30
+ elem_sym_perms,
31
+ elem_sym_perms_op,
32
+ is_coeff_irreducible,
33
+ is_split_two,
31
34
  pull_out_var,
32
35
  reduce_coeff,
33
36
  reduce_descents,
34
- theta,
35
37
  try_reduce_u,
36
38
  try_reduce_v,
37
- uncode,
38
39
  will_formula_work,
39
- zero,
40
40
  )
41
+ from schubmult.utils.logging import get_logger
42
+ from schubmult.utils.perm_utils import add_perm_dict
43
+
44
+ zero = sympify(0)
41
45
 
42
- # NO GLOBAL VARS
43
- # from ._vars import (
44
- # n,
45
- # var2,
46
- # var3,
47
- # _vars.var1,
48
- # var_y,
49
- # )
46
+ logger = get_logger(__name__)
50
47
 
51
48
 
52
49
  class _gvars:
@@ -60,19 +57,28 @@ class _gvars:
60
57
 
61
58
  @cached_property
62
59
  def var1(self):
63
- return tuple(symarray("x", self.n).tolist())
60
+ return GeneratingSet("x")
64
61
 
65
62
  @cached_property
66
63
  def var2(self):
67
- return tuple(symarray("y", self.n).tolist())
64
+ return GeneratingSet("y")
68
65
 
69
66
  @cached_property
70
67
  def var3(self):
71
- return tuple(symarray("z", self.n).tolist())
68
+ return GeneratingSet("z")
72
69
 
73
70
  @cached_property
74
71
  def var_r(self):
75
- return symarray("r", 100)
72
+ return GeneratingSet("r")
73
+
74
+ @cached_property
75
+ def var_g1(self):
76
+ return GeneratingSet("y")
77
+
78
+ @cached_property
79
+ def var_g2(self):
80
+ return GeneratingSet("z")
81
+
76
82
 
77
83
 
78
84
  _vars = _gvars()
@@ -87,8 +93,8 @@ def count_sorted(mn, tp):
87
93
  return ct
88
94
 
89
95
 
90
- def E(p, k, varl=_vars.var2[1:]):
91
- return elem_sym_poly(p, k, _vars.var1[1:], varl)
96
+ # def E(p, k, varl=_vars.var2[1:]):
97
+ # return elem_sym_poly(p, k, _vars.var1[1:], varl)
92
98
 
93
99
 
94
100
  def single_variable(coeff_dict, varnum, var2=None):
@@ -131,25 +137,34 @@ def single_variable_down(coeff_dict, varnum, var2=_vars.var2):
131
137
  return ret
132
138
 
133
139
 
134
- def mult_poly(coeff_dict, poly, var_x=_vars.var1, var_y=_vars.var2):
135
- if poly in var_x:
140
+ def mult_poly_double(coeff_dict, poly, var_x=_vars.var1, var_y=_vars.var2):
141
+ # try:
142
+ # poly = sympify(poly)
143
+ # except SympifyError:
144
+ # poly = sympy.sympify(poly)
145
+ # var_x = tuple([sympy.sympify(v) for v in var_x])
146
+ # var_y = tuple([sympy.sympify(v) for v in var_y])
147
+ # return mult_poly_sympy(coeff_dict, poly, var_x=_vars.var1, var_y=_vars.var2)
148
+ if not isinstance(var_x, GeneratingSet_base):
149
+ var_x = CustomGeneratingSet(var_x)
150
+ if var_x.index(poly) != -1:
136
151
  return single_variable(coeff_dict, var_x.index(poly), var_y)
137
152
  if isinstance(poly, Mul):
138
153
  ret = coeff_dict
139
154
  for a in poly.args:
140
- ret = mult_poly(ret, a, var_x, var_y)
155
+ ret = mult_poly_double(ret, a, var_x, var_y)
141
156
  return ret
142
157
  if isinstance(poly, Pow):
143
158
  base = poly.args[0]
144
159
  exponent = int(poly.args[1])
145
160
  ret = coeff_dict
146
161
  for i in range(int(exponent)):
147
- ret = mult_poly(ret, base, var_x, var_y)
162
+ ret = mult_poly_double(ret, base, var_x, var_y)
148
163
  return ret
149
164
  if isinstance(poly, Add):
150
165
  ret = {}
151
166
  for a in poly.args:
152
- ret = add_perm_dict(ret, mult_poly(coeff_dict, a, var_x, var_y))
167
+ ret = add_perm_dict(ret, mult_poly_double(coeff_dict, a, var_x, var_y))
153
168
  return ret
154
169
  ret = {}
155
170
  for perm in coeff_dict:
@@ -157,6 +172,9 @@ def mult_poly(coeff_dict, poly, var_x=_vars.var1, var_y=_vars.var2):
157
172
  return ret
158
173
 
159
174
 
175
+ # def mult_poly_symy(coeff_dict, poly, var_x=_vars.sympy_var1, var_y=_vars.sympy_var2):
176
+
177
+
160
178
  def mult_poly_down(coeff_dict, poly):
161
179
  if poly in _vars.var1:
162
180
  return single_variable_down(coeff_dict, _vars.var1.index(poly))
@@ -186,15 +204,15 @@ def mult_poly_down(coeff_dict, poly):
186
204
  def nilhecke_mult(coeff_dict1, coeff_dict2):
187
205
  ret = {}
188
206
  for w in coeff_dict2:
189
- w1 = [*w]
207
+ w1 = w
190
208
  inv_w1 = inv(w1)
191
209
  poly = coeff_dict2[w]
192
210
  did_mul = mult_poly_down(coeff_dict1, poly)
193
211
  for v in did_mul:
194
212
  v1 = [*v]
195
- addperm = mulperm(v1, w1)
213
+ addperm = v1 * w1
196
214
  if inv(addperm) == inv(v1) + inv_w1:
197
- toadd = tuple(permtrim(addperm))
215
+ toadd = addperm
198
216
  ret[toadd] = ret.get(toadd, 0) + did_mul[v]
199
217
  return ret
200
218
 
@@ -202,48 +220,63 @@ def nilhecke_mult(coeff_dict1, coeff_dict2):
202
220
  def forwardcoeff(u, v, perm, var2=None, var3=None):
203
221
  th = theta(v)
204
222
  muv = uncode(th)
205
- vmun1 = mulperm(inverse([*v]), muv)
223
+ vmun1 = (~v) * muv
206
224
 
207
- w = mulperm([*perm], vmun1)
225
+ w = perm * vmun1
208
226
  if inv(w) == inv(vmun1) + inv(perm):
209
- coeff_dict = schubmult_one(tuple(permtrim([*u])), tuple(muv), var2, var3)
210
- return coeff_dict.get(tuple(permtrim(w)), 0)
227
+ coeff_dict = schubmult_double_pair(u, muv, var2, var3)
228
+ # logger.debug(f"{coeff_dict.get(w,0)=} {w=} {perm=} {vmun1=} {v=} {muv=}")
229
+ return coeff_dict.get(w, 0)
211
230
  return 0
212
231
 
213
232
 
214
233
  def dualcoeff(u, v, perm, var2=None, var3=None):
215
- if u == (1, 2):
216
- vp = mulperm([*v], inverse(perm))
234
+ if inv(u) == 0:
235
+ # logger.debug("Recording line number")
236
+ vp = v * (~perm)
217
237
  if inv(vp) == inv(v) - inv(perm):
218
- val = schubpoly(vp, var2, var3)
219
- else:
220
- val = 0
238
+ return schubpoly(vp, var2, var3)
239
+ dpret = []
240
+ ret = 0
241
+ if dominates(u, perm):
242
+ dpret = dualpieri(u, v, perm)
221
243
  else:
244
+ # logger.debug("Recording line number")
222
245
  dpret = []
223
- if dominates(u, perm):
224
- dpret = dualpieri([*u], [*v], [*perm])
225
- else:
226
- th = theta(u)
227
- muu = uncode(th)
228
- umun1 = mulperm(inverse([*u]), muu)
229
- w = mulperm([*perm], umun1)
230
- if inv(w) == inv(umun1) + inv(perm):
231
- dpret = dualpieri(muu, [*v], w)
232
- ret = 0
233
- for vlist, vp in dpret:
234
- toadd = 1
235
- for i in range(len(vlist)):
236
- for j in range(len(vlist[i])):
237
- toadd *= var2[i + 1] - var3[vlist[i][j]]
238
- toadd *= schubpoly(vp, var2, var3, len(vlist) + 1)
239
- ret += toadd
240
- val = ret
241
- return val
246
+ # logger.debug("Recording line number")
247
+ th = theta(u)
248
+ muu = uncode(th)
249
+ umun1 = (~u) * muu
250
+ w = perm * umun1
251
+ # logger.debug("spiggle")
252
+ # logger.debug(f"{u=} {muu=} {v=} {w=} {perm=}")
253
+ # logger.debug(f"{w=} {perm=}")
254
+ if inv(w) == inv(umun1) + inv(perm):
255
+ dpret = dualpieri(muu, v, w)
256
+ # logger.debug(f"{muu=} {v=} {w=}")
257
+ # logger.debug(f"{dpret=}")
258
+ for vlist, vp in dpret:
259
+ # logger.debug("Recording line number")
260
+ toadd = 1
261
+ for i in range(len(vlist)):
262
+ for j in range(len(vlist[i])):
263
+ toadd *= var2[i + 1] - var3[vlist[i][j]]
264
+ toadd *= schubpoly(vp, var2, var3, len(vlist) + 1)
265
+ ret += toadd
266
+ return ret
267
+ # logger.debug("Recording line number")
268
+ # schub_val = schubmult_one(u, v, var2, var3)
269
+ # val_ret = schub_val.get(perm, 0)
270
+ # if expand(val - val_ret) != 0:
271
+ # # logger.debug(f"{schub_val=}")
272
+ # # logger.debug(f"{val=} {u=} {v=} {var2[1]=} {var3[1]=} {perm=} {schub_val.get(perm,0)=}")
273
+ # logger.debug(f"good to go {ret=}")
242
274
 
243
275
 
244
276
  def dualpieri(mu, v, w):
245
- lm = code(inverse(mu))
246
- cn1w = code(inverse(w))
277
+ # logger.debug(f"dualpieri {mu=} {v=} {w=}")
278
+ lm = code(~mu)
279
+ cn1w = code(~w)
247
280
  while len(lm) > 0 and lm[-1] == 0:
248
281
  lm.pop()
249
282
  while len(cn1w) > 0 and cn1w[-1] == 0:
@@ -253,19 +286,24 @@ def dualpieri(mu, v, w):
253
286
  for i in range(len(lm)):
254
287
  if lm[i] > cn1w[i]:
255
288
  return []
256
- c = [1, 2]
289
+ c = Permutation([1, 2])
257
290
  for i in range(len(lm), len(cn1w)):
258
- c = mulperm(cycle(i - len(lm) + 1, cn1w[i]), c)
259
- c = permtrim(c)
291
+ c = cycle(i - len(lm) + 1, cn1w[i]) * c
292
+ # c = permtrim(c)
293
+ # logger.debug("Recording line number")
260
294
  res = [[[], v]]
295
+ # logger.debug(f"{v=} {type(v)=}")
261
296
  for i in range(len(lm)):
297
+ # logger.debug(f"{res=}")
262
298
  res2 = []
263
299
  for vlist, vplist in res:
264
300
  vp = vplist
265
301
  vpl = divdiffable(vp, cycle(lm[i] + 1, cn1w[i] - lm[i]))
266
- if vpl == []:
302
+ # logger.debug(f"{vpl=} {type(vpl)=}")
303
+ if len(vpl) == 0:
267
304
  continue
268
305
  vl = pull_out_var(lm[i] + 1, vpl)
306
+ # logger.debug(f"{vl=}")
269
307
  for pw, vpl2 in vl:
270
308
  res2 += [[[*vlist, pw], vpl2]]
271
309
  res = res2
@@ -275,9 +313,10 @@ def dualpieri(mu, v, w):
275
313
  for vlist, vplist in res:
276
314
  vp = vplist
277
315
  vpl = divdiffable(vp, c)
278
- if vpl == []:
316
+ if len(vpl) == 0:
279
317
  continue
280
318
  res2 += [[vlist, vpl]]
319
+ # logger.debug(f"{res2=}")
281
320
  return res2
282
321
 
283
322
 
@@ -286,19 +325,30 @@ monom_to_vec = {}
286
325
 
287
326
 
288
327
  @cache
289
- def schubmult_one(perm1, perm2, var2=None, var3=None):
290
- return schubmult({perm1: 1}, perm2, var2, var3)
328
+ def schubmult_double_pair(perm1, perm2, var2=None, var3=None):
329
+ return schubmult_double({perm1: 1}, perm2, var2, var3)
291
330
 
292
331
 
293
- def schubmult(perm_dict, v, var2=None, var3=None):
294
- vn1 = inverse(v)
332
+ @cache
333
+ def schubmult_double_pair_generic(perm1, perm2):
334
+ return schubmult_double({perm1: 1}, perm2, _vars.var_g1, _vars.var_g2)
335
+
336
+
337
+ def schubmult_double(perm_dict, v, var2=None, var3=None):
338
+ if isinstance(var2, str):
339
+ var2 = GeneratingSet(var2)
340
+ if isinstance(var3, str):
341
+ var3 = GeneratingSet(var3)
342
+ perm_dict = {Permutation(k): v for k, v in perm_dict.items()}
343
+ v = Permutation(v)
344
+ vn1 = ~v
295
345
  th = theta(vn1)
296
346
  if len(th) == 0:
297
347
  return perm_dict
298
348
  if th[0] == 0:
299
349
  return perm_dict
300
- mu = permtrim(uncode(th))
301
- vmu = permtrim(mulperm([*v], mu))
350
+ mu = uncode(th)
351
+ vmu = v * mu
302
352
  inv_vmu = inv(vmu)
303
353
  inv_mu = inv(mu)
304
354
  ret_dict = {}
@@ -308,7 +358,7 @@ def schubmult(perm_dict, v, var2=None, var3=None):
308
358
  vpathdicts = compute_vpathdicts(th, vmu, True)
309
359
  for u, val in perm_dict.items():
310
360
  inv_u = inv(u)
311
- vpathsums = {u: {(1, 2): val}}
361
+ vpathsums = {u: {Permutation([1, 2]): val}}
312
362
  for index in range(thL):
313
363
  mx_th = 0
314
364
  for vp in vpathdicts[index]:
@@ -346,18 +396,18 @@ def schubmult(perm_dict, v, var2=None, var3=None):
346
396
  var3,
347
397
  )
348
398
  vpathsums = newpathsums
349
- toget = tuple(vmu)
350
- ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
399
+ toget = vmu
400
+ ret_dict = add_perm_dict({Permutation(ep): vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
351
401
  return ret_dict
352
402
 
353
403
 
354
404
  def schubmult_down(perm_dict, v, var2=None, var3=None):
355
- vn1 = inverse(v)
405
+ vn1 = ~v
356
406
  th = theta(vn1)
357
407
  if th[0] == 0:
358
408
  return perm_dict
359
- mu = permtrim(uncode(th))
360
- vmu = permtrim(mulperm([*v], mu))
409
+ mu = uncode(th)
410
+ vmu = v * mu
361
411
  ret_dict = {}
362
412
 
363
413
  while th[-1] == 0:
@@ -365,7 +415,7 @@ def schubmult_down(perm_dict, v, var2=None, var3=None):
365
415
  thL = len(th)
366
416
  vpathdicts = compute_vpathdicts(th, vmu, True)
367
417
  for u, val in perm_dict.items():
368
- vpathsums = {u: {(1, 2): val}}
418
+ vpathsums = {u: {Permutation([1, 2]): val}}
369
419
  for index in range(thL):
370
420
  mx_th = 0
371
421
  for vp in vpathdicts[index]:
@@ -398,13 +448,13 @@ def schubmult_down(perm_dict, v, var2=None, var3=None):
398
448
  var3,
399
449
  )
400
450
  vpathsums = newpathsums
401
- toget = tuple(vmu)
451
+ toget = vmu
402
452
  ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
403
453
  return ret_dict
404
454
 
405
455
 
406
456
  def poly_to_vec(poly, vec0=None, var3=_vars.var3):
407
- poly = expand(poly.xreplace({var3[1]: 0}))
457
+ poly = expand(sympify(poly).xreplace({var3[1]: 0}))
408
458
 
409
459
  dc = poly.as_coefficients_dict()
410
460
 
@@ -429,12 +479,12 @@ def poly_to_vec(poly, vec0=None, var3=_vars.var3):
429
479
 
430
480
  def shiftsub(pol, var2=_vars.var2):
431
481
  subs_dict = {var2[i]: var2[i + 1] for i in range(99)}
432
- return sympify(pol).subs(subs_dict)
482
+ return efficient_subs(sympify(pol), subs_dict)
433
483
 
434
484
 
435
485
  def shiftsubz(pol, var3=_vars.var3):
436
486
  subs_dict = {var3[i]: var3[i + 1] for i in range(99)}
437
- return sympify(pol).subs(subs_dict)
487
+ return efficient_subs(sympify(pol), subs_dict)
438
488
 
439
489
 
440
490
  def init_basevec(dc):
@@ -624,12 +674,12 @@ def is_negative(term):
624
674
  mulsign = 1
625
675
  if str(arg.args[0]).find("-y") != -1:
626
676
  mulsign = -1
627
- sign *= mulsign ** term.args[1]
677
+ sign *= mulsign**term.index
628
678
  elif isinstance(term, Pow):
629
679
  mulsign = 1
630
680
  if str(term.args[0]).find("-y") != -1:
631
681
  mulsign = -1
632
- sign *= mulsign ** term.args[1]
682
+ sign *= mulsign**term.index
633
683
  return sign < 0
634
684
 
635
685
 
@@ -641,32 +691,15 @@ def find_base_vectors(monom_list, var2, var3, depth):
641
691
  ct = 0
642
692
  while ct < depth and size != len(monom_list):
643
693
  size = len(monom_list)
644
- # found = False
645
- # for mn in mons2:
646
- # if mn not in monom_list:
647
- # found = True
648
- # break
649
- # if not found:
650
- # print("Breaking")
651
- # break
652
-
653
694
  monom_list2 = set(monom_list)
654
695
  additional_set2 = set()
655
696
  for mn in monom_list:
656
- # res = 1
657
- # for tp in mn:
658
- # res *= var2[tp[0]] - var3[tp[1]]
659
- # if poly_to_vec(res,vec) is None:
660
- # continue
661
-
662
697
  mncount = mn_fullcount.get(mn, {})
663
698
  if mncount == {}:
664
699
  for tp in mn:
665
700
  mncount[tp] = mncount.get(tp, 0) + 1
666
701
  mn_fullcount[mn] = mncount
667
702
  for mn2 in monom_list:
668
- # if (mn,mn2) in pairs_checked:
669
- # continue
670
703
  mn2count = mn_fullcount.get(mn2, {})
671
704
  if mn2count == {}:
672
705
  for tp in mn2:
@@ -691,8 +724,7 @@ def find_base_vectors(monom_list, var2, var3, depth):
691
724
  break
692
725
  # print(f"{mn,mn2}")
693
726
  if diff_term1 is None or diff_term2 is None:
694
- print(f"{mn=} {mn2=}")
695
- exit(1)
727
+ raise Exception(f"{mn=} {mn2=}")
696
728
  if diff_term2[1] == diff_term1[1]:
697
729
  continue
698
730
  new_term1 = (diff_term1[0], diff_term2[1])
@@ -707,19 +739,9 @@ def find_base_vectors(monom_list, var2, var3, depth):
707
739
  mn4 = list(mn2[:index2]) + list(mn2[index2 + 1 :])
708
740
  index2 = bisect_left(mn4, new_term2)
709
741
  mn4_t = tuple(mn4[:index2] + [new_term2] + mn4[index2:])
710
- # res = 1
711
- # for tp in mn3_t:
712
- # res *= var2[tp[0]] - var3[tp[1]]
713
- # if poly_to_vec(res,vec) is not None:
714
742
  if mn3_t not in monom_list2:
715
743
  additional_set2.add(mn3_t)
716
744
  monom_list2.add(mn3_t)
717
- # res = 1
718
- # for tp in mn4_t:
719
- # res *= var2[tp[0]] - var3[tp[1]]
720
- ##
721
- ## additional_set2.add(mn3_t)
722
- # if poly_to_vec(res,vec) is not None:
723
745
  if mn4_t not in monom_list2:
724
746
  additional_set2.add(mn4_t)
725
747
  monom_list2.add(mn4_t)
@@ -736,41 +758,34 @@ def find_base_vectors(monom_list, var2, var3, depth):
736
758
  return ret, monom_list
737
759
 
738
760
 
739
- def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
761
+ def compute_positive_rep(val, var2=GeneratingSet("y"), var3=GeneratingSet("z"), msg=False, do_pos_neg=True):
762
+ do_pos_neg = False
740
763
  notint = False
741
764
  try:
742
- int(expand(val))
743
- val2 = expand(val)
765
+ val2 = int(expand(val))
766
+ # val2 = expand(val)
744
767
  except Exception:
745
768
  notint = True
746
769
  if notint:
747
770
  frees = val.free_symbols
748
- var2list = [*var2]
749
- var3list = [*var3]
750
-
751
- for i in range(len(var2list)):
752
- symset = var2list[i].free_symbols
753
- for sym in symset:
754
- var2list[i] = sym
755
-
756
- for i in range(len(var3list)):
757
- symset = var3list[i].free_symbols
758
- for sym in symset:
759
- var3list[i] = sym
760
-
761
- varsimp2 = [m for m in frees if m in var2list]
762
- varsimp3 = [m for m in frees if m in var3list]
763
- varsimp2.sort(key=lambda k: var2list.index(k))
764
- varsimp3.sort(key=lambda k: var3list.index(k))
765
-
766
- var22 = [sympy.sympify(m) for m in varsimp2]
767
- var33 = [sympy.sympify(m) for m in varsimp3]
771
+ # logger.debug(f"{frees=}")
772
+ # logger.debug(f"{[type(s) for s in frees]=}")
773
+ varsimp2 = [m for m in frees if var2.index(m) != -1]
774
+ varsimp3 = [m for m in frees if var3.index(m) != -1]
775
+ varsimp2.sort(key=lambda k: var2.index(k))
776
+ varsimp3.sort(key=lambda k: var3.index(k))
777
+ # logger.debug(f"{varsimp2=}")
778
+ # logger.debug(f"{varsimp3=}")
779
+ var22 = [sympy.sympify(v) for v in varsimp2]
780
+ var33 = [sympy.sympify(v) for v in varsimp3]
781
+ # var22 = [sympy.sympify(m) for m in varsimp2]
782
+ # var33 = [sympy.sympify(m) for m in varsimp3]
768
783
  n1 = len(varsimp2)
769
784
 
770
- for i in range(len(varsimp2)):
771
- varsimp2[i] = var2[var2list.index(varsimp2[i])]
772
- for i in range(len(varsimp3)):
773
- varsimp3[i] = var3[var3list.index(varsimp3[i])]
785
+ # for i in range(len(varsimp2)):
786
+ # varsimp2[i] = var2[var2list.index(varsimp2[i])]
787
+ # for i in range(len(varsimp3)):
788
+ # varsimp3[i] = var3[var3list.index(varsimp3[i])]
774
789
 
775
790
  base_vectors = []
776
791
  base_monoms = []
@@ -858,12 +873,14 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
858
873
  raise KeyboardInterrupt()
859
874
  status = lp_prob.status
860
875
  else:
876
+ # logger.debug("this")
861
877
  val_poly = sympy.poly(expand(val), *var22, *var33)
862
878
  vec = poly_to_vec(val)
863
879
  mn = val_poly.monoms()
864
880
  L1 = tuple([0 for i in range(n1)])
865
881
  mn1L = []
866
882
  lookup = {}
883
+ # logger.debug("this")
867
884
  for mm0 in mn:
868
885
  key = mm0[n1:]
869
886
  if key not in lookup:
@@ -874,6 +891,7 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
874
891
  lookup[key] += [mm0]
875
892
  if mm0n1 == L1:
876
893
  mn1L += [mm0]
894
+ # logger.debug("this")
877
895
  for mn1 in mn1L:
878
896
  comblistmn1 = [1]
879
897
  for i in range(n1, len(mn1)):
@@ -908,7 +926,9 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
908
926
  eqs[i] += bvi * vrs[j]
909
927
  for i in range(dimen):
910
928
  lp_prob += eqs[i] == vec[i]
929
+ # logger.debug("I IS SOLVING")
911
930
  try:
931
+ # logger.debug("I IS SOLVING BOLVING")
912
932
  solver = pu.PULP_CBC_CMD(msg=msg)
913
933
  status = lp_prob.solve(solver)
914
934
  except KeyboardInterrupt:
@@ -933,96 +953,28 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
933
953
  b1 = base_monoms[k]
934
954
  if x != 0 and x is not None:
935
955
  val2 += int(x) * b1
956
+ # logger.debug(f"{val2=}")
936
957
  return val2
937
958
 
938
959
 
939
- def is_split_two(u, v, w): # noqa: ARG001
940
- if inv(w) - inv(u) != 2:
941
- return False, []
942
- diff_perm = mulperm(inverse([*u]), [*w])
943
- identity = [i + 1 for i in range(len(diff_perm))]
944
- cycles = []
945
- for i in range(len(identity)):
946
- if diff_perm[i] != identity[i]:
947
- cycle0 = set()
948
- cycle = {i + 1}
949
- last = i
950
- while len(cycle0) != len(cycle):
951
- cycle0 = cycle
952
- last = diff_perm[last] - 1
953
- cycle.add(last + 1)
954
- if len(cycle) > 1 and cycle not in cycles:
955
- cycles += [cycle]
956
- if len(cycles) > 2:
957
- break
958
- if len(cycles) == 2:
959
- return True, cycles
960
- return False, []
961
-
962
-
963
- def is_coeff_irreducible(u, v, w):
964
- return (
965
- not will_formula_work(u, v)
966
- and not will_formula_work(v, u)
967
- and not one_dominates(u, w)
968
- and not is_reducible(v)
969
- and inv(w) - inv(u) > 1
970
- and not is_split_two(u, v, w)[0]
971
- and len([i for i in code(v) if i != 0]) > 1
972
- )
973
-
974
-
975
- def is_hook(cd):
976
- started = False
977
- done = False
978
- found_zero_after = False
979
- for i in range(len(cd)):
980
- if (done or found_zero_after) and cd[i] != 0:
981
- return False
982
- if cd[i] == 1 and not started:
983
- started = True
984
- if cd[i] > 1:
985
- done = True
986
- if started and cd[i] == 0:
987
- found_zero_after = True
988
- if started or done:
989
- return True
990
- return False
991
-
992
-
993
- def div_diff(i, poly, var2=_vars.var2):
994
- return sympify(
995
- sympy.div(sympy.sympify(poly - permy(poly, i)), sympy.sympify(var2[i] - var2[i + 1]))[0],
996
- )
997
-
998
-
999
- def skew_div_diff(u, w, poly):
1000
- d = -1
1001
- for i in range(len(w) - 1):
1002
- if w[i] > w[i + 1]:
1003
- d = i
1004
- break
1005
- d2 = -1
1006
- for i in range(len(u) - 1):
1007
- if u[i] > u[i + 1]:
1008
- d2 = i
1009
- break
1010
- if d == -1:
1011
- if d2 == -1:
1012
- return poly
1013
- return 0
1014
- w2 = [*w]
1015
- w2[d], w2[d + 1] = w2[d + 1], w2[d]
1016
- if d < len(u) - 1 and u[d] > u[d + 1]:
1017
- u2 = [*u]
1018
- u2[d], u2[d + 1] = u2[d + 1], u2[d]
1019
- return skew_div_diff(u2, w2, permy(poly, d + 1))
1020
- return skew_div_diff(u, w2, div_diff(d + 1, poly))
960
+ def posify_generic_partial(val, u2, v2, w2):
961
+ val2 = val
962
+ val = posify(val, u2, v2, w2, var2=_vars.var_g1, var3=_vars.var_g2, msg=True, do_pos_neg=False, sign_only=False, optimize=False)
963
+ if expand(val - val2) != 0:
964
+ # logger.debug("Warning, failed on a case")
965
+ raise Exception(f"{val=} {val2=} {u2=} {v2=} {w2=}")
966
+ # print("FROFL")
967
+ return val
968
+
969
+
970
+ @cache
971
+ def schubmult_generic_partial_posify(u2, v2):
972
+ return {w2: posify_generic_partial(val, u2, v2, w2) for w2, val in schubmult_double_pair_generic(u2, v2).items()}
1021
973
 
1022
974
 
1023
975
  @cached(
1024
976
  cache={},
1025
- key=lambda val, u2, v2, w2, var2=None, var3=None, msg=False, do_pos_neg=True, sign_only=False: hashkey(u2, v2, w2, var2, var3, msg, do_pos_neg, sign_only),
977
+ key=lambda val, u2, v2, w2, var2=None, var3=None, msg=False, do_pos_neg=False, sign_only=False, optimize=True: hashkey(val, u2, v2, w2, var2, var3, msg, do_pos_neg, sign_only, optimize),
1026
978
  )
1027
979
  def posify(
1028
980
  val,
@@ -1032,44 +984,43 @@ def posify(
1032
984
  var2=None,
1033
985
  var3=None,
1034
986
  msg=False,
1035
- do_pos_neg=True,
987
+ do_pos_neg=False,
1036
988
  sign_only=False,
989
+ optimize=True,
1037
990
  n=_vars.n,
1038
991
  ):
992
+ # logger.debug(f"NEW {val=} {u2=} {v2=} {w2=}")
993
+ oldval = val
1039
994
  if inv(u2) + inv(v2) - inv(w2) == 0:
1040
- return val
1041
- cdv = code(v2)
1042
- if set(cdv) == {0, 1} and do_pos_neg:
995
+ # logger.debug(f"Hmm this is probably not or val inty true {val=}")
1043
996
  return val
1044
997
 
1045
998
  if not sign_only and expand(val) == 0:
999
+ # logger.debug(f"Hmm this is probably not true {u2=} {v2=} {w2=} {val=}")
1046
1000
  return 0
1047
-
1048
- u, v, w = try_reduce_v(u2, v2, w2)
1049
- if is_coeff_irreducible(u, v, w):
1001
+ # logger.debug("proceeding")
1002
+ u, v, w = u2, v2, w2
1003
+ # u, v, w = try_reduce_v(u2, v2, w2)
1004
+ if is_coeff_irreducible(u2, v2, w2):
1050
1005
  u, v, w = try_reduce_u(u2, v2, w2)
1051
1006
  if is_coeff_irreducible(u, v, w):
1052
- u, v, w = [*u2], [*v2], [*w2]
1007
+ u, v, w = u2, v2, w2
1053
1008
  if is_coeff_irreducible(u, v, w):
1054
- w0 = [*w]
1009
+ w0 = w
1055
1010
  u, v, w = reduce_descents(u, v, w)
1056
1011
  if is_coeff_irreducible(u, v, w):
1057
1012
  u, v, w = reduce_coeff(u, v, w)
1058
1013
  if is_coeff_irreducible(u, v, w):
1059
- while is_coeff_irreducible(u, v, w) and tuple(permtrim(w0)) != tuple(
1060
- permtrim([*w]),
1061
- ):
1014
+ while is_coeff_irreducible(u, v, w) and w0 != w:
1062
1015
  w0 = w
1063
1016
  u, v, w = reduce_descents(u, v, w)
1064
1017
  if is_coeff_irreducible(u, v, w):
1065
1018
  u, v, w = reduce_coeff(u, v, w)
1066
- u = tuple(u)
1067
- v = tuple(v)
1068
- w = tuple(w)
1069
1019
 
1070
1020
  if w != w2 and sign_only:
1021
+ # logger.debug(f"Return 0 ")
1071
1022
  return 0
1072
-
1023
+ # logger.debug(f"Reduced to {u2=} {v2=} {w2=} {val=}")
1073
1024
  if is_coeff_irreducible(u, v, w):
1074
1025
  u3, v3, w3 = try_reduce_v(u, v, w)
1075
1026
  if not is_coeff_irreducible(u3, v3, w3):
@@ -1079,8 +1030,9 @@ def posify(
1079
1030
  if not is_coeff_irreducible(u3, v3, w3):
1080
1031
  u, v, w = u3, v3, w3
1081
1032
  split_two_b, split_two = is_split_two(u, v, w)
1082
-
1033
+ # logger.debug("Recording line number")
1083
1034
  if len([i for i in code(v) if i != 0]) == 1:
1035
+ # logger.debug("Recording line number")
1084
1036
  if sign_only:
1085
1037
  return 0
1086
1038
  cv = code(v)
@@ -1094,17 +1046,27 @@ def posify(
1094
1046
  val = 0
1095
1047
  w2 = w
1096
1048
  hvarset = [w2[i] for i in range(min(len(w2), k))] + [i + 1 for i in range(len(w2), k)] + [w2[b] for b in range(k, len(u)) if u[b] != w2[b]] + [w2[b] for b in range(len(u), len(w2))]
1097
- val = elem_sym_poly(
1049
+ # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1050
+ return elem_sym_poly(
1098
1051
  p - r,
1099
1052
  k + p - 1,
1100
1053
  [-var3[i] for i in range(1, n)],
1101
1054
  [-var2[i] for i in hvarset],
1102
1055
  )
1103
- elif will_formula_work(v, u) or dominates(u, w):
1056
+ # if expand(val - oldval) != 0:
1057
+ # # logger.debug("This is bad")
1058
+ # # logger.debug(f"{u2=} {v2=} {w2=} {val=} {oldval=}")
1059
+ if will_formula_work(v, u) or dominates(u, w):
1060
+ # logger.debug("Recording line number")
1104
1061
  if sign_only:
1105
1062
  return 0
1106
- val = dualcoeff(u, v, w, var2, var3)
1107
- elif inv(w) - inv(u) == 1:
1063
+ return dualcoeff(u, v, w, var2, var3)
1064
+ # if expand(val - oldval) != 0:
1065
+ # logger.debug("This is bad")
1066
+ # logger.debug(f"{u2=} {v2=} {w2=} {val=} {oldval=} {will_formula_work(v,u)=} {dominates(u,w)=}")
1067
+ # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1068
+ if inv(w) - inv(u) == 1:
1069
+ # logger.debug("Recording line number")
1108
1070
  if sign_only:
1109
1071
  return 0
1110
1072
  a, b = -1, -1
@@ -1128,16 +1090,16 @@ def posify(
1128
1090
  elif i > a:
1129
1091
  i2 += 1
1130
1092
  for vr, v2 in arr:
1131
- dpret = pull_out_var(i2, [*v2])
1093
+ dpret = pull_out_var(i2, v2)
1132
1094
  for v3r, v3 in dpret:
1133
1095
  arr2 += [[[*vr, v3r], v3]]
1134
1096
  arr = arr2
1135
1097
  val = 0
1136
1098
  for L in arr:
1137
- v3 = [*L[-1]]
1099
+ v3 = L[-1]
1138
1100
  if v3[0] < v3[1]:
1139
1101
  continue
1140
- v3[0], v3[1] = v3[1], v3[0]
1102
+ v3 = v3.swap(0, 1)
1141
1103
  toadd = 1
1142
1104
  for i in range(d):
1143
1105
  if i in [a, b]:
@@ -1156,359 +1118,333 @@ def posify(
1156
1118
  toadd *= var2[yv] - var3[oaf[j]]
1157
1119
  toadd *= schubpoly(v3, [0, var2[w[a]], var2[w[b]]], var3)
1158
1120
  val += toadd
1159
- elif split_two_b:
1121
+ # if expand(val - oldval) != 0:
1122
+ # logger.debug("This is bad")
1123
+ # logger.debug(f"{u2=} {v2=} {w2=} {val=} {oldval=}")
1124
+ # logger.debug(f"good to go {u2=} {v2=} {w2=}")
1125
+ return val
1126
+ # if split_two_b:
1127
+ # # logger.debug("Recording line number")
1128
+ # if sign_only:
1129
+ # return 0
1130
+ # cycles = split_two
1131
+ # a1, b1 = cycles[0]
1132
+ # a2, b2 = cycles[1]
1133
+ # a1 -= 1
1134
+ # b1 -= 1
1135
+ # a2 -= 1
1136
+ # b2 -= 1
1137
+ # spo = sorted([a1, b1, a2, b2])
1138
+ # real_a1 = min(spo.index(a1), spo.index(b1))
1139
+ # real_a2 = min(spo.index(a2), spo.index(b2))
1140
+ # real_b1 = max(spo.index(a1), spo.index(b1))
1141
+ # real_b2 = max(spo.index(a2), spo.index(b2))
1142
+
1143
+ # good1 = False
1144
+ # good2 = False
1145
+ # if real_b1 - real_a1 == 1:
1146
+ # good1 = True
1147
+ # if real_b2 - real_a2 == 1:
1148
+ # good2 = True
1149
+ # a, b = -1, -1
1150
+ # if good1 and not good2:
1151
+ # a, b = min(a2, b2), max(a2, b2)
1152
+ # if good2 and not good1:
1153
+ # a, b = min(a1, b1), max(a1, b1)
1154
+ # arr = [[[], v]]
1155
+ # d = -1
1156
+ # for i in range(len(v) - 1):
1157
+ # if v[i] > v[i + 1]:
1158
+ # d = i + 1
1159
+ # for i in range(d):
1160
+ # arr2 = []
1161
+
1162
+ # if i in [a1, b1, a2, b2]:
1163
+ # continue
1164
+ # i2 = 1
1165
+ # i2 += len([aa for aa in [a1, b1, a2, b2] if i > aa])
1166
+ # for vr, v2 in arr:
1167
+ # dpret = pull_out_var(i2, v2)
1168
+ # for v3r, v3 in dpret:
1169
+ # arr2 += [[[*vr, (v3r, i + 1)], v3]]
1170
+ # arr = arr2
1171
+ # val = 0
1172
+
1173
+ # if good1:
1174
+ # arr2 = []
1175
+ # for L in arr:
1176
+ # v3 = L[-1]
1177
+ # if v3[real_a1] < v3[real_b1]:
1178
+ # continue
1179
+ # v3 = v3.swap(real_a1, real_b1)
1180
+ # arr2 += [[L[0], v3]]
1181
+ # arr = arr2
1182
+ # if not good2:
1183
+ # for i in range(4):
1184
+ # arr2 = []
1185
+
1186
+ # if i in [real_a2, real_b2]:
1187
+ # continue
1188
+ # if i == real_a1:
1189
+ # var_index = min(a1, b1) + 1
1190
+ # elif i == real_b1:
1191
+ # var_index = max(a1, b1) + 1
1192
+ # i2 = 1
1193
+ # i2 += len([aa for aa in [real_a2, real_b2] if i > aa])
1194
+ # for vr, v2 in arr:
1195
+ # dpret = pull_out_var(i2, v2)
1196
+ # for v3r, v3 in dpret:
1197
+ # arr2 += [[[*vr, (v3r, var_index)], v3]]
1198
+ # arr = arr2
1199
+ # if good2:
1200
+ # arr2 = []
1201
+ # for L in arr:
1202
+ # v3 = L[-1]
1203
+ # try:
1204
+ # if v3[real_a2] < v3[real_b2]:
1205
+ # continue
1206
+ # v3 = v3.swap(real_a2, real_b2)
1207
+ # except IndexError:
1208
+ # continue
1209
+ # arr2 += [[L[0], v3]]
1210
+ # arr = arr2
1211
+ # if not good1:
1212
+ # for i in range(4):
1213
+ # arr2 = []
1214
+
1215
+ # if i in [real_a1, real_b1]:
1216
+ # continue
1217
+ # i2 = 1
1218
+ # i2 += len([aa for aa in [real_a1, real_b1] if i > aa])
1219
+ # if i == real_a2:
1220
+ # var_index = min(a2, b2) + 1
1221
+ # elif i == real_b2:
1222
+ # var_index = max(a2, b2) + 1
1223
+ # for vr, v2 in arr:
1224
+ # dpret = pull_out_var(i2, v2)
1225
+ # for v3r, v3 in dpret:
1226
+ # arr2 += [[[*vr, (v3r, var_index)], v3]]
1227
+ # arr = arr2
1228
+
1229
+ # for L in arr:
1230
+ # v3 = L[-1]
1231
+ # tomul = 1
1232
+ # doschubpoly = True
1233
+ # if (not good1 or not good2) and v3[0] < v3[1] and (good1 or good2):
1234
+ # continue
1235
+ # if (good1 or good2) and (not good1 or not good2):
1236
+ # v3 = v3.swap(0, 1)
1237
+ # elif not good1 and not good2:
1238
+ # doschubpoly = False
1239
+ # if v3[0] < v3[1]:
1240
+ # dual_u = uncode([2, 0])
1241
+ # dual_w = Permutation([4, 2, 1, 3])
1242
+ # coeff = perm_act(dualcoeff(dual_u, v3, dual_w, var2, var3), 2, var2)
1243
+
1244
+ # elif len(v3) < 3 or v3[1] < v3[2]:
1245
+ # if len(v3) <= 3 or v3[2] < v3[3]:
1246
+ # coeff = 0
1247
+ # continue
1248
+ # v3 = v3.swap(0, 1).swap(2, 3)
1249
+ # coeff = perm_act(schubpoly(v3, var2, var3), 2, var2)
1250
+ # elif len(v3) <= 3 or v3[2] < v3[3]:
1251
+ # if len(v3) <= 3:
1252
+ # v3 += [4]
1253
+ # v3 = v3.swap(2, 3)
1254
+ # coeff = perm_act(
1255
+ # posify(
1256
+ # schubmult_one(Permutation([1, 3, 2]), v3, var2, var3).get(
1257
+ # Permutation([2, 4, 3, 1]),
1258
+ # 0,
1259
+ # ),
1260
+ # Permutation([1, 3, 2]),
1261
+ # v3,
1262
+ # Permutation([2, 4, 3, 1]),
1263
+ # var2,
1264
+ # var3,
1265
+ # msg,
1266
+ # do_pos_neg,
1267
+ # optimize=optimize,
1268
+ # ),
1269
+ # 2,
1270
+ # var2,
1271
+ # )
1272
+ # # logger.debug(f"{coeff=}")
1273
+ # else:
1274
+ # coeff = perm_act(
1275
+ # schubmult_one(Permutation([1, 3, 2]), v3, var2, var3).get(
1276
+ # Permutation([2, 4, 1, 3]),
1277
+ # 0,
1278
+ # ),
1279
+ # 2,
1280
+ # var2,
1281
+ # )
1282
+ # # logger.debug(f"{coeff=}")
1283
+ # # if expand(coeff) == 0:
1284
+ # # # logger.debug("coeff 0 oh no")
1285
+ # tomul = sympify(coeff)
1286
+ # toadd = 1
1287
+ # for i in range(len(L[0])):
1288
+ # var_index = L[0][i][1]
1289
+ # oaf = L[0][i][0]
1290
+ # if var_index - 1 >= len(w):
1291
+ # yv = var_index
1292
+ # else:
1293
+ # yv = w[var_index - 1]
1294
+ # for j in range(len(oaf)):
1295
+ # toadd *= var2[yv] - var3[oaf[j]]
1296
+ # if (not good1 or not good2) and (good1 or good2):
1297
+ # varo = [0, var2[w[a]], var2[w[b]]]
1298
+ # else:
1299
+ # varo = [0, *[var2[w[spo[k]]] for k in range(4)]]
1300
+ # if doschubpoly:
1301
+ # toadd *= schubpoly(v3, varo, var3)
1302
+ # else:
1303
+ # subs_dict3 = {var2[i]: varo[i] for i in range(len(varo))}
1304
+ # toadd *= efficient_subs(tomul, subs_dict3)
1305
+ # val += toadd
1306
+ # # logger.debug(f"accum {val=}")
1307
+ # #logger.debug(f"{expand(val-oldval)=}")
1308
+ # # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1309
+ # return val
1310
+ if will_formula_work(u, v):
1311
+ # logger.debug("Recording line number")
1160
1312
  if sign_only:
1161
1313
  return 0
1162
- cycles = split_two
1163
- a1, b1 = cycles[0]
1164
- a2, b2 = cycles[1]
1165
- a1 -= 1
1166
- b1 -= 1
1167
- a2 -= 1
1168
- b2 -= 1
1169
- spo = sorted([a1, b1, a2, b2])
1170
- real_a1 = min(spo.index(a1), spo.index(b1))
1171
- real_a2 = min(spo.index(a2), spo.index(b2))
1172
- real_b1 = max(spo.index(a1), spo.index(b1))
1173
- real_b2 = max(spo.index(a2), spo.index(b2))
1174
-
1175
- good1 = False
1176
- good2 = False
1177
- if real_b1 - real_a1 == 1:
1178
- good1 = True
1179
- if real_b2 - real_a2 == 1:
1180
- good2 = True
1181
- a, b = -1, -1
1182
- if good1 and not good2:
1183
- a, b = min(a2, b2), max(a2, b2)
1184
- if good2 and not good1:
1185
- a, b = min(a1, b1), max(a1, b1)
1186
- arr = [[[], v]]
1187
- d = -1
1188
- for i in range(len(v) - 1):
1189
- if v[i] > v[i + 1]:
1190
- d = i + 1
1191
- for i in range(d):
1192
- arr2 = []
1193
-
1194
- if i in [a1, b1, a2, b2]:
1195
- continue
1196
- i2 = 1
1197
- i2 += len([aa for aa in [a1, b1, a2, b2] if i > aa])
1198
- for vr, v2 in arr:
1199
- dpret = pull_out_var(i2, [*v2])
1200
- for v3r, v3 in dpret:
1201
- arr2 += [[[*vr, (v3r, i + 1)], v3]]
1202
- arr = arr2
1203
- val = 0
1204
-
1205
- if good1:
1206
- arr2 = []
1207
- for L in arr:
1208
- v3 = [*L[-1]]
1209
- if v3[real_a1] < v3[real_b1]:
1210
- continue
1211
- v3[real_a1], v3[real_b1] = v3[real_b1], v3[real_a1]
1212
- arr2 += [[L[0], v3]]
1213
- arr = arr2
1214
- if not good2:
1215
- for i in range(4):
1216
- arr2 = []
1217
-
1218
- if i in [real_a2, real_b2]:
1219
- continue
1220
- if i == real_a1:
1221
- var_index = min(a1, b1) + 1
1222
- elif i == real_b1:
1223
- var_index = max(a1, b1) + 1
1224
- i2 = 1
1225
- i2 += len([aa for aa in [real_a2, real_b2] if i > aa])
1226
- for vr, v2 in arr:
1227
- dpret = pull_out_var(i2, [*v2])
1228
- for v3r, v3 in dpret:
1229
- arr2 += [[[*vr, (v3r, var_index)], v3]]
1230
- arr = arr2
1231
- if good2:
1232
- arr2 = []
1233
- for L in arr:
1234
- v3 = [*L[-1]]
1235
- try:
1236
- if v3[real_a2] < v3[real_b2]:
1237
- continue
1238
- v3[real_a2], v3[real_b2] = v3[real_b2], v3[real_a2]
1239
- except IndexError:
1240
- continue
1241
- arr2 += [[L[0], v3]]
1242
- arr = arr2
1243
- if not good1:
1244
- for i in range(4):
1245
- arr2 = []
1246
-
1247
- if i in [real_a1, real_b1]:
1248
- continue
1249
- i2 = 1
1250
- i2 += len([aa for aa in [real_a1, real_b1] if i > aa])
1251
- if i == real_a2:
1252
- var_index = min(a2, b2) + 1
1253
- elif i == real_b2:
1254
- var_index = max(a2, b2) + 1
1255
- for vr, v2 in arr:
1256
- dpret = pull_out_var(i2, [*v2])
1257
- for v3r, v3 in dpret:
1258
- arr2 += [[[*vr, (v3r, var_index)], v3]]
1259
- arr = arr2
1260
-
1261
- for L in arr:
1262
- v3 = [*L[-1]]
1263
- tomul = 1
1264
- doschubpoly = True
1265
- if (not good1 or not good2) and v3[0] < v3[1] and (good1 or good2):
1266
- continue
1267
- if (good1 or good2) and (not good1 or not good2):
1268
- v3[0], v3[1] = v3[1], v3[0]
1269
- elif not good1 and not good2:
1270
- doschubpoly = False
1271
- if v3[0] < v3[1]:
1272
- dual_u = uncode([2, 0])
1273
- dual_w = [4, 2, 1, 3]
1274
- coeff = permy(dualcoeff(dual_u, v3, dual_w, var2, var3), 2)
1275
-
1276
- elif len(v3) < 3 or v3[1] < v3[2]:
1277
- if len(v3) <= 3 or v3[2] < v3[3]:
1278
- coeff = 0
1279
- continue
1280
- v3[0], v3[1] = v3[1], v3[0]
1281
- v3[2], v3[3] = v3[3], v3[2]
1282
- coeff = permy(schubpoly(v3, var2, var3), 2)
1283
- elif len(v3) <= 3 or v3[2] < v3[3]:
1284
- if len(v3) <= 3:
1285
- v3 += [4]
1286
- v3[2], v3[3] = v3[3], v3[2]
1287
- coeff = permy(
1288
- posify(
1289
- schubmult_one((1, 3, 2), tuple(permtrim([*v3])), var2, var3).get(
1290
- (2, 4, 3, 1),
1291
- 0,
1292
- ),
1293
- (1, 3, 2),
1294
- tuple(permtrim([*v3])),
1295
- (2, 4, 3, 1),
1296
- var2,
1297
- var3,
1298
- msg,
1299
- do_pos_neg,
1300
- ),
1301
- 2,
1302
- )
1303
- else:
1304
- coeff = permy(
1305
- schubmult_one((1, 3, 2), tuple(permtrim([*v3])), var2, var3).get(
1306
- (2, 4, 1, 3),
1307
- 0,
1308
- ),
1309
- 2,
1310
- )
1311
- tomul = sympify(coeff)
1312
- toadd = 1
1313
- for i in range(len(L[0])):
1314
- var_index = L[0][i][1]
1315
- oaf = L[0][i][0]
1316
- if var_index - 1 >= len(w):
1317
- yv = var_index
1318
- else:
1319
- yv = w[var_index - 1]
1320
- for j in range(len(oaf)):
1321
- toadd *= var2[yv] - var3[oaf[j]]
1322
- if (not good1 or not good2) and (good1 or good2):
1323
- varo = [0, var2[w[a]], var2[w[b]]]
1324
- else:
1325
- varo = [0, *[var2[w[spo[k]]] for k in range(4)]]
1326
- if doschubpoly:
1327
- toadd *= schubpoly(v3, varo, var3)
1328
- else:
1329
- subs_dict3 = {var2[i]: varo[i] for i in range(len(varo))}
1330
- toadd *= tomul.subs(subs_dict3)
1331
- val += toadd
1332
- elif will_formula_work(u, v):
1314
+ # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1315
+ return forwardcoeff(u, v, w, var2, var3)
1316
+ # if expand(val - oldval) != 0:
1317
+ # # logger.debug("This is bad")
1318
+ # # logger.debug(f"{u2=} {v2=} {w2=} {val=} {oldval=}")
1319
+ # logger.debug("Recording line number")
1320
+ # c01 = code(u)
1321
+ # c02 = code(w)
1322
+ # c03 = code(v)
1323
+
1324
+ c1 = code(~u)
1325
+ c2 = code(~w)
1326
+
1327
+ if one_dominates(u, w):
1333
1328
  if sign_only:
1334
1329
  return 0
1335
- val = forwardcoeff(u, v, w, var2, var3)
1336
- else:
1337
- c01 = code(u)
1338
- c02 = code(w)
1339
- c03 = code(v)
1340
-
1341
- c1 = code(inverse(u))
1342
- c2 = code(inverse(w))
1343
-
1344
- if one_dominates(u, w):
1345
- if sign_only:
1346
- return 0
1347
- while c1[0] != c2[0]:
1348
- w = [*w]
1349
- v = [*v]
1350
- w[c2[0] - 1], w[c2[0]] = w[c2[0]], w[c2[0] - 1]
1351
- v[c2[0] - 1], v[c2[0]] = v[c2[0]], v[c2[0] - 1]
1352
- w = tuple(w)
1353
- v = tuple(v)
1354
- c2 = code(inverse(w))
1355
- c03 = code(v)
1356
- c01 = code(u)
1357
- c02 = code(w)
1358
-
1359
- if is_reducible(v):
1360
- if sign_only:
1361
- return 0
1362
- newc = []
1363
- elemc = []
1364
- for i in range(len(c03)):
1365
- if c03[i] > 0:
1366
- newc += [c03[i] - 1]
1367
- elemc += [1]
1368
- else:
1369
- break
1370
- v3 = uncode(newc)
1371
- coeff_dict = schubmult_one(
1372
- tuple(permtrim([*u])),
1373
- tuple(permtrim(uncode(elemc))),
1374
- var2,
1375
- var3,
1376
- )
1377
- val = 0
1378
- for new_w in coeff_dict:
1379
- tomul = coeff_dict[new_w]
1380
- newval = schubmult_one(new_w, tuple(permtrim(uncode(newc))), var2, var3).get(
1381
- tuple(permtrim([*w])),
1382
- 0,
1383
- )
1384
- newval = posify(
1385
- newval,
1386
- new_w,
1387
- tuple(permtrim(uncode(newc))),
1388
- w,
1389
- var2,
1390
- var3,
1391
- msg,
1392
- do_pos_neg,
1393
- )
1394
- val += tomul * shiftsubz(newval)
1395
- elif c01[0] == c02[0] and c01[0] != 0:
1396
- if sign_only:
1397
- return 0
1398
- varl = c01[0]
1399
- u3 = uncode([0] + c01[1:])
1400
- w3 = uncode([0] + c02[1:])
1401
- val = 0
1402
- val = schubmult_one(tuple(permtrim(u3)), tuple(permtrim([*v])), var2, var3).get(
1403
- tuple(permtrim(w3)),
1404
- 0,
1405
- )
1406
- val = posify(
1407
- val,
1408
- tuple(permtrim(u3)),
1409
- tuple(permtrim([*v])),
1410
- tuple(permtrim(w3)),
1411
- var2,
1412
- var3,
1413
- msg,
1414
- do_pos_neg,
1415
- )
1416
- for i in range(varl):
1417
- val = permy(val, i + 1)
1418
- elif c1[0] == c2[0]:
1330
+ while c1[0] != c2[0]:
1331
+ w = w.swap(c2[0] - 1, c2[0])
1332
+ v = v.swap(c2[0] - 1, c2[0])
1333
+ # w[c2[0] - 1], w[c2[0]] = w[c2[0]], w[c2[0] - 1]
1334
+ # v[c2[0] - 1], v[c2[0]] = v[c2[0]], v[c2[0] - 1]
1335
+ # w = tuple(w)
1336
+ # v = tuple(v)
1337
+ c2 = code(~w)
1338
+ # c03 = code(v)
1339
+ # c01 = code(u)
1340
+ # c02 = code(w)
1341
+ # if is_reducible(v):
1342
+ # # logger.debug("Recording line number")
1343
+ # if sign_only:
1344
+ # return 0
1345
+ # newc = []
1346
+ # elemc = []
1347
+ # for i in range(len(c03)):
1348
+ # if c03[i] > 0:
1349
+ # newc += [c03[i] - 1]
1350
+ # elemc += [1]
1351
+ # else:
1352
+ # break
1353
+ # v3 = uncode(newc)
1354
+ # coeff_dict = schubmult_one(
1355
+ # u,
1356
+ # uncode(elemc),
1357
+ # var2,
1358
+ # var3,
1359
+ # )
1360
+ # val = 0
1361
+ # for new_w in coeff_dict:
1362
+ # tomul = coeff_dict[new_w]
1363
+ # newval = schubmult_one(new_w, uncode(newc), var2, var3).get(
1364
+ # w,
1365
+ # 0,
1366
+ # )
1367
+ # # logger.debug(f"Calling posify on {newval=} {new_w=} {uncode(newc)=} {w=}")
1368
+ # newval = posify(newval, new_w, uncode(newc), w, var2, var3, msg, do_pos_neg, optimize=optimize)
1369
+ # val += tomul * shiftsubz(newval)
1370
+ # # if expand(val - oldval) != 0:
1371
+ # # # logger.debug("This is bad")
1372
+ # # # logger.debug(f"{u2=} {v2=} {w2=} {val=} {oldval=}")
1373
+ # # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1374
+ # return val
1375
+ # removed, iffy (hard to implement)
1376
+ # if c01[0] == c02[0] and c01[0] != 0:
1377
+ # # logger.debug("Recording line number")
1378
+ # if sign_only:
1379
+ # return 0
1380
+ # varl = c01[0]
1381
+ # u3 = uncode([0] + c01[1:])
1382
+ # w3 = uncode([0] + c02[1:])
1383
+ # val = 0
1384
+ # val = schubmult_one(u3, v, var2, var3).get(
1385
+ # w3,
1386
+ # 0,
1387
+ # )
1388
+ # # logger.debug(f"Calling posify on {val=} {u3=} {v=} {w3=}")
1389
+ # val = posify(val, u3, v, w3, var2, var3, msg, do_pos_neg, optimize=optimize)
1390
+ # for i in range(varl):
1391
+ # val = perm_act(val, i + 1, var2)
1392
+ # # if expand(val - oldval) != 0:
1393
+ # # # logger.debug("This is bad")
1394
+ # # # logger.debug(f"{u2=} {v2=} {w2=} {val=} {oldval=}")
1395
+ # # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1396
+ # return val
1397
+ if c1[0] == c2[0]:
1398
+ # logger.debug("Recording line number")
1419
1399
  if sign_only:
1420
1400
  return 0
1421
- vp = pull_out_var(c1[0] + 1, [*v])
1422
- u3 = tuple(permtrim(phi1(u)))
1423
- w3 = tuple(permtrim(phi1(w)))
1401
+ vp = pull_out_var(c1[0] + 1, v)
1402
+ u3 = phi1(u)
1403
+ w3 = phi1(w)
1424
1404
  val = 0
1425
1405
  for arr, v3 in vp:
1426
1406
  tomul = 1
1427
1407
  for i in range(len(arr)):
1428
1408
  tomul *= var2[1] - var3[arr[i]]
1429
1409
 
1430
- val2 = schubmult_one(tuple(permtrim(u3)), tuple(permtrim(v3)), var2, var3).get(
1431
- tuple(permtrim(w3)),
1410
+ val2 = schubmult_double_pair(u3, v3, var2, var3).get(
1411
+ w3,
1432
1412
  0,
1433
1413
  )
1434
- val2 = posify(val2, u3, tuple(permtrim(v3)), w3, var2, var3, msg, do_pos_neg)
1414
+ val2 = posify(val2, u3, v3, w3, var2, var3, msg, do_pos_neg, optimize=optimize)
1435
1415
  val += tomul * shiftsub(val2)
1436
- elif not sign_only:
1416
+ # if expand(val - oldval) != 0:
1417
+ # # logger.debug("This is bad")
1418
+ # # logger.debug(f"{u2=} {v2=} {w2=} {val=} {oldval=")
1419
+ # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1420
+ return val
1421
+ # logger.debug("Fell all the way through. Cleverness did not save us")
1422
+ if not sign_only:
1423
+ # logger.debug("Recording line number")
1424
+ if optimize:
1437
1425
  if inv(u) + inv(v) - inv(w) == 1:
1438
1426
  val2 = compute_positive_rep(val, var2, var3, msg, False)
1439
1427
  else:
1440
1428
  val2 = compute_positive_rep(val, var2, var3, msg, do_pos_neg)
1441
1429
  if val2 is not None:
1442
1430
  val = val2
1443
- else:
1444
- d = expand(val).as_coefficients_dict()
1445
- for v in d.values():
1446
- if v < 0:
1447
- return -1
1448
- return 1
1449
- return val
1450
-
1451
-
1452
- def split_perms(perms):
1453
- perms2 = [perms[0]]
1454
- for perm in perms[1:]:
1455
- cd = code(perm)
1456
- index = -1
1457
- not_zero = False
1458
- did = False
1459
- for i in range(len(cd)):
1460
- if cd[i] != 0:
1461
- not_zero = True
1462
- elif not_zero and cd[i] == 0:
1463
- not_zero = False
1464
- index = i
1465
- num_zeros_to_miss = 0
1466
- for j in range(index):
1467
- if cd[j] != 0:
1468
- num_zeros_to_miss = max(num_zeros_to_miss, cd[j] - (index - 1 - j))
1469
- num_zeros = 0
1470
- for j in range(index, len(cd)):
1471
- if cd[j] != 0:
1472
- break
1473
- num_zeros += 1
1474
- if num_zeros >= num_zeros_to_miss:
1475
- cd1 = cd[:index]
1476
- cd2 = [0 for i in range(index)] + cd[index:]
1477
- perms2 += [
1478
- tuple(permtrim(uncode(cd1))),
1479
- tuple(permtrim(uncode(cd2))),
1480
- ]
1481
- did = True
1482
- break
1483
- if not did:
1484
- perms2 += [perm]
1485
- return perms2
1486
-
1487
-
1488
- def schubpoly(v, var2=None, var3=None, start_var=1):
1489
- n = 0
1490
- for j in range(len(v) - 2, -1, -1):
1491
- if v[j] > v[j + 1]:
1492
- n = j + 1
1493
- break
1494
- if n == 0:
1495
- return 1
1496
- lst = pull_out_var(n, v)
1497
- ret = 0
1498
- for pw, vp in lst:
1499
- tomul = 1
1500
- for p in pw:
1501
- tomul *= var2[start_var + n - 1] - var3[p]
1502
- ret += tomul * schubpoly(vp, var2, var3, start_var)
1503
- return ret
1504
-
1505
-
1506
- def permy(val, i, var2=_vars.var2):
1507
- subsdict = {var2[i]: var2[i + 1], var2[i + 1]: var2[i]}
1508
- return sympify(val).subs(subsdict)
1509
-
1510
-
1511
- def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1431
+ return val
1432
+ # logger.debug("RETURNINGOLDVAL")
1433
+ return oldval
1434
+ # logger.debug("Recording line number")
1435
+ d = expand(val).as_coefficients_dict()
1436
+ for v in d.values():
1437
+ if v < 0:
1438
+ return -1
1439
+ return 1
1440
+
1441
+ # if expand(val - oldval) !=0:
1442
+ # # logger.debug("NONONOONOO")
1443
+ # raise Exception
1444
+ # return val
1445
+
1446
+
1447
+ def schub_coprod_double(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1512
1448
  indices = sorted(indices)
1513
1449
  subs_dict_coprod = {}
1514
1450
  k = len(indices)
@@ -1517,9 +1453,9 @@ def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1517
1453
  max_required = max([kcd[i] + i for i in range(len(kcd))])
1518
1454
  kcd2 = kcd + [0 for i in range(len(kcd), max_required)] + [0]
1519
1455
  N = len(kcd)
1520
- kperm = permtrim(inverse(uncode(kcd2)))
1456
+ kperm = ~uncode(kcd2)
1521
1457
  inv_kperm = inv(kperm)
1522
- vn = symarray("soible", 100)
1458
+ vn = GeneratingSet("soible")
1523
1459
 
1524
1460
  for i in range(1, N * 2 + 1):
1525
1461
  if i <= N:
@@ -1527,14 +1463,14 @@ def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1527
1463
  else:
1528
1464
  subs_dict_coprod[vn[i]] = var3[i - N]
1529
1465
 
1530
- coeff_dict = {tuple(kperm): 1}
1531
- coeff_dict = schubmult(coeff_dict, mperm, vn, var2)
1466
+ coeff_dict = {kperm: 1}
1467
+ coeff_dict = schubmult_double(coeff_dict, mperm, vn, var2)
1532
1468
 
1533
- inverse_kperm = inverse(kperm)
1469
+ inverse_kperm = ~kperm
1534
1470
 
1535
1471
  ret_dict = {}
1536
1472
  for perm in coeff_dict:
1537
- downperm = mulperm(list(perm), inverse_kperm)
1473
+ downperm = perm * inverse_kperm
1538
1474
  if inv(downperm) == inv(perm) - inv_kperm:
1539
1475
  flag = True
1540
1476
  for i in range(N):
@@ -1543,12 +1479,12 @@ def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1543
1479
  break
1544
1480
  if not flag:
1545
1481
  continue
1546
- firstperm = downperm[0:N]
1547
- secondperm = [downperm[i] - N for i in range(N, len(downperm))]
1482
+ firstperm = Permutation(downperm[0:N])
1483
+ secondperm = Permutation([downperm[i] - N for i in range(N, len(downperm))])
1548
1484
 
1549
- val = sympify(coeff_dict[perm]).subs(subs_dict_coprod)
1485
+ val = efficient_subs(sympify(coeff_dict[perm]), subs_dict_coprod)
1550
1486
 
1551
- key = (tuple(permtrim(firstperm)), tuple(permtrim(secondperm)))
1487
+ key = (firstperm, secondperm)
1552
1488
  ret_dict[key] = val
1553
1489
 
1554
1490
  return ret_dict