Repository: sagemath/sage

Issue:
Squares not working in completion of free algebra
### Steps To Reproduce

```
sage: R=algebras.Free(QQ,('A','B'),degrees=(1,2))
sage: Rc=R.completion()
sage: A,B=R.gens()
sage: Rc(A)+1
1 + A
sage: Rc(A)**2
...
TypeError: unable to convert (A,) to a rational
```

### Expected Behavior

This should return `A^2`

### Actual Behavior

raise TypeError

### Additional Information

_No response_

### Environment

```markdown
- **OS**:ubuntu 22.04
- **Sage Version**:10.3.rc4
```


### Checklist

- [X] I have searched the existing issues for a bug report that matches the one I want to file, without success.
- [X] I have read the documentation and troubleshoot guide


Discussion:
@mantepse (for the record)
The problem is as follows.  We describe terminating elements (i.e., elements that have finite degree, and all coefficients are known) of the completion of a non-commutative algebra as elements of `self._internal_poly_ring = FreeAlgebra(self._laurent_poly_ring, 1, "DUMMY_VARIABLE")`, whereas in the commutative case we use `self._internal_poly_ring = PolynomialRing(self._laurent_poly_ring, "DUMMY_VARIABLE", sparse=sparse)`.

The latter supports the construction of an element from a tuple.  For example:
```
sage: QQ["DUMMMY"]((1,2,3,4))
4*DUMMMY^3 + 3*DUMMMY^2 + 2*DUMMMY + 1
```
The former doesn't:
```
sage: FreeAlgebra(QQ, 1, "DUMMY")((1,2,3))
...
TypeError: unable to convert (1, 2, 3) to a rational
```
I actually don't see the reason why we did this:
```
e7bf85306d1e src/sage/rings/lazy_series_ring.py         (Martin Rubey      2022-07-27 18:50:34 +0530 2740)         self._laurent_poly_ring = basis
dff4fc4b7ecd src/sage/rings/lazy_series_ring.py         (Travis Scrimshaw  2022-08-22 18:44:28 +0900 2741)         if self._laurent_poly_ring not in Rings().Commutative():
dff4fc4b7ecd src/sage/rings/lazy_series_ring.py         (Travis Scrimshaw  2022-08-22 18:44:28 +0900 2742)             from sage.algebras.free_algebra import FreeAlgebra
dff4fc4b7ecd src/sage/rings/lazy_series_ring.py         (Travis Scrimshaw  2022-08-22 18:44:28 +0900 2743)             self._internal_poly_ring = FreeAlgebra(self._laurent_poly_ring, 1, "DUMMY_VARIABLE")
dff4fc4b7ecd src/sage/rings/lazy_series_ring.py         (Travis Scrimshaw  2022-08-22 18:44:28 +0900 2744)         else:
de424bd78aab src/sage/rings/lazy_series_ring.py         (Martin Rubey      2022-10-13 08:50:39 +0200 2745)             self._internal_poly_ring = PolynomialRing(self._laurent_poly_ring, "DUMMY_VARIABLE", sparse=sparse)
```
@tscrim, might this be a thinko?


No, this is because we need to care about the order of the coefficient multiplication and the free algebra should make sure of that (or at least it doesn’t require the base ring to be commutative in contrast to the polynomial ring).

To fix this, we might want to have our own special class for univariate free algebras. This could be useful to speed up some things for general completions…
Doesn't the polynomial ring support non-commutative base rings?  I would have thought it does:
```
age: M = MatrixSpace(QQ, 2)                                                                                                                                 
sage: R.<x> = M[]                                                                                                                                            
sage: R                                                                                                                                                      
Univariate Polynomial Ring in x over Full MatrixSpace of 2 by 2 dense matrices over Rational Field                                                           
sage: m1 = matrix([[1,0],[1,1]])                                                                                                                             
sage: m2 = matrix([[1,1],[0,1]])                                                                                                                             
sage: m1*m2 - m2*m1                                                                                                                                          
[-1  0]                                                                                                                                                      
[ 0  1]                                                                                                                                                      
sage: p = m1*x + m2                                                                                                                                          
sage: q = m2*x + m1                                                                                                                                          
sage: list(p*q - q*p)
[
[ 1  0]  [0 0]  [-1  0]
[ 0 -1], [0 0], [ 0  1]
]
```
The univariate polynomial ring says it supports noncommutative base rings, but I vaguely remember having issues with it when I tried it previously.  Perhaps everything is fine, and I am just misremembering.


Resolving patch:
diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py
--- a/src/sage/rings/lazy_series_ring.py
+++ b/src/sage/rings/lazy_series_ring.py
@@ -2716,6 +2716,13 @@ def __init__(self, basis, sparse=True, category=None):
             ...
             ValueError: basis should be in GradedAlgebrasWithBasis
 
+        Check that :issue:`37625` is fixed::
+
+            sage: R = algebras.Free(QQ, ('a', 'b'), degrees=(1, 2))
+            sage: L = R.completion()
+            sage: a, b = R.gens()
+            sage: (L(a) + L(b))^2
+            a^2 + (a*b+b*a) + b^2
         """
         base_ring = basis.base_ring()
         self._minimal_valuation = 0
@@ -2738,11 +2745,7 @@ def __init__(self, basis, sparse=True, category=None):
         Parent.__init__(self, base=base_ring, category=category)
         self._sparse = sparse
         self._laurent_poly_ring = basis
-        if self._laurent_poly_ring not in Rings().Commutative():
-            from sage.algebras.free_algebra import FreeAlgebra
-            self._internal_poly_ring = FreeAlgebra(self._laurent_poly_ring, 1, "DUMMY_VARIABLE")
-        else:
-            self._internal_poly_ring = PolynomialRing(self._laurent_poly_ring, "DUMMY_VARIABLE", sparse=sparse)
+        self._internal_poly_ring = PolynomialRing(self._laurent_poly_ring, "DUMMY_VARIABLE", sparse=sparse)
 
     def _repr_(self):
         """


Test patch: