New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add gotchas note about Python bool vs SymPy Boolean behavior #13427
Comments
What should |
That already works and and has nothing to do with SymPy (or I fail to see what the connection should be) as it only uses plain Python. |
Sorry for the confusion. I meant the list to be illustrative, e.g.
|
Well, the same question can be asked for SymPy breaks this for no reason. I listed some reasons why this is bad in the initial comment. Yes, using integers explicitly is better in many cases, but that doesn’t mean that using booleans should not work. |
I agree. I'm not sure of the ramifications in terms of the code base, bowever. |
cf #8571 |
One of the reasons we created a separate boolean type for SymPy is because the Python booleans behave like integers, which is incorrect for our mathematical needs. For me, putting True or False in an expression (non-boolean) context is a garbage in-garbage out scenario. |
See also the docstring of BooleanTrue. |
Here's some history for anyone interested (I'm pretty sure I'm the "happy elephant" on Google Code) #2560 |
Okay, Python booleans and SymPy booleans work differently, I accept that. But if there is already inconsistency here anyway (e.g., |
One of the idioms that we use is to convert python values to sympy values. As for the inconsistent results in something like
I imagine that you want to use each value as a selector, e.g. |
I am not sufficiently familiar with SymPy’s code to make substantiated statements on this, but it could be as easy as replacing
Well, it’s of course a simplified example and I do not suggest that either of this is typed. Rather all elements of
While I am all in favour of such explicit solutions and you can always convert, if you know that you need it, it can easily happen that such things are more buried in application. Suppose, for example, that you represent the weight matrix of a network as a NumPy matrix |
The results of all but a few low-level functions are all SymPy objects so I don't think this will occur unless a user is writing their own functions and returning non-sympified results and combining them with bool results. It might be worth a word in a gotchas section of the tutorial. |
I agree with @smichr that this could be documented better. There are some notes in the BooleanTrue docstring that hint at why it exists, but it would be good to just write down somewhere the motivation for having it not be an integer, even for cases where it doesn't necessarily conflict with boolean operations. |
SymPy does not have to factor into this part at all. The function that sometimes returns a boolean in that example could be any Python routine, user-defined or by some other module (e.g., NumPy). Yes, in most cases, this would be non-perfect behaviour, but given Python’s standards on booleans, it’s not really bad either. |
I think what we are discussing is inherent to the CAS-in-python world. What you are saying makes sense in Python. Sympy has isolated Boolean behavior which makes sense mathematically. This is just one if those areas where a decision has been made not to let Python norms dictate something that doesn't make mathematical sense. |
… and that’s all fine and proper. But that doesn’t mean that SymPy has to break with Python standard with respect to Python booleans. As far as I can see, there are only a few ways to obtain a SymPy boolean anyway:
Neither of these breaks with the suggested change. |
… and that’s all fine and proper. But that doesn’t mean that SymPy has to break with Python standard with respect to Python booleans. As far as I can see, there are only a few ways to obtain a SymPy boolean anyway:
Neither of these is affected or somewhat interacting with the suggested change, as far as I can see. |
But the problem is that we want the ability to use True and False in SymPy boolean contexts. So sympify() currently converts those to the corresponding SymPy types. This is more important than having them work in integer contexts, since that's much rarer. You could try to be context sensitive, but it adds complication to the code, and you can't always guess correctly in every case. |
Right now, adding or multiplying Python booleans with SymPy arrays raises a
TypeError
(BooleanAtom not allowed in this context). Please change this such that booleans behave like the respective integers (0 or 1):It is specified in PEP 285 (which introduced the bool type) that booleans should just behave like integers except for printing (boldface mine):
Also see Python’s data model (boldface mine):
I see no reason why SymPy should not adhere to this.
Some practical problems arising due to this:
The user needs to make a pointless conversion.
The resulting error may be difficult to find, in particular if some other function only returns booleans some times, but otherwise returns integers.
It leads to inconsistencies:
Many other Python modules adhere to this standard and thus combining them with SymPy can cause problems. For example, if you have a NumPy array of integers that can only be 1 or 0, it may be wise to make this a boolean array (instead of a regular integer array). The same goes for NumPy arrays resulting from piecewise logical operations. Elements of these arrays cannot be directly used together with SymPy.
The text was updated successfully, but these errors were encountered: