Hi.
There are two basic issues here.
The first issue is that Relational is not clearly a boolean or not a
boolean. It acts like a boolean sometimes, as you saw, in that it
reduces to True or False in some cases. But in other ways, it does
not.
http://code.google.com/p/sympy/issues/detail?id=1887 is the key
issue here.
Actually, Booleans are kind of a mess in SymPy. The only reason that
x | y => And(x, y) works is that Symbol is a subclass of Boolean. But
this (at least to me) is wrong, because Symbol represents an
indeterminate complex number. We really should have a separate
BooleanSymbol class that represents an indeterminate boolean. We
could make Symbol coerce to BooleanSymbol automatically with | and &
(assuming it has no assumptions on it that makes it necessarily not a
boolean) for user convenience, but at the core, they should be
different. So actually, Symbol has the exact same problem as
Relational from issue 1887.
The second issue is that And, Or, etc. do not do type checking on
their arguments, which is why And(x < y, y < z) works, even though x <
y is not a Boolean. It also allows nonsensical things like
In [873]: print And(x**2, x)
And(x, x**2)
We could fix this, and then relationals would not work in boolean
classes at all (until 1887 was fixed). This would be a regression,
however, because as you noted, relationals do (sort of) work in the
logic classes.
Practically, you can fix this problem in one of two ways. The first
way is to make Relational a subclass of Boolean, i.e., apply this
patch:
diff --git a/sympy/core/relational.py b/sympy/core/relational.py
index 9e0ea3d..931637a 100644
--- a/sympy/core/relational.py
+++ b/sympy/core/relational.py
@@ -3,6 +3,8 @@
from evalf import EvalfMixin
from sympify import _sympify
+from sympy.logic.boolalg import Boolean
+
__all__ = (
'Rel', 'Eq', 'Ne', 'Lt', 'Le', 'Gt', 'Ge',
'Relational', 'Equality', 'Unequality', 'StrictLessThan', 'LessThan',
@@ -122,7 +124,7 @@ def Ge(a, b):
"""
return Relational(a,b,'>=')
-class Relational(Expr, EvalfMixin):
+class Relational(Boolean, Expr, EvalfMixin):
__slots__ = []
This might break some things (though I ran the tests, and everything
passed, so maybe not).
The other way is to just add the relevant methods to Relational. This
way is ideal if you don't want to modify the code, because they can be
hooked at runtime. So if you add something like
from sympy.logic.boolalg import Relational
Relational.__and__ = lambda self, other: And(self, other)
Relational.__or__ = lambda self, other: Or(self, other)
...
at the top of whatever file you want to use (x > y) & (y < z) syntax,
it will work.
Finally, I want to ask if people think the first option (making
Relational subclass from Boolean) would be an acceptable workaround to
push into SymPy until we can get issue 1887 pushed in. If you look at
the code, the class Boolean just defines the __methods__ for logic
operations, so it essentially would do nothing but fix this
regression. Since we are already doing the same thing for Symbol, I
don't think it is too bad (at least no worse than what we are already
doing). This would also allow us to add type checking to Add, Or,
etc., so that And(x, x**2) stops working.
If so, I'll write up some tests and submit it as a pull request.
Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To post to this group, send email to
sy...@googlegroups.com.
> To unsubscribe from this group, send email to
sympy+un...@googlegroups.com.
> For more options, visit this group at
http://groups.google.com/group/sympy?hl=en.
>