Repository: sympy/sympy
Pull request: Solvers: NotImplementedError for an equation containing absolute value in Python 3
Fixes #17650 

||x² - 1| - x| = x

When did:

from sympy import *
x = Symbol('x', real=True)
solve(abs((abs(x**2-1)-x))-x)

The following error was encountered:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python36-32\lib\site-packages\sympy\solvers\solvers.py", line 1065, in solve
solution = _solve(f[0], *symbols, **flags)
  File "C:\Python36-32\lib\site-packages\sympy\solvers\solvers.py", line 1366, in _solve
candidates = _solve(piecewise_fold(expr), symbol, **flags)
  File "C:\Python36-32\lib\site-packages\sympy\solvers\solvers.py", line 1634, in _solve
raise NotImplementedError('\n'.join([msg, not_impl_msg % f]))
NotImplementedError: multiple generators [x, Abs(-x**2 + x + 1)]
No algorithms are implemented to solve equation -x + Abs(-x**2 + x + 1)

Now this error is resolved.

<!-- BEGIN RELEASE NOTES -->
* solvers
  * Fixes **NotImplementedError** for an equation containing absolute value in Python 3
<!-- END RELEASE NOTES -->


Problem statement:
Solving an equation containing absolute value, with python 3
I'm trying to solve the following equation, with python 3.6.3 on Windows 7:

||x² - 1| - x| = x

I did

    from sympy import *
    x = Symbol('x', real=True)
    solve(abs((abs(x**2-1)-x))-x)

but I get the following error:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\Python36-32\lib\site-packages\sympy\solvers\solvers.py", line 1065, in solve
    solution = _solve(f[0], *symbols, **flags)
      File "C:\Python36-32\lib\site-packages\sympy\solvers\solvers.py", line 1366, in _solve
    candidates = _solve(piecewise_fold(expr), symbol, **flags)
      File "C:\Python36-32\lib\site-packages\sympy\solvers\solvers.py", line 1634, in _solve
    raise NotImplementedError('\n'.join([msg, not_impl_msg % f]))
    NotImplementedError: multiple generators [x, Abs(-x**2 + x + 1)]
    No algorithms are implemented to solve equation -x + Abs(-x**2 + x + 1)

I updated SymPy to the latest version, 1.4, but I get the same error.

But, with python 2.7.14 I get answers, namely [1, -1+sqrt(2), 1+sqrt(2)].
Am I missing something with Python 3?

Many thanks in advance,

-- 
Cesar

Hints from issue discussion:
The SymPy codebase could be changed with the following diff to correct the problem:
```diff
diff --git a/sympy/solvers/solvers.py b/sympy/solvers/solvers.py
index 172d504..96bfa94 100644
--- a/sympy/solvers/solvers.py
+++ b/sympy/solvers/solvers.py
@@ -1020,8 +1020,13 @@ def _sympified_list(w):
         # Abs
         fi = fi.replace(Abs, lambda arg:
             separatevars(Abs(arg)) if arg.has(*symbols) else Abs(arg))
-        fi = fi.replace(Abs, lambda arg:
-            Abs(arg).rewrite(Piecewise) if arg.has(*symbols) else Abs(arg))
+        while True:
+            was = fi
+            fi = fi.replace(Abs, lambda arg:
+                (Abs(arg).rewrite(Piecewise) if arg.has(*symbols)
+                else Abs(arg)))
+            if was == fi:
+                break

         for e in fi.find(Abs):
             if e.has(*symbols):
```
Why was this closed?
Please review the PR @smichr @oscarbenjamin 
If any changes are required, please suggest.

Commit message: Added a test case

Patch to review:
diff --git a/sympy/solvers/solvers.py b/sympy/solvers/solvers.py
index f5a9d80009e8..0f2f0e7a1037 100644
--- a/sympy/solvers/solvers.py
+++ b/sympy/solvers/solvers.py
@@ -1020,8 +1020,13 @@ def _sympified_list(w):
         # Abs
         fi = fi.replace(Abs, lambda arg:
             separatevars(Abs(arg)) if arg.has(*symbols) else Abs(arg))
-        fi = fi.replace(Abs, lambda arg:
-            Abs(arg).rewrite(Piecewise) if arg.has(*symbols) else Abs(arg))
+        while True:
+            was = fi
+            fi = fi.replace(Abs, lambda arg:
+                (Abs(arg).rewrite(Piecewise) if arg.has(*symbols)
+                else Abs(arg)))
+            if was == fi:
+                break
 
         for e in fi.find(Abs):
             if e.has(*symbols):
diff --git a/sympy/solvers/tests/test_solvers.py b/sympy/solvers/tests/test_solvers.py
index 0b98a394286c..927bea804e59 100644
--- a/sympy/solvers/tests/test_solvers.py
+++ b/sympy/solvers/tests/test_solvers.py
@@ -2113,3 +2113,8 @@ def test_issue_17452():
     assert solve((7**x)**x + pi, x) == [-sqrt(log(pi) + I*pi)/sqrt(log(7)),
                                         sqrt(log(pi) + I*pi)/sqrt(log(7))]
     assert solve(x**(x/11) + pi/11, x) == [exp(LambertW(-11*log(11) + 11*log(pi) + 11*I*pi))]
+
+
+def test_issue_17650():
+    x = Symbol('x', real=True)
+    assert solve(abs((abs(x**2-1)-x))-x) == [1, -1 + sqrt(2), 1 + sqrt(2)]


Code review comments:
diff_hunk: @@ -2113,3 +2113,8 @@ def test_issue_17452():
     assert solve((7**x)**x + pi, x) == [-sqrt(log(pi) + I*pi)/sqrt(log(7)),
                                         sqrt(log(pi) + I*pi)/sqrt(log(7))]
     assert solve(x**(x/11) + pi/11, x) == [exp(LambertW(-11*log(11) + 11*log(pi) + 11*I*pi))]
+
+
+def test_issue_17650():
+    x = Symbol('x', real=True)
+    assert solve(abs((abs(x**2-1)-x))-x) == [1, -1 + sqrt(2), 1 + sqrt(2)]
path: sympy/solvers/tests/test_solvers.py
text: @user1:
Please put spaces around `-`, readability is too low.

@user1:
Does `solve(abs((abs(x**2-1)-x))-x)` always return canonical results?

@author:
What do you mean by canonical results?