Repository: sympy/sympy

Issue:
Piecewise.rewrite_as_ITE wrong conversion?
Hey, 
I'm using Piecewise functions to dynamically assign variables. At some point, I have a compound expression composed from several nested Piecewise (as well as other core functions). 

For Example:
With two symbols:
` n_start; n_end ` 

The expression:
`
 out_n_shape =  -2.0*Piecewise((0, ITE((n_end - n_start > 1) | (2.0*n_end - 2.0*n_start > 1.0), False, ITE(n_end - n_start > 1, 2.0*n_start - 2.0 < -1, 2.0*n_end - 2.0*n_start > 1))), (Piecewise((0, ITE(n_end - n_start > 1, True, 2.0*n_end - 2.0*n_start > 1)), (2.0*Piecewise((0, n_end - n_start > 1), (n_start, True)), True)), True)) + 2.0*Piecewise((1.0, ITE((n_end - n_start > 1) | (2.0*n_end - 2.0*n_start > 1.0), False, ITE(n_end - n_start > 1, 2.0*n_start - 2.0 < -1, 2.0*n_end - 2.0*n_start > 1))), (Piecewise((1.0, ITE(n_end - n_start > 1, True, 2.0*n_end - 2.0*n_start > 1)), (2.0*Piecewise((1.0, n_end - n_start > 1), (n_end, True)), True)), True))    
`

While adding the above to to another Piecewise, i.e.:
```
 sympy.Piecewise((orig_out_range.start.n, orig_n_shape < out_n_shape),
                                                    (self.in_range.start.n, True))
 ```

I get:
```traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "../lib/python3.8/site-packages/sympy/functions/elementary/piecewise.py", line 127, in __new__
    pair = ExprCondPair(*getattr(ec, 'args', ec))
  File "../lib/python3.8/site-packages/sympy/functions/elementary/piecewise.py", line 27, in __new__
    cond = cond.rewrite(ITE)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1803, in rewrite
    return self._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in _rewrite
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in <listcomp>
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in _rewrite
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in <listcomp>
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in _rewrite
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in <listcomp>
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in _rewrite
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in <listcomp>
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in _rewrite
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1808, in <listcomp>
    args = [a._rewrite(pattern, rule, method, **hints)
  File "../lib/python3.8/site-packages/sympy/core/basic.py", line 1815, in _rewrite
    rewritten = meth(*args, **hints)\
File "../lib/python3.8/site-packages/sympy/functions/elementary/piecewise.py", line 950, in _eval_rewrite_as_ITE
    raise TypeError(filldedent('''
TypeError: 
Expecting Boolean or bool but got Float
```

Is it might be from wrong usage or is it potentially bug?

I will also note that:
* ` orig_n_shape=1`
and all other variables are integers (not symbolic in that case).

* Also, after executing the above with `simplify(out_n_shape)` function, i get no exceptions. 

Thank you

Discussion:
sympy-bot: :white_check_mark:

Hi, I am the [SymPy bot](https://github.com/sympy/sympy-bot) (v167). I'm here to help you write a release notes entry. Please read the [guide on how to write release notes](https://github.com/sympy/sympy/wiki/Writing-Release-Notes).



Your release notes are in good order.

Here is what the release notes will look like:
* functions
  * `piecewise_fold` is applied recursively to always fold fully. ([#23987](https://github.com/sympy/sympy/pull/23987) by [@oscargus](https://github.com/oscargus))

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.12.

<details><summary>Click here to see the pull request description that was parsed.</summary>

    <!-- Your title above should be a short description of what
    was changed. Do not include the issue number in the title. -->

    #### References to other Issues or PRs
    <!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
    format, e.g. "Fixes #1234" (see
    https://tinyurl.com/auto-closing for more information). Also, please
    write a comment on that issue linking back to this pull request once it is
    open. -->

    Fixes #22917

    #### Brief description of what is fixed or changed

    In some situation, `piecewise_fold` requires a second execution. This checks if there are any Piecewise left inside a Piecewise and if so applies `piecewise_fold` again. It may be that this should happen for other situations as well, e..g. check if `len(atoms(Piecewise)) > 1`?

    #### Other comments


    #### Release Notes

    <!-- Write the release notes for this release below between the BEGIN and END
    statements. The basic format is a bulleted list with the name of the subpackage
    and the release note for this PR. For example:

    * solvers
      * Added a new solver for logarithmic equations.

    * functions
      * Fixed a bug with log of integers.

    or if no release note(s) should be included use:

    NO ENTRY

    See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
    information on how to write release notes. The bot will check your release
    notes automatically to see if they are formatted correctly. -->

    <!-- BEGIN RELEASE NOTES -->
    * functions
       * `piecewise_fold` is applied recursively to always fold fully.
    <!-- END RELEASE NOTES -->


</details><p>


Patch:
diff --git a/sympy/functions/elementary/piecewise.py b/sympy/functions/elementary/piecewise.py
index 4d2c8e48b0..93cd5540e2 100644
--- a/sympy/functions/elementary/piecewise.py
+++ b/sympy/functions/elementary/piecewise.py
@@ -1071,6 +1071,8 @@ def piecewise_fold(expr, evaluate=True):
     rv = Piecewise(*new_args, evaluate=evaluate)
     if evaluate is None and len(rv.args) == 1 and rv.args[0].cond == True:
         return rv.args[0].expr
+    if any(s.expr.has(Piecewise) for p in rv.atoms(Piecewise) for s in p.args):
+        return piecewise_fold(rv)
     return rv
 
 


Test patch:
diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py
index c8bf38878d..d7b202d03b 100644
--- a/sympy/functions/elementary/tests/test_piecewise.py
+++ b/sympy/functions/elementary/tests/test_piecewise.py
@@ -442,6 +442,22 @@ def test_piecewise_integrate5_independent_conditions():
     assert integrate(p, (x, 1, 3)) == Piecewise((0, Eq(y, 0)), (4*y, True))
 
 
+def test_issue_22917():
+    p = (Piecewise((0, ITE((x - y > 1) | (2 * x - 2 * y > 1), False,
+                           ITE(x - y > 1, 2 * y - 2 < -1, 2 * x - 2 * y > 1))),
+                   (Piecewise((0, ITE(x - y > 1, True, 2 * x - 2 * y > 1)),
+                              (2 * Piecewise((0, x - y > 1), (y, True)), True)), True))
+         + 2 * Piecewise((1, ITE((x - y > 1) | (2 * x - 2 * y > 1), False,
+                                 ITE(x - y > 1, 2 * y - 2 < -1, 2 * x - 2 * y > 1))),
+                         (Piecewise((1, ITE(x - y > 1, True, 2 * x - 2 * y > 1)),
+                                    (2 * Piecewise((1, x - y > 1), (x, True)), True)), True)))
+    assert piecewise_fold(p) == Piecewise((2, (x - y > S.Half) | (x - y > 1)),
+                                          (2*y + 4, x - y > 1),
+                                          (4*x + 2*y, True))
+    assert piecewise_fold(p > 1).rewrite(ITE) == ITE((x - y > S.Half) | (x - y > 1), True,
+                                                     ITE(x - y > 1, 2*y + 4 > 1, 4*x + 2*y > 1))
+
+
 def test_piecewise_simplify():
     p = Piecewise(((x**2 + 1)/x**2, Eq(x*(1 + x) - x**2, 0)),
                   ((-1)**x*(-1), True))