Repository: sympy/sympy

Issue:
Solvify cannot solve Piecewise
```
>>> p = Piecewise((0, x < -1), (x**2, x <= 1), (log(x), True))
>>> solvify(p,x,S.Reals)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/sayandip/sympy/sympy/solvers/solveset.py", line 2446, in solvify
    period = periodicity(f, symbol)
  File "/home/sayandip/sympy/sympy/calculus/util.py", line 516, in periodicity
    g_s = decompogen(f, symbol)
  File "/home/sayandip/sympy/sympy/solvers/decompogen.py", line 47, in decompogen
    result += [f.subs(f.args[0], symbol)] + decompogen(f.args[0], symbol)
  File "/home/sayandip/sympy/sympy/solvers/decompogen.py", line 37, in decompogen
    raise TypeError('expecting Expr but got: `%s`' % func_name(f))
TypeError: expecting Expr but got: `ExprCondPair`
>>> solveset(p,x,S.Reals)
Union(FiniteSet(0), Interval.open(-oo, -1))

```



Discussion:

Patch:
diff --git a/doc/src/documentation-style-guide.rst b/doc/src/documentation-style-guide.rst
index 639b01c40d..8e677469cb 100644
--- a/doc/src/documentation-style-guide.rst
+++ b/doc/src/documentation-style-guide.rst
@@ -206,8 +206,7 @@ For Fedora (and maybe other RPM-based distributions), install the
 prerequisites::
 
    dnf install python3-sphinx librsvg2 ImageMagick docbook2X texlive-dvipng-bin
-   texlive-scheme-medium librsvg2-tools
-   python -m pip install sphinx-math-dollar
+   texlive-scheme-medium librsvg2-tools python -m pip install sphinx-math-dollar
 
 After that, run::
 
diff --git a/sympy/calculus/util.py b/sympy/calculus/util.py
index 81cdec0d18..4a5e72a80c 100644
--- a/sympy/calculus/util.py
+++ b/sympy/calculus/util.py
@@ -1,4 +1,4 @@
-from sympy import Order, S, log, limit, lcm_list, im, re, Dummy
+from sympy import Order, S, log, limit, lcm_list, im, re, Dummy, Piecewise
 from sympy.core import Add, Mul, Pow
 from sympy.core.basic import Basic
 from sympy.core.compatibility import iterable
@@ -511,6 +511,9 @@ def _check(orig_f, period):
             symbol not in n.free_symbols):
                 period = Abs(n / a.diff(symbol))
 
+    elif isinstance(f, Piecewise):
+        pass  # not handling Piecewise yet as the return type is not favorable
+
     elif period is None:
         from sympy.solvers.decompogen import compogen
         g_s = decompogen(f, symbol)
diff --git a/sympy/solvers/solveset.py b/sympy/solvers/solveset.py
index c0d2616a9b..c39aaea5f7 100644
--- a/sympy/solvers/solveset.py
+++ b/sympy/solvers/solveset.py
@@ -2318,6 +2318,8 @@ def solvify(f, symbol, domain):
     ImageSet,   | list (if `f` is periodic)
     Union       |
 
+    Union       | list (with FiniteSet)
+
     EmptySet    | empty list
 
     Others      | None
@@ -2377,7 +2379,16 @@ def solvify(f, symbol, domain):
 
         else:
             solution = solution_set.intersect(domain)
-            if isinstance(solution, FiniteSet):
+            if isinstance(solution, Union):
+                # concerned about only FiniteSet with Union but not about ImageSet
+                # if required could be extend
+                if any(isinstance(i, FiniteSet) for i in solution.args):
+                    result = [sol for soln in solution.args \
+                     for sol in soln.args if isinstance(soln,FiniteSet)]
+                else:
+                    return None
+
+            elif isinstance(solution, FiniteSet):
                 result += solution
 
     return result


Test patch:
diff --git a/sympy/calculus/tests/test_util.py b/sympy/calculus/tests/test_util.py
index 510fb12741..d29f1edfbe 100644
--- a/sympy/calculus/tests/test_util.py
+++ b/sympy/calculus/tests/test_util.py
@@ -1,6 +1,6 @@
 from sympy import (Symbol, S, exp, log, sqrt, oo, E, zoo, pi, tan, sin, cos,
                    cot, sec, csc, Abs, symbols, I, re, simplify,
-                   expint, Rational)
+                   expint, Rational, Piecewise)
 from sympy.calculus.util import (function_range, continuous_domain, not_empty_in,
                                  periodicity, lcim, AccumBounds, is_convex,
                                  stationary_points, minimum, maximum)
@@ -171,6 +171,9 @@ def test_periodicity():
     assert periodicity((E**x)%3, x) is None
 
     assert periodicity(sin(expint(1, x))/expint(1, x), x) is None
+    # returning `None` for any Piecewise
+    p = Piecewise((0, x < -1), (x**2, x <= 1), (log(x), True))
+    assert periodicity(p, x) is None
 
 
 def test_periodicity_check():
diff --git a/sympy/solvers/tests/test_solveset.py b/sympy/solvers/tests/test_solveset.py
index 08d989363d..5cc2d3746c 100644
--- a/sympy/solvers/tests/test_solveset.py
+++ b/sympy/solvers/tests/test_solveset.py
@@ -1320,7 +1320,24 @@ def test_solvify():
     raises(NotImplementedError, lambda: solvify(sin(exp(x)), x, S.Complexes))
 
 
+def test_solvify_piecewise():
+    p1 = Piecewise((0, x < -1), (x**2, x <= 1), (log(x), True))
+    p2 = Piecewise((0, x < -10), (x**2 + 5*x - 6, x >= -9))
+    p3 = Piecewise((0, Eq(x, 0)), (x**2/Abs(x), True))
+    p4 = Piecewise((0, Eq(x, pi)), ((x - pi)/sin(x), True))
+
+    # issue 21079
+    assert solvify(p1, x, S.Reals) == [0]
+    assert solvify(p2, x, S.Reals) == [-6, 1]
+    assert solvify(p3, x, S.Reals) == [0]
+    assert solvify(p4, x, S.Reals) == [pi]
+
+
 def test_abs_invert_solvify():
+
+    x = Symbol('x',positive=True)
+    assert solvify(sin(Abs(x)), x, S.Reals) == [0, pi]
+    x = Symbol('x')
     assert solvify(sin(Abs(x)), x, S.Reals) is None