Repository: sagemath/sage

Issue:
speed up conversion of lrcalc partitions to sage partitions
<div id="comment:0"></div>

We can trust lrcalc to produce partitions, and not checking this again saves a lot of time.

Component: **combinatorics**

Author: **Martin Rubey**

Branch/Commit: **[u/mantepse/speed_up_conversion_of_lrcalc_partitions_to_sage_partitions](https://github.com/sagemath/sagetrac-mirror/tree/u/mantepse/speed_up_conversion_of_lrcalc_partitions_to_sage_partitions) @ [`f87fbf8`](https://github.com/sagemath/sagetrac-mirror/commit/f87fbf86ebb7a4c424e19a2aed270910a50f1c61)**

_Issue created by migration from https://trac.sagemath.org/ticket/34549_




Discussion:
Branch: **[u/mantepse/speed_up_conversion_of_lrcalc_partitions_to_sage_partitions](https://github.com/sagemath/sagetrac-mirror/tree/u/mantepse/speed_up_conversion_of_lrcalc_partitions_to_sage_partitions)**
Commit: **[`031f85b`](https://github.com/sagemath/sagetrac-mirror/commit/031f85b1b924a7cd8d91de1b488ae6d0e9e4db3a)**
Description changed:
``````diff
--- 
+++ 
@@ -1 +1 @@
-
+We can trust lrcalc to produce partitions, and not checking this again saves a lot of time.
``````

<div id="comment:2" align="right">comment:2</div>

However, the current branch is incorrect, we want elements in `ZZ`, not python `int`

---
New commits:
<table><tr><td><a href="https://github.com/sagemath/sagetrac-mirror/commit/031f85b1b924a7cd8d91de1b488ae6d0e9e4db3a"><code>031f85b</code></a></td><td><code>bypass the element constructor of partitions, since we know that the data are good</code></td></tr></table>

Author: **Martin Rubey**
Changed commit from **[`031f85b`](https://github.com/sagemath/sagetrac-mirror/commit/031f85b1b924a7cd8d91de1b488ae6d0e9e4db3a)** to **[`f87fbf8`](https://github.com/sagemath/sagetrac-mirror/commit/f87fbf86ebb7a4c424e19a2aed270910a50f1c61)**
<div id="comment:3"></div>

Branch pushed to git repo; I updated commit sha1. New commits:
<table><tr><td><a href="https://github.com/sagemath/sagetrac-mirror/commit/f87fbf86ebb7a4c424e19a2aed270910a50f1c61"><code>f87fbf8</code></a></td><td><code>the elements of the list in a partition should be Integer, not int</code></td></tr></table>

<div id="comment:4" align="right">comment:4</div>

Comparison:

```
sage: from sage.libs.lrcalc.lrcalc import mult
sage: n=10; l = [(la, mu) for la in Partitions(n) for mu in Partitions(n)]
sage: %timeit [mult(la, mu) for la, mu in l]
1.9 s ± 321 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
sage: %timeit [mult(la, mu) for la, mu in l]
2.12 s ± 40.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
sage: %timeit [mult(la, mu) for la, mu in l]
2.08 s ± 19 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
```
vs. old:

```
sage: from sage.libs.lrcalc.lrcalc import mult
sage: n=10; l = [(la, mu) for la in Partitions(n) for mu in Partitions(n)]
sage: %timeit [mult(la, mu) for la, mu in l]
2.98 s ± 212 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
sage: %timeit [mult(la, mu) for la, mu in l]
2.64 s ± 478 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
sage: %timeit [mult(la, mu) for la, mu in l]
2.42 s ± 433 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
```

Resolving patch:
diff --git a/src/sage/libs/lrcalc/lrcalc.py b/src/sage/libs/lrcalc/lrcalc.py
--- a/src/sage/libs/lrcalc/lrcalc.py
+++ b/src/sage/libs/lrcalc/lrcalc.py
@@ -193,7 +193,7 @@
 import lrcalc
 
 
-def _lrcalc_dict_to_sage(result):
+def _lrcalc_dict_to_sage(result) -> dict:
     r"""
     Translate from lrcalc output format to Sage expected format.
 
@@ -203,7 +203,9 @@ def _lrcalc_dict_to_sage(result):
         sage: mult([2,1],[3,2,1],3) # indirect doctest
         {[3, 3, 3]: 1, [4, 3, 2]: 2, [4, 4, 1]: 1, [5, 2, 2]: 1, [5, 3, 1]: 1}
     """
-    return {_Partitions(la): Integer(k) for la, k in result.items()}
+    return {_Partitions.element_class(_Partitions, [Integer(p) for p in la]):
+            Integer(k) for la, k in result.items()}
+
 
 def lrcoef_unsafe(outer, inner1, inner2):
     r"""
@@ -268,7 +270,7 @@ def lrcoef(outer, inner1, inner2):
     return lrcoef_unsafe(_Partitions(outer), _Partitions(inner1), _Partitions(inner2))
 
 
-def mult(part1, part2, maxrows=None, level=None, quantum=None):
+def mult(part1, part2, maxrows=None, level=None, quantum=None) -> dict:
     r"""
     Compute a product of two Schur functions.
 
@@ -345,13 +347,13 @@ def mult(part1, part2, maxrows=None, level=None, quantum=None):
     result = lrcalc.mult_quantum(part1, part2, maxrows, level, degrees=True)
     P = quantum.parent()
     output = {}
-    for i,k in result.items():
+    for i, k in result.items():
         la = _Partitions(i[0])
         output[la] = output.get(la, P.zero()) + k * quantum**(i[1])
     return output
 
 
-def skew(outer, inner, maxrows=-1):
+def skew(outer, inner, maxrows=-1) -> dict:
     """
     Compute the Schur expansion of a skew Schur function.
 
@@ -377,7 +379,7 @@ def skew(outer, inner, maxrows=-1):
     return _lrcalc_dict_to_sage(lrcalc.skew(outer, inner, maxrows))
 
 
-def coprod(part, all=0):
+def coprod(part, all=0) -> dict:
     """
     Compute the coproduct of a Schur function.
 
@@ -404,11 +406,13 @@ def coprod(part, all=0):
         [(([1, 1], [1]), 1), (([2], [1]), 1), (([2, 1], []), 1)]
     """
     result = lrcalc.coprod(part, all)
-    return {tuple([_Partitions(mu) for mu in la]): Integer(k)
+    return {tuple([_Partitions.element_class(_Partitions,
+                                             [Integer(p) for p in mu])
+                   for mu in la]): Integer(k)
             for la, k in result.items()}
 
 
-def mult_schubert(w1, w2, rank=0):
+def mult_schubert(w1, w2, rank=0) -> dict:
     r"""
     Compute a product of two Schubert polynomials.
 
@@ -436,7 +440,7 @@ def mult_schubert(w1, w2, rank=0):
          ([7, 3, 4, 1, 2, 5, 6], 1), ([7, 4, 2, 1, 3, 5, 6], 1)]
     """
     result = lrcalc.schubmult(w1, w2, rank)
-    return {Permutation(list(la)):Integer(k) for la,k in result.items()}
+    return {Permutation(list(la)): Integer(k) for la, k in result.items()}
 
 
 def lrskew(outer, inner, weight=None, maxrows=-1):
@@ -503,7 +507,7 @@ def lrskew(outer, inner, weight=None, maxrows=-1):
     if weight is None:
         ST = SemistandardSkewTableaux(shape)
         for data in iterator:
-            yield ST.from_shape_and_word(shape, [i+1 for i in data])
+            yield ST.from_shape_and_word(shape, [i + 1 for i in data])
     else:
         wt = _Partitions(weight)
         ST = SemistandardSkewTableaux(shape, wt)
@@ -517,4 +521,4 @@ def lrskew(outer, inner, weight=None, maxrows=-1):
                     break
                 w[j] += 1
             if w == wt:
-                yield ST.from_shape_and_word(shape, [i+1 for i in data])
+                yield ST.from_shape_and_word(shape, [i + 1 for i in data])


Test patch: