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,51 +1,49 @@
1
1
  from bisect import bisect_left
2
- from functools import cache
2
+ from functools import cache, cached_property
3
+
4
+ import numpy as np
5
+ import psutil
6
+ import pulp as pu
7
+ import sympy
3
8
  from cachetools import cached
4
9
  from cachetools.keys import hashkey
5
- from symengine import sympify, Add, Mul, Pow, expand, Integer, symarray
10
+ from sortedcontainers import SortedList
11
+ from symengine import Add, Integer, Mul, Pow, sympify
12
+
6
13
  from schubmult.perm_lib import (
7
- elem_sym_perms,
8
- elem_sym_poly,
9
- add_perm_dict,
14
+ Permutation,
15
+ code,
16
+ cycle,
10
17
  dominates,
11
- compute_vpathdicts,
12
- inverse,
13
- theta,
14
- permtrim,
15
18
  inv,
16
- mulperm,
17
- code,
19
+ one_dominates,
20
+ phi1,
21
+ theta,
18
22
  uncode,
19
- elem_sym_func,
20
- elem_sym_perms_op,
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,
21
29
  divdiffable,
30
+ elem_sym_perms,
31
+ elem_sym_perms_op,
32
+ is_coeff_irreducible,
33
+ is_split_two,
22
34
  pull_out_var,
23
- cycle,
24
- will_formula_work,
25
- one_dominates,
26
- is_reducible,
27
35
  reduce_coeff,
28
36
  reduce_descents,
29
37
  try_reduce_u,
30
38
  try_reduce_v,
31
- phi1,
32
- zero,
39
+ will_formula_work,
33
40
  )
34
- import numpy as np
35
- import pulp as pu
36
- import sympy
37
- import psutil
38
- from sortedcontainers import SortedList
39
- from functools import cached_property
41
+ from schubmult.utils.logging import get_logger
42
+ from schubmult.utils.perm_utils import add_perm_dict
40
43
 
41
- # NO GLOBAL VARS
42
- # from ._vars import (
43
- # n,
44
- # var2,
45
- # var3,
46
- # _vars.var1,
47
- # var_y,
48
- # )
44
+ zero = sympify(0)
45
+
46
+ logger = get_logger(__name__)
49
47
 
50
48
 
51
49
  class _gvars:
@@ -59,19 +57,28 @@ class _gvars:
59
57
 
60
58
  @cached_property
61
59
  def var1(self):
62
- return tuple(symarray("x", self.n).tolist())
60
+ return GeneratingSet("x")
63
61
 
64
62
  @cached_property
65
63
  def var2(self):
66
- return tuple(symarray("y", self.n).tolist())
64
+ return GeneratingSet("y")
67
65
 
68
66
  @cached_property
69
67
  def var3(self):
70
- return tuple(symarray("z", self.n).tolist())
68
+ return GeneratingSet("z")
71
69
 
72
70
  @cached_property
73
71
  def var_r(self):
74
- 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
+
75
82
 
76
83
 
77
84
  _vars = _gvars()
@@ -86,8 +93,8 @@ def count_sorted(mn, tp):
86
93
  return ct
87
94
 
88
95
 
89
- def E(p, k, varl=_vars.var2[1:]):
90
- 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)
91
98
 
92
99
 
93
100
  def single_variable(coeff_dict, varnum, var2=None):
@@ -130,72 +137,82 @@ def single_variable_down(coeff_dict, varnum, var2=_vars.var2):
130
137
  return ret
131
138
 
132
139
 
133
- def mult_poly(coeff_dict, poly, var_x=_vars.var1, var_y=_vars.var2):
134
- 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:
135
151
  return single_variable(coeff_dict, var_x.index(poly), var_y)
136
- elif isinstance(poly, Mul):
152
+ if isinstance(poly, Mul):
137
153
  ret = coeff_dict
138
154
  for a in poly.args:
139
- ret = mult_poly(ret, a, var_x, var_y)
155
+ ret = mult_poly_double(ret, a, var_x, var_y)
140
156
  return ret
141
- elif isinstance(poly, Pow):
157
+ if isinstance(poly, Pow):
142
158
  base = poly.args[0]
143
159
  exponent = int(poly.args[1])
144
160
  ret = coeff_dict
145
161
  for i in range(int(exponent)):
146
- ret = mult_poly(ret, base, var_x, var_y)
162
+ ret = mult_poly_double(ret, base, var_x, var_y)
147
163
  return ret
148
- elif isinstance(poly, Add):
164
+ if isinstance(poly, Add):
149
165
  ret = {}
150
166
  for a in poly.args:
151
- ret = add_perm_dict(ret, mult_poly(coeff_dict, a, var_x, var_y))
152
- return ret
153
- else:
154
- ret = {}
155
- for perm in coeff_dict:
156
- ret[perm] = poly * coeff_dict[perm]
167
+ ret = add_perm_dict(ret, mult_poly_double(coeff_dict, a, var_x, var_y))
157
168
  return ret
169
+ ret = {}
170
+ for perm in coeff_dict:
171
+ ret[perm] = poly * coeff_dict[perm]
172
+ return ret
173
+
174
+
175
+ # def mult_poly_symy(coeff_dict, poly, var_x=_vars.sympy_var1, var_y=_vars.sympy_var2):
158
176
 
159
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))
163
- elif isinstance(poly, Mul):
181
+ if isinstance(poly, Mul):
164
182
  ret = coeff_dict
165
183
  for a in poly.args:
166
184
  ret = mult_poly_down(ret, a)
167
185
  return ret
168
- elif isinstance(poly, Pow):
186
+ if isinstance(poly, Pow):
169
187
  base = poly.args[0]
170
188
  exponent = int(poly.args[1])
171
189
  ret = coeff_dict
172
190
  for i in range(int(exponent)):
173
191
  ret = mult_poly_down(ret, base)
174
192
  return ret
175
- elif isinstance(poly, Add):
193
+ if isinstance(poly, Add):
176
194
  ret = {}
177
195
  for a in poly.args:
178
196
  ret = add_perm_dict(ret, mult_poly_down(coeff_dict, a))
179
197
  return ret
180
- else:
181
- ret = {}
182
- for perm in coeff_dict:
183
- ret[perm] = poly * coeff_dict[perm]
184
- return ret
198
+ ret = {}
199
+ for perm in coeff_dict:
200
+ ret[perm] = poly * coeff_dict[perm]
201
+ return ret
185
202
 
186
203
 
187
204
  def nilhecke_mult(coeff_dict1, coeff_dict2):
188
205
  ret = {}
189
206
  for w in coeff_dict2:
190
- w1 = [*w]
207
+ w1 = w
191
208
  inv_w1 = inv(w1)
192
209
  poly = coeff_dict2[w]
193
210
  did_mul = mult_poly_down(coeff_dict1, poly)
194
211
  for v in did_mul:
195
212
  v1 = [*v]
196
- addperm = mulperm(v1, w1)
213
+ addperm = v1 * w1
197
214
  if inv(addperm) == inv(v1) + inv_w1:
198
- toadd = tuple(permtrim(addperm))
215
+ toadd = addperm
199
216
  ret[toadd] = ret.get(toadd, 0) + did_mul[v]
200
217
  return ret
201
218
 
@@ -203,48 +220,63 @@ def nilhecke_mult(coeff_dict1, coeff_dict2):
203
220
  def forwardcoeff(u, v, perm, var2=None, var3=None):
204
221
  th = theta(v)
205
222
  muv = uncode(th)
206
- vmun1 = mulperm(inverse([*v]), muv)
223
+ vmun1 = (~v) * muv
207
224
 
208
- w = mulperm([*perm], vmun1)
225
+ w = perm * vmun1
209
226
  if inv(w) == inv(vmun1) + inv(perm):
210
- coeff_dict = schubmult_one(tuple(permtrim([*u])), tuple(muv), var2, var3)
211
- 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)
212
230
  return 0
213
231
 
214
232
 
215
233
  def dualcoeff(u, v, perm, var2=None, var3=None):
216
- if u == (1, 2):
217
- vp = mulperm([*v], inverse(perm))
234
+ if inv(u) == 0:
235
+ # logger.debug("Recording line number")
236
+ vp = v * (~perm)
218
237
  if inv(vp) == inv(v) - inv(perm):
219
- val = schubpoly(vp, var2, var3)
220
- else:
221
- val = 0
238
+ return schubpoly(vp, var2, var3)
239
+ dpret = []
240
+ ret = 0
241
+ if dominates(u, perm):
242
+ dpret = dualpieri(u, v, perm)
222
243
  else:
244
+ # logger.debug("Recording line number")
223
245
  dpret = []
224
- if dominates(u, perm):
225
- dpret = dualpieri([*u], [*v], [*perm])
226
- else:
227
- th = theta(u)
228
- muu = uncode(th)
229
- umun1 = mulperm(inverse([*u]), muu)
230
- w = mulperm([*perm], umun1)
231
- if inv(w) == inv(umun1) + inv(perm):
232
- dpret = dualpieri(muu, [*v], w)
233
- ret = 0
234
- for vlist, vp in dpret:
235
- toadd = 1
236
- for i in range(len(vlist)):
237
- for j in range(len(vlist[i])):
238
- toadd *= var2[i + 1] - var3[vlist[i][j]]
239
- toadd *= schubpoly(vp, var2, var3, len(vlist) + 1)
240
- ret += toadd
241
- val = ret
242
- 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=}")
243
274
 
244
275
 
245
276
  def dualpieri(mu, v, w):
246
- lm = code(inverse(mu))
247
- cn1w = code(inverse(w))
277
+ # logger.debug(f"dualpieri {mu=} {v=} {w=}")
278
+ lm = code(~mu)
279
+ cn1w = code(~w)
248
280
  while len(lm) > 0 and lm[-1] == 0:
249
281
  lm.pop()
250
282
  while len(cn1w) > 0 and cn1w[-1] == 0:
@@ -254,33 +286,38 @@ def dualpieri(mu, v, w):
254
286
  for i in range(len(lm)):
255
287
  if lm[i] > cn1w[i]:
256
288
  return []
257
- c = [1, 2]
289
+ c = Permutation([1, 2])
258
290
  for i in range(len(lm), len(cn1w)):
259
- c = mulperm(cycle(i - len(lm) + 1, cn1w[i]), c)
260
- c = permtrim(c)
291
+ c = cycle(i - len(lm) + 1, cn1w[i]) * c
292
+ # c = permtrim(c)
293
+ # logger.debug("Recording line number")
261
294
  res = [[[], v]]
295
+ # logger.debug(f"{v=} {type(v)=}")
262
296
  for i in range(len(lm)):
297
+ # logger.debug(f"{res=}")
263
298
  res2 = []
264
299
  for vlist, vplist in res:
265
300
  vp = vplist
266
301
  vpl = divdiffable(vp, cycle(lm[i] + 1, cn1w[i] - lm[i]))
267
- if vpl == []:
302
+ # logger.debug(f"{vpl=} {type(vpl)=}")
303
+ if len(vpl) == 0:
268
304
  continue
269
305
  vl = pull_out_var(lm[i] + 1, vpl)
306
+ # logger.debug(f"{vl=}")
270
307
  for pw, vpl2 in vl:
271
- res2 += [[vlist + [pw], vpl2]]
308
+ res2 += [[[*vlist, pw], vpl2]]
272
309
  res = res2
273
310
  if len(lm) == len(cn1w):
274
311
  return res
275
- else:
276
- res2 = []
277
- for vlist, vplist in res:
278
- vp = vplist
279
- vpl = divdiffable(vp, c)
280
- if vpl == []:
281
- continue
282
- res2 += [[vlist, vpl]]
283
- return res2
312
+ res2 = []
313
+ for vlist, vplist in res:
314
+ vp = vplist
315
+ vpl = divdiffable(vp, c)
316
+ if len(vpl) == 0:
317
+ continue
318
+ res2 += [[vlist, vpl]]
319
+ # logger.debug(f"{res2=}")
320
+ return res2
284
321
 
285
322
 
286
323
  dimen = 0
@@ -288,19 +325,30 @@ monom_to_vec = {}
288
325
 
289
326
 
290
327
  @cache
291
- def schubmult_one(perm1, perm2, var2=None, var3=None):
292
- 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)
293
330
 
294
331
 
295
- def schubmult(perm_dict, v, var2=None, var3=None):
296
- 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
297
345
  th = theta(vn1)
298
346
  if len(th) == 0:
299
347
  return perm_dict
300
348
  if th[0] == 0:
301
349
  return perm_dict
302
- mu = permtrim(uncode(th))
303
- vmu = permtrim(mulperm([*v], mu))
350
+ mu = uncode(th)
351
+ vmu = v * mu
304
352
  inv_vmu = inv(vmu)
305
353
  inv_mu = inv(mu)
306
354
  ret_dict = {}
@@ -310,18 +358,19 @@ def schubmult(perm_dict, v, var2=None, var3=None):
310
358
  vpathdicts = compute_vpathdicts(th, vmu, True)
311
359
  for u, val in perm_dict.items():
312
360
  inv_u = inv(u)
313
- vpathsums = {u: {(1, 2): val}}
361
+ vpathsums = {u: {Permutation([1, 2]): val}}
314
362
  for index in range(thL):
315
363
  mx_th = 0
316
364
  for vp in vpathdicts[index]:
317
365
  for v2, vdiff, s in vpathdicts[index][vp]:
318
- if th[index] - vdiff > mx_th:
319
- mx_th = th[index] - vdiff
366
+ mx_th = max(mx_th, th[index] - vdiff)
320
367
  newpathsums = {}
321
368
  for up in vpathsums:
322
369
  inv_up = inv(up)
323
370
  newperms = elem_sym_perms(
324
- up, min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu), th[index]
371
+ up,
372
+ min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu),
373
+ th[index],
325
374
  )
326
375
  for up2, udiff in newperms:
327
376
  if up2 not in newpathsums:
@@ -332,7 +381,8 @@ def schubmult(perm_dict, v, var2=None, var3=None):
332
381
  continue
333
382
  for v2, vdiff, s in vpathdicts[index][v]:
334
383
  newpathsums[up2][v2] = newpathsums[up2].get(
335
- v2, zero
384
+ v2,
385
+ zero,
336
386
  ) + s * sumval * elem_sym_func(
337
387
  th[index],
338
388
  index + 1,
@@ -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,13 +415,12 @@ 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]:
372
422
  for v2, vdiff, s in vpathdicts[index][vp]:
373
- if th[index] - vdiff > mx_th:
374
- mx_th = th[index] - vdiff
423
+ mx_th = max(mx_th, th[index] - vdiff)
375
424
  newpathsums = {}
376
425
  for up in vpathsums:
377
426
  newperms = elem_sym_perms_op(up, mx_th, th[index])
@@ -384,7 +433,8 @@ def schubmult_down(perm_dict, v, var2=None, var3=None):
384
433
  continue
385
434
  for v2, vdiff, s in vpathdicts[index][v]:
386
435
  newpathsums[up2][v2] = newpathsums[up2].get(
387
- v2, zero
436
+ v2,
437
+ zero,
388
438
  ) + s * sumval * elem_sym_func(
389
439
  th[index],
390
440
  index + 1,
@@ -398,14 +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
- global dimen, monom_to_vec, base_vec
408
- poly = expand(poly.xreplace({var3[1]: 0}))
457
+ poly = expand(sympify(poly).xreplace({var3[1]: 0}))
409
458
 
410
459
  dc = poly.as_coefficients_dict()
411
460
 
@@ -428,18 +477,18 @@ def poly_to_vec(poly, vec0=None, var3=_vars.var3):
428
477
  return vec
429
478
 
430
479
 
431
- def shiftsub(pol, var2=_vars.var2, var3=_vars.var3):
432
- subs_dict = dict([(var2[i], var2[i + 1]) for i in range(99)])
433
- return sympify(pol).subs(subs_dict)
480
+ def shiftsub(pol, var2=_vars.var2):
481
+ subs_dict = {var2[i]: var2[i + 1] for i in range(99)}
482
+ return efficient_subs(sympify(pol), subs_dict)
434
483
 
435
484
 
436
- def shiftsubz(pol, var2=_vars.var2, var3=_vars.var3):
437
- subs_dict = dict([(var3[i], var3[i + 1]) for i in range(99)])
438
- return sympify(pol).subs(subs_dict)
485
+ def shiftsubz(pol, var3=_vars.var3):
486
+ subs_dict = {var3[i]: var3[i + 1] for i in range(99)}
487
+ return efficient_subs(sympify(pol), subs_dict)
439
488
 
440
489
 
441
490
  def init_basevec(dc):
442
- global dimen, monom_to_vec, base_vec
491
+ global dimen, monom_to_vec, base_vec # noqa: PLW0603
443
492
  monom_to_vec = {}
444
493
  index = 0
445
494
  for mn in dc:
@@ -462,12 +511,11 @@ def split_flat_term(arg):
462
511
  ys += [arg2.args[1]]
463
512
  else:
464
513
  ys += [arg2]
514
+ elif isinstance(arg2, Mul):
515
+ for i in range(abs(int(arg2.args[0]))):
516
+ zs += [-arg2.args[1]]
465
517
  else:
466
- if isinstance(arg2, Mul):
467
- for i in range(abs(int(arg2.args[0]))):
468
- zs += [-arg2.args[1]]
469
- else:
470
- zs += [arg2]
518
+ zs += [arg2]
471
519
  return ys, zs
472
520
 
473
521
 
@@ -481,11 +529,11 @@ def is_flat_term(term):
481
529
  return True
482
530
 
483
531
 
484
- def flatten_factors(term, var2=_vars.var2, var3=_vars.var3):
532
+ def flatten_factors(term):
485
533
  found_one = False
486
534
  if is_flat_term(term):
487
535
  return term, False
488
- elif isinstance(term, Pow):
536
+ if isinstance(term, Pow):
489
537
  if is_flat_term(term.args[0]) and len(term.args[0].args) > 2:
490
538
  ys, zs = split_flat_term(term.args[0])
491
539
  terms = [1]
@@ -496,11 +544,10 @@ def flatten_factors(term, var2=_vars.var2, var3=_vars.var3):
496
544
  terms2 += [t * (ys[i] + zs[i])]
497
545
  terms = terms2
498
546
  return Add(*terms)
499
- elif is_flat_term(term.args[0]):
547
+ if is_flat_term(term.args[0]):
500
548
  return term, False
501
- else:
502
- return flatten_factors(term.args[0]) ** term.args[1], True
503
- elif isinstance(term, Mul):
549
+ return flatten_factors(term.args[0]) ** term.args[1], True
550
+ if isinstance(term, Mul):
504
551
  terms = [1]
505
552
  for arg in term.args:
506
553
  terms2 = []
@@ -528,7 +575,7 @@ def flatten_factors(term, var2=_vars.var2, var3=_vars.var3):
528
575
  else:
529
576
  term = Add(*terms)
530
577
  return term, found_one
531
- elif isinstance(term, Add):
578
+ if isinstance(term, Add):
532
579
  res = 0
533
580
  for arg in term.args:
534
581
  flat, found = flatten_factors(arg)
@@ -536,11 +583,13 @@ def flatten_factors(term, var2=_vars.var2, var3=_vars.var3):
536
583
  found_one = True
537
584
  res += flat
538
585
  return res, found_one
586
+ return None
539
587
 
540
588
 
541
589
  def fres(v):
542
590
  for s in v.free_symbols:
543
591
  return s
592
+ return None
544
593
 
545
594
 
546
595
  def split_mul(arg0, var2=None, var3=None):
@@ -614,7 +663,7 @@ def is_negative(term):
614
663
  sign = 1
615
664
  if isinstance(term, Integer) or isinstance(term, int):
616
665
  return term < 0
617
- elif isinstance(term, Mul):
666
+ if isinstance(term, Mul):
618
667
  for arg in term.args:
619
668
  if isinstance(arg, Integer):
620
669
  sign *= arg
@@ -625,49 +674,32 @@ def is_negative(term):
625
674
  mulsign = 1
626
675
  if str(arg.args[0]).find("-y") != -1:
627
676
  mulsign = -1
628
- sign *= mulsign ** term.args[1]
677
+ sign *= mulsign**term.index
629
678
  elif isinstance(term, Pow):
630
679
  mulsign = 1
631
680
  if str(term.args[0]).find("-y") != -1:
632
681
  mulsign = -1
633
- sign *= mulsign ** term.args[1]
682
+ sign *= mulsign**term.index
634
683
  return sign < 0
635
684
 
636
685
 
637
- def find_base_vectors(monom_list, monom_list_neg, var2, var3, depth):
686
+ def find_base_vectors(monom_list, var2, var3, depth):
638
687
  size = 0
639
688
  mn_fullcount = {}
640
689
  # pairs_checked = set()
641
- monom_list = set([tuple(mn) for mn in monom_list])
690
+ monom_list = {tuple(mn) for mn in monom_list}
642
691
  ct = 0
643
692
  while ct < depth and size != len(monom_list):
644
693
  size = len(monom_list)
645
- # found = False
646
- # for mn in mons2:
647
- # if mn not in monom_list:
648
- # found = True
649
- # break
650
- # if not found:
651
- # print("Breaking")
652
- # break
653
-
654
694
  monom_list2 = set(monom_list)
655
695
  additional_set2 = set()
656
696
  for mn in monom_list:
657
- # res = 1
658
- # for tp in mn:
659
- # res *= var2[tp[0]] - var3[tp[1]]
660
- # if poly_to_vec(res,vec) is None:
661
- # continue
662
-
663
697
  mncount = mn_fullcount.get(mn, {})
664
698
  if mncount == {}:
665
699
  for tp in mn:
666
700
  mncount[tp] = mncount.get(tp, 0) + 1
667
701
  mn_fullcount[mn] = mncount
668
702
  for mn2 in monom_list:
669
- # if (mn,mn2) in pairs_checked:
670
- # continue
671
703
  mn2count = mn_fullcount.get(mn2, {})
672
704
  if mn2count == {}:
673
705
  for tp in mn2:
@@ -692,8 +724,7 @@ def find_base_vectors(monom_list, monom_list_neg, var2, var3, depth):
692
724
  break
693
725
  # print(f"{mn,mn2}")
694
726
  if diff_term1 is None or diff_term2 is None:
695
- print(f"{mn=} {mn2=}")
696
- exit(1)
727
+ raise Exception(f"{mn=} {mn2=}")
697
728
  if diff_term2[1] == diff_term1[1]:
698
729
  continue
699
730
  new_term1 = (diff_term1[0], diff_term2[1])
@@ -708,19 +739,9 @@ def find_base_vectors(monom_list, monom_list_neg, var2, var3, depth):
708
739
  mn4 = list(mn2[:index2]) + list(mn2[index2 + 1 :])
709
740
  index2 = bisect_left(mn4, new_term2)
710
741
  mn4_t = tuple(mn4[:index2] + [new_term2] + mn4[index2:])
711
- # res = 1
712
- # for tp in mn3_t:
713
- # res *= var2[tp[0]] - var3[tp[1]]
714
- # if poly_to_vec(res,vec) is not None:
715
742
  if mn3_t not in monom_list2:
716
743
  additional_set2.add(mn3_t)
717
744
  monom_list2.add(mn3_t)
718
- # res = 1
719
- # for tp in mn4_t:
720
- # res *= var2[tp[0]] - var3[tp[1]]
721
- ##
722
- ## additional_set2.add(mn3_t)
723
- # if poly_to_vec(res,vec) is not None:
724
745
  if mn4_t not in monom_list2:
725
746
  additional_set2.add(mn4_t)
726
747
  monom_list2.add(mn4_t)
@@ -737,41 +758,34 @@ def find_base_vectors(monom_list, monom_list_neg, var2, var3, depth):
737
758
  return ret, monom_list
738
759
 
739
760
 
740
- 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
741
763
  notint = False
742
764
  try:
743
- int(expand(val))
744
- val2 = expand(val)
765
+ val2 = int(expand(val))
766
+ # val2 = expand(val)
745
767
  except Exception:
746
768
  notint = True
747
769
  if notint:
748
770
  frees = val.free_symbols
749
- var2list = [*var2]
750
- var3list = [*var3]
751
-
752
- for i in range(len(var2list)):
753
- symset = var2list[i].free_symbols
754
- for sym in symset:
755
- var2list[i] = sym
756
-
757
- for i in range(len(var3list)):
758
- symset = var3list[i].free_symbols
759
- for sym in symset:
760
- var3list[i] = sym
761
-
762
- varsimp2 = [m for m in frees if m in var2list]
763
- varsimp3 = [m for m in frees if m in var3list]
764
- varsimp2.sort(key=lambda k: var2list.index(k))
765
- varsimp3.sort(key=lambda k: var3list.index(k))
766
-
767
- var22 = [sympy.sympify(m) for m in varsimp2]
768
- 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]
769
783
  n1 = len(varsimp2)
770
784
 
771
- for i in range(len(varsimp2)):
772
- varsimp2[i] = var2[var2list.index(varsimp2[i])]
773
- for i in range(len(varsimp3)):
774
- 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])]
775
789
 
776
790
  base_vectors = []
777
791
  base_monoms = []
@@ -798,9 +812,9 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
798
812
  depth = 1
799
813
 
800
814
  mons = split_monoms(pos_part, varsimp2, varsimp3)
801
- mons = set([tuple(mn) for mn in mons])
815
+ mons = {tuple(mn) for mn in mons}
802
816
  mons2 = split_monoms(neg_part, varsimp2, varsimp3)
803
- mons2 = set([tuple(mn2) for mn2 in mons2])
817
+ mons2 = {tuple(mn2) for mn2 in mons2}
804
818
 
805
819
  # mons2 = split_monoms(neg_part)
806
820
  # for mn in mons2:
@@ -827,12 +841,9 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
827
841
  for j in range(len(bad_vectors) - 1, -1, -1):
828
842
  base_monoms.pop(bad_vectors[j])
829
843
 
830
- vrs = [
831
- pu.LpVariable(name=f"a{i}", lowBound=0, cat="Integer")
832
- for i in range(len(base_vectors))
833
- ]
844
+ vrs = [pu.LpVariable(name=f"a{i}", lowBound=0, cat="Integer") for i in range(len(base_vectors))]
834
845
  lp_prob = pu.LpProblem("Problem", pu.LpMinimize)
835
- lp_prob += int(0)
846
+ lp_prob += 0
836
847
  eqs = [*base_vec]
837
848
  for j in range(len(base_vectors)):
838
849
  for i in base_vectors[j]:
@@ -862,38 +873,37 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
862
873
  raise KeyboardInterrupt()
863
874
  status = lp_prob.status
864
875
  else:
876
+ # logger.debug("this")
865
877
  val_poly = sympy.poly(expand(val), *var22, *var33)
866
878
  vec = poly_to_vec(val)
867
879
  mn = val_poly.monoms()
868
880
  L1 = tuple([0 for i in range(n1)])
869
881
  mn1L = []
870
882
  lookup = {}
883
+ # logger.debug("this")
871
884
  for mm0 in mn:
872
885
  key = mm0[n1:]
873
886
  if key not in lookup:
874
887
  lookup[key] = []
875
888
  mm0n1 = mm0[:n1]
876
889
  st = set(mm0n1)
877
- if len(st.intersection(set([0, 1]))) == len(st) and 1 in st:
890
+ if len(st.intersection({0, 1})) == len(st) and 1 in st:
878
891
  lookup[key] += [mm0]
879
892
  if mm0n1 == L1:
880
893
  mn1L += [mm0]
894
+ # logger.debug("this")
881
895
  for mn1 in mn1L:
882
896
  comblistmn1 = [1]
883
897
  for i in range(n1, len(mn1)):
884
898
  if mn1[i] != 0:
885
899
  arr = np.array(comblistmn1)
886
900
  comblistmn12 = []
887
- mn1_2 = tuple([*mn1[n1:i]] + [0] + [*mn1[i + 1 :]])
901
+ mn1_2 = (*mn1[n1:i], 0, *mn1[i + 1 :])
888
902
  for mm0 in lookup[mn1_2]:
889
903
  comblistmn12 += (
890
904
  arr
891
905
  * np.prod(
892
- [
893
- varsimp2[k] - varsimp3[i - n1]
894
- for k in range(n1)
895
- if mm0[k] == 1
896
- ]
906
+ [varsimp2[k] - varsimp3[i - n1] for k in range(n1) if mm0[k] == 1],
897
907
  )
898
908
  ).tolist()
899
909
  comblistmn1 = comblistmn12
@@ -903,12 +913,9 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
903
913
  if vec0 is not None:
904
914
  base_vectors += [vec0]
905
915
  base_monoms += [b1]
906
- vrs = [
907
- pu.LpVariable(name=f"a{i}", lowBound=0, cat="Integer")
908
- for i in range(len(base_vectors))
909
- ]
916
+ vrs = [pu.LpVariable(name=f"a{i}", lowBound=0, cat="Integer") for i in range(len(base_vectors))]
910
917
  lp_prob = pu.LpProblem("Problem", pu.LpMinimize)
911
- lp_prob += int(0)
918
+ lp_prob += 0
912
919
  eqs = [*base_vec]
913
920
  for j in range(len(base_vectors)):
914
921
  for i in base_vectors[j]:
@@ -919,7 +926,9 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
919
926
  eqs[i] += bvi * vrs[j]
920
927
  for i in range(dimen):
921
928
  lp_prob += eqs[i] == vec[i]
929
+ # logger.debug("I IS SOLVING")
922
930
  try:
931
+ # logger.debug("I IS SOLVING BOLVING")
923
932
  solver = pu.PULP_CBC_CMD(msg=msg)
924
933
  status = lp_prob.solve(solver)
925
934
  except KeyboardInterrupt:
@@ -944,145 +953,74 @@ def compute_positive_rep(val, var2=None, var3=None, msg=False, do_pos_neg=True):
944
953
  b1 = base_monoms[k]
945
954
  if x != 0 and x is not None:
946
955
  val2 += int(x) * b1
956
+ # logger.debug(f"{val2=}")
947
957
  return val2
948
958
 
949
959
 
950
- def is_split_two(u, v, w):
951
- if inv(w) - inv(u) != 2:
952
- return False, []
953
- diff_perm = mulperm(inverse([*u]), [*w])
954
- identity = [i + 1 for i in range(len(diff_perm))]
955
- cycles = []
956
- for i in range(len(identity)):
957
- if diff_perm[i] != identity[i]:
958
- cycle0 = set()
959
- cycle = set([i + 1])
960
- last = i
961
- while len(cycle0) != len(cycle):
962
- cycle0 = cycle
963
- last = diff_perm[last] - 1
964
- cycle.add(last + 1)
965
- if len(cycle) > 1 and cycle not in cycles:
966
- cycles += [cycle]
967
- if len(cycles) > 2:
968
- break
969
- if len(cycles) == 2:
970
- return True, cycles
971
- else:
972
- return False, []
973
-
974
-
975
- def is_coeff_irreducible(u, v, w):
976
- return (
977
- not will_formula_work(u, v)
978
- and not will_formula_work(v, u)
979
- and not one_dominates(u, w)
980
- and not is_reducible(v)
981
- and inv(w) - inv(u) > 1
982
- and not is_split_two(u, v, w)[0]
983
- and len([i for i in code(v) if i != 0]) > 1
984
- )
985
-
986
-
987
- def is_hook(cd):
988
- started = False
989
- done = False
990
- found_zero_after = False
991
- for i in range(len(cd)):
992
- if (done or found_zero_after) and cd[i] != 0:
993
- return False
994
- if cd[i] == 1 and not started:
995
- started = True
996
- if cd[i] > 1:
997
- done = True
998
- if started and cd[i] == 0:
999
- found_zero_after = True
1000
- if started or done:
1001
- return True
1002
- return False
1003
-
1004
-
1005
- def div_diff(i, poly, var2=_vars.var2):
1006
- return sympify(
1007
- sympy.div(sympy.sympify(poly - permy(poly, i)), sympy.sympify(var2[i] - var2[i + 1]))[0]
1008
- )
1009
-
1010
-
1011
- def skew_div_diff(u, w, poly):
1012
- d = -1
1013
- for i in range(len(w) - 1):
1014
- if w[i] > w[i + 1]:
1015
- d = i
1016
- break
1017
- d2 = -1
1018
- for i in range(len(u) - 1):
1019
- if u[i] > u[i + 1]:
1020
- d2 = i
1021
- break
1022
- if d == -1:
1023
- if d2 == -1:
1024
- return poly
1025
- return 0
1026
- w2 = [*w]
1027
- w2[d], w2[d + 1] = w2[d + 1], w2[d]
1028
- if d < len(u) - 1 and u[d] > u[d + 1]:
1029
- u2 = [*u]
1030
- u2[d], u2[d + 1] = u2[d + 1], u2[d]
1031
- return skew_div_diff(u2, w2, permy(poly, d + 1))
1032
- else:
1033
- 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()}
1034
973
 
1035
974
 
1036
975
  @cached(
1037
976
  cache={},
1038
- key=lambda val,
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),
978
+ )
979
+ def posify(
980
+ val,
1039
981
  u2,
1040
982
  v2,
1041
983
  w2,
1042
984
  var2=None,
1043
985
  var3=None,
1044
986
  msg=False,
1045
- do_pos_neg=True,
1046
- sign_only=False: hashkey(u2, v2, w2, var2, var3, msg, do_pos_neg, sign_only),
1047
- )
1048
- def posify(
1049
- val, u2, v2, w2, var2=None, var3=None, msg=False, do_pos_neg=True, sign_only=False, n=_vars.n
987
+ do_pos_neg=False,
988
+ sign_only=False,
989
+ optimize=True,
990
+ n=_vars.n,
1050
991
  ):
992
+ # logger.debug(f"NEW {val=} {u2=} {v2=} {w2=}")
993
+ oldval = val
1051
994
  if inv(u2) + inv(v2) - inv(w2) == 0:
995
+ # logger.debug(f"Hmm this is probably not or val inty true {val=}")
1052
996
  return val
1053
- cdv = code(v2)
1054
- if set(cdv) == set([0, 1]) and do_pos_neg:
1055
- return val
1056
- # if is_hook(cdv):
1057
- # print(f"Could've {cdv}")
997
+
1058
998
  if not sign_only and expand(val) == 0:
999
+ # logger.debug(f"Hmm this is probably not true {u2=} {v2=} {w2=} {val=}")
1059
1000
  return 0
1060
-
1061
- u, v, w = try_reduce_v(u2, v2, w2)
1062
- 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):
1063
1005
  u, v, w = try_reduce_u(u2, v2, w2)
1064
1006
  if is_coeff_irreducible(u, v, w):
1065
- u, v, w = [*u2], [*v2], [*w2]
1007
+ u, v, w = u2, v2, w2
1066
1008
  if is_coeff_irreducible(u, v, w):
1067
- w0 = [*w]
1009
+ w0 = w
1068
1010
  u, v, w = reduce_descents(u, v, w)
1069
1011
  if is_coeff_irreducible(u, v, w):
1070
1012
  u, v, w = reduce_coeff(u, v, w)
1071
1013
  if is_coeff_irreducible(u, v, w):
1072
- while is_coeff_irreducible(u, v, w) and tuple(permtrim(w0)) != tuple(
1073
- permtrim([*w])
1074
- ):
1014
+ while is_coeff_irreducible(u, v, w) and w0 != w:
1075
1015
  w0 = w
1076
1016
  u, v, w = reduce_descents(u, v, w)
1077
1017
  if is_coeff_irreducible(u, v, w):
1078
1018
  u, v, w = reduce_coeff(u, v, w)
1079
- u = tuple(u)
1080
- v = tuple(v)
1081
- w = tuple(w)
1082
1019
 
1083
1020
  if w != w2 and sign_only:
1021
+ # logger.debug(f"Return 0 ")
1084
1022
  return 0
1085
-
1023
+ # logger.debug(f"Reduced to {u2=} {v2=} {w2=} {val=}")
1086
1024
  if is_coeff_irreducible(u, v, w):
1087
1025
  u3, v3, w3 = try_reduce_v(u, v, w)
1088
1026
  if not is_coeff_irreducible(u3, v3, w3):
@@ -1092,8 +1030,9 @@ def posify(
1092
1030
  if not is_coeff_irreducible(u3, v3, w3):
1093
1031
  u, v, w = u3, v3, w3
1094
1032
  split_two_b, split_two = is_split_two(u, v, w)
1095
-
1033
+ # logger.debug("Recording line number")
1096
1034
  if len([i for i in code(v) if i != 0]) == 1:
1035
+ # logger.debug("Recording line number")
1097
1036
  if sign_only:
1098
1037
  return 0
1099
1038
  cv = code(v)
@@ -1106,32 +1045,35 @@ def posify(
1106
1045
  r = inv(w) - inv_u
1107
1046
  val = 0
1108
1047
  w2 = w
1109
- hvarset = (
1110
- [w2[i] for i in range(min(len(w2), k))]
1111
- + [i + 1 for i in range(len(w2), k)]
1112
- + [w2[b] for b in range(k, len(u)) if u[b] != w2[b]]
1113
- + [w2[b] for b in range(len(u), len(w2))]
1114
- )
1115
- val = elem_sym_poly(
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))]
1049
+ # logger.debug(f"Returning {u2=} {v2=} {w2=} {val=}")
1050
+ return elem_sym_poly(
1116
1051
  p - r,
1117
1052
  k + p - 1,
1118
1053
  [-var3[i] for i in range(1, n)],
1119
1054
  [-var2[i] for i in hvarset],
1120
1055
  )
1121
- 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")
1122
1061
  if sign_only:
1123
1062
  return 0
1124
- val = dualcoeff(u, v, w, var2, var3)
1125
- 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")
1126
1070
  if sign_only:
1127
1071
  return 0
1128
1072
  a, b = -1, -1
1129
1073
  for i in range(len(w)):
1130
1074
  if a == -1 and u[i] != w[i]:
1131
1075
  a = i
1132
- elif i >= len(u) and w[i] != i + 1:
1133
- b = i
1134
- elif b == -1 and u[i] != w[i]:
1076
+ elif (i >= len(u) and w[i] != i + 1) or (b == -1 and u[i] != w[i]):
1135
1077
  b = i
1136
1078
  arr = [[[], v]]
1137
1079
  d = -1
@@ -1148,17 +1090,16 @@ def posify(
1148
1090
  elif i > a:
1149
1091
  i2 += 1
1150
1092
  for vr, v2 in arr:
1151
- dpret = pull_out_var(i2, [*v2])
1093
+ dpret = pull_out_var(i2, v2)
1152
1094
  for v3r, v3 in dpret:
1153
- arr2 += [[vr + [v3r], v3]]
1095
+ arr2 += [[[*vr, v3r], v3]]
1154
1096
  arr = arr2
1155
1097
  val = 0
1156
1098
  for L in arr:
1157
- v3 = [*L[-1]]
1099
+ v3 = L[-1]
1158
1100
  if v3[0] < v3[1]:
1159
1101
  continue
1160
- else:
1161
- v3[0], v3[1] = v3[1], v3[0]
1102
+ v3 = v3.swap(0, 1)
1162
1103
  toadd = 1
1163
1104
  for i in range(d):
1164
1105
  if i in [a, b]:
@@ -1177,454 +1118,333 @@ def posify(
1177
1118
  toadd *= var2[yv] - var3[oaf[j]]
1178
1119
  toadd *= schubpoly(v3, [0, var2[w[a]], var2[w[b]]], var3)
1179
1120
  val += toadd
1180
- 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")
1181
1312
  if sign_only:
1182
1313
  return 0
1183
- cycles = split_two
1184
- a1, b1 = cycles[0]
1185
- a2, b2 = cycles[1]
1186
- a1 -= 1
1187
- b1 -= 1
1188
- a2 -= 1
1189
- b2 -= 1
1190
- spo = sorted([a1, b1, a2, b2])
1191
- real_a1 = min(spo.index(a1), spo.index(b1))
1192
- real_a2 = min(spo.index(a2), spo.index(b2))
1193
- real_b1 = max(spo.index(a1), spo.index(b1))
1194
- real_b2 = max(spo.index(a2), spo.index(b2))
1195
-
1196
- good1 = False
1197
- good2 = False
1198
- if real_b1 - real_a1 == 1:
1199
- good1 = True
1200
- if real_b2 - real_a2 == 1:
1201
- good2 = True
1202
- a, b = -1, -1
1203
- if good1 and not good2:
1204
- a, b = min(a2, b2), max(a2, b2)
1205
- if good2 and not good1:
1206
- a, b = min(a1, b1), max(a1, b1)
1207
- arr = [[[], v]]
1208
- d = -1
1209
- for i in range(len(v) - 1):
1210
- if v[i] > v[i + 1]:
1211
- d = i + 1
1212
- for i in range(d):
1213
- arr2 = []
1214
-
1215
- if i in [a1, b1, a2, b2]:
1216
- continue
1217
- i2 = 1
1218
- i2 += len([aa for aa in [a1, b1, a2, b2] if i > aa])
1219
- for vr, v2 in arr:
1220
- dpret = pull_out_var(i2, [*v2])
1221
- for v3r, v3 in dpret:
1222
- arr2 += [[vr + [(v3r, i + 1)], v3]]
1223
- arr = arr2
1224
- val = 0
1225
-
1226
- if good1:
1227
- arr2 = []
1228
- for L in arr:
1229
- v3 = [*L[-1]]
1230
- if v3[real_a1] < v3[real_b1]:
1231
- continue
1232
- else:
1233
- v3[real_a1], v3[real_b1] = v3[real_b1], v3[real_a1]
1234
- arr2 += [[L[0], v3]]
1235
- arr = arr2
1236
- if not good2:
1237
- for i in range(4):
1238
- arr2 = []
1239
-
1240
- if i in [real_a2, real_b2]:
1241
- continue
1242
- if i == real_a1:
1243
- var_index = min(a1, b1) + 1
1244
- elif i == real_b1:
1245
- var_index = max(a1, b1) + 1
1246
- i2 = 1
1247
- i2 += len([aa for aa in [real_a2, real_b2] if i > aa])
1248
- for vr, v2 in arr:
1249
- dpret = pull_out_var(i2, [*v2])
1250
- for v3r, v3 in dpret:
1251
- arr2 += [[vr + [(v3r, var_index)], v3]]
1252
- arr = arr2
1253
- if good2:
1254
- arr2 = []
1255
- for L in arr:
1256
- v3 = [*L[-1]]
1257
- try:
1258
- if v3[real_a2] < v3[real_b2]:
1259
- continue
1260
- else:
1261
- v3[real_a2], v3[real_b2] = v3[real_b2], v3[real_a2]
1262
- except IndexError:
1263
- continue
1264
- arr2 += [[L[0], v3]]
1265
- arr = arr2
1266
- if not good1:
1267
- for i in range(4):
1268
- arr2 = []
1269
-
1270
- if i in [real_a1, real_b1]:
1271
- continue
1272
- i2 = 1
1273
- i2 += len([aa for aa in [real_a1, real_b1] if i > aa])
1274
- if i == real_a2:
1275
- var_index = min(a2, b2) + 1
1276
- elif i == real_b2:
1277
- var_index = max(a2, b2) + 1
1278
- for vr, v2 in arr:
1279
- dpret = pull_out_var(i2, [*v2])
1280
- for v3r, v3 in dpret:
1281
- arr2 += [[vr + [(v3r, var_index)], v3]]
1282
- arr = arr2
1283
-
1284
- for L in arr:
1285
- v3 = [*L[-1]]
1286
- tomul = 1
1287
- doschubpoly = True
1288
- if (not good1 or not good2) and v3[0] < v3[1] and (good1 or good2):
1289
- continue
1290
- elif (good1 or good2) and (not good1 or not good2):
1291
- v3[0], v3[1] = v3[1], v3[0]
1292
- elif not good1 and not good2:
1293
- doschubpoly = False
1294
- if v3[0] < v3[1]:
1295
- dual_u = uncode([2, 0])
1296
- dual_w = [4, 2, 1, 3]
1297
- coeff = permy(dualcoeff(dual_u, v3, dual_w, var2, var3), 2)
1298
-
1299
- elif len(v3) < 3 or v3[1] < v3[2]:
1300
- if len(v3) <= 3 or v3[2] < v3[3]:
1301
- coeff = 0
1302
- continue
1303
- else:
1304
- v3[0], v3[1] = v3[1], v3[0]
1305
- v3[2], v3[3] = v3[3], v3[2]
1306
- coeff = permy(schubpoly(v3, var2, var3), 2)
1307
- elif len(v3) <= 3 or v3[2] < v3[3]:
1308
- if len(v3) <= 3:
1309
- v3 += [4]
1310
- v3[2], v3[3] = v3[3], v3[2]
1311
- coeff = permy(
1312
- posify(
1313
- schubmult_one((1, 3, 2), tuple(permtrim([*v3])), var2, var3).get(
1314
- (2, 4, 3, 1), 0
1315
- ),
1316
- (1, 3, 2),
1317
- tuple(permtrim([*v3])),
1318
- (2, 4, 3, 1),
1319
- var2,
1320
- var3,
1321
- msg,
1322
- do_pos_neg,
1323
- ),
1324
- 2,
1325
- )
1326
- else:
1327
- coeff = permy(
1328
- schubmult_one((1, 3, 2), tuple(permtrim([*v3])), var2, var3).get(
1329
- (2, 4, 1, 3), 0
1330
- ),
1331
- 2,
1332
- )
1333
- tomul = sympify(coeff)
1334
- toadd = 1
1335
- for i in range(len(L[0])):
1336
- var_index = L[0][i][1]
1337
- oaf = L[0][i][0]
1338
- if var_index - 1 >= len(w):
1339
- yv = var_index
1340
- else:
1341
- yv = w[var_index - 1]
1342
- for j in range(len(oaf)):
1343
- toadd *= var2[yv] - var3[oaf[j]]
1344
- if (not good1 or not good2) and (good1 or good2):
1345
- varo = [0, var2[w[a]], var2[w[b]]]
1346
- else:
1347
- varo = [0, *[var2[w[spo[k]]] for k in range(4)]]
1348
- if doschubpoly:
1349
- toadd *= schubpoly(v3, varo, var3)
1350
- else:
1351
- subs_dict3 = {var2[i]: varo[i] for i in range(len(varo))}
1352
- toadd *= tomul.subs(subs_dict3)
1353
- val += toadd
1354
- 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):
1355
1328
  if sign_only:
1356
1329
  return 0
1357
- val = forwardcoeff(u, v, w, var2, var3)
1358
- # elif inv(w) - inv(u) == 2:
1359
- # indices = []
1360
- # for i in range(len(w)):
1361
- # if i>=len(u) or u[i]!=w[i]:
1362
- # indices += [i+1]
1363
- # arr = [[[],v]]
1364
- # d = -1
1365
- # for i in range(len(v)-1):
1366
- # if v[i]>v[i+1]:
1367
- # d = i + 1
1368
- # for i in range(d):
1369
- # arr2 = []
1370
- #
1371
- # if i+1 in indices:
1372
- # continue
1373
- # i2 = 1
1374
- # i2 += len([aa for aa in indices if i+1>aa])
1375
- # for vr, v2 in arr:
1376
- # dpret = pull_out_var(i2,[*v2])
1377
- # for v3r, v3 in dpret:
1378
- # arr2 += [[vr + [(v3r,i+1)],v3]]
1379
- # arr = arr2
1380
- # val = 0
1381
- #
1382
- # for L in arr:
1383
- # v3 = [*L[-1]]
1384
- # tomul = 1
1385
- # pooly = skew_div_diff(u,w,schubpoly(v3,[0,*[var2[a] for a in indices]],var3))
1386
- # coeff = compute_positive_rep(pooly,var2,var3,msg,False)
1387
- # if coeff == -1:
1388
- # return -1
1389
- # tomul = sympify(coeff)
1390
- # toadd = 1
1391
- # for i in range(len(L[0])):
1392
- # var_index = L[0][i][1]
1393
- # oaf = L[0][i][0]
1394
- # if var_index-1>=len(w):
1395
- # yv = var_index
1396
- # else:
1397
- # yv = w[var_index-1]
1398
- # for j in range(len(oaf)):
1399
- # toadd*= var2[yv] - var3[oaf[j]]
1400
- # toadd*=tomul#.subs(subs_dict3)
1401
- # val += toadd
1402
- else:
1403
- c01 = code(u)
1404
- c02 = code(w)
1405
- c03 = code(v)
1406
-
1407
- c1 = code(inverse(u))
1408
- c2 = code(inverse(w))
1409
-
1410
- if one_dominates(u, w):
1411
- if sign_only:
1412
- return 0
1413
- while c1[0] != c2[0]:
1414
- w = [*w]
1415
- v = [*v]
1416
- w[c2[0] - 1], w[c2[0]] = w[c2[0]], w[c2[0] - 1]
1417
- v[c2[0] - 1], v[c2[0]] = v[c2[0]], v[c2[0] - 1]
1418
- w = tuple(w)
1419
- v = tuple(v)
1420
- c2 = code(inverse(w))
1421
- c03 = code(v)
1422
- c01 = code(u)
1423
- c02 = code(w)
1424
-
1425
- if is_reducible(v):
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")
1426
1399
  if sign_only:
1427
1400
  return 0
1428
- newc = []
1429
- elemc = []
1430
- for i in range(len(c03)):
1431
- if c03[i] > 0:
1432
- newc += [c03[i] - 1]
1433
- elemc += [1]
1434
- else:
1435
- break
1436
- v3 = uncode(newc)
1437
- coeff_dict = schubmult_one(
1438
- tuple(permtrim([*u])), tuple(permtrim(uncode(elemc))), var2, var3
1439
- )
1440
- val = 0
1441
- for new_w in coeff_dict:
1442
- tomul = coeff_dict[new_w]
1443
- newval = schubmult_one(new_w, tuple(permtrim(uncode(newc))), var2, var3).get(
1444
- tuple(permtrim([*w])), 0
1445
- )
1446
- newval = posify(
1447
- newval,
1448
- new_w,
1449
- tuple(permtrim(uncode(newc))),
1450
- w,
1451
- var2,
1452
- var3,
1453
- msg,
1454
- do_pos_neg,
1455
- )
1456
- val += tomul * shiftsubz(newval)
1457
- elif c01[0] == c02[0] and c01[0] != 0:
1458
- if sign_only:
1459
- return 0
1460
- varl = c01[0]
1461
- u3 = uncode([0] + c01[1:])
1462
- w3 = uncode([0] + c02[1:])
1463
- val = 0
1464
- val = schubmult_one(tuple(permtrim(u3)), tuple(permtrim([*v])), var2, var3).get(
1465
- tuple(permtrim(w3)), 0
1466
- )
1467
- val = posify(
1468
- val,
1469
- tuple(permtrim(u3)),
1470
- tuple(permtrim([*v])),
1471
- tuple(permtrim(w3)),
1472
- var2,
1473
- var3,
1474
- msg,
1475
- do_pos_neg,
1476
- )
1477
- for i in range(varl):
1478
- val = permy(val, i + 1)
1479
- elif c1[0] == c2[0]:
1480
- if sign_only:
1481
- return 0
1482
- vp = pull_out_var(c1[0] + 1, [*v])
1483
- u3 = tuple(permtrim(phi1(u)))
1484
- w3 = tuple(permtrim(phi1(w)))
1401
+ vp = pull_out_var(c1[0] + 1, v)
1402
+ u3 = phi1(u)
1403
+ w3 = phi1(w)
1485
1404
  val = 0
1486
1405
  for arr, v3 in vp:
1487
1406
  tomul = 1
1488
1407
  for i in range(len(arr)):
1489
1408
  tomul *= var2[1] - var3[arr[i]]
1490
1409
 
1491
- val2 = schubmult_one(tuple(permtrim(u3)), tuple(permtrim(v3)), var2, var3).get(
1492
- tuple(permtrim(w3)), 0
1410
+ val2 = schubmult_double_pair(u3, v3, var2, var3).get(
1411
+ w3,
1412
+ 0,
1493
1413
  )
1494
- 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)
1495
1415
  val += tomul * shiftsub(val2)
1496
- # elif inv(w)-inv(u)==2 and len(trimcode(u)) == len(trimcode(w)):
1497
- # indices = []
1498
- # for i in range(len(w)):
1499
- # if i>=len(u) or u[i]!=w[i]:
1500
- # indices += [i+1]
1501
- # arr = [[[],v]]
1502
- # d = -1
1503
- # for i in range(len(v)-1):
1504
- # if v[i]>v[i+1]:
1505
- # d = i + 1
1506
- # for i in range(d):
1507
- # arr2 = []
1508
- #
1509
- # if i+1 in indices:
1510
- # continue
1511
- # i2 = 1
1512
- # i2 += len([aa for aa in indices if i+1>aa])
1513
- # for vr, v2 in arr:
1514
- # dpret = pull_out_var(i2,[*v2])
1515
- # for v3r, v3 in dpret:
1516
- # arr2 += [[vr + [(v3r,i+1)],v3]]
1517
- # arr = arr2
1518
- # val = 0
1519
- #
1520
- # for L in arr:
1521
- # v3 = [*L[-1]]
1522
- # tomul = 1
1523
- # toadd = 1
1524
- # for i in range(len(L[0])):
1525
- # var_index = L[0][i][1]
1526
- # oaf = L[0][i][0]
1527
- # if var_index-1>=len(w):
1528
- # yv = var_index
1529
- # else:
1530
- # yv = w[var_index-1]
1531
- # for j in range(len(oaf)):
1532
- # toadd*= var2[yv] - var3[oaf[j]]
1533
- # pooly = skew_div_diff(u,w,schubpoly(v3,[0,*[var2[a] for a in indices]],var3))
1534
- # if toadd == 0:
1535
- # continue
1536
- # if pooly !=0:
1537
- # coeff = compute_positive_rep(pooly,var2,var3,msg,False)
1538
- # else:
1539
- # coeff = 0
1540
- # if coeff == -1:
1541
- # return -1
1542
- # tomul = sympify(coeff)
1543
- # toadd*=tomul#.subs(subs_dict3)
1544
- # val += toadd
1545
- else:
1546
- if not sign_only:
1547
- if inv(u) + inv(v) - inv(w) == 1:
1548
- val2 = compute_positive_rep(val, var2, var3, msg, False)
1549
- else:
1550
- val2 = compute_positive_rep(val, var2, var3, msg, do_pos_neg)
1551
- if val2 is not None:
1552
- val = val2
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:
1425
+ if inv(u) + inv(v) - inv(w) == 1:
1426
+ val2 = compute_positive_rep(val, var2, var3, msg, False)
1553
1427
  else:
1554
- # st = str(expand(val))
1555
- # if st.find("-")!=-1:
1556
- # return -1
1557
- # else:
1558
- # return val
1559
- d = expand(val).as_coefficients_dict()
1560
- for v in d.values():
1561
- if v < 0:
1562
- return -1
1563
- return 1
1564
- return val
1565
-
1566
-
1567
- def split_perms(perms):
1568
- perms2 = [perms[0]]
1569
- for perm in perms[1:]:
1570
- cd = code(perm)
1571
- index = -1
1572
- not_zero = False
1573
- did = False
1574
- for i in range(len(cd)):
1575
- if cd[i] != 0:
1576
- not_zero = True
1577
- elif not_zero and cd[i] == 0:
1578
- not_zero = False
1579
- index = i
1580
- num_zeros_to_miss = 0
1581
- for j in range(index):
1582
- if cd[j] != 0:
1583
- num_zeros_to_miss = max(num_zeros_to_miss, cd[j] - (index - 1 - j))
1584
- num_zeros = 0
1585
- for j in range(index, len(cd)):
1586
- if cd[j] != 0:
1587
- break
1588
- else:
1589
- num_zeros += 1
1590
- if num_zeros >= num_zeros_to_miss:
1591
- cd1 = cd[:index]
1592
- cd2 = [0 for i in range(index)] + cd[index:]
1593
- perms2 += [
1594
- tuple(permtrim(uncode(cd1))),
1595
- tuple(permtrim(uncode(cd2))),
1596
- ]
1597
- did = True
1598
- break
1599
- if not did:
1600
- perms2 += [perm]
1601
- return perms2
1602
-
1603
-
1604
- def schubpoly(v, var2=None, var3=None, start_var=1):
1605
- n = 0
1606
- for j in range(len(v) - 2, -1, -1):
1607
- if v[j] > v[j + 1]:
1608
- n = j + 1
1609
- break
1610
- if n == 0:
1611
- return 1
1612
- lst = pull_out_var(n, v)
1613
- ret = 0
1614
- for pw, vp in lst:
1615
- tomul = 1
1616
- for p in pw:
1617
- tomul *= var2[start_var + n - 1] - var3[p]
1618
- ret += tomul * schubpoly(vp, var2, var3, start_var)
1619
- return ret
1620
-
1621
-
1622
- def permy(val, i, var2=_vars.var2):
1623
- subsdict = {var2[i]: var2[i + 1], var2[i + 1]: var2[i]}
1624
- return sympify(val).subs(subsdict)
1625
-
1626
-
1627
- def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1428
+ val2 = compute_positive_rep(val, var2, var3, msg, do_pos_neg)
1429
+ if val2 is not None:
1430
+ val = val2
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):
1628
1448
  indices = sorted(indices)
1629
1449
  subs_dict_coprod = {}
1630
1450
  k = len(indices)
@@ -1633,9 +1453,9 @@ def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1633
1453
  max_required = max([kcd[i] + i for i in range(len(kcd))])
1634
1454
  kcd2 = kcd + [0 for i in range(len(kcd), max_required)] + [0]
1635
1455
  N = len(kcd)
1636
- kperm = permtrim(inverse(uncode(kcd2)))
1456
+ kperm = ~uncode(kcd2)
1637
1457
  inv_kperm = inv(kperm)
1638
- vn = symarray("soible", 100)
1458
+ vn = GeneratingSet("soible")
1639
1459
 
1640
1460
  for i in range(1, N * 2 + 1):
1641
1461
  if i <= N:
@@ -1643,14 +1463,14 @@ def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1643
1463
  else:
1644
1464
  subs_dict_coprod[vn[i]] = var3[i - N]
1645
1465
 
1646
- coeff_dict = {tuple(kperm): 1}
1647
- coeff_dict = schubmult(coeff_dict, mperm, vn, var2)
1466
+ coeff_dict = {kperm: 1}
1467
+ coeff_dict = schubmult_double(coeff_dict, mperm, vn, var2)
1648
1468
 
1649
- inverse_kperm = inverse(kperm)
1469
+ inverse_kperm = ~kperm
1650
1470
 
1651
1471
  ret_dict = {}
1652
1472
  for perm in coeff_dict:
1653
- downperm = mulperm(list(perm), inverse_kperm)
1473
+ downperm = perm * inverse_kperm
1654
1474
  if inv(downperm) == inv(perm) - inv_kperm:
1655
1475
  flag = True
1656
1476
  for i in range(N):
@@ -1659,12 +1479,12 @@ def schub_coprod(mperm, indices, var2=_vars.var2, var3=_vars.var3):
1659
1479
  break
1660
1480
  if not flag:
1661
1481
  continue
1662
- firstperm = downperm[0:N]
1663
- 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))])
1664
1484
 
1665
- val = sympify(coeff_dict[perm]).subs(subs_dict_coprod)
1485
+ val = efficient_subs(sympify(coeff_dict[perm]), subs_dict_coprod)
1666
1486
 
1667
- key = (tuple(permtrim(firstperm)), tuple(permtrim(secondperm)))
1487
+ key = (firstperm, secondperm)
1668
1488
  ret_dict[key] = val
1669
1489
 
1670
1490
  return ret_dict