Repository: sympy/sympy

Issue:
Simplifying Piecewise when two cases have same value
```
In [92]: Piecewise((0, Eq(x, 0)), (sin(x), True))
Out[92]: Piecewise((0, x == 0), (sin(x), True))

In [93]: pprint(_)
⎧  0     for x = 0
⎨                 
⎩sin(x)  otherwise

In [94]: simplify(_)
Out[94]: Piecewise((0, x == 0), (sin(x), True))
```

Perhaps this should not happen automatically, but it would be nice if `simplify()` did it.  Apologies if this is a dupe, didn't see it.  Figure its related to #1009 somehow.

---

Very simple cases work:

```
In [97]: Piecewise((10, Eq(x,0)), (10, True))
Out[97]: 10
```

And some more complicated things work too:

```
In [101]: p3 = Piecewise((10, Eq(x, 0)), (y, True))

In [101]: p3
Out[101]: Piecewise((10, x == 0), (y, True))

In [102]: p3.subs(y,10)
Out[102]: 10
```


Discussion:

Patch:
diff --git a/sympy/functions/elementary/piecewise.py b/sympy/functions/elementary/piecewise.py
index 2e74b08975..f6217bf4ad 100644
--- a/sympy/functions/elementary/piecewise.py
+++ b/sympy/functions/elementary/piecewise.py
@@ -351,6 +351,38 @@ def _eval_simplify(self, ratio, measure, rational, inverse):
                         other = [ei.subs(*e.args) for ei in other]
                 cond = And(*(eqs + other))
                 args[i] = args[i].func(expr, cond)
+        # See if expressions valid for a single point happens to evaluate
+        # to the same function as in the next piecewise segment, see:
+        # https://github.com/sympy/sympy/issues/8458
+        prevexpr = None
+        for i, (expr, cond) in reversed(list(enumerate(args))):
+            if prevexpr is not None:
+                _prevexpr = prevexpr
+                _expr = expr
+                if isinstance(cond, And):
+                    eqs, other = sift(cond.args,
+                        lambda i: isinstance(i, Equality), binary=True)
+                elif isinstance(cond, Equality):
+                    eqs, other = [cond], []
+                else:
+                    eqs = other = []
+                if eqs:
+                    eqs = list(ordered(eqs))
+                    for j, e in enumerate(eqs):
+                        # these blessed lhs objects behave like Symbols
+                        # and the rhs are simple replacements for the "symbols"
+                        if isinstance(e.lhs, (Symbol, UndefinedFunction)) and \
+                            isinstance(e.rhs,
+                                (Rational, NumberSymbol,
+                                Symbol, UndefinedFunction)):
+                            _prevexpr = _prevexpr.subs(*e.args)
+                            _expr = _expr.subs(*e.args)
+                if _prevexpr == _expr:
+                    args[i] = args[i].func(args[i+1][0], cond)
+                else:
+                    prevexpr = expr
+            else:
+                prevexpr = expr
         return self.func(*args)
 
     def _eval_as_leading_term(self, x):


Test patch:
diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py
index 98c9f4f4d3..9840e0c5b6 100644
--- a/sympy/functions/elementary/tests/test_piecewise.py
+++ b/sympy/functions/elementary/tests/test_piecewise.py
@@ -1125,7 +1125,21 @@ def test_issue_14240():
         Piecewise((i, a), (0, True)) for i in range(1, 41)])
         ) == Piecewise((factorial(40), a), (0, True))
 
+
 def test_issue_14787():
     x = Symbol('x')
     f = Piecewise((x, x < 1), ((S(58) / 7), True))
     assert str(f.evalf()) == "Piecewise((x, x < 1), (8.28571428571429, True))"
+
+
+def test_issue_8458():
+    x, y = symbols('x y')
+    # Original issue
+    p1 = Piecewise((0, Eq(x, 0)), (sin(x), True))
+    assert p1.simplify() == sin(x)
+    # Slightly larger variant
+    p2 = Piecewise((x, Eq(x, 0)), (4*x + (y-2)**4, Eq(x, 0) & Eq(x+y, 2)), (sin(x), True))
+    assert p2.simplify() == sin(x)
+    # Test for problem highlighted during review
+    p3 = Piecewise((x+1, Eq(x, -1)), (4*x + (y-2)**4, Eq(x, 0) & Eq(x+y, 2)), (sin(x), True))
+    assert p3.simplify() == Piecewise((0, Eq(x, -1)), (sin(x), True))