schubmult 1.2.1__tar.gz → 1.2.3__tar.gz

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 (24) hide show
  1. {schubmult-1.2.1 → schubmult-1.2.3}/PKG-INFO +1 -1
  2. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/perm_lib.py +32 -35
  3. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_yz/schubmult_yz.py +287 -83
  4. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult.egg-info/PKG-INFO +1 -1
  5. {schubmult-1.2.1 → schubmult-1.2.3}/setup.py +1 -1
  6. {schubmult-1.2.1 → schubmult-1.2.3}/LICENSE +0 -0
  7. {schubmult-1.2.1 → schubmult-1.2.3}/README.md +0 -0
  8. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/__init__.py +0 -0
  9. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_double/__init__.py +0 -0
  10. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_double/__main__.py +0 -0
  11. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_double/schubmult_double.py +0 -0
  12. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_py/__init__.py +0 -0
  13. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_py/__main__.py +0 -0
  14. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_py/schubmult_py.py +0 -0
  15. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_py/schubmult_py_bak.py +0 -0
  16. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_py/schubmult_py_parallel.py +0 -0
  17. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_yz/__init__.py +0 -0
  18. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult/schubmult_yz/__main__.py +0 -0
  19. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult.egg-info/SOURCES.txt +0 -0
  20. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult.egg-info/dependency_links.txt +0 -0
  21. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult.egg-info/entry_points.txt +0 -0
  22. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult.egg-info/requires.txt +0 -0
  23. {schubmult-1.2.1 → schubmult-1.2.3}/schubmult.egg-info/top_level.txt +0 -0
  24. {schubmult-1.2.1 → schubmult-1.2.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schubmult
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: Computing Littlewood-Richardson coefficients of Schubert polynomials
5
5
  Home-page: https://github.com/matthematics/schubmult
6
6
  Author: Matt Samuel
@@ -470,40 +470,6 @@ def try_reduce_u(u, v, w):
470
470
  return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
471
471
  return tuple(permtrim(u2)), tuple(permtrim(v2)), tuple(permtrim(w2))
472
472
 
473
- def pull_out_var(vnum,v):
474
- vn1 = inverse(v)
475
- th = theta(vn1)
476
- if th[0]==0:
477
- return [[[],v]]
478
- muvn1 = permtrim(uncode(th))
479
- lm = p_trans(th)
480
- if vnum>len(lm):
481
- return [[[],v]]
482
- lmpop = [*lm]
483
- k = lmpop.pop(vnum-1)
484
- inv_v = inv(v)
485
- vmuvn1 = mulperm(v,muvn1)
486
- muvn1in1 = permtrim(uncode(lmpop))
487
- ret_list = []
488
- vpm_list = [(vmuvn1,k)]
489
- for p in range(k+1):
490
- vpm_list2 = []
491
- for vpm, b in vpm_list:
492
- vp = permtrim(mulperm(vpm,muvn1in1))
493
-
494
- pos_list = [i for i in range(k) if ((i<len(vpm) and vmuvn1[i] == vpm[i]) or (i>=len(vpm) and vmuvn1[i] == i+1))]
495
- if inv(vp)==inv_v-k+p:
496
- ret_list += [[[vpm[i] for i in pos_list if i<len(vpm)]+[i+1 for i in pos_list if i>=len(vpm) and vmuvn1[i] == i+1],vp]]
497
- if len(vpm) < k + 1:
498
- continue
499
- for j in range(b,len(vpm)):
500
- for i in pos_list:
501
- if has_bruhat_descent(vpm,i,j):
502
- vpm[i],vpm[j] = vpm[j],vpm[i]
503
- vpm_list2+=[(permtrim([*vpm]),j)]
504
- vpm[i],vpm[j] = vpm[j],vpm[i]
505
- vpm_list = vpm_list2
506
- return ret_list
507
473
 
508
474
  def divdiffable(v,u):
509
475
  inv_v = inv(v)
@@ -527,4 +493,35 @@ def will_formula_work(u,v):
527
493
  vn1muv[i],vn1muv[i+1] = vn1muv[i+1],vn1muv[i]
528
494
  break
529
495
  if not found_one:
530
- return True
496
+ return True
497
+
498
+ def pull_out_var(vnum,v):
499
+ vup = v + [len(v)+1]
500
+ if vnum>=len(v):
501
+ return [[[],v]]
502
+ vpm_list = [(vup,0)]
503
+ ret_list = []
504
+ for p in range(len(v)+1-vnum):
505
+ vpm_list2 = []
506
+ for vpm, b in vpm_list:
507
+ if vpm[vnum-1]==len(v)+1:
508
+ vpm2 = [*vpm]
509
+ vpm2.pop(vnum-1)
510
+ vp = permtrim(vpm2)
511
+ ret_list += [[[v[i] for i in range(vnum,len(v)) if ((i>len(vp) and v[i]==i) or (i<=len(vp) and v[i]==vp[i-1]))],vp]]
512
+ for j in range(vnum,len(vup)):
513
+ if vpm[j]<=b:
514
+ continue
515
+ for i in range(vnum):
516
+ if has_bruhat_ascent(vpm,i,j):
517
+ vpm[i],vpm[j] = vpm[j],vpm[i]
518
+ vpm_list2+=[([*vpm],vpm[i])]
519
+ vpm[i],vpm[j] = vpm[j],vpm[i]
520
+ vpm_list = vpm_list2
521
+ for vpm, b in vpm_list:
522
+ if vpm[vnum-1]==len(v)+1:
523
+ vpm2 = [*vpm]
524
+ vpm2.pop(vnum-1)
525
+ vp = permtrim(vpm2)
526
+ ret_list += [[[v[i] for i in range(vnum,len(v)) if ((i>len(vp) and v[i]==i) or (i<=len(vp) and v[i]==vp[i-1]))],vp]]
527
+ return ret_list
@@ -7,14 +7,14 @@ import numpy as np
7
7
  import pulp as pu
8
8
  import itertools as it
9
9
  import sympy
10
- import re
11
-
10
+
12
11
  n = 100
13
12
 
14
13
  var = symarray('x',n)
15
14
  var2 = symarray('y',n)
16
15
  var3 = symarray('z',n)
17
16
 
17
+
18
18
  def forwardcoeff(u,v,perm,var2=var2,var3=var3):
19
19
  th = theta(v)
20
20
  muv = uncode(th)
@@ -155,26 +155,26 @@ def schubmult(perm_dict,v,var2=var2,var3=var3):
155
155
  ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
156
156
  return ret_dict
157
157
 
158
+ fvar = 0
159
+
158
160
  def poly_to_vec(poly,vec0=None):
159
161
  global dimen, monom_to_vec, n1, n2
160
- poly = expand(poly.subs({var3[1]: 0}))
162
+ poly = expand(poly.xreplace({var3[1]: 0}))
163
+
161
164
  dc = poly.as_coefficients_dict()
162
- mn = list(dc.keys())
163
-
164
165
 
165
166
  if vec0 is None:
166
167
  init_basevec(dc)
167
168
  vec = np.zeros(dimen)
168
169
 
169
- for i in range(len(mn)-1,-1,-1):
170
- cf = dc[mn[i]]
170
+ for mn in dc:
171
+ cf = dc[mn]
171
172
  if cf == 0:
172
173
  continue
173
- cf = abs(cf)
174
174
  try:
175
- index = monom_to_vec[mn[i]]
176
- except Exception:
177
- return None
175
+ index = monom_to_vec[mn]
176
+ except KeyError:
177
+ return None
178
178
  if vec0 is not None and abs(vec0[index])<abs(cf):
179
179
  return None
180
180
  vec[index] = cf
@@ -196,7 +196,7 @@ def init_basevec(dc):
196
196
  if dc[mn] == 0:
197
197
  continue
198
198
  monom_to_vec[mn] = index
199
- index+=1
199
+ index+=1
200
200
  dimen = index
201
201
 
202
202
 
@@ -362,70 +362,113 @@ def compute_positive_rep(val,var2=var2,var3=var3,msg=False):
362
362
  except Exception:
363
363
  notint = True
364
364
  if notint:
365
- sval = str(val)
366
- regex = re.compile("y_([0-9]+)")
367
- regex2 = re.compile("z_([0-9]+)")
368
- n1 = max([int(index) for index in regex.findall(sval)])+1
369
- n2 = max([int(index) for index in regex2.findall(sval)])+1
370
-
371
- var22 = sympy.symarray('y',n1)
372
- var33 = sympy.symarray('z',n2)
365
+ #smp = val.simplify()
366
+ #flat, found_one = flatten_factors(smp)
367
+ #while found_one:
368
+ # flat, found_one = flatten_factors(flat)
369
+ #flat = flat.simplify()
370
+ #while found_one:
371
+ # flat, found_one = flatten_factors(flat)
372
+ #pos_part = 0
373
+ #neg_part = 0
374
+ #if isinstance(flat,Add) and not is_flat_term(flat):
375
+ # for arg in flat.args:
376
+ # if not is_negative(arg):
377
+ # pos_part += arg
378
+ # else:
379
+ # neg_part -= arg
380
+ # if neg_part == 0:
381
+ # print("no neg")
382
+ # return pos_part
383
+
384
+ frees = val.free_symbols
385
+ var2list = var2.tolist()
386
+ var3list = var3.tolist()
387
+
388
+ for i in range(len(var2list)):
389
+ symset = var2list[i].free_symbols
390
+ for sym in symset:
391
+ var2list[i] = sym
392
+
393
+ for i in range(len(var3list)):
394
+ symset = var3list[i].free_symbols
395
+ for sym in symset:
396
+ var3list[i] = sym
397
+
398
+ varsimp2 = [m for m in frees if m in var2list]
399
+ varsimp3 = [m for m in frees if m in var3list]
400
+ varsimp2.sort(key=lambda k: var2list.index(k))
401
+ varsimp3.sort(key=lambda k: var3list.index(k))
402
+
403
+
404
+ #fvar = var2list.index(varsimp2[0])
405
+ var22 = [sympy.sympify(m) for m in varsimp2]
406
+ var33 = [sympy.sympify(m) for m in varsimp3]
407
+ n1 = len(varsimp2)
408
+ n2 = len(varsimp3)
409
+
410
+ for i in range(len(varsimp2)):
411
+ varsimp2[i] = var2[var2list.index(varsimp2[i])]
412
+ for i in range(len(varsimp3)):
413
+ varsimp3[i] = var3[var3list.index(varsimp3[i])]
373
414
 
374
- vec = poly_to_vec(val)
375
-
376
- base = []
377
415
  base_vectors = []
378
416
  base_monoms = []
379
417
 
380
- val_poly = sympy.poly(sval,*var22[1:],*var33[1:])
418
+ #t = time.time()
419
+ #val_poly = sympy.poly(val,*var22,*var33)
420
+ val_poly = sympy.poly(val,*var22,*var33)
421
+ #print(f"{time.time()-t} polytime")
422
+ #t = time.time()
423
+ vec = poly_to_vec(val)
424
+ #print(f"{time.time()-t} vectime")
381
425
  mn = val_poly.monoms()
382
-
383
- L1 = [0 for i in range(1,n1)]
426
+ #mn = val_poly.keys()
427
+ L1 = tuple([0 for i in range(n1)])
384
428
  mn1L = []
429
+ lookup = {}
385
430
  for mm0 in mn:
386
- if list(mm0[:n1-1]) == L1:
387
- mn1L += [mm0]
388
-
389
- for mn1 in mn1L:
431
+ key = mm0[n1:]
432
+ if key not in lookup:
433
+ lookup[key] = []
434
+ mm0n1 = mm0[:n1]
435
+ st = set(mm0n1)
436
+ #if len(st.intersection(set([0,1])))==len(st):
437
+ if len(st.intersection(set([0,1])))==len(st) and 1 in st:
438
+ lookup[key]+=[mm0]
439
+ if mm0n1 == L1:
440
+ mn1L += [mm0]
441
+ #vs = [[varsimp2[i] - varsimp3[k] for k in range(n2)] for i in range(n1)]
442
+ #fooktime = 0
443
+ #blucktime = 0
444
+ for mn1 in mn1L:
390
445
  comblistmn1 = [1]
391
- for i in range(n2-1):
392
- if mn1[n1-1+i]!=0:
446
+ #t = time.time()
447
+ for i in range(n1,len(mn1)):
448
+ if mn1[i]!=0:
393
449
  arr = np.array(comblistmn1)
394
450
  comblistmn12 = []
395
- mn1_2 = tuple(list(mn1[:n1-1+i])+[0]+list(mn1[n1+i:]))
396
- newset = []
397
- for mm0 in mn:
398
- if mm0[n1-1:] == mn1_2[n1-1:]:
399
- toadd = 1
400
- bad = False
401
- st = set([mm0[k] for k in range(n1-1)])
402
- if len(st.intersection(set([0,1])))<len(st):
403
- bad = True
404
- else:
405
- for k in range(n1-1):
406
- if mm0[k] == 1:
407
- toadd *= var2[k+1] - var3[i+1]
408
- if not bad:
409
- newset += [toadd]
410
- for term in newset:
411
- comblistmn12 += (arr*term).tolist()
451
+ mn1_2 = tuple(list(mn1[n1:i])+[0]+list(mn1[i+1:]))
452
+ for mm0 in lookup[mn1_2]:
453
+ comblistmn12 += (arr*np.prod([varsimp2[k] - varsimp3[i - n1] for k in range(n1) if mm0[k]==1])).tolist()
412
454
  comblistmn1 = comblistmn12
413
- for b1 in comblistmn1:
455
+ #fooktime += time.time() - t
456
+ #t = time.time()
457
+ for i in range(len(comblistmn1)):
458
+ b1 = comblistmn1[i]
414
459
  vec0 = poly_to_vec(b1,vec)
415
460
  if vec0 is not None:
416
461
  base_vectors += [vec0]
417
- base_monoms += [b1]
462
+ base_monoms += [b1]
463
+ #blucktime+= time.time()-t
464
+ #print(f"{fooktime=} {blucktime=}")
465
+ #print(f"{dimen=} {len(base_vectors)=}")
466
+ #print(f"Time time {time.time()-t}")
418
467
  vrs = [pu.LpVariable(name=f"a{i}",lowBound=0,cat='Integer') for i in range(len(base_vectors))]
419
468
  lp_prob = pu.LpProblem('Problem',pu.LpMinimize)
420
469
  lp_prob += int(0)
421
- last = 0
422
- indices = [i for i in range(len(base_vectors[0]))]
423
-
424
- for i in indices:
425
- eq = 0
426
- for j in range(len(base_vectors)):
427
- if base_vectors[j][i]!=0:
428
- eq += int((base_vectors[j][i]))*vrs[j]
470
+ for i in range(dimen):
471
+ eq = pu.lpSum([int(base_vectors[j][i])*vrs[j] for j in range(len(base_vectors)) if base_vectors[j][i]!=0])
429
472
  lp_prob += eq == int(vec[i])
430
473
 
431
474
  try:
@@ -452,40 +495,77 @@ def compute_positive_rep(val,var2=var2,var3=var3,msg=False):
452
495
  val2 += int(x)*b1
453
496
  return val2
454
497
 
498
+ def is_split_two(u,v,w):
499
+ if inv(w)-inv(u)!=2:
500
+ return False, []
501
+ diff_perm = mulperm(inverse(list(u)),list(w))
502
+ identity = [i+1 for i in range(len(diff_perm))]
503
+ cycles = []
504
+ for i in range(len(identity)):
505
+ if diff_perm[i] != identity[i]:
506
+ cycle0 = set()
507
+ cycle = set([i+1])
508
+ last = i
509
+ while len(cycle0) != len(cycle):
510
+ cycle0 = cycle
511
+ last = diff_perm[last] - 1
512
+ cycle.add(last+1)
513
+ if len(cycle)>1 and cycle not in cycles:
514
+ cycles += [cycle]
515
+ if len(cycles)>2:
516
+ break
517
+ if len(cycles) == 2:
518
+ cyclist = list(cycles)
519
+ cyc1 = sorted(list(cyclist[0]))
520
+ cyc2 = sorted(list(cyclist[1]))
521
+ tot_list = sorted(cyc1+cyc2)
522
+ if tot_list.index(cyc1[1]) - tot_list.index(cyc1[0]) == 2:
523
+ #print(f"no {cycles}")
524
+ return False, []
525
+ return True, cycles
526
+ else:
527
+ return False, []
528
+
529
+ def is_coeff_irreducible(u,v,w):
530
+ return not will_formula_work(u,v) and not will_formula_work(v,u) and not one_dominates(u,w) and not is_reducible(v) and inv(w) - inv(u)>1 and not is_split_two(u,v,w)[0]
531
+
455
532
  def posify(val,u2,v2,w2,var2=var2,var3=var3,msg=False):
456
533
  if inv(u2)+inv(v2) - inv(w2)<=1:
457
534
  return expand(val)
535
+ #valo = expand(val)
458
536
  if expand(val) == 0:
459
537
  return 0
460
538
 
461
539
  u, v, w = try_reduce_v(u2, v2, w2)
462
- if not will_formula_work(u,v) and not will_formula_work(v,u) and not one_dominates(u,w) and not is_reducible(v) and inv(w) - inv(u)!=1:
540
+ if is_coeff_irreducible(u,v,w):
463
541
  u, v, w = try_reduce_u(u2, v2, w2)
464
- if not will_formula_work(u,v) and not will_formula_work(v,u) and not one_dominates(u,w) and not is_reducible(v) and inv(w) - inv(u)!=1:
542
+ if is_coeff_irreducible(u,v,w):
465
543
  u, v, w = [*u2], [*v2], [*w2]
466
- if not will_formula_work(u,v) and not will_formula_work(v,u) and not one_dominates(u,w) and not is_reducible(v) and inv(w) - inv(u)!=1:
544
+ if is_coeff_irreducible(u,v,w):
467
545
  w0 = list(w)
468
546
  u, v, w = reduce_descents(u,v,w)
469
- if not will_formula_work(u,v) and not will_formula_work(v,u) and not one_dominates(u,w) and not is_reducible(v) and inv(w) - inv(u)!=1:
547
+ if is_coeff_irreducible(u,v,w):
470
548
  u, v, w = reduce_coeff(u,v,w)
471
- if not will_formula_work(u,v) and not will_formula_work(v,u) and not one_dominates(u,w) and not is_reducible(v) and inv(w) - inv(u)!=1:
472
- while not will_formula_work(u,v) and not will_formula_work(v,u) and tuple(permtrim(w0))!=tuple(permtrim(list(w))) and not one_dominates(u,w) and inv(w) - inv(u)!=1 and not is_reducible(v):
549
+ if is_coeff_irreducible(u,v,w):
550
+ while is_coeff_irreducible(u,v,w) and tuple(permtrim(w0))!=tuple(permtrim(list(w))):
473
551
  w0 = w
474
552
  u, v, w = reduce_descents(u,v,w)
475
- if not will_formula_work(u,v) and not will_formula_work(v,u) and not one_dominates(u,w) and not is_reducible(v) and inv(w) - inv(u)!=1:
553
+ if is_coeff_irreducible(u,v,w):
476
554
  u, v, w = reduce_coeff(u,v,w)
477
555
  u = tuple(u)
478
556
  v = tuple(v)
479
557
  w = tuple(w)
480
558
 
481
-
482
- u3, v3, w3 = try_reduce_v(u, v, w)
483
- if is_reducible(v3):
484
- u, v, w = u3, v3, w3
485
- else:
486
- u3, v3, w3 = try_reduce_u(u, v, w)
487
- if one_dominates(u3,w3):
559
+ if is_coeff_irreducible(u,v,w):
560
+ u3, v3, w3 = try_reduce_v(u, v, w)
561
+ #split_two_b, split_two = is_split_two(u3,v3,w3)
562
+ if not is_coeff_irreducible(u3,v3,w3):
488
563
  u, v, w = u3, v3, w3
564
+ else:
565
+ u3, v3, w3 = try_reduce_u(u, v, w)
566
+ if not is_coeff_irreducible(u3,v3,w3):
567
+ u, v, w = u3, v3, w3
568
+ split_two_b, split_two = is_split_two(u,v,w)
489
569
  if (will_formula_work(v,u) or dominates(u,w)):
490
570
  val = dualcoeff(u,v,w,var2,var3)
491
571
  elif inv(w) - inv(u) == 1:
@@ -541,7 +621,133 @@ def posify(val,u2,v2,w2,var2=var2,var3=var3,msg=False):
541
621
  toadd*= var2[yv] - var3[oaf[j]]
542
622
  toadd *= schubpoly(v3,[0,var2[w[a]],var2[w[b]]],var3)
543
623
  val += toadd
544
- elif expand(val) != 0:
624
+ elif split_two_b:
625
+ #print(f"split_two {u=} {v=} {w=}")
626
+ cycles = split_two
627
+ a1, b1 = cycles[0]
628
+ a2, b2 = cycles[1]
629
+ #print(cycles)
630
+ a1-=1
631
+ b1-=1
632
+ a2-=1
633
+ b2-=1
634
+ spo = sorted([a1,b1,a2,b2])
635
+ real_a1 = min(spo.index(a1),spo.index(b1))
636
+ real_a2 = min(spo.index(a2),spo.index(b2))
637
+ real_b1 = max(spo.index(a1),spo.index(b1))
638
+ real_b2 = max(spo.index(a2),spo.index(b2))
639
+
640
+ good1 = False
641
+ good2 = False
642
+ if real_b1 - real_a1 == 1:
643
+ good1 = True
644
+ if real_b2 - real_a2 == 1:
645
+ good2 = True
646
+ a, b = -1, -1
647
+ if good1 and not good2:
648
+ a, b = min(a2,b2), max(a2,b2)
649
+ if good2 and not good1:
650
+ a, b = min(a1,b1), max(a1,b1)
651
+ arr = [[[],v]]
652
+ d = -1
653
+ for i in range(len(v)-1):
654
+ if v[i]>v[i+1]:
655
+ d = i + 1
656
+ for i in range(d):
657
+ arr2 = []
658
+
659
+ if i in [a1,b1,a2,b2]:
660
+ continue
661
+ i2 = 1
662
+ i2 += len([aa for aa in [a1,b1,a2,b2] if i>aa])
663
+ for vr, v2 in arr:
664
+ dpret = pull_out_var(i2,[*v2])
665
+ for v3r, v3 in dpret:
666
+ arr2 += [[vr + [(v3r,i+1)],v3]]
667
+ arr = arr2
668
+ val = 0
669
+
670
+ if good1:
671
+ arr2 = []
672
+ for L in arr:
673
+ v3 = [*L[-1]]
674
+ if v3[real_a1]<v3[real_b1]:
675
+ continue
676
+ else:
677
+ v3[real_a1], v3[real_b1] = v3[real_b1], v3[real_a1]
678
+ arr2 += [[L[0],v3]]
679
+ arr = arr2
680
+ if not good2:
681
+ for i in range(4):
682
+ arr2 = []
683
+
684
+ if i in [real_a2,real_b2]:
685
+ continue
686
+ if i == real_a1:
687
+ var_index = min(a1,b1) + 1
688
+ elif i == real_b1:
689
+ var_index = max(a1,b1) + 1
690
+ i2 = 1
691
+ i2 += len([aa for aa in [real_a2,real_b2] if i>aa])
692
+ for vr, v2 in arr:
693
+ dpret = pull_out_var(i2,[*v2])
694
+ for v3r, v3 in dpret:
695
+ arr2 += [[vr + [(v3r,var_index)],v3]]
696
+ arr = arr2
697
+ if good2:
698
+ arr2 = []
699
+ for L in arr:
700
+ v3 = [*L[-1]]
701
+ try:
702
+ if v3[real_a2]<v3[real_b2]:
703
+ continue
704
+ else:
705
+ v3[real_a2], v3[real_b2] = v3[real_b2], v3[real_a2]
706
+ except IndexError:
707
+ continue
708
+ arr2 += [[L[0],v3]]
709
+ arr = arr2
710
+ if not good1:
711
+ for i in range(4):
712
+ arr2 = []
713
+
714
+ if i in [real_a1,real_b1]:
715
+ continue
716
+ i2 = 1
717
+ i2 += len([aa for aa in [real_a1,real_b1] if i>aa])
718
+ if i == real_a2:
719
+ var_index = min(a2,b2) + 1
720
+ elif i == real_b2:
721
+ var_index = max(a2,b2) + 1
722
+ for vr, v2 in arr:
723
+ dpret = pull_out_var(i2,[*v2])
724
+ for v3r, v3 in dpret:
725
+ arr2 += [[vr + [(v3r,var_index)],v3]]
726
+ arr = arr2
727
+
728
+ for L in arr:
729
+ v3 = [*L[-1]]
730
+ if (not good1 or not good2) and v3[0]<v3[1]:
731
+ continue
732
+ elif not good1 or not good2:
733
+ v3[0], v3[1] = v3[1], v3[0]
734
+ toadd = 1
735
+ for i in range(len(L[0])):
736
+ var_index = L[0][i][1]
737
+ oaf = L[0][i][0]
738
+ if var_index-1>=len(w):
739
+ yv = var_index
740
+ else:
741
+ yv = w[var_index-1]
742
+ for j in range(len(oaf)):
743
+ toadd*= var2[yv] - var3[oaf[j]]
744
+ if not good1 or not good2:
745
+ varo = [0,var2[w[a]],var2[w[b]]]
746
+ else:
747
+ varo = [0,*[var2[w[spo[k]]] for k in range(4)]]
748
+ toadd *= schubpoly(v3,varo,var3)
749
+ val += toadd
750
+ else:
545
751
  c01 = code(u)
546
752
  c02 = code(w)
547
753
  c03 = code(v)
@@ -608,8 +814,6 @@ def posify(val,u2,v2,w2,var2=var2,var3=var3,msg=False):
608
814
  val2 = compute_positive_rep(val,var2,var3,msg)
609
815
  if val2 is not None:
610
816
  val = val2
611
- else:
612
- val = 0
613
817
  return val
614
818
 
615
819
  def split_perms(perms):
@@ -737,8 +941,8 @@ def main():
737
941
  kcd = [pos[i]-i-1 for i in range(len(pos))] + [n+1-k for i in range(k,n)]
738
942
  N = len(kcd)
739
943
 
740
- var2neg = [-var2[i] for i in range(len(var2))]
741
- var3neg = [-var3[i] for i in range(len(var3))]
944
+ var2neg = np.array([-var2[i] for i in range(len(var2))])
945
+ var3neg = np.array([-var3[i] for i in range(len(var3))])
742
946
 
743
947
  for i in range(1,100):
744
948
  if i<=N:
@@ -797,8 +1001,10 @@ def main():
797
1001
  if display_positive:
798
1002
  if expand(val) != 0:
799
1003
  val2 = compute_positive_rep(val,var2neg,var3neg,msg)
800
- if val2 is not None:
801
- val = val2
1004
+ if expand(val - val2) != 0:
1005
+ print(f"error; write to schubmult@gmail.com with the case {perms=} {firstperm=} {secondperm=} {val2=} {val=}")
1006
+ exit(1)
1007
+ val = val2
802
1008
  else:
803
1009
  val = 0
804
1010
  if val != 0:
@@ -879,9 +1085,7 @@ def main():
879
1085
  if len(perms) == 2 and not posified:
880
1086
  val = posify(val,perms[0],perms[1],perm,var2,var3,msg)
881
1087
  elif not posified:
882
- val2 = compute_positive_rep(val,var2,var3,msg)
883
- if val2 is not None:
884
- val2 = val
1088
+ val = compute_positive_rep(val,var2,var3,msg)
885
1089
  if check and expand(val - check_coeff_dict.get(perm,0))!=0:
886
1090
  print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_coeff_dict.get(perm,0)=}")
887
1091
  print(f"{perms=},{perm=}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schubmult
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: Computing Littlewood-Richardson coefficients of Schubert polynomials
5
5
  Home-page: https://github.com/matthematics/schubmult
6
6
  Author: Matt Samuel
@@ -6,7 +6,7 @@ long_description = (this_directory / "README.md").read_text()
6
6
 
7
7
  setup(
8
8
  name="schubmult",
9
- version="1.2.1",
9
+ version="1.2.3",
10
10
  description="Computing Littlewood-Richardson coefficients of Schubert polynomials",
11
11
  long_description=long_description,
12
12
  long_description_content_type='text/markdown',
File without changes
File without changes
File without changes