Repository: sympy/sympy

Issue:
coeff() fails with non-commutative argument
Diffgeom results in a wrong result for the double Lie Bracket of three vectors 
Commutator(Commutator(v1,v2),v3)
where
v1 = exp(r)*e_r + exp(r**2)*e_theta
v2 = sin(theta)*e_r
v3 = e_theta+e_r 
xs = r,    theta   = spherical.coord_functions()
es = e_r,  e_theta = spherical.base_vectors() 

Full example in [sympy googlegroup thread](https://groups.google.com/forum/#!topic/sympy/zmGIsxmzV0c).

This leads to violation of Jacobi identities for Commutator.

Ideas:
> It looks like there is a bug in Expr.coeff. It cannot find the coefficient of e_r in Commutator(v1, v2), apparently because of non-commutativity.  K Souminen

Discussion:

Patch:
diff --git a/sympy/core/expr.py b/sympy/core/expr.py
index 1d56135839..4f46a2d8ca 100644
--- a/sympy/core/expr.py
+++ b/sympy/core/expr.py
@@ -11,6 +11,7 @@
 from .compatibility import as_int, default_sort_key
 from .kind import NumberKind
 from sympy.utilities.misc import func_name
+from sympy.utilities.iterables import has_variety
 from mpmath.libmp import mpf_log, prec_to_dps
 
 from collections import defaultdict
@@ -1369,7 +1370,7 @@ def args_cnc(self, cset=False, warn=True, split_1=True):
                                  [ci for ci in c if list(self.args).count(ci) > 1])
         return [c, nc]
 
-    def coeff(self, x, n=1, right=False):
+    def coeff(self, x, n=1, right=False, _first=True):
         """
         Returns the coefficient from the term(s) containing ``x**n``. If ``n``
         is zero then all terms independent of ``x`` will be returned.
@@ -1565,6 +1566,18 @@ def find(l, sub, first=True):
         x_c = x.is_commutative
         if self_c and not x_c:
             return S.Zero
+        if _first and self.is_Add and not self_c and not x_c:
+            # get the part that depends on x exactly
+            xargs = Mul.make_args(x)
+            d = Add(*[i for i in Add.make_args(self.as_independent(x)[1])
+                if all(xi in Mul.make_args(i) for xi in xargs)])
+            rv = d.coeff(x, right=right, _first=False)
+            if not rv.is_Add or not right:
+                return rv
+            c_part, nc_part = zip(*[i.args_cnc() for i in rv.args])
+            if has_variety(c_part):
+                return rv
+            return Add(*[Mul._from_args(i) for i in nc_part])
 
         one_c = self_c or x_c
         xargs, nx = x.args_cnc(cset=True, warn=bool(not x_c))


Test patch:
diff --git a/sympy/core/tests/test_expr.py b/sympy/core/tests/test_expr.py
index 5cc0307a26..9fae0124a0 100644
--- a/sympy/core/tests/test_expr.py
+++ b/sympy/core/tests/test_expr.py
@@ -1412,11 +1412,18 @@ def test_coeff():
     assert (n*m + m*n*m).coeff(n, right=True) == m  # = (1 + m)*n*m
     assert (n*m + m*n).coeff(n) == 0
     assert (n*m + o*m*n).coeff(m*n) == o
-    assert (n*m + o*m*n).coeff(m*n, right=1) == 1
-    assert (n*m + n*m*n).coeff(n*m, right=1) == 1 + n  # = n*m*(n + 1)
+    assert (n*m + o*m*n).coeff(m*n, right=True) == 1
+    assert (n*m + n*m*n).coeff(n*m, right=True) == 1 + n  # = n*m*(n + 1)
 
     assert (x*y).coeff(z, 0) == x*y
 
+    assert (x*n + y*n + z*m).coeff(n) == x + y
+    assert (n*m + n*o + o*l).coeff(n, right=True) == m + o
+    assert (x*n*m*n + y*n*m*o + z*l).coeff(m, right=True) == x*n + y*o
+    assert (x*n*m*n + x*n*m*o + z*l).coeff(m, right=True) == n + o
+    assert (x*n*m*n + x*n*m*o + z*l).coeff(m) == x*n
+
+
 def test_coeff2():
     r, kappa = symbols('r, kappa')
     psi = Function("psi")
diff --git a/sympy/diffgeom/tests/test_diffgeom.py b/sympy/diffgeom/tests/test_diffgeom.py
index 362a77e4aa..d0d39f3619 100644
--- a/sympy/diffgeom/tests/test_diffgeom.py
+++ b/sympy/diffgeom/tests/test_diffgeom.py
@@ -318,3 +318,10 @@ def test_simplify():
     assert simplify(dx*dy) == dx*dy
     assert simplify(ex*ey) == ex*ey
     assert ((1-x)*dx)/(1-x)**2 == dx/(1-x)
+
+
+def test_issue_17917():
+    X = R2.x*R2.e_x - R2.y*R2.e_y
+    Y = (R2.x**2 + R2.y**2)*R2.e_x - R2.x*R2.y*R2.e_y
+    assert LieDerivative(X, Y).expand() == (
+        R2.x**2*R2.e_x - 3*R2.y**2*R2.e_x - R2.x*R2.y*R2.e_y)