CrepeGoat
CrepeGoat

Reputation: 2515

Sympy generating broken `Piecewise` conditions when simplifying

My Code

I effectively have the following reduced code snippet within a larger program:

import sympy as sp
print('sympy version:', sp.__version__)

n = sp.symbols('n', integer=True)
expr = sp.Piecewise((0, sp.Ne(n, 3)), (-1/2, True))*sp.Piecewise((2, sp.Ne(n, 0)), (1, True))

print('raw expression:', expr)
print('simplified expression:', sp.simplify(expr))

For the simplified expression, I expect something equivalent to:

simplified expression: Piecewise((0, Eq(n, 0)), (-1.0, Eq(n, 3)), (0, True))

(This potentially could be simplified further to just two branches, but something like that.)

However, my actual output is:

sympy version: 1.3

raw expression: Piecewise((0, Ne(n, 3)), (-0.5, True))*Piecewise((2, Ne(n, 0)), (1, True))

simplified expression: Piecewise((0, Ne(n, 3)), (-1.0, Ne(n, 0)), (-0.5, True))

My Problem

The obvious issue is that I did not get what I expected. But more than that, there are blatant logical issues in the simplified resulting piecewise expression; more specifically, in the conditions therein.

The first condition is Ne(n, 3), meaning "the first value will be used when n is not equal to 3". That's fine on it's own.

However, the second condition is Ne(n, 0), which in light of the first condition is completely nonsensical. If n were 0, the first condition would be true and the first branch value would be used, thus it's logically guaranteed that n is not 0 if the second condition is being evaluated.

Worse yet, the last condition is True (i.e., "otherwise"), which is the default condition should those of the earlier branches not be met. However, it is logically impossible to reach this branch, since the prior two conditions partition the full space of integers (and n is defined as an integer; however, the same problem occurs when n's number type is left unspecified).

(I want to also note that this problem does not exist in either of the original Piecewise expressions before simplifying. While they do use Ne for their first branch condition, the second condition is the default True, which is perfectly valid.)

My Question

Can anyone explain this as an intended behavior?

If not, I plan to submit this as a bug to SymPy. I did briefly search the SymPy issue tracker for my problem before posting, but I didn't see anything that matched it. I just wanted to double-check here that I'm not overlooking anything first.

Upvotes: 3

Views: 927

Answers (1)

user6655984
user6655984

Reputation:

The output is not "broken" or "nonsensical". It is logically correct, although not presented in the simplest form possible.

The condition if n == 3 and n != 0 could be simplified to if n == 3. There is a difference between "could be simplified" and "is completely nonsensical".

But yes, please report it on SymPy tracker, since the simplification is incomplete; a better result would be Piecewise((0, Ne(n, 3)), (-1.0, True)).

Upvotes: 1

Related Questions