schubmult 1.3.2__tar.gz → 1.3.4__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 (32) hide show
  1. {schubmult-1.3.2 → schubmult-1.3.4}/PKG-INFO +15 -13
  2. {schubmult-1.3.2 → schubmult-1.3.4}/README.md +14 -12
  3. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/perm_lib.py +22 -0
  4. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_double/schubmult_double.py +7 -0
  5. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_py/schubmult_py.py +2 -0
  6. schubmult-1.3.4/schubmult/schubmult_q/schubmult_q.py +318 -0
  7. schubmult-1.3.4/schubmult/schubmult_q_double/__init__.py +1 -0
  8. schubmult-1.3.4/schubmult/schubmult_q_double/__main__.py +5 -0
  9. schubmult-1.3.4/schubmult/schubmult_q_double/schubmult_q_double.py +119 -0
  10. schubmult-1.3.4/schubmult/schubmult_q_yz/__init__.py +1 -0
  11. schubmult-1.3.4/schubmult/schubmult_q_yz/__main__.py +5 -0
  12. schubmult-1.3.4/schubmult/schubmult_q_yz/schubmult_q_yz.py +206 -0
  13. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_yz/schubmult_yz.py +10 -4
  14. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult.egg-info/PKG-INFO +15 -13
  15. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult.egg-info/SOURCES.txt +6 -0
  16. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult.egg-info/entry_points.txt +2 -0
  17. {schubmult-1.3.2 → schubmult-1.3.4}/setup.py +4 -2
  18. schubmult-1.3.2/schubmult/schubmult_q/schubmult_q.py +0 -105
  19. {schubmult-1.3.2 → schubmult-1.3.4}/LICENSE +0 -0
  20. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/__init__.py +0 -0
  21. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_double/__init__.py +0 -0
  22. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_double/__main__.py +0 -0
  23. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_py/__init__.py +0 -0
  24. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_py/__main__.py +0 -0
  25. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_q/__init__.py +0 -0
  26. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_q/__main__.py +0 -0
  27. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_yz/__init__.py +0 -0
  28. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult/schubmult_yz/__main__.py +0 -0
  29. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult.egg-info/dependency_links.txt +0 -0
  30. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult.egg-info/requires.txt +0 -0
  31. {schubmult-1.3.2 → schubmult-1.3.4}/schubmult.egg-info/top_level.txt +0 -0
  32. {schubmult-1.3.2 → schubmult-1.3.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schubmult
3
- Version: 1.3.2
3
+ Version: 1.3.4
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,13 +15,15 @@ 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.0, it also handles quantum Schubert polynomials. 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 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:
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
22
22
  schubmult_double 1 3 4 6 2 5 - 2 1 5 7 3 4 6
23
- schubmult_yz 1 3 4 6 2 5 - 2 1 5 7 3 4 6
24
- schubmult_q 5 1 4 3 2 - 2 1 3 5 4
23
+ schubmult_yz 1 3 4 6 2 5 - 2 1 5 7 3 4 6 --display-positive
24
+ schubmult_q 5 1 4 3 2 - 5 1 3 4 2
25
+ schubmult_q_double 5 1 4 3 2 - 5 1 3 4 2
26
+ schubmult_q_yz 5 1 4 3 2 - 2 5 1 3 4 --display-positive
25
27
  ```
26
28
 
27
29
  The same execution with the Lehmer code:
@@ -29,28 +31,30 @@ The same execution with the Lehmer code:
29
31
  ```
30
32
  schubmult_py -code 0 0 1 5 6 2 3 4 - 5 6 0 0 0 0 1 2 3 4
31
33
  schubmult_double -code 0 1 1 2 - 1 0 2 3
32
- schubmult_yz -code 0 1 1 2 - 1 0 2 3
33
- schubmult_q -code 4 0 2 1 - 1 0 0 1
34
+ schubmult_yz -code 0 1 1 2 - 1 0 2 3 --display-positive
35
+ schubmult_q -code 4 0 2 1 - 4 0 1 1
36
+ schubmult_q_double -code 4 0 2 1 - 4 0 1 1
37
+ schubmult_q_yz -code 4 0 2 1 - 1 3 --display-positive
34
38
  ```
35
39
 
36
40
  For coproducts:
37
41
  ```
38
42
  schubmult_py -coprod 1 3 5 7 2 4 6 - 2 4
39
43
  schubmult_double -coprod 1 3 5 7 2 4 6 - 2 4
40
- schubmult_yz -coprod 1 3 5 7 2 4 6 - 2 4
44
+ schubmult_yz -coprod 1 3 5 7 2 4 6 - 2 4 --display-positive
41
45
  ```
42
46
  or
43
47
  ```
44
48
  schubmult_py -code -coprod 0 1 2 3 - 2 4
45
49
  schubmult_double -code -coprod 0 1 2 3 - 2 4
46
- schubmult_yz -code -coprod 0 1 2 3 - 2 4
50
+ schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
47
51
  ```
48
52
 
49
53
 
50
54
 
51
- Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative and the problem is in GapP, it is not known to be in #P at this time.
55
+ Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative (which at least is known for schubmult_py, schubmult_q, schubmult_double, and schubmult_q_double) and the problem is in GapP, it is not known to be in #P at this time.
52
56
 
53
- 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. Both have the same command line syntax as schubmult. schubmult_double displays the result with nonnegative coefficients in terms of the negative simple roots. Both are of course slower than schubmult_py, and expressing the result positively for schubmult_double slows it down even more.
57
+ 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.
54
58
 
55
59
  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).
56
60
 
@@ -69,9 +73,7 @@ from schubmult.schubmult_py import schubmult
69
73
  coeff_dict = schubmult({(1,3,4,6,2,5): 1},(2,1,5,7,3,4,6))
70
74
  ```
71
75
 
72
- Note versions 1.0.15 and prior had a bug that failed to upgrade the executable. The coefficients it computed were correct, but it was not using the updated version.
73
-
74
- Version 1.0.18 adds the command line argument --display-positive to schubmult_yz, which displays the result positively (if possible, this is still only always possible conjecturally). This is highly processor intensive.
76
+ 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.
75
77
 
76
78
  ![](https://raw.githubusercontent.com/matthematics/schubmult/main/positive_image.png)
77
79
 
@@ -2,13 +2,15 @@
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.0, it also handles quantum Schubert polynomials. 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 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:
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
9
9
  schubmult_double 1 3 4 6 2 5 - 2 1 5 7 3 4 6
10
- schubmult_yz 1 3 4 6 2 5 - 2 1 5 7 3 4 6
11
- schubmult_q 5 1 4 3 2 - 2 1 3 5 4
10
+ schubmult_yz 1 3 4 6 2 5 - 2 1 5 7 3 4 6 --display-positive
11
+ schubmult_q 5 1 4 3 2 - 5 1 3 4 2
12
+ schubmult_q_double 5 1 4 3 2 - 5 1 3 4 2
13
+ schubmult_q_yz 5 1 4 3 2 - 2 5 1 3 4 --display-positive
12
14
  ```
13
15
 
14
16
  The same execution with the Lehmer code:
@@ -16,28 +18,30 @@ The same execution with the Lehmer code:
16
18
  ```
17
19
  schubmult_py -code 0 0 1 5 6 2 3 4 - 5 6 0 0 0 0 1 2 3 4
18
20
  schubmult_double -code 0 1 1 2 - 1 0 2 3
19
- schubmult_yz -code 0 1 1 2 - 1 0 2 3
20
- schubmult_q -code 4 0 2 1 - 1 0 0 1
21
+ schubmult_yz -code 0 1 1 2 - 1 0 2 3 --display-positive
22
+ schubmult_q -code 4 0 2 1 - 4 0 1 1
23
+ schubmult_q_double -code 4 0 2 1 - 4 0 1 1
24
+ schubmult_q_yz -code 4 0 2 1 - 1 3 --display-positive
21
25
  ```
22
26
 
23
27
  For coproducts:
24
28
  ```
25
29
  schubmult_py -coprod 1 3 5 7 2 4 6 - 2 4
26
30
  schubmult_double -coprod 1 3 5 7 2 4 6 - 2 4
27
- schubmult_yz -coprod 1 3 5 7 2 4 6 - 2 4
31
+ schubmult_yz -coprod 1 3 5 7 2 4 6 - 2 4 --display-positive
28
32
  ```
29
33
  or
30
34
  ```
31
35
  schubmult_py -code -coprod 0 1 2 3 - 2 4
32
36
  schubmult_double -code -coprod 0 1 2 3 - 2 4
33
- schubmult_yz -code -coprod 0 1 2 3 - 2 4
37
+ schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
34
38
  ```
35
39
 
36
40
 
37
41
 
38
- Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative and the problem is in GapP, it is not known to be in #P at this time.
42
+ Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative (which at least is known for schubmult_py, schubmult_q, schubmult_double, and schubmult_q_double) and the problem is in GapP, it is not known to be in #P at this time.
39
43
 
40
- 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. Both have the same command line syntax as schubmult. schubmult_double displays the result with nonnegative coefficients in terms of the negative simple roots. Both are of course slower than schubmult_py, and expressing the result positively for schubmult_double slows it down even more.
44
+ 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.
41
45
 
42
46
  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).
43
47
 
@@ -56,9 +60,7 @@ from schubmult.schubmult_py import schubmult
56
60
  coeff_dict = schubmult({(1,3,4,6,2,5): 1},(2,1,5,7,3,4,6))
57
61
  ```
58
62
 
59
- Note versions 1.0.15 and prior had a bug that failed to upgrade the executable. The coefficients it computed were correct, but it was not using the updated version.
60
-
61
- Version 1.0.18 adds the command line argument --display-positive to schubmult_yz, which displays the result positively (if possible, this is still only always possible conjecturally). This is highly processor intensive.
63
+ 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.
62
64
 
63
65
  ![](https://raw.githubusercontent.com/matthematics/schubmult/main/positive_image.png)
64
66
 
@@ -313,6 +313,28 @@ def elem_sym_func(k,i,u1,u2,v1,v2,udiff,vdiff,varl1,varl2):
313
313
  zvars = [varl2[i] for i in call_zvars(v1,v2,k,i)]
314
314
  return elem_sym_poly(newk-vdiff,newk,yvars,zvars)
315
315
 
316
+ def elem_sym_func_q(k,i,u1,u2,v1,v2,udiff,vdiff,varl1,varl2):
317
+ global zero, one
318
+ newk = k - udiff
319
+ if newk < vdiff:
320
+ return zero
321
+ if newk == vdiff:
322
+ return one
323
+ yvars = []
324
+ mlen = max(len(u1),len(u2))
325
+ u1 = [*u1] + [a+1 for a in range(len(u1),mlen)]
326
+ u2 = [*u2] + [a+1 for a in range(len(u2),mlen)]
327
+ for j in range(min(len(u1),k)):
328
+ if u1[j]==u2[j]:
329
+ yvars += [varl1[u2[j]]]
330
+ for j in range(len(u1),min(k,len(u2))):
331
+ if u2[j]==j+1:
332
+ yvars += [varl1[u2[j]]]
333
+ for j in range(len(u2),k):
334
+ yvars += [varl1[j+1]]
335
+ zvars = [varl2[a] for a in call_zvars(v1,v2,k,i)]
336
+ return elem_sym_poly(newk-vdiff,newk,yvars,zvars)
337
+
316
338
  def trimcode(perm):
317
339
  cd = code(perm)
318
340
  while len(cd)>0 and cd[-1] == 0:
@@ -12,6 +12,8 @@ var2 = symarray('y',n)
12
12
  var3 = var2
13
13
  var_r = symarray('r',n)
14
14
 
15
+ var_q = Symbol("q")
16
+
15
17
  subs_dict = {}
16
18
 
17
19
  for i in range(1,n):
@@ -20,6 +22,8 @@ for i in range(1,n):
20
22
  sm += var_r[j]
21
23
  subs_dict[var2[i]] = sm
22
24
 
25
+
26
+
23
27
  def main():
24
28
  try:
25
29
  perms=[]
@@ -45,12 +49,15 @@ def main():
45
49
  continue
46
50
  curperm += [int(s)]
47
51
  except Exception:
52
+ print("**** schubmult_double ****")
53
+ print("Purpose: Compute products (and coproducts) of double Schubert polynomials in the same set of variables")
48
54
  print("Usage: schubmult_double <-np|--no-print> <-code> perm1 - perm2 < - perm 3 ... >")
49
55
  print("Alternative usage: schubmult_double <-code> -coprod perm - indexlist")
50
56
  exit(1)
51
57
 
52
58
  perms += [curperm]
53
59
 
60
+
54
61
  if coprod:
55
62
  subs_dict_coprod = {}
56
63
  if ascode:
@@ -76,6 +76,8 @@ def main():
76
76
  continue
77
77
  curperm += [int(s)]
78
78
  except Exception:
79
+ print("**** schubmult_py ****")
80
+ print("Purpose: Compute products (and coproducts) of ordinary Schubert polynomials")
79
81
  print("Usage: schubmult_py <-np|--no-print> <-code> perm1 - perm2 <- perm3...>")
80
82
  print("Alternative usage: schubmult_py -coprod <-np> <perm> - <index list>")
81
83
  exit(1)
@@ -0,0 +1,318 @@
1
+ from symengine import *
2
+ from functools import cache
3
+ from itertools import chain
4
+ from schubmult.perm_lib import *
5
+ import schubmult.schubmult_yz as yz
6
+ import sys
7
+
8
+ var = symarray('x', n)
9
+ var2 = symarray('y',n)
10
+ var3 = var2
11
+ var_r = symarray('r',n)
12
+
13
+ var_q = Symbol("q")
14
+
15
+ subs_dict = {}
16
+
17
+ for i in range(1,n):
18
+ sm = var_r[0]
19
+ for j in range(1,i):
20
+ sm += var_r[j]
21
+ subs_dict[var2[i]] = sm
22
+
23
+ def schubmult(perm_dict,v):
24
+ vn1 = inverse(v)
25
+ th = [len(v)-i for i in range(1,len(v)+1)]
26
+ mu = permtrim(uncode(th))
27
+ vmu = permtrim(mulperm([*v],mu))
28
+ #print(f"{th=} {mu=} {vmu=}")
29
+ inv_vmu = inv(vmu)
30
+ inv_mu = inv(mu)
31
+ ret_dict = {}
32
+ vpaths = [([(vmu,0)],1)]
33
+ while th[-1] == 0:
34
+ th.pop()
35
+ thL = len(th)
36
+ vpathdicts = compute_vpathdicts(th,vmu,True)
37
+ for u,val in perm_dict.items():
38
+ inv_u = inv(u)
39
+ vpathsums = {u: {(1,2): val}}
40
+ for index in range(thL):
41
+ mx_th = 0
42
+ for vp in vpathdicts[index]:
43
+ for v2,vdiff,s in vpathdicts[index][vp]:
44
+ if th[index]-vdiff > mx_th:
45
+ mx_th = th[index] - vdiff
46
+ newpathsums = {}
47
+ for up in vpathsums:
48
+ newperms = elem_sym_perms_q(up,mx_th,th[index])
49
+ for up2, udiff, mul_val in newperms:
50
+ if up2 not in newpathsums:
51
+ newpathsums[up2]={}
52
+ for v in vpathdicts[index]:
53
+ sumval = vpathsums[up].get(v,zero)
54
+ if sumval == 0:
55
+ continue
56
+ for v2,vdiff,s in vpathdicts[index][v]:
57
+ if udiff+vdiff==th[index]:
58
+ newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s*sumval*mul_val
59
+ vpathsums = newpathsums
60
+ toget = tuple(vmu)
61
+ ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
62
+ return ret_dict
63
+
64
+ var_q = Symbol("q")
65
+
66
+ def grass_q_replace(perm,k,d,n):
67
+ if k-d<0:
68
+ return None
69
+ #print("Here")
70
+ ret = []
71
+ cd = code(perm)
72
+ for i in range(k-d,k):
73
+ if i>=len(cd) or cd[i]<d:
74
+ return None
75
+ grass_rep = [0 for i in range(n)]
76
+ perm2 = [*perm] + [i+1 for i in range(len(perm),n)]
77
+ for i in range(k,n):
78
+ grass_rep[perm2[i]-1] = 2
79
+ num_0 = 0
80
+ #print(f"{grass_rep=} {d=}")
81
+ for i in range(len(grass_rep)-1,-1,-1):
82
+ if num_0 == d:
83
+ break
84
+ if grass_rep[i] == 0:
85
+ grass_rep[i] = 1
86
+ num_0 += 1
87
+ num_2 = 0
88
+ for i in range(len(grass_rep)):
89
+ if num_2 == d:
90
+ break
91
+ if grass_rep[i] == 2:
92
+ grass_rep[i] = 1
93
+ num_2 += 1
94
+ #print(f"New {grass_rep=}")
95
+ k1 = k - d
96
+ k2 = k + d
97
+ pos_1 = 0
98
+ pos_2 = 0
99
+ pos_3 = 0
100
+ new_perm = [0 for i in range(n)]
101
+ for i in range(len(grass_rep)):
102
+ if grass_rep[i] == 0:
103
+ new_perm[pos_1] = i+1
104
+ pos_1 += 1
105
+ if grass_rep[i] == 1:
106
+ new_perm[k1+pos_2] = i+1
107
+ pos_2 += 1
108
+ if grass_rep[i] == 2:
109
+ new_perm[k2+pos_3] = i+1
110
+ pos_3 += 1
111
+ return tuple(permtrim(new_perm))
112
+
113
+ def to_two_step(perm,k1,k2,n):
114
+ rep = [0 for i in range(n)]
115
+ perm2 = [*perm] + [i+1 for i in range(len(perm),n)]
116
+ for i in range(n):
117
+ if i<k1:
118
+ rep[perm2[i]-1] = 0
119
+ elif i<k2:
120
+ rep[perm2[i]-1] = 1
121
+ else:
122
+ rep[perm2[i]-1] = 2
123
+ return rep
124
+
125
+ def main():
126
+ try:
127
+ perms=[]
128
+ curperm = []
129
+
130
+ pr = True
131
+ ascode = False
132
+ grass = False
133
+ grass_q_n = 0
134
+ equiv = False
135
+ try:
136
+ for s in sys.argv[1:]:
137
+ if s == "-np" or s == "--no-print":
138
+ pr = False
139
+ continue
140
+ if s == "-code":
141
+ ascode = True
142
+ continue
143
+ if s == "-grass":
144
+ grass = None
145
+ continue
146
+ if s == "-equiv":
147
+ equiv = True
148
+ continue
149
+ if grass is None:
150
+ grass = True
151
+ grass_q_n = int(s)
152
+ continue
153
+ if s == "-":
154
+ perms += [curperm]
155
+ curperm = []
156
+ continue
157
+ curperm += [int(s)]
158
+ except Exception:
159
+ print("**** schubmult_q ****")
160
+ print("Purpose: Compute the structure constants of quantum Schubert polynomials")
161
+ print("Usage: schubmult_q <-np|--no-print> <-code> <-grass n> <-equiv> perm1 - perm2 < - perm 3 ... >")
162
+ print("For the -grass option, must use Grassmannian permutations. -equiv only works together with -grass.")
163
+ exit(1)
164
+
165
+ perms += [curperm]
166
+
167
+
168
+ if grass:
169
+ perms_t = []
170
+ if ascode:
171
+ perms_t = [tuple(permtrim(uncode(perms[i]))) for i in range(len(perms))]
172
+ else:
173
+ perms_t = [tuple(permtrim(perms[i])) for i in range(len(perms))]
174
+
175
+ k = -1
176
+
177
+ for perm in perms_t:
178
+ desc = -1
179
+ for i in range(len(perm)-1):
180
+ if desc != -1 and perm[i]>perm[i+1]:
181
+ print("Error: permutations must have one descent")
182
+ exit(1)
183
+ elif desc == -1:
184
+ if perm[i]>perm[i+1]:
185
+ if k != -1 and k != i+1:
186
+ print("Error: permutations must all have the same descent")
187
+ exit(1)
188
+ k = i+1
189
+ desc = i+1
190
+ #perms1 = [perms_t[0]]
191
+ #perms2 = [perms_t[1]]
192
+ perms1 = []
193
+ perms2 = []
194
+ for d in range(100,-1,-1):
195
+ #print(f"{k=} {d=}")
196
+ grass_rep_1 = grass_q_replace(perms_t[0],k,d,grass_q_n)
197
+ grass_rep_2 = grass_q_replace(perms_t[1],k,d,grass_q_n)
198
+ #print(f"{grass_rep_1} {grass_rep_2}")
199
+ if grass_rep_1 is None or grass_rep_2 is None:
200
+ continue
201
+ perms1 += [grass_rep_1]
202
+ perms2 += [grass_rep_2]
203
+ for i in range(len(perms1)):
204
+ d = len(perms1) - i - 1
205
+ #print(f"{d=} {perms1[i]=} {perms2[i]=}")
206
+ if equiv:
207
+ coeff_dict = yz.schubmult({perms1[i]: 1},perms2[i],var2,var2)
208
+ else:
209
+ coeff_dict = yz.schubmult({perms1[i]: 1},perms2[i],[0 for i in range(100)],[0 for i in range(100)])
210
+
211
+ #if ascode:
212
+ # width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys()])
213
+ #else:
214
+ # width = max([len(str(perm)) for perm in coeff_dict.keys()])
215
+ k1 = k - d
216
+ k2 = k + d
217
+ coeff_perms = list([key for key in coeff_dict.keys() if len(key)<=grass_q_n])
218
+
219
+ coeff_perms.sort(key=lambda x: (inv(x),*x))
220
+
221
+ coeff_perms2 = []
222
+
223
+ for perm in coeff_perms:
224
+ two_step = to_two_step(perm,k1,k2,grass_q_n)
225
+ num_1 = len([i for i in range(len(two_step)) if two_step[i] == 1])
226
+ if num_1 != 2*d:
227
+ coeff_perms2 += [None]
228
+ continue
229
+ one_step = [*two_step]
230
+ one_step.reverse()
231
+ two_step_r = [*two_step]
232
+ two_step_r.reverse()
233
+ for i in range(len(one_step)-1,-1,-1):
234
+ if one_step[i] == 0:
235
+ break
236
+ if one_step[i] == 1:
237
+ one_step[i] = 0
238
+ no_good = False
239
+ for i in range(len(one_step)):
240
+ if one_step[i] == 1:
241
+ one_step[i] = 2
242
+ elif one_step[i] == 2:
243
+ if len([j for j in range(len(one_step)) if one_step[j]==1]) != 0:
244
+ no_good = True
245
+ break
246
+ num_0 = len([i for i in range(len(one_step)) if one_step[i] == 0])
247
+ if num_0 != k or no_good:
248
+ #print(f"No good {one_step=} {two_step_r=} {no_good=}")
249
+ coeff_perms2 += [None]
250
+ continue
251
+ pos_0 = 0
252
+ pos_1 = 0
253
+ one_step.reverse()
254
+ #print(f"{two_step=}")
255
+ #print(f"{one_step=}")
256
+ grass_perm = [0 for i in range(len(one_step))]
257
+ for i in range(len(one_step)):
258
+ if one_step[i] == 0:
259
+ grass_perm[pos_0] = i+1
260
+ pos_0 += 1
261
+ else:
262
+ grass_perm[k+pos_1] = i+1
263
+ pos_1 += 1
264
+ coeff_perms2 += [tuple(permtrim(grass_perm))]
265
+
266
+ try:
267
+ if ascode:
268
+ width = max([len(str(trimcode(perm))) for perm in coeff_perms2 if perm is not None])
269
+ else:
270
+ width = max([len(str(perm)) for perm in coeff_perms2 if perm is not None])
271
+ except ValueError:
272
+ continue
273
+
274
+ for i in range(len(coeff_perms)):
275
+ if coeff_perms2[i] is None:
276
+ continue
277
+ perm = coeff_perms[i]
278
+ val = (var_q**d) * sympify(coeff_dict[perm]).subs(subs_dict).expand()
279
+
280
+ if val != 0:
281
+ if ascode:
282
+ print(f"{str(trimcode(coeff_perms2[i])):>{width}} {str(val).replace('**','^').replace('*',' ')}")
283
+ else:
284
+ print(f"{str(coeff_perms2[i]):>{width}} {str(val).replace('**','^').replace('*',' ')}")
285
+ #print(f"{str(two_step):>{width}} {str(val).replace('**','^').replace('*',' ')}")
286
+ #else:
287
+ # print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ')}")
288
+ else:
289
+ if ascode:
290
+ for i in range(len(perms)):
291
+ perms[i] = uncode(perms[i])
292
+
293
+ coeff_dict = {tuple(permtrim([*perms[0]])): 1}
294
+
295
+ for perm in perms[1:]:
296
+ coeff_dict = schubmult(coeff_dict,tuple(permtrim([*perm])))
297
+
298
+ if pr:
299
+ if ascode:
300
+ width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
301
+ else:
302
+ width = max([len(str(perm)) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
303
+
304
+ coeff_perms = list(coeff_dict.keys())
305
+ coeff_perms.sort(key=lambda x: (inv(x),*x))
306
+
307
+ for perm in coeff_perms:
308
+ val = sympify(coeff_dict[perm]).expand()
309
+ if val != 0:
310
+ if ascode:
311
+ print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ')}")
312
+ else:
313
+ print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ')}")
314
+ except BrokenPipeError:
315
+ pass
316
+
317
+ if __name__ == "__main__":
318
+ main()
@@ -0,0 +1 @@
1
+ from .schubmult_q_double import *
@@ -0,0 +1,5 @@
1
+ import sys
2
+ from .schubmult_q_double import main
3
+
4
+ if __name__ == "__main__":
5
+ sys.exit(main())
@@ -0,0 +1,119 @@
1
+ from schubmult.perm_lib import *
2
+ from schubmult.schubmult_q_yz import schubmult
3
+ from symengine import *
4
+ import sys
5
+
6
+
7
+ q_var = symarray("q",100)
8
+
9
+ var2 = symarray("y",100)
10
+ var3 = symarray("z",100)
11
+
12
+ var3 = var2
13
+ var_r = symarray('r',100)
14
+
15
+ subs_dict = {}
16
+
17
+ for i in range(1,100):
18
+ sm = var_r[0]
19
+ for j in range(1,i):
20
+ sm += var_r[j]
21
+ subs_dict[var2[i]] = sm
22
+
23
+
24
+
25
+ def main():
26
+ global var2
27
+ try:
28
+ sys.setrecursionlimit(1000000)
29
+
30
+ perms=[]
31
+ curperm = []
32
+
33
+ pr = True
34
+ display_positive = False
35
+ ascode = False
36
+ coprod = False
37
+ check = True
38
+ msg = False
39
+ try:
40
+ for s in sys.argv[1:]:
41
+ if s == "-np" or s == "--no-print":
42
+ pr = False
43
+ continue
44
+ if s == "-nocheck":
45
+ check = False
46
+ continue
47
+ if s == "--display-positive":
48
+ display_positive = True
49
+ continue
50
+ if s == "--optimizer-message":
51
+ msg = True
52
+ continue
53
+ if s == "--version":
54
+ print(f"Python version {sys.version}")
55
+ exit(0)
56
+ if s == "-code":
57
+ ascode = True
58
+ continue
59
+ if s == "--usage":
60
+ print("**** schubmult_q_double ****")
61
+ print("Purpose: Compute equivariant Gromov-Witten invariants, structure constants of quantum double Schubert polynomials")
62
+ print("Usage: schubmult_q_double <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
63
+ #print("Alternative usage: schubmult_yz <-code> <--display-positive> -coprod perm - indexlist")
64
+ exit(0)
65
+ if s == "-":
66
+ perms += [curperm]
67
+ curperm = []
68
+ continue
69
+ curperm += [int(s)]
70
+ except Exception:
71
+ print("**** schubmult_q_double ****")
72
+ print("Purpose: Compute equivariant Gromov-Witten invariants, structure constants of quantum double Schubert polynomials")
73
+ print("Usage: schubmult_q_double <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
74
+ exit(1)
75
+
76
+ perms += [curperm]
77
+
78
+
79
+ if ascode:
80
+ for i in range(len(perms)):
81
+ perms[i] = tuple(permtrim(uncode(perms[i])))
82
+ else:
83
+ for i in range(len(perms)):
84
+ perms[i] = tuple(permtrim([*perms[i]]))
85
+
86
+ size = 0
87
+ L = len(perms)
88
+
89
+ coeff_dict = {perms[0]: 1}
90
+ for perm in perms[1:]:
91
+ coeff_dict = schubmult(coeff_dict,perm,var2,var2)
92
+
93
+ if pr:
94
+ if ascode:
95
+ width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys() if expand(sympify(coeff_dict[perm]).subs(subs_dict))!=0])
96
+ else:
97
+ width = max([len(str(perm)) for perm in coeff_dict.keys() if expand(sympify(coeff_dict[perm]).subs(subs_dict))!=0])
98
+
99
+ coeff_perms = list(coeff_dict.keys())
100
+ coeff_perms.sort(key=lambda x: (inv(x),*x))
101
+
102
+ for perm in coeff_perms:
103
+ val = expand(sympify(coeff_dict[perm]).subs(subs_dict)).simplify()
104
+ if val != 0:
105
+ notint = False
106
+ try:
107
+ int(val)
108
+ except Exception:
109
+ notint = True
110
+ if val!=0:
111
+ if ascode:
112
+ print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ')}")
113
+ else:
114
+ print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ')}")
115
+ except BrokenPipeError:
116
+ pass
117
+
118
+ if __name__ == "__main__":
119
+ main()
@@ -0,0 +1 @@
1
+ from .schubmult_q_yz import *
@@ -0,0 +1,5 @@
1
+ import sys
2
+ from .schubmult_q_yz import main
3
+
4
+ if __name__ == "__main__":
5
+ sys.exit(main())
@@ -0,0 +1,206 @@
1
+ from schubmult.perm_lib import *
2
+ from schubmult.schubmult_yz import compute_positive_rep
3
+ from symengine import *
4
+ import sys
5
+
6
+
7
+ #q_var = symarray("q",100)
8
+
9
+ var2 = symarray("y",100)
10
+ var3 = symarray("z",100)
11
+
12
+
13
+
14
+
15
+
16
+
17
+ def schubmult(perm_dict,v,var2=var2,var3=var3):
18
+ vn1 = inverse(v)
19
+ th = [len(v)-i for i in range(1,len(v))]
20
+ mu = permtrim(uncode(th))
21
+ vmu = permtrim(mulperm([*v],mu))
22
+ inv_vmu = inv(vmu)
23
+ inv_mu = inv(mu)
24
+ ret_dict = {}
25
+ vpaths = [([(vmu,0)],1)]
26
+ while th[-1] == 0:
27
+ th.pop()
28
+ thL = len(th)
29
+ vpathdicts = compute_vpathdicts(th,vmu,True)
30
+ for u,val in perm_dict.items():
31
+ inv_u = inv(u)
32
+ vpathsums = {u: {(1,2): val}}
33
+ for index in range(thL):
34
+ mx_th = 0
35
+ for vp in vpathdicts[index]:
36
+ for v2,vdiff,s in vpathdicts[index][vp]:
37
+ if th[index]-vdiff > mx_th:
38
+ mx_th = th[index] - vdiff
39
+ newpathsums = {}
40
+ for up in vpathsums:
41
+ inv_up = inv(up)
42
+ newperms = elem_sym_perms_q(up,mx_th,th[index])
43
+ for up2, udiff,mul_val in newperms:
44
+ if up2 not in newpathsums:
45
+ newpathsums[up2]={}
46
+ for v in vpathdicts[index]:
47
+ sumval = vpathsums[up].get(v,zero)*mul_val
48
+ if sumval == 0:
49
+ continue
50
+ for v2,vdiff,s in vpathdicts[index][v]:
51
+ #print(f"{code(up2)=} {elem_sym_func_q(th[index],index+1,up,up2,v,v2,udiff,vdiff,var2,var3)=} {mul_val=} {sumval=}")
52
+ 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)
53
+ vpathsums = newpathsums
54
+ toget = tuple(vmu)
55
+ ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
56
+ return ret_dict
57
+
58
+ def factor_out_q(poly):
59
+ coeff_dict = expand(poly).as_coefficients_dict()
60
+ ret = {}
61
+ q_var2 = q_var.tolist()
62
+ for key in coeff_dict:
63
+ coeff = coeff_dict[key]
64
+ if coeff == 0:
65
+ continue
66
+ q_part = 1
67
+ yz_part = coeff
68
+ if isinstance(key,Mul):
69
+ for var_maybe_pow in key.args:
70
+ if isinstance(var_maybe_pow,Pow):
71
+ real_var = var_maybe_pow.args[0]
72
+ if real_var in q_var2:
73
+ q_part*=var_maybe_pow
74
+ else:
75
+ yz_part*=var_maybe_pow
76
+ else:
77
+ real_var = var_maybe_pow
78
+ if real_var in q_var2:
79
+ q_part*=var_maybe_pow
80
+ else:
81
+ yz_part*=var_maybe_pow
82
+ elif isinstance(key,Pow):
83
+ real_var = key.args[0]
84
+ if real_var in q_var2:
85
+ q_part*=key
86
+ else:
87
+ yz_part*=key
88
+ else:
89
+ if key in q_var2:
90
+ q_part *= key
91
+ else:
92
+ yz_part*=key
93
+
94
+ ret[q_part] = ret.get(q_part,0) + yz_part
95
+ return ret
96
+ def main():
97
+ global var2
98
+ try:
99
+ sys.setrecursionlimit(1000000)
100
+
101
+ perms=[]
102
+ curperm = []
103
+
104
+ pr = True
105
+ display_positive = False
106
+ ascode = False
107
+ coprod = False
108
+ check = True
109
+ msg = False
110
+ try:
111
+ for s in sys.argv[1:]:
112
+ if s == "-np" or s == "--no-print":
113
+ pr = False
114
+ continue
115
+ if s == "-nocheck":
116
+ check = False
117
+ continue
118
+ if s == "--display-positive":
119
+ display_positive = True
120
+ continue
121
+ if s == "--optimizer-message":
122
+ msg = True
123
+ continue
124
+ if s == "--version":
125
+ print(f"Python version {sys.version}")
126
+ exit(0)
127
+ if s == "-code":
128
+ ascode = True
129
+ continue
130
+ if s == "--usage":
131
+ print("**** schubmult_q_yz ****")
132
+ print("Purpose: Compute Molev-Sagan coefficients of quantum double Schubert polynomials")
133
+ print("Usage: schubmult_q_yz <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
134
+ exit(0)
135
+ if s == "-":
136
+ perms += [curperm]
137
+ curperm = []
138
+ continue
139
+ curperm += [int(s)]
140
+ except Exception:
141
+ print("**** schubmult_q_yz ****")
142
+ print("Purpose: Compute Molev-Sagan coefficients of quantum double Schubert polynomials")
143
+ print("Usage: schubmult_q_yz <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
144
+ exit(1)
145
+
146
+ perms += [curperm]
147
+
148
+
149
+ if ascode:
150
+ for i in range(len(perms)):
151
+ perms[i] = tuple(permtrim(uncode(perms[i])))
152
+ else:
153
+ for i in range(len(perms)):
154
+ perms[i] = tuple(permtrim([*perms[i]]))
155
+
156
+ size = 0
157
+ L = len(perms)
158
+
159
+ coeff_dict = {perms[0]: 1}
160
+ for perm in perms[1:]:
161
+ coeff_dict = schubmult(coeff_dict,perm)
162
+
163
+ if pr:
164
+ if ascode:
165
+ width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
166
+ else:
167
+ width = max([len(str(perm)) for perm in coeff_dict.keys() if expand(coeff_dict[perm])!=0])
168
+
169
+ coeff_perms = list(coeff_dict.keys())
170
+ coeff_perms.sort(key=lambda x: (inv(x),*x))
171
+
172
+ for perm in coeff_perms:
173
+ val = sympify(coeff_dict[perm]).simplify()
174
+ if val != 0:
175
+ notint = False
176
+ try:
177
+ int(val)
178
+ except Exception:
179
+ notint = True
180
+ val2 = 0
181
+ if display_positive:
182
+ q_dict = factor_out_q(val)
183
+ for q_part in q_dict:
184
+ #print(f"{q_part=} {q_dict[q_part]=}")
185
+ try:
186
+ val2 += q_part*int(q_dict[q_part])
187
+ except Exception:
188
+ try:
189
+ val2 += q_part*compute_positive_rep(q_dict[q_part],var2,var3,msg,False)
190
+ except TypeError:
191
+ print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_coeff_dict.get(perm,0)=}")
192
+ exit(1)
193
+ if check and expand(val - val2)!=0:
194
+ print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_coeff_dict.get(perm,0)=}")
195
+ exit(1)
196
+ val = val2
197
+ if val!=0:
198
+ if ascode:
199
+ print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ')}")
200
+ else:
201
+ print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ')}")
202
+ except BrokenPipeError:
203
+ pass
204
+
205
+ if __name__ == "__main__":
206
+ main()
@@ -1327,6 +1327,8 @@ def main():
1327
1327
  continue
1328
1328
  curperm += [int(s)]
1329
1329
  except Exception:
1330
+ print("**** schubmult_yz ****")
1331
+ print("Purpose: Compute products (and coproducts) of double Schubert polynomials in different sets of variables")
1330
1332
  print("Usage: schubmult_yz <-np|--no-print> <-code> <--display-positive> <--optimizer-message> perm1 - perm2 < - perm3 .. >")
1331
1333
  print("Alternative usage: schubmult_yz <-code> <--display-positive> <--optimizer-message> -coprod perm - indexlist")
1332
1334
  exit(1)
@@ -1510,10 +1512,14 @@ def main():
1510
1512
  notint = True
1511
1513
  if notint and display_positive:
1512
1514
  valu = val
1513
- if len(perms) == 2 and not posified:
1514
- val = posify(val,perms[0],perms[1],perm,var2,var3,msg)
1515
- elif not posified:
1516
- val = compute_positive_rep(val,var2,var3,msg)
1515
+ try:
1516
+ if len(perms) == 2 and not posified:
1517
+ val = posify(val,perms[0],perms[1],perm,var2,var3,msg)
1518
+ elif not posified:
1519
+ val = compute_positive_rep(val,var2,var3,msg)
1520
+ except TypeError:
1521
+ print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_coeff_dict.get(perm,0)=}")
1522
+ exit(1)
1517
1523
  if check and expand(val - check_coeff_dict.get(perm,0))!=0:
1518
1524
  print(f"error; write to schubmult@gmail.com with the case {perms=} {perm=} {val=} {check_coeff_dict.get(perm,0)=}")
1519
1525
  exit(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schubmult
3
- Version: 1.3.2
3
+ Version: 1.3.4
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,13 +15,15 @@ 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.0, it also handles quantum Schubert polynomials. 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 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:
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
22
22
  schubmult_double 1 3 4 6 2 5 - 2 1 5 7 3 4 6
23
- schubmult_yz 1 3 4 6 2 5 - 2 1 5 7 3 4 6
24
- schubmult_q 5 1 4 3 2 - 2 1 3 5 4
23
+ schubmult_yz 1 3 4 6 2 5 - 2 1 5 7 3 4 6 --display-positive
24
+ schubmult_q 5 1 4 3 2 - 5 1 3 4 2
25
+ schubmult_q_double 5 1 4 3 2 - 5 1 3 4 2
26
+ schubmult_q_yz 5 1 4 3 2 - 2 5 1 3 4 --display-positive
25
27
  ```
26
28
 
27
29
  The same execution with the Lehmer code:
@@ -29,28 +31,30 @@ The same execution with the Lehmer code:
29
31
  ```
30
32
  schubmult_py -code 0 0 1 5 6 2 3 4 - 5 6 0 0 0 0 1 2 3 4
31
33
  schubmult_double -code 0 1 1 2 - 1 0 2 3
32
- schubmult_yz -code 0 1 1 2 - 1 0 2 3
33
- schubmult_q -code 4 0 2 1 - 1 0 0 1
34
+ schubmult_yz -code 0 1 1 2 - 1 0 2 3 --display-positive
35
+ schubmult_q -code 4 0 2 1 - 4 0 1 1
36
+ schubmult_q_double -code 4 0 2 1 - 4 0 1 1
37
+ schubmult_q_yz -code 4 0 2 1 - 1 3 --display-positive
34
38
  ```
35
39
 
36
40
  For coproducts:
37
41
  ```
38
42
  schubmult_py -coprod 1 3 5 7 2 4 6 - 2 4
39
43
  schubmult_double -coprod 1 3 5 7 2 4 6 - 2 4
40
- schubmult_yz -coprod 1 3 5 7 2 4 6 - 2 4
44
+ schubmult_yz -coprod 1 3 5 7 2 4 6 - 2 4 --display-positive
41
45
  ```
42
46
  or
43
47
  ```
44
48
  schubmult_py -code -coprod 0 1 2 3 - 2 4
45
49
  schubmult_double -code -coprod 0 1 2 3 - 2 4
46
- schubmult_yz -code -coprod 0 1 2 3 - 2 4
50
+ schubmult_yz -code -coprod 0 1 2 3 - 2 4 --display-positive
47
51
  ```
48
52
 
49
53
 
50
54
 
51
- Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative and the problem is in GapP, it is not known to be in #P at this time.
55
+ Runtime will vary tremendously by case. The general problem is #P-hard. Though the result is always nonnegative (which at least is known for schubmult_py, schubmult_q, schubmult_double, and schubmult_q_double) and the problem is in GapP, it is not known to be in #P at this time.
52
56
 
53
- 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. Both have the same command line syntax as schubmult. schubmult_double displays the result with nonnegative coefficients in terms of the negative simple roots. Both are of course slower than schubmult_py, and expressing the result positively for schubmult_double slows it down even more.
57
+ 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.
54
58
 
55
59
  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).
56
60
 
@@ -69,9 +73,7 @@ from schubmult.schubmult_py import schubmult
69
73
  coeff_dict = schubmult({(1,3,4,6,2,5): 1},(2,1,5,7,3,4,6))
70
74
  ```
71
75
 
72
- Note versions 1.0.15 and prior had a bug that failed to upgrade the executable. The coefficients it computed were correct, but it was not using the updated version.
73
-
74
- Version 1.0.18 adds the command line argument --display-positive to schubmult_yz, which displays the result positively (if possible, this is still only always possible conjecturally). This is highly processor intensive.
76
+ 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.
75
77
 
76
78
  ![](https://raw.githubusercontent.com/matthematics/schubmult/main/positive_image.png)
77
79
 
@@ -19,6 +19,12 @@ schubmult/schubmult_py/schubmult_py.py
19
19
  schubmult/schubmult_q/__init__.py
20
20
  schubmult/schubmult_q/__main__.py
21
21
  schubmult/schubmult_q/schubmult_q.py
22
+ schubmult/schubmult_q_double/__init__.py
23
+ schubmult/schubmult_q_double/__main__.py
24
+ schubmult/schubmult_q_double/schubmult_q_double.py
25
+ schubmult/schubmult_q_yz/__init__.py
26
+ schubmult/schubmult_q_yz/__main__.py
27
+ schubmult/schubmult_q_yz/schubmult_q_yz.py
22
28
  schubmult/schubmult_yz/__init__.py
23
29
  schubmult/schubmult_yz/__main__.py
24
30
  schubmult/schubmult_yz/schubmult_yz.py
@@ -2,5 +2,7 @@
2
2
  schubmult_double = schubmult.schubmult_double.__main__:main
3
3
  schubmult_py = schubmult.schubmult_py.__main__:main
4
4
  schubmult_q = schubmult.schubmult_q.__main__:main
5
+ schubmult_q_double = schubmult.schubmult_q_double.__main__:main
6
+ schubmult_q_yz = schubmult.schubmult_q_yz.__main__:main
5
7
  schubmult_yz = schubmult.schubmult_yz.__main__:main
6
8
 
@@ -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.2",
9
+ version="1.3.4",
10
10
  description="Computing Littlewood-Richardson coefficients of Schubert polynomials",
11
11
  long_description=long_description,
12
12
  long_description_content_type='text/markdown',
@@ -31,6 +31,8 @@ setup(
31
31
  entry_points={"console_scripts": ["schubmult_py=schubmult.schubmult_py.__main__:main",
32
32
  "schubmult_double=schubmult.schubmult_double.__main__:main",
33
33
  "schubmult_yz=schubmult.schubmult_yz.__main__:main",
34
- "schubmult_q=schubmult.schubmult_q.__main__:main"
34
+ "schubmult_q=schubmult.schubmult_q.__main__:main",
35
+ "schubmult_q_double=schubmult.schubmult_q_double.__main__:main",
36
+ "schubmult_q_yz=schubmult.schubmult_q_yz.__main__:main"
35
37
  ]},
36
38
  )
@@ -1,105 +0,0 @@
1
- from symengine import *
2
- from functools import cache
3
- from itertools import chain
4
- from schubmult.perm_lib import *
5
- import sys
6
-
7
- def schubmult(perm_dict,v):
8
- vn1 = inverse(v)
9
- th = [len(v)-i for i in range(1,len(v)+1)]
10
- mu = permtrim(uncode(th))
11
- vmu = permtrim(mulperm([*v],mu))
12
- #print(f"{th=} {mu=} {vmu=}")
13
- inv_vmu = inv(vmu)
14
- inv_mu = inv(mu)
15
- ret_dict = {}
16
- vpaths = [([(vmu,0)],1)]
17
- while th[-1] == 0:
18
- th.pop()
19
- thL = len(th)
20
- vpathdicts = compute_vpathdicts(th,vmu,True)
21
- for u,val in perm_dict.items():
22
- inv_u = inv(u)
23
- vpathsums = {u: {(1,2): val}}
24
- for index in range(thL):
25
- mx_th = 0
26
- for vp in vpathdicts[index]:
27
- for v2,vdiff,s in vpathdicts[index][vp]:
28
- if th[index]-vdiff > mx_th:
29
- mx_th = th[index] - vdiff
30
- newpathsums = {}
31
- for up in vpathsums:
32
- newperms = elem_sym_perms_q(up,mx_th,th[index])
33
- for up2, udiff, mul_val in newperms:
34
- if up2 not in newpathsums:
35
- newpathsums[up2]={}
36
- for v in vpathdicts[index]:
37
- sumval = vpathsums[up].get(v,zero)
38
- if sumval == 0:
39
- continue
40
- for v2,vdiff,s in vpathdicts[index][v]:
41
- if udiff+vdiff==th[index]:
42
- newpathsums[up2][v2] = newpathsums[up2].get(v2,zero)+s*sumval*mul_val
43
- vpathsums = newpathsums
44
- toget = tuple(vmu)
45
- ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget,0) for ep in vpathsums},ret_dict)
46
- return ret_dict
47
-
48
-
49
- def main():
50
- try:
51
- perms=[]
52
- curperm = []
53
-
54
- pr = True
55
- ascode = False
56
- try:
57
- for s in sys.argv[1:]:
58
- if s == "-np" or s == "--no-print":
59
- pr = False
60
- continue
61
- if s == "-code":
62
- ascode = True
63
- continue
64
- if s == "-":
65
- perms += [curperm]
66
- curperm = []
67
- continue
68
- curperm += [int(s)]
69
- except Exception:
70
- print("Usage: schubmult_q <-np|--no-print> <-code> perm1 - perm2 < - perm 3 ... >")
71
- exit(1)
72
-
73
- perms += [curperm]
74
-
75
-
76
- if ascode:
77
- for i in range(len(perms)):
78
- perms[i] = uncode(perms[i])
79
-
80
- coeff_dict = {tuple(permtrim([*perms[0]])): 1}
81
-
82
- for perm in perms[1:]:
83
- coeff_dict = schubmult(coeff_dict,tuple(permtrim([*perm])))
84
-
85
- if pr:
86
- if ascode:
87
- width = max([len(str(trimcode(perm))) for perm in coeff_dict.keys()])
88
- else:
89
- width = max([len(str(perm)) for perm in coeff_dict.keys()])
90
-
91
- coeff_perms = list(coeff_dict.keys())
92
- coeff_perms.sort(key=lambda x: (inv(x),*x))
93
-
94
- for perm in coeff_perms:
95
- val = sympify(coeff_dict[perm]).expand()
96
- if val != 0:
97
- if ascode:
98
- print(f"{str(trimcode(perm)):>{width}} {str(val).replace('**','^').replace('*',' ')}")
99
- else:
100
- print(f"{str(perm):>{width}} {str(val).replace('**','^').replace('*',' ')}")
101
- except BrokenPipeError:
102
- pass
103
-
104
- if __name__ == "__main__":
105
- main()
File without changes
File without changes