Repository: sagemath/sage

Issue:
g_algebras don't work over fields with parameters.
<div id="comment:0"></div>

We can create g_algebras over QQ, but not over QQ(s), for example:

```
sage: F.<x,y>=FreeAlgebra(QQ)                                                                                                                            
sage: F.g_algebra({y*x:x*y})                                                                                                                             
Noncommutative Multivariate Polynomial Ring in x, y over Rational Field, nc-relations: {}
sage: S=QQ['t'].fraction_field()                                                                                                                         
sage: F.<x,y>=FreeAlgebra(S)                                                                                                                             
sage: F.g_algebra({y*x:x*y})                                                                                                                             
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-47-86bec682bf82> in <module>()
----> 1 F.g_algebra({y*x:x*y})

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/algebras/free_algebra.pyc in g_algebra(self, relations, names, order, check)
    869                 dmat[v2_ind,v1_ind]=d_poly
    870         from sage.rings.polynomial.plural import g_Algebra
--> 871         return g_Algebra(base_ring, cmat, dmat, names = names or self.variable_names(), order=order, check=check)
    872 
    873 from sage.misc.cache import Cache

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/factory.so in sage.structure.factory.UniqueFactory.__call__ (sage/structure/factory.c:1157)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/polynomial/plural.so in sage.rings.polynomial.plural.G_AlgFactory.create_key_and_extra_args (sage/rings/polynomial/plural.cpp:4858)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/matrix/matrix0.so in sage.matrix.matrix0.Matrix.change_ring (sage/matrix/matrix0.c:8931)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/matrix/matrix_space.pyc in __call__(self, entries, coerce, copy, rows)
    505             deprecation(13012, "'rows=True/False' parameter is deprecated!")
    506             return self.matrix(entries, coerce, copy, rows)
--> 507         return self.matrix(entries, coerce, copy)
    508 
    509     def change_ring(self, R):

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/matrix/matrix_space.pyc in matrix(self, x, coerce, copy, rows)
   1376                 x = list_to_dict(x, m, n)
   1377                 copy = False
-> 1378         return MC(self, x, copy=copy, coerce=coerce)
   1379 
   1380     def matrix_space(self, nrows=None, ncols=None, sparse=False):

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/matrix/matrix_generic_dense.so in sage.matrix.matrix_generic_dense.Matrix_generic_dense.__init__ (sage/matrix/matrix_generic_dense.c:2764)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/polynomial/multi_polynomial_ring.pyc in __call__(self, x, check)
    485             return MPolynomial_polydict(self, x)
    486         else:
--> 487             c = self.base_ring()(x)
    488             return MPolynomial_polydict(self, {self._zero_tuple:c})
    489 

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/parent.so in sage.structure.parent.Parent.__call__ (sage/structure/parent.c:8134)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/coerce_maps.so in sage.structure.coerce_maps.DefaultConvertMap_unique._call_ (sage/structure/coerce_maps.c:3856)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/coerce_maps.so in sage.structure.coerce_maps.DefaultConvertMap_unique._call_ (sage/structure/coerce_maps.c:3757)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/fraction_field.pyc in _element_constructor_(self, x, y, coerce)
    491                 return self._element_class(self, x.numerator(), x.denominator())
    492         return self._element_class(self, x, y,
--> 493                 coerce=coerce, reduce = self.is_exact())
    494 
    495     def construction(self):

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/fraction_field_element.so in sage.rings.fraction_field_element.FractionFieldElement.__init__ (sage/rings/fraction_field_element.c:2539)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/fraction_field_element.so in sage.rings.fraction_field_element.FractionFieldElement.__init__ (sage/rings/fraction_field_element.c:2381)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/parent.so in sage.structure.parent.Parent.__call__ (sage/structure/parent.c:8134)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/coerce_maps.so in sage.structure.coerce_maps.DefaultConvertMap_unique._call_ (sage/structure/coerce_maps.c:3856)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/coerce_maps.so in sage.structure.coerce_maps.DefaultConvertMap_unique._call_ (sage/structure/coerce_maps.c:3757)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/polynomial/polynomial_ring.pyc in _element_constructor_(self, x, check, is_gen, construct, **kwds)                                                                                                                                        
    424             if x.type() != 't_POL':
    425                 x = x.Polrev()
--> 426         return C(self, x, check, is_gen, construct=construct, **kwds)
    427 
    428     def is_integral_domain(self, proof = True):

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/polynomial/polynomial_rational_flint.so in sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint.__init__ (sage/rings/polynomial/polynomial_rational_flint.cpp:6205)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/parent.so in sage.structure.parent.Parent.__call__ (sage/structure/parent.c:8134)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/coerce_maps.so in sage.structure.coerce_maps.DefaultConvertMap_unique._call_ (sage/structure/coerce_maps.c:3856)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/coerce_maps.so in sage.structure.coerce_maps.DefaultConvertMap_unique._call_ (sage/structure/coerce_maps.c:3757)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/rational.so in sage.rings.rational.Rational.__init__ (sage/rings/rational.c:6728)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/rational.so in sage.rings.rational.Rational.__set_value (sage/rings/rational.c:8028)()

TypeError: Unable to coerce 0 (<class 'sage.algebras.free_algebra_element.FreeAlgebra_generic_with_category.element_class'>) to Rational
```

It is not a problem with singular, since it supports these constructions, i guess there is some bug somewhere, but i am having a hard time trying to track it.


CC:  @burcin @simon-king-jena @malb @alauve @sagetrac-meeseongim @canozanoguz

Component: **algebra**

Keywords: **q_algebras, plural, sagedays@icerm**

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




Discussion:
Attachment: **[minor_improvement_coercion.patch.gz](https://github.com/sagemath/sage-prod/files/10658129/minor_improvement_coercion.patch.gz)**
<div id="comment:1" align="right">comment:1</div>

Ok, i could investigate something. One problem was that the d_matrix was created in the free algebra, and at some point, it tried to convert it to the corresponding polynomial ring (which is what singular expects). For some reason, sage didn't know how to do it if the base ring is a fraction field. There is even a comment in the source code stating that the coercion doesn't work, and we have to use a workaround. This patch makes the wourkaround an bit more complicated, but now builds the matrix in the polynomial ring.

Although now we hit a new proble: apparently, the plural interface does not support this kind of rings:

```

sage: S=FractionField(QQ['t'])                                                                                                                     
sage: F.<x,y>=FreeAlgebra(S)                                                                                                                       
sage: F.g_algebra({y*x:-x*y+1+y})                                                                                                                  
singular_ring_delete(ring*) called with NULL pointer.
  File "/home/mmarco/sage-5.11.beta1/local/bin/sage-ipython", line 18, in <module>
    app.start()
  File "/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/IPython/frontend/terminal/ipapp.py", line 363, in start
    self.shell.mainloop()
  File "/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/IPython/frontend/terminal/interactiveshell.py", line 467, in mainloop
    self.interact(display_banner=display_banner)
  File "/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/IPython/frontend/terminal/interactiveshell.py", line 586, in interact
    self.run_cell(source_raw, store_history=True)
  File "/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2592, in run_cell
    interactivity=interactivity)
  File "/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2671, in run_ast_nodes
    if self.run_code(code):
  File "/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2721, in run_code
    exec code_obj in self.user_global_ns, self.user_ns
  File "<ipython-input-11-ec881bbe4ed3>", line 1, in <module>
    F.g_algebra({y*x:-x*y+Integer(1)+y})
  File "/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/algebras/free_algebra.py", line 876, in g_algebra
    order=order, check=check)
Exception KeyError: (The ring pointer 0x0,) in 'sage.libs.singular.ring.singular_ring_delete' ignored
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-11-ec881bbe4ed3> in <module>()
----> 1 F.g_algebra({y*x:-x*y+Integer(1)+y})

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/algebras/free_algebra.pyc in g_algebra(self, relations, names, order, check)
    874         from sage.rings.polynomial.plural import g_Algebra
    875         return g_Algebra(base_ring, cmat, dmat, names = names or self.variable_names(),
--> 876                          order=order, check=check)
    877 
    878 from sage.misc.cache import Cache

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/factory.so in sage.structure.factory.UniqueFactory.__call__ (sage/structure/factory.c:1242)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/structure/factory.so in sage.structure.factory.UniqueFactory.get_object (sage/structure/factory.c:1435)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/polynomial/plural.so in sage.rings.polynomial.plural.G_AlgFactory.create_object (sage/rings/polynomial/plural.cpp:4450)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/rings/polynomial/plural.so in sage.rings.polynomial.plural.NCPolynomialRing_plural.__init__ (sage/rings/polynomial/plural.cpp:5300)()

/home/mmarco/sage-5.11.beta1/local/lib/python2.7/site-packages/sage/libs/singular/function.so in sage.libs.singular.function.SingularFunction.__call__ (sage/libs/singular/function.cpp:12438)()

TypeError: Cannot call Singular function 'nc_algebra' with ring parameter of type '<class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_domain_with_category'>'

```
<div id="comment:5" align="right">comment:5</div>

The coercion seems to work fine in g_algebra. The problem occurs in the g_Algebra function, which is in the plural file. I still made some changes to the g_algebra, namely now the error messages are more informative when the inputs are not valid. Here is the modified code: 


```
   #from sage.matrix.constructor import Matrix
        import six
        
        base_ring = self.base_ring()  #pick out the base ring
        n = self.ngens()   #pick out the number of generators of the algebra
        cmat = Matrix(base_ring, n)    #matrix of coefficients
        dmat = Matrix(self, n)         #matrix of resolution terms
        for i in range(n):
            for j in range(i + 1, n):
                cmat[i,j] = 1          #set all entries of coefficient matrix to be 1, modify as necessary down below
        for (to_commute,commuted) in six.iteritems(relations):   #to_commute is yx, commuted is c_ij*xy+d_ij
                                                                  #This is dirty, coercion is broken
            assert isinstance(to_commute, FreeAlgebraElement), str(to_commute)+" should be a FreeAlgebraElement, however right now it belongs to "+str(to_commute.__class__)    #check if yx is in the free algebra
            assert isinstance(commuted, FreeAlgebraElement), str(commuted)+" should be a FreeAlgebraElement, however right now it belongs to "+str(commuted.__class__)    #check if c_ij*xy+d_ij is in the free algebra
            ((v1,e1),(v2,e2)) = list(list(to_commute)[0][0])  #store the order and exponents of yx
            assert e1 == 1    #check both variables have exponent 1
            assert e2 == 1
            assert v1 > v2    #check the terms in yx are in the correct  declared order
            c_coef = None
            d_poly = None
            #print(list(commuted))
            for (m,c) in commuted:        #find xy on the right hand side and its coefficient c_ij, then calculate d_ij
                if list(m) == [(v2,1),(v1,1)]:
                    c_coef = c
                    #buggy coercion workaround
                    d_poly = commuted - self(c) * self(m)
                    break
            assert not c_coef is None,list(m)  #check if xy appeared on the right hand side
            v2_ind = self.gens().index(v2)    #get the indices of the variables x and y
            v1_ind = self.gens().index(v1)
            cmat[v2_ind,v1_ind] = c_coef   #change the coefficient matrix using the indices obtained above
            if d_poly:
                dmat[v2_ind,v1_ind] = d_poly   #change the resolution terms matrix using the indices obtained above
            #print cmat
            #print dmat
        from sage.rings.polynomial.plural import g_Algebra
        return g_Algebra(base_ring, cmat, dmat, names = names or self.variable_names(),
                         order=order, check=check)
```
Changed keywords from **q_algebras, plural** to **q_algebras, plural, sagedays@ICERM**
<div id="comment:7" align="right">comment:7</div>

You should make that into a branch and upload it to trac (and add your real name to the authors field). :)
Changed keywords from **q_algebras, plural, sagedays@ICERM** to **q_algebras, plural, sagedays@icerm**
<div id="comment:9" align="right">comment:9</div>

update milestone 8.3 -> 8.4
<div id="comment:10" align="right">comment:10</div>

Here is a more basic bug:

```
sage: S = QQ['t'].fraction_field()                       
sage: F.<x,y> = FreeAlgebra(S)                   
sage: S(F.zero())
```

and even more simple:

```
sage: F=FreeAlgebra(QQ,'x')                                                     
sage: QQ(F.zero()) 
```
<div id="comment:11" align="right">comment:11</div>

#16567 solves this now. Please review it

Resolving patch:
diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py
--- a/src/sage/algebras/free_algebra.py
+++ b/src/sage/algebras/free_algebra.py
@@ -127,7 +127,7 @@
     NotImplementedError: polynomials over Free Algebra on 2 generators (a, b) over Integer Ring are not supported in Singular
 """
 
-#*****************************************************************************
+# ***************************************************************************
 #       Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu>
 #       Copyright (C) 2005,2006 William Stein <wstein@gmail.com>
 #       Copyright (C) 2011 Simon King <simon.king@uni-jena.de>
@@ -136,8 +136,8 @@
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 2 of the License, or
 # (at your option) any later version.
-#                  http://www.gnu.org/licenses/
-#*****************************************************************************
+#                  https://www.gnu.org/licenses/
+# ***************************************************************************
 
 
 from sage.categories.rings import Rings
@@ -240,9 +240,9 @@ class FreeAlgebraFactory(UniqueFactory):
         a*b^2*c^3
     """
     def create_key(self, base_ring, arg1=None, arg2=None,
-            sparse=None, order=None,
-            names=None, name=None,
-            implementation=None, degrees=None):
+                   sparse=None, order=None,
+                   names=None, name=None,
+                   implementation=None, degrees=None):
         """
         Create the key under which a free algebra is stored.
 
@@ -268,7 +268,7 @@ def create_key(self, base_ring, arg1=None, arg2=None,
             # this is used for pickling
             if degrees is None:
                 return (base_ring,)
-            return tuple(degrees),base_ring
+            return tuple(degrees), base_ring
         # test if we can use libSingular/letterplace
         if implementation == "letterplace":
             if order is None:
@@ -321,7 +321,6 @@ def create_object(self, version, key):
             Free Associative Unital Algebra on 2 generators (x, y) over Rational Field
             sage: FreeAlgebra.create_object('4.7.1', (QQ['x','y'],)) is FreeAlgebra(QQ,['x','y'])
             False
-
         """
         if len(key) == 1:
             from sage.algebras.letterplace.free_algebra_letterplace import FreeAlgebra_letterplace
@@ -335,7 +334,7 @@ def create_object(self, version, key):
 FreeAlgebra = FreeAlgebraFactory('FreeAlgebra')
 
 
-def is_FreeAlgebra(x):
+def is_FreeAlgebra(x) -> bool:
     """
     Return True if x is a free algebra; otherwise, return False.
 
@@ -352,10 +351,9 @@ def is_FreeAlgebra(x):
         True
         sage: is_FreeAlgebra(FreeAlgebra(ZZ,10,'x',implementation='letterplace', degrees=list(range(1,11))))
         True
-
     """
     from sage.algebras.letterplace.free_algebra_letterplace import FreeAlgebra_letterplace
-    return isinstance(x, (FreeAlgebra_generic,FreeAlgebra_letterplace))
+    return isinstance(x, (FreeAlgebra_generic, FreeAlgebra_letterplace))
 
 
 class FreeAlgebra_generic(CombinatorialFreeModule, Algebra):
@@ -383,8 +381,7 @@ class FreeAlgebra_generic(CombinatorialFreeModule, Algebra):
 
     TESTS:
 
-    Free algebras commute with their base ring.
-    ::
+    Free algebras commute with their base ring::
 
         sage: K.<a,b> = FreeAlgebra(QQ)
         sage: K.is_commutative()
@@ -463,9 +460,11 @@ def one_basis(self):
         """
         return self._indices.one()
 
-    def is_field(self, proof=True):
+    def is_field(self, proof=True) -> bool:
         """
-        Return True if this Free Algebra is a field, which is only if the
+        Return ``True`` if this Free Algebra is a field.
+
+        This happens only if the
         base ring is a field and there are no generators
 
         EXAMPLES::
@@ -481,9 +480,9 @@ def is_field(self, proof=True):
             return self.base_ring().is_field(proof)
         return False
 
-    def is_commutative(self):
+    def is_commutative(self) -> bool:
         """
-        Return True if this free algebra is commutative.
+        Return ``True`` if this free algebra is commutative.
 
         EXAMPLES::
 
@@ -496,7 +495,7 @@ def is_commutative(self):
         """
         return self.__ngens <= 1 and self.base_ring().is_commutative()
 
-    def _repr_(self):
+    def _repr_(self) -> str:
         """
         Text representation of this free algebra.
 
@@ -514,7 +513,7 @@ def _repr_(self):
         return "Free Algebra on {} generators {} over {}".format(
             self.__ngens, self.gens(), self.base_ring())
 
-    def _latex_(self):
+    def _latex_(self) -> str:
         r"""
         Return a latex representation of ``self``.
 
@@ -588,9 +587,9 @@ def _element_constructor_(self, x):
                 return x
             if P is not self.base_ring():
                 return self.element_class(self, x)
-        elif hasattr(x,'letterplace_polynomial'):
+        elif hasattr(x, 'letterplace_polynomial'):
             P = x.parent()
-            if self.has_coerce_map_from(P): # letterplace versus generic
+            if self.has_coerce_map_from(P):  # letterplace versus generic
                 ngens = P.ngens()
                 M = self._indices
 
@@ -598,14 +597,15 @@ def exp_to_monomial(T):
                     out = []
                     for i in range(len(T)):
                         if T[i]:
-                            out.append((i % ngens,T[i]))
+                            out.append((i % ngens, T[i]))
                     return M(out)
-                return self.element_class(self, {exp_to_monomial(T):c for T,c in x.letterplace_polynomial().dict().items()})
+                return self.element_class(self, {exp_to_monomial(T): c
+                                                 for T, c in x.letterplace_polynomial().dict().items()})
         # ok, not a free algebra element (or should not be viewed as one).
         if isinstance(x, str):
             from sage.misc.sage_eval import sage_eval
             G = self.gens()
-            d = {str(v): G[i] for i,v in enumerate(self.variable_names())}
+            d = {str(v): G[i] for i, v in enumerate(self.variable_names())}
             return self(sage_eval(x, locals=d))
         R = self.base_ring()
         # coercion from free monoid
@@ -619,7 +619,7 @@ def exp_to_monomial(T):
         # Check if it's a factorization
         from sage.structure.factorization import Factorization
         if isinstance(x, Factorization):
-            return self.prod(f**i for f,i in x)
+            return self.prod(f**i for f, i in x)
 
         # coercion via base ring
         x = R(x)
@@ -849,38 +849,50 @@ def g_algebra(self, relations, names=None, order='degrevlex', check=True):
             sage: (x,y,z) = G.gens()
             sage: y*x
             -x*y + z
+
+        TESTS::
+
+            sage: S = FractionField(QQ['t'])
+            sage: t = S.gen()
+            sage: F.<x,y> = FreeAlgebra(S)
+            sage: K = F.g_algebra({y*x:-x*y+1+y})
+            sage: x,y = K.gens()
+            sage: 1+t*y*x
+            (-t)*x*y + t*y + (t + 1)
         """
         from sage.matrix.constructor import Matrix
 
         base_ring = self.base_ring()
+        polynomial_ring = PolynomialRing(base_ring, self.gens())
         n = self.__ngens
         cmat = Matrix(base_ring, n)
-        dmat = Matrix(self, n)
+        dmat = Matrix(polynomial_ring, n)
         for i in range(n):
             for j in range(i + 1, n):
-                cmat[i,j] = 1
-        for (to_commute,commuted) in relations.items():
-            #This is dirty, coercion is broken
-            assert isinstance(to_commute, FreeAlgebraElement), to_commute.__class__
+                cmat[i, j] = 1
+        for to_commute, commuted in relations.items():
+            # This is dirty, coercion is broken
+            assert isinstance(to_commute, FreeAlgebraElement), to_commute
             assert isinstance(commuted, FreeAlgebraElement), commuted
-            ((v1,e1),(v2,e2)) = list(list(to_commute)[0][0])
+            (v1, e1), (v2, e2) = next(iter(to_commute))[0]
             assert e1 == 1
             assert e2 == 1
             assert v1 > v2
             c_coef = None
             d_poly = None
+            reverse_monomial = v2 * v1
             for m, c in commuted:
-                if list(m) == [(v2,1),(v1,1)]:
+                if m == reverse_monomial:
                     c_coef = c
                     # buggy coercion workaround
-                    d_poly = commuted - self(c) * self(m)
+                    d_poly = commuted - c * self.monomial(m)
                     break
-            assert c_coef is not None, list(m)
+            assert c_coef is not None, m
             v2_ind = self.gens().index(v2)
             v1_ind = self.gens().index(v1)
-            cmat[v2_ind,v1_ind] = c_coef
+            cmat[v2_ind, v1_ind] = c_coef
             if d_poly:
-                dmat[v2_ind,v1_ind] = d_poly
+                dmat[v2_ind, v1_ind] = polynomial_ring(d_poly)
         from sage.rings.polynomial.plural import g_Algebra
         return g_Algebra(base_ring, cmat, dmat,
                          names=names or self.variable_names(),
@@ -920,18 +932,18 @@ def pbw_element(self, elt):
             return PBW.zero()
 
         l = {}
-        while elt: # != 0
+        while elt:  # != 0
             lst = list(elt)
             support = [i[0].to_word() for i in lst]
             min_elt = support[0]
-            for word in support[1:len(support)-1]:
+            for word in support[1:len(support) - 1]:
                 if min_elt.lex_less(word):
                     min_elt = word
             coeff = lst[support.index(min_elt)][1]
             min_elt = min_elt.to_monoid_element()
             l[min_elt] = l.get(min_elt, 0) + coeff
             elt = elt - coeff * self.lie_polynomial(min_elt)
-        return PBW.sum_of_terms([(k, v) for k,v in l.items() if v != 0], distinct=True)
+        return PBW.sum_of_terms([(k, v) for k, v in l.items() if v != 0], distinct=True)
 
     def lie_polynomial(self, w):
         """
@@ -1000,10 +1012,10 @@ def lie_polynomial(self, w):
             if len(factor) == 1:
                 ret = ret * self(M(factor))
                 continue
-            x,y = factor.standard_factorization()
+            x, y = factor.standard_factorization()
             x = self.lie_polynomial(M(x))
             y = self.lie_polynomial(M(y))
-            ret = ret * (x*y - y*x)
+            ret = ret * (x * y - y * x)
         return ret
 
 


Test patch: