schubmult 1.3.8__tar.gz → 1.4.0__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 (31) hide show
  1. {schubmult-1.3.8 → schubmult-1.4.0}/PKG-INFO +5 -5
  2. {schubmult-1.3.8 → schubmult-1.4.0}/README.md +4 -4
  3. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/perm_lib.py +89 -1
  4. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q/schubmult_q.py +96 -2
  5. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q_double/schubmult_q_double.py +9 -2
  6. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q_yz/schubmult_q_yz.py +143 -10
  7. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_yz/schubmult_yz.py +21 -2
  8. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult.egg-info/PKG-INFO +5 -5
  9. {schubmult-1.3.8 → schubmult-1.4.0}/setup.py +1 -1
  10. {schubmult-1.3.8 → schubmult-1.4.0}/LICENSE +0 -0
  11. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/__init__.py +0 -0
  12. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_double/__init__.py +0 -0
  13. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_double/__main__.py +0 -0
  14. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_double/schubmult_double.py +0 -0
  15. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_py/__init__.py +0 -0
  16. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_py/__main__.py +0 -0
  17. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_py/schubmult_py.py +0 -0
  18. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q/__init__.py +0 -0
  19. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q/__main__.py +0 -0
  20. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q_double/__init__.py +0 -0
  21. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q_double/__main__.py +0 -0
  22. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q_yz/__init__.py +0 -0
  23. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_q_yz/__main__.py +0 -0
  24. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_yz/__init__.py +0 -0
  25. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult/schubmult_yz/__main__.py +0 -0
  26. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult.egg-info/SOURCES.txt +0 -0
  27. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult.egg-info/dependency_links.txt +0 -0
  28. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult.egg-info/entry_points.txt +0 -0
  29. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult.egg-info/requires.txt +0 -0
  30. {schubmult-1.3.8 → schubmult-1.4.0}/schubmult.egg-info/top_level.txt +0 -0
  31. {schubmult-1.3.8 → schubmult-1.4.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schubmult
3
- Version: 1.3.8
3
+ Version: 1.4.0
4
4
  Summary: Computing Littlewood-Richardson coefficients of Schubert polynomials
5
5
  Home-page: https://github.com/matthematics/schubmult
6
6
  Author: Matt Samuel
@@ -15,7 +15,7 @@ License-File: LICENSE
15
15
 
16
16
  ## Program and package for computing Littlewood-Richardson coefficients of Schubert polynomials
17
17
 
18
- This is a set of python scripts written by Matt Samuel for computing Littlewood-Richardson coefficients of (ordinary or double) Schubert polynomials. Since version 1.3.3, it also handles (double) quantum Schubert polynomials, if double then either in the same set or different sets of coefficient variables; that is to say it compute the (equivariant/mixed) Gromov-Witten invariants of the complete flag variety. It has the same command line syntax as the program "schubmult" in lrcalc by Anders Buch. Example:
18
+ This is a set of python scripts written by Matt Samuel for computing (equivariant, Molev-Sagan) Littlewood-Richardson coefficients of (ordinary or double) Schubert polynomials. It also handles (double) quantum Schubert polynomials, if double then either in the same set or different sets of coefficient variables; that is to say it compute the (equivariant/mixed) Gromov-Witten invariants of the complete flag variety. It has the same command line syntax as the program "schubmult" in lrcalc by Anders Buch. Example:
19
19
 
20
20
  ```
21
21
  schubmult_py 1 2 4 9 11 6 8 12 3 5 7 10 - 6 8 1 2 3 4 7 10 12 14 5 9 11 13
@@ -50,7 +50,7 @@ schubmult_double -code -coprod 0 1 2 3 - 2 4
50
50
  schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
51
51
  ```
52
52
 
53
- Since version 1.3.7, schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
53
+ schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
54
54
  ```
55
55
  schubmult_q_yz -nil-hecke 6 -code 2 2 --display-positive
56
56
  ```
@@ -59,7 +59,7 @@ Runtime will vary tremendously by case. The general problem is #P-hard. Though t
59
59
 
60
60
  schubmult_py is for multiplying ordinary Schubert polynomials. schubmult_yz is for multiplying double Schubert polynomials in different sets of coefficient variables (labeled y and z), and schubmult_double is for multiplying double Schubert polynomials in the same set of coefficient variables. Similarly, schubmult_q is for multiplying quantum Schubert polynomials, schubmult_q_double is for multiplying quantum double Schubert polynomials in the same set of coefficient variables, and schubmult_q_yz is for multiplying quantum double Schubert polynomials in different sets of coefficient variables, or in other words it computes the Gromov-Witten invariants, equivariant Gromov-Witten invariants, and (mixed?) equivariant Gromov-Witten invariants of the complete flag variety. All have the same command line syntax as schubmult, except when using the -code option. schubmult_double/schubmult_q_double display the result with nonnegative coefficients in terms of the negative simple roots (and the q variables), and schubmult_yz and schubmult_q_yz optionally display the result positively in terms of y_i-z_j (and q) with the --display-positive option.
61
61
 
62
- New in version 1.1.0, schubmult_xx -coprod allows you to split (double) Schubert polynomials along certain indices (not available for schubmult_q). It takes one permutation as an argument, followed by a dash -, then the set of indices you would like to split on. These coefficients are always nonnegative since they occur as product coefficients (this is actually how they are computed).
62
+ schubmult_xx -coprod allows you to split (double) Schubert polynomials along certain indices (not available for quantum). It takes one permutation as an argument, followed by a dash -, then the set of indices you would like to split on. These coefficients are always nonnegative since they occur as product coefficients (this is actually how they are computed).
63
63
 
64
64
  When imported as a python package, the relevant packages are schubmult.perm_lib, which has various permutation manipulation functions, and three modules that have functions of the same name (function name is "schubmult"): schubmult.schubmult_py, schubmult.schubmult_yz, schubmult.schubmult_double. Function takes a permutation dictionary (keys are tuples of ints, which must be trimmed permutations, and values are either integers or symengine values, which can also be integers) as well as a permutation as its second argument, which is the (double) Schubert polynomial to multiply by. Returns a dictionary of the same form with the coefficients.
65
65
 
@@ -76,7 +76,7 @@ from schubmult.schubmult_py import schubmult
76
76
  coeff_dict = schubmult({(1,3,4,6,2,5): 1},(2,1,5,7,3,4,6))
77
77
  ```
78
78
 
79
- Version 1.0.18 adds the command line argument --display-positive to schubmult_yz (and version 1.3.3 adds --display-positive to schubmult_q_yz), which displays the result positively (if possible, this is still only always possible conjecturally). It will fail and print out the offending case if it finds a counterexample. This is highly processor intensive.
79
+ The command line argument --display-positive is available in schubmult_yz and schubmult_q_yz, which displays the result positively (if possible, this is still only always possible conjecturally). It will fail and print out the offending case if it finds a counterexample. This is highly processor intensive.
80
80
 
81
81
  ![](https://raw.githubusercontent.com/matthematics/schubmult/main/positive_image.png)
82
82
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Program and package for computing Littlewood-Richardson coefficients of Schubert polynomials
4
4
 
5
- This is a set of python scripts written by Matt Samuel for computing Littlewood-Richardson coefficients of (ordinary or double) Schubert polynomials. Since version 1.3.3, it also handles (double) quantum Schubert polynomials, if double then either in the same set or different sets of coefficient variables; that is to say it compute the (equivariant/mixed) Gromov-Witten invariants of the complete flag variety. It has the same command line syntax as the program "schubmult" in lrcalc by Anders Buch. Example:
5
+ This is a set of python scripts written by Matt Samuel for computing (equivariant, Molev-Sagan) Littlewood-Richardson coefficients of (ordinary or double) Schubert polynomials. It also handles (double) quantum Schubert polynomials, if double then either in the same set or different sets of coefficient variables; that is to say it compute the (equivariant/mixed) Gromov-Witten invariants of the complete flag variety. It has the same command line syntax as the program "schubmult" in lrcalc by Anders Buch. Example:
6
6
 
7
7
  ```
8
8
  schubmult_py 1 2 4 9 11 6 8 12 3 5 7 10 - 6 8 1 2 3 4 7 10 12 14 5 9 11 13
@@ -37,7 +37,7 @@ schubmult_double -code -coprod 0 1 2 3 - 2 4
37
37
  schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
38
38
  ```
39
39
 
40
- Since version 1.3.7, schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
40
+ schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
41
41
  ```
42
42
  schubmult_q_yz -nil-hecke 6 -code 2 2 --display-positive
43
43
  ```
@@ -46,7 +46,7 @@ Runtime will vary tremendously by case. The general problem is #P-hard. Though t
46
46
 
47
47
  schubmult_py is for multiplying ordinary Schubert polynomials. schubmult_yz is for multiplying double Schubert polynomials in different sets of coefficient variables (labeled y and z), and schubmult_double is for multiplying double Schubert polynomials in the same set of coefficient variables. Similarly, schubmult_q is for multiplying quantum Schubert polynomials, schubmult_q_double is for multiplying quantum double Schubert polynomials in the same set of coefficient variables, and schubmult_q_yz is for multiplying quantum double Schubert polynomials in different sets of coefficient variables, or in other words it computes the Gromov-Witten invariants, equivariant Gromov-Witten invariants, and (mixed?) equivariant Gromov-Witten invariants of the complete flag variety. All have the same command line syntax as schubmult, except when using the -code option. schubmult_double/schubmult_q_double display the result with nonnegative coefficients in terms of the negative simple roots (and the q variables), and schubmult_yz and schubmult_q_yz optionally display the result positively in terms of y_i-z_j (and q) with the --display-positive option.
48
48
 
49
- New in version 1.1.0, schubmult_xx -coprod allows you to split (double) Schubert polynomials along certain indices (not available for schubmult_q). It takes one permutation as an argument, followed by a dash -, then the set of indices you would like to split on. These coefficients are always nonnegative since they occur as product coefficients (this is actually how they are computed).
49
+ schubmult_xx -coprod allows you to split (double) Schubert polynomials along certain indices (not available for quantum). It takes one permutation as an argument, followed by a dash -, then the set of indices you would like to split on. These coefficients are always nonnegative since they occur as product coefficients (this is actually how they are computed).
50
50
 
51
51
  When imported as a python package, the relevant packages are schubmult.perm_lib, which has various permutation manipulation functions, and three modules that have functions of the same name (function name is "schubmult"): schubmult.schubmult_py, schubmult.schubmult_yz, schubmult.schubmult_double. Function takes a permutation dictionary (keys are tuples of ints, which must be trimmed permutations, and values are either integers or symengine values, which can also be integers) as well as a permutation as its second argument, which is the (double) Schubert polynomial to multiply by. Returns a dictionary of the same form with the coefficients.
52
52
 
@@ -63,7 +63,7 @@ from schubmult.schubmult_py import schubmult
63
63
  coeff_dict = schubmult({(1,3,4,6,2,5): 1},(2,1,5,7,3,4,6))
64
64
  ```
65
65
 
66
- Version 1.0.18 adds the command line argument --display-positive to schubmult_yz (and version 1.3.3 adds --display-positive to schubmult_q_yz), which displays the result positively (if possible, this is still only always possible conjecturally). It will fail and print out the offending case if it finds a counterexample. This is highly processor intensive.
66
+ The command line argument --display-positive is available in schubmult_yz and schubmult_q_yz, which displays the result positively (if possible, this is still only always possible conjecturally). It will fail and print out the offending case if it finds a counterexample. This is highly processor intensive.
67
67
 
68
68
  ![](https://raw.githubusercontent.com/matthematics/schubmult/main/positive_image.png)
69
69
 
@@ -8,6 +8,11 @@ n = 100
8
8
 
9
9
  q_var = symarray("q",n)
10
10
 
11
+ def getpermval(perm,index):
12
+ if index<len(perm):
13
+ return perm[index]
14
+ return index+1
15
+
11
16
  def inv(perm):
12
17
  L = len(perm)
13
18
  v = [i for i in range(1,L+1)]
@@ -322,6 +327,13 @@ def add_perm_dict(d1,d2):
322
327
  zero = sympify(0)
323
328
  one = sympify(1)
324
329
 
330
+ def elem_sym_poly_q(p,k,varl1,varl2):
331
+ if p == 0 and k>=0:
332
+ return one
333
+ if p<0 or p>k:
334
+ return zero
335
+ return (varl1[k-1] - varl2[k-p])*elem_sym_poly_q(p-1,k-1,varl1,varl2)+elem_sym_poly_q(p,k-1,varl1,varl2)+q_var[k-1]*elem_sym_poly_q(p-2,k-2,varl1,varl2)
336
+
325
337
  def elem_sym_poly(p,k,varl1,varl2,xstart=0,ystart=0):
326
338
  global zero, one
327
339
  if p>k:
@@ -656,4 +668,80 @@ def pull_out_var(vnum,v):
656
668
  vpm2.pop(vnum-1)
657
669
  vp = permtrim(vpm2)
658
670
  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]]
659
- return ret_list
671
+ return ret_list
672
+
673
+ def get_cycles(perm):
674
+ cycle_set = []
675
+ done_vals = set()
676
+ for i in range(len(perm)):
677
+ p = i + 1
678
+ if perm[i] == p:
679
+ continue
680
+ if p in done_vals:
681
+ continue
682
+ cycle = []
683
+ m = -1
684
+ max_index = -1
685
+ while p not in done_vals:
686
+ cycle += [p]
687
+ done_vals.add(p)
688
+ if p>m:
689
+ m = p
690
+ max_index = len(cycle) - 1
691
+ p = perm[p-1]
692
+ cycle = tuple(cycle[max_index+1:] + cycle[:max_index+1])
693
+ cycle_set += [cycle]
694
+ return cycle_set
695
+
696
+ def double_elem_sym_q(u,p1,p2,k):
697
+ ret_list = {}
698
+ perms1 = elem_sym_perms_q(u,p1,k)
699
+ iu = inverse(u)
700
+ for perm1, udiff1, mul_val1 in perms1:
701
+ perms2 = elem_sym_perms_q(perm1,p2,k)
702
+ cycles1 = get_cycles(tuple(permtrim(mulperm(iu,[*perm1]))))
703
+ cycles1_dict = {}
704
+ for c in cycles1:
705
+ if c[-1] not in cycles1_dict:
706
+ cycles1_dict[c[-1]] = []
707
+ cycles1_dict[c[-1]]+= [set(c)]
708
+ ip1 = inverse(perm1)
709
+ for perm2, udiff2, mul_val2 in perms2:
710
+ cycles2 = get_cycles(tuple(permtrim(mulperm(ip1,[*perm2]))))
711
+ good = True
712
+ for i in range(len(cycles2)):
713
+ c2 = cycles2[i]
714
+ if c2[-1] not in cycles1_dict:
715
+ continue
716
+ for c1_s in cycles1_dict[c2[-1]]:
717
+ for a in range(len(c2)-2,-1,-1):
718
+ if c2[a] in c1_s:
719
+ good = False
720
+ break
721
+ if not good:
722
+ break
723
+ if not good:
724
+ break
725
+
726
+ if good:
727
+ if (perm1,udiff1,mul_val1) not in ret_list:
728
+ ret_list[(perm1,udiff1,mul_val1)] = []
729
+ ret_list[(perm1,udiff1,mul_val1)] += [(perm2,udiff2,mul_val2)]
730
+ return ret_list
731
+
732
+ def medium_theta(perm):
733
+ cd = code(perm)
734
+ found_one = True
735
+ while found_one:
736
+ found_one = False
737
+ for i in range(len(cd)-1):
738
+ if cd[i]<cd[i+1]:
739
+ found_one = True
740
+ cd[i], cd[i+1] = cd[i+1]+1, cd[i]
741
+ break
742
+ if cd[i]==cd[i+1] and cd[i]!=0 and i>0 and cd[i-1]<=cd[i]+1:
743
+ #if cd[i]==cd[i+1] and i>0 and cd[i-1]<=cd[i]+1:
744
+ cd[i]+=1
745
+ found_one = True
746
+ break
747
+ return cd
@@ -63,6 +63,92 @@ for i in range(1,n):
63
63
  sm += var_r[j]
64
64
  subs_dict[var2[i]] = sm
65
65
 
66
+ def schubmult_db(perm_dict,v,var2=var2,var3=var3):
67
+ if v == (1,2):
68
+ return perm_dict
69
+ th = medium_theta(inverse(v))
70
+ #print(f"{th=}")
71
+ while th[-1] == 0:
72
+ th.pop()
73
+ #if len(set(th))!=len(th):
74
+ # print(f"medium theta {th=}")
75
+ mu = permtrim(uncode(th))
76
+ vmu = permtrim(mulperm([*v],mu))
77
+ inv_vmu = inv(vmu)
78
+ inv_mu = inv(mu)
79
+ ret_dict = {}
80
+ vpaths = [([(vmu,0)],1)]
81
+
82
+ thL = len(th)
83
+ #if thL!=2 and len(set(thL))!=1:
84
+ # raise ValueError("Not what I can do")
85
+ vpathdicts = compute_vpathdicts(th,vmu,True)
86
+ #print(f"{vpathdicts=}")
87
+ for u,val in perm_dict.items():
88
+ inv_u = inv(u)
89
+ vpathsums = {u: {(1,2): val}}
90
+ for index in range(thL):
91
+ if index>0 and th[index-1] == th[index]:
92
+ continue
93
+ mx_th = 0
94
+ for vp in vpathdicts[index]:
95
+ for v2,vdiff,s in vpathdicts[index][vp]:
96
+ if th[index]-vdiff > mx_th:
97
+ mx_th = th[index] - vdiff
98
+ if index<len(th)-1 and th[index] == th[index+1]:
99
+ mx_th1 = 0
100
+ for vp in vpathdicts[index+1]:
101
+ for v2,vdiff,s in vpathdicts[index+1][vp]:
102
+ if th[index+1]-vdiff > mx_th1:
103
+ mx_th1 = th[index+1] - vdiff
104
+ newpathsums = {}
105
+ for up in vpathsums:
106
+ newpathsums0 = {}
107
+ inv_up = inv(up)
108
+ newperms = double_elem_sym_q(up,mx_th,mx_th1,th[index])
109
+ for v in vpathdicts[index]:
110
+ sumval = vpathsums[up].get(v,zero)
111
+ if sumval == 0:
112
+ continue
113
+ for v2,vdiff2,s2 in vpathdicts[index][v]:
114
+ for up1, udiff1, mul_val1 in newperms:
115
+ if (up1,udiff1,mul_val1) not in newpathsums0:
116
+ newpathsums0[(up1,udiff1,mul_val1)] = {}
117
+ if udiff1 + vdiff2 == th[index]:
118
+ newpathsums0[(up1,udiff1,mul_val1)][v2] = newpathsums0[(up1,udiff1,mul_val1)].get(v2,zero)+s2*sumval*mul_val1
119
+
120
+ for up1, udiff1, mul_val1 in newpathsums0:
121
+ for v in vpathdicts[index+1]:
122
+ sumval = newpathsums0[(up1,udiff1,mul_val1)].get(v,zero)
123
+ if sumval == 0:
124
+ continue
125
+ for v2,vdiff2,s2 in vpathdicts[index+1][v]:
126
+ for up2, udiff2, mul_val2 in newperms[(up1,udiff1,mul_val1)]:
127
+ if up2 not in newpathsums:
128
+ newpathsums[up2]={}
129
+ if udiff2 + vdiff2 == th[index+1]:
130
+ newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s2*sumval*mul_val2
131
+ else:
132
+ newpathsums = {}
133
+ for up in vpathsums:
134
+ inv_up = inv(up)
135
+ newperms = elem_sym_perms_q(up,min(mx_th,(inv_mu-(inv_up-inv_u))-inv_vmu),th[index])
136
+ for up2, udiff, mul_val in newperms:
137
+ if up2 not in newpathsums:
138
+ newpathsums[up2]={}
139
+ for v in vpathdicts[index]:
140
+ sumval = vpathsums[up].get(v,zero)
141
+ if sumval == 0:
142
+ continue
143
+ for v2,vdiff,s in vpathdicts[index][v]:
144
+ if udiff+vdiff==th[index]:
145
+ newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s*sumval*mul_val
146
+ vpathsums = newpathsums
147
+ toget = tuple(vmu)
148
+ ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
149
+ return ret_dict
150
+
151
+
66
152
  def schubmult(perm_dict,v):
67
153
  th = strict_theta(inverse(v))
68
154
  mu = permtrim(uncode(th))
@@ -177,12 +263,16 @@ def main():
177
263
  equiv = False
178
264
  mult = False
179
265
  mulstring = ""
266
+ slow = False
180
267
 
181
268
  try:
182
269
  for s in sys.argv[1:]:
183
270
  if s == "-np" or s == "--no-print":
184
271
  pr = False
185
272
  continue
273
+ if s == "--slow":
274
+ slow = True
275
+ continue
186
276
  if mult:
187
277
  mulstring += s
188
278
  continue
@@ -344,8 +434,12 @@ def main():
344
434
 
345
435
  coeff_dict = {tuple(permtrim([*perms[0]])): 1}
346
436
 
347
- for perm in perms[1:]:
348
- coeff_dict = schubmult(coeff_dict,tuple(permtrim([*perm])))
437
+ if not slow:
438
+ for perm in perms[1:]:
439
+ coeff_dict = schubmult_db(coeff_dict,tuple(permtrim([*perm])))
440
+ else:
441
+ for perm in perms[1:]:
442
+ coeff_dict = schubmult(coeff_dict,tuple(permtrim([*perm])))
349
443
 
350
444
  if mult:
351
445
  mul_exp = sympify(mulstring)
@@ -1,5 +1,5 @@
1
1
  from schubmult.perm_lib import *
2
- from schubmult.schubmult_q_yz import schubmult, mult_poly
2
+ from schubmult.schubmult_q_yz import schubmult, schubmult_db, mult_poly
3
3
  from symengine import *
4
4
  import sys
5
5
 
@@ -37,12 +37,16 @@ def main():
37
37
  check = True
38
38
  msg = False
39
39
  mult = False
40
+ slow = False
40
41
  mulstring = ""
41
42
  try:
42
43
  for s in sys.argv[1:]:
43
44
  if s == "-np" or s == "--no-print":
44
45
  pr = False
45
46
  continue
47
+ if s == "--slow":
48
+ slow = True
49
+ continue
46
50
  if mult:
47
51
  mulstring += s
48
52
  continue
@@ -96,7 +100,10 @@ def main():
96
100
 
97
101
  coeff_dict = {perms[0]: 1}
98
102
  for perm in perms[1:]:
99
- coeff_dict = schubmult(coeff_dict,perm,var2,var2)
103
+ if slow:
104
+ coeff_dict = schubmult(coeff_dict,perm,var2,var2)
105
+ else:
106
+ coeff_dict = schubmult_db(coeff_dict,perm,var2,var2)
100
107
  if mult:
101
108
  mul_exp = sympify(mulstring)
102
109
  coeff_dict = mult_poly(coeff_dict,mul_exp)
@@ -10,6 +10,13 @@ var_y = var2.tolist()
10
10
  var_z = var3.tolist()
11
11
  var_x = symarray("x",100).tolist()
12
12
 
13
+ x = var_x
14
+ y = var_y
15
+ z = var_z
16
+
17
+ def E(p,k,varl=var_y[1:]):
18
+ return elem_sym_poly_q(p,k,var_x[1:],varl)
19
+
13
20
  def single_variable(coeff_dict,varnum):
14
21
  ret = {}
15
22
  for u in coeff_dict:
@@ -142,6 +149,99 @@ def schubmult(perm_dict,v,var2=var2,var3=var3):
142
149
  ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
143
150
  return ret_dict
144
151
 
152
+ def schubmult_db(perm_dict,v,var2=var2,var3=var3):
153
+ if v == (1,2):
154
+ return perm_dict
155
+ th = medium_theta(inverse(v))
156
+ #print(f"{th=}")
157
+ while th[-1] == 0:
158
+ th.pop()
159
+ #if len(set(th))!=len(th):
160
+ # print(f"medium theta {th=}")
161
+ mu = permtrim(uncode(th))
162
+ vmu = permtrim(mulperm([*v],mu))
163
+ inv_vmu = inv(vmu)
164
+ inv_mu = inv(mu)
165
+ ret_dict = {}
166
+ vpaths = [([(vmu,0)],1)]
167
+
168
+ thL = len(th)
169
+ #if thL!=2 and len(set(thL))!=1:
170
+ # raise ValueError("Not what I can do")
171
+ vpathdicts = compute_vpathdicts(th,vmu,True)
172
+ #print(f"{vpathdicts=}")
173
+ for u,val in perm_dict.items():
174
+ inv_u = inv(u)
175
+ vpathsums = {u: {(1,2): val}}
176
+ for index in range(thL):
177
+ if index>0 and th[index-1] == th[index]:
178
+ continue
179
+ mx_th = 0
180
+ for vp in vpathdicts[index]:
181
+ for v2,vdiff,s in vpathdicts[index][vp]:
182
+ if th[index]-vdiff > mx_th:
183
+ mx_th = th[index] - vdiff
184
+ if index<len(th)-1 and th[index] == th[index+1]:
185
+ mx_th1 = 0
186
+ for vp in vpathdicts[index+1]:
187
+ for v2,vdiff,s in vpathdicts[index+1][vp]:
188
+ if th[index+1]-vdiff > mx_th1:
189
+ mx_th1 = th[index+1] - vdiff
190
+ newpathsums = {}
191
+ for up in vpathsums:
192
+ newpathsums0 = {}
193
+ inv_up = inv(up)
194
+ newperms = double_elem_sym_q(up,mx_th,mx_th1,th[index])
195
+ #for up1, up2, udiff1,udiff2,mul_val1,mul_val2 in newperms:
196
+ for v in vpathdicts[index]:
197
+ sumval = vpathsums[up].get(v,zero)
198
+ if sumval == 0:
199
+ continue
200
+ for v2,vdiff2,s2 in vpathdicts[index][v]:
201
+ for up1, udiff1, mul_val1 in newperms:
202
+ esim1 = elem_sym_func_q(th[index],index+1,up,up1,v,v2,udiff1,vdiff2,var2,var3)*mul_val1*s2
203
+ mulfac = sumval*esim1
204
+ if (up1,udiff1,mul_val1) not in newpathsums0:
205
+ newpathsums0[(up1,udiff1,mul_val1)] = {}
206
+ #newpathsums0[(up1, udiff1, mul_val1
207
+ newpathsums0[(up1,udiff1,mul_val1)][v2] = newpathsums0[(up1,udiff1,mul_val1)].get(v2,0) + mulfac
208
+
209
+ for up1, udiff1, mul_val1 in newpathsums0:
210
+ for v in vpathdicts[index+1]:
211
+ sumval = newpathsums0[(up1,udiff1,mul_val1)].get(v,zero)
212
+ if sumval == 0:
213
+ continue
214
+ for v2,vdiff2,s2 in vpathdicts[index+1][v]:
215
+ for up2, udiff2, mul_val2 in newperms[(up1,udiff1,mul_val1)]:
216
+ esim1 = elem_sym_func_q(th[index+1],index+2,up1,up2,v,v2,udiff2,vdiff2,var2,var3)*mul_val2*s2
217
+ mulfac = sumval*esim1
218
+ if up2 not in newpathsums:
219
+ newpathsums[up2] = {}
220
+ newpathsums[up2][v2] = newpathsums[up2].get(v2,0) + mulfac
221
+ #for up2, udiff2, mul_val2 in newperms[(up1,udiff1,mul_val1)]:
222
+ # if up2 not in newpathsums:
223
+ # newpathsums[up2]={}
224
+ # for v3,vdiff3,s3 in vpathdicts[index+1][v2]:
225
+ # newpathsums[up2][v3] = newpathsums[up2].get(v3,zero)+s3*mul_val2*mulfac*elem_sym_func_q(th[index+1],index+2,up1,up2,v2,v3,udiff2,vdiff3,var2,var3)
226
+ else:
227
+ newpathsums = {}
228
+ for up in vpathsums:
229
+ inv_up = inv(up)
230
+ newperms = elem_sym_perms_q(up,min(mx_th,(inv_mu-(inv_up-inv_u))-inv_vmu),th[index])
231
+ for up2, udiff,mul_val in newperms:
232
+ if up2 not in newpathsums:
233
+ newpathsums[up2]={}
234
+ for v in vpathdicts[index]:
235
+ sumval = vpathsums[up].get(v,zero)*mul_val
236
+ if sumval == 0:
237
+ continue
238
+ for v2,vdiff,s in vpathdicts[index][v]:
239
+ newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s*sumval*elem_sym_func_q(th[index],index+1,up,up2,v,v2,udiff,vdiff,var2,var3)
240
+ vpathsums = newpathsums
241
+ toget = tuple(vmu)
242
+ ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
243
+ return ret_dict
244
+
145
245
  q_var2 = q_var.tolist()
146
246
 
147
247
  def sum_q_dict(q_dict1,q_dict2):
@@ -263,10 +363,13 @@ def main():
263
363
  msg = False
264
364
  just_nil = False
265
365
  mult = False
366
+ slow = False
266
367
 
267
368
  nil_N = 0
268
369
 
269
370
  mulstring = ""
371
+ norep = False
372
+ expa = False
270
373
 
271
374
  try:
272
375
  for s in sys.argv[1:]:
@@ -274,6 +377,15 @@ def main():
274
377
  just_nil = False
275
378
  nil_N = int(s)
276
379
  continue
380
+ if s == "--slow":
381
+ slow = True
382
+ continue
383
+ if s == "--norep":
384
+ norep = True
385
+ continue
386
+ if s == "--expand":
387
+ expa = True
388
+ continue
277
389
  if s == "-np" or s == "--no-print":
278
390
  pr = False
279
391
  continue
@@ -322,6 +434,8 @@ def main():
322
434
  perms[i] = tuple(permtrim(uncode(perms[i])))
323
435
  else:
324
436
  for i in range(len(perms)):
437
+ if len(perms[i])<2 and (len(perms[i])==0 or perms[i][0]==1):
438
+ perms[i] = (1,2)
325
439
  perms[i] = tuple(permtrim([*perms[i]]))
326
440
 
327
441
  size = 0
@@ -333,18 +447,29 @@ def main():
333
447
  else:
334
448
  coeff_dict = {perms[0]: 1}
335
449
  for perm in perms[1:]:
336
- coeff_dict = schubmult(coeff_dict,perm)
450
+ if not slow:
451
+ coeff_dict = schubmult_db(coeff_dict,perm)
452
+ else:
453
+ coeff_dict = schubmult(coeff_dict,perm)
337
454
  if mult:
338
- mul_exp = sympify(mulstring)
455
+ for v in var2:
456
+ globals()[str(v)] = v
457
+ for v in var3:
458
+ globals()[str(v)] = v
459
+ for v in var_x:
460
+ globals()[str(v)] = v
461
+ for v in q_var:
462
+ globals()[str(v)] = v
463
+ q = q_var
464
+ mul_exp = eval(mulstring)
339
465
  coeff_dict = mult_poly(coeff_dict,mul_exp)
340
- rep = ("","")
341
- rep = ("","")
466
+ rep = ("","")
342
467
 
343
468
  if pr:
344
- if ascode:
345
- width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
346
- else:
347
- width = max([len(str(perm)) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
469
+ #if ascode:
470
+ # width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
471
+ #else:
472
+ # width = max([len(str(perm)) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
348
473
 
349
474
  coeff_perms = list(coeff_dict.keys())
350
475
  coeff_perms.sort(key=lambda x: (inv(x),*x))
@@ -398,11 +523,19 @@ def main():
398
523
  print(f"error: value not equal; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {coeff_dict.get(perm,0)=}")
399
524
  exit(1)
400
525
  val = val2
526
+ if expa:
527
+ val = expand(val)
401
528
  if val!=0:
402
529
  if ascode:
403
- print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ').replace(*rep)}")
530
+ if norep:
531
+ print(f"{str(trimcode(perm))} {str(val).replace(*rep)}")
532
+ else:
533
+ print(f"{str(trimcode(perm))} {str(val).replace('**','^').replace('*',' ').replace(*rep)}")
404
534
  else:
405
- print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ').replace(*rep)}")
535
+ if norep:
536
+ print(f"{str(perm)} {str(val).replace(*rep)}")
537
+ else:
538
+ print(f"{str(perm)} {str(val).replace('**','^').replace('*',' ').replace(*rep)}")
406
539
  except BrokenPipeError:
407
540
  pass
408
541
 
@@ -28,6 +28,15 @@ var2 = tuple(symarray('y',n).tolist())
28
28
  var3 = tuple(symarray('z',n).tolist())
29
29
 
30
30
  var_x = symarray("x",100).tolist()
31
+ var_y = var2
32
+ var_z = var3
33
+
34
+ x = var_x
35
+ y = var_y
36
+ z = var_z
37
+
38
+ def E(p,k,varl=var_y[1:]):
39
+ return elem_sym_poly(p,k,var_x[1:],varl)
31
40
 
32
41
  def single_variable(coeff_dict,varnum):
33
42
  ret = {}
@@ -1600,6 +1609,8 @@ def main():
1600
1609
  perms[i] = tuple(permtrim(uncode(perms[i])))
1601
1610
  else:
1602
1611
  for i in range(len(perms)):
1612
+ if len(perms[i])<2 and (len(perms[i])==0 or perms[i][0]==1):
1613
+ perms[i] = (1,2)
1603
1614
  perms[i] = tuple(permtrim([*perms[i]]))
1604
1615
 
1605
1616
  size = 0
@@ -1612,17 +1623,25 @@ def main():
1612
1623
  coeff_dict = {perms[0]: 1}
1613
1624
  check_coeff_dict = {perms[0]: 1}
1614
1625
 
1626
+ if mult:
1627
+ for v in var2:
1628
+ globals()[str(v)] = v
1629
+ for v in var3:
1630
+ globals()[str(v)] = v
1631
+ for v in var_x:
1632
+ globals()[str(v)] = v
1633
+
1615
1634
  if down:
1616
1635
  for perm in orig_perms[1:]:
1617
1636
  check_coeff_dict = schubmult_down(check_coeff_dict,perm)
1618
1637
  if mult:
1619
- mul_exp = sympify(mulstring)
1638
+ mul_exp = eval(mulstring)
1620
1639
  check_coeff_dict = mult_poly_down(check_coeff_dict,mul_exp)
1621
1640
  else:
1622
1641
  for perm in orig_perms[1:]:
1623
1642
  check_coeff_dict = schubmult(check_coeff_dict,perm)
1624
1643
  if mult:
1625
- mul_exp = sympify(mulstring)
1644
+ mul_exp = eval(mulstring)
1626
1645
  check_coeff_dict = mult_poly(check_coeff_dict,mul_exp)
1627
1646
 
1628
1647
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schubmult
3
- Version: 1.3.8
3
+ Version: 1.4.0
4
4
  Summary: Computing Littlewood-Richardson coefficients of Schubert polynomials
5
5
  Home-page: https://github.com/matthematics/schubmult
6
6
  Author: Matt Samuel
@@ -15,7 +15,7 @@ License-File: LICENSE
15
15
 
16
16
  ## Program and package for computing Littlewood-Richardson coefficients of Schubert polynomials
17
17
 
18
- This is a set of python scripts written by Matt Samuel for computing Littlewood-Richardson coefficients of (ordinary or double) Schubert polynomials. Since version 1.3.3, it also handles (double) quantum Schubert polynomials, if double then either in the same set or different sets of coefficient variables; that is to say it compute the (equivariant/mixed) Gromov-Witten invariants of the complete flag variety. It has the same command line syntax as the program "schubmult" in lrcalc by Anders Buch. Example:
18
+ This is a set of python scripts written by Matt Samuel for computing (equivariant, Molev-Sagan) Littlewood-Richardson coefficients of (ordinary or double) Schubert polynomials. It also handles (double) quantum Schubert polynomials, if double then either in the same set or different sets of coefficient variables; that is to say it compute the (equivariant/mixed) Gromov-Witten invariants of the complete flag variety. It has the same command line syntax as the program "schubmult" in lrcalc by Anders Buch. Example:
19
19
 
20
20
  ```
21
21
  schubmult_py 1 2 4 9 11 6 8 12 3 5 7 10 - 6 8 1 2 3 4 7 10 12 14 5 9 11 13
@@ -50,7 +50,7 @@ schubmult_double -code -coprod 0 1 2 3 - 2 4
50
50
  schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
51
51
  ```
52
52
 
53
- Since version 1.3.7, schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
53
+ schubmult_q_yz has a feature for displaying the coefficients of the divided difference operators in the evaluation of the quantum double Schubert polynomials on the commuting difference operators of Fomin, Gelfand, and Postnikov. It is necessary to cap the value of n in the group S_n we are working in because as n increases the expression does not stabilize.
54
54
  ```
55
55
  schubmult_q_yz -nil-hecke 6 -code 2 2 --display-positive
56
56
  ```
@@ -59,7 +59,7 @@ Runtime will vary tremendously by case. The general problem is #P-hard. Though t
59
59
 
60
60
  schubmult_py is for multiplying ordinary Schubert polynomials. schubmult_yz is for multiplying double Schubert polynomials in different sets of coefficient variables (labeled y and z), and schubmult_double is for multiplying double Schubert polynomials in the same set of coefficient variables. Similarly, schubmult_q is for multiplying quantum Schubert polynomials, schubmult_q_double is for multiplying quantum double Schubert polynomials in the same set of coefficient variables, and schubmult_q_yz is for multiplying quantum double Schubert polynomials in different sets of coefficient variables, or in other words it computes the Gromov-Witten invariants, equivariant Gromov-Witten invariants, and (mixed?) equivariant Gromov-Witten invariants of the complete flag variety. All have the same command line syntax as schubmult, except when using the -code option. schubmult_double/schubmult_q_double display the result with nonnegative coefficients in terms of the negative simple roots (and the q variables), and schubmult_yz and schubmult_q_yz optionally display the result positively in terms of y_i-z_j (and q) with the --display-positive option.
61
61
 
62
- New in version 1.1.0, schubmult_xx -coprod allows you to split (double) Schubert polynomials along certain indices (not available for schubmult_q). It takes one permutation as an argument, followed by a dash -, then the set of indices you would like to split on. These coefficients are always nonnegative since they occur as product coefficients (this is actually how they are computed).
62
+ schubmult_xx -coprod allows you to split (double) Schubert polynomials along certain indices (not available for quantum). It takes one permutation as an argument, followed by a dash -, then the set of indices you would like to split on. These coefficients are always nonnegative since they occur as product coefficients (this is actually how they are computed).
63
63
 
64
64
  When imported as a python package, the relevant packages are schubmult.perm_lib, which has various permutation manipulation functions, and three modules that have functions of the same name (function name is "schubmult"): schubmult.schubmult_py, schubmult.schubmult_yz, schubmult.schubmult_double. Function takes a permutation dictionary (keys are tuples of ints, which must be trimmed permutations, and values are either integers or symengine values, which can also be integers) as well as a permutation as its second argument, which is the (double) Schubert polynomial to multiply by. Returns a dictionary of the same form with the coefficients.
65
65
 
@@ -76,7 +76,7 @@ from schubmult.schubmult_py import schubmult
76
76
  coeff_dict = schubmult({(1,3,4,6,2,5): 1},(2,1,5,7,3,4,6))
77
77
  ```
78
78
 
79
- Version 1.0.18 adds the command line argument --display-positive to schubmult_yz (and version 1.3.3 adds --display-positive to schubmult_q_yz), which displays the result positively (if possible, this is still only always possible conjecturally). It will fail and print out the offending case if it finds a counterexample. This is highly processor intensive.
79
+ The command line argument --display-positive is available in schubmult_yz and schubmult_q_yz, which displays the result positively (if possible, this is still only always possible conjecturally). It will fail and print out the offending case if it finds a counterexample. This is highly processor intensive.
80
80
 
81
81
  ![](https://raw.githubusercontent.com/matthematics/schubmult/main/positive_image.png)
82
82
 
@@ -6,7 +6,7 @@ long_description = (this_directory / "README.md").read_text()
6
6
 
7
7
  setup(
8
8
  name="schubmult",
9
- version="1.3.8",
9
+ version="1.4.0",
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