Aaron, Thanks for the response...replies inline
> In [66]: bool(x<0) > > Out[66]: False > > > > This is obviously not consistent and it a bug in Relational.__nonzero__ > > Yes, let's make any SymPy expression return True if and only if it is not > the object S.Zero (or maybe also some empty containers, like Matrix([])). > Yep and that is what Basic.__nonzero__ does. > I'm not sure what to do about the relational (see below). > Right. > > Relational classes don't properly evaluate to booleans > > ====================================================== > > > > Consider these examples: > > > > In [67]: Eq(0,0) > > Out[67]: 0 == 0 > > > > In [68]: Ge(1,0) > > Out[68]: 0 <= 1 > > > > Obviously, these should resolve to booleans. You may think, why wouldn't > > you just do 0==0 or 1<0? But consider this: > > Just to be clear we overload __lt__, etc. to return the Le() class, but == > is just the simple equality testing (not the Eq class). This is fine, but > like you say, there needs to still be a way to do actual comparison. The > problem I have seen is that it likes to turn things into booleans that don't > make sense that way, other than being non-empty. For example, the x<0 > above. > Right. > Another thing, automatic evaluation should proceed on a SymPy object only > if three conditions are met: > 1. The evaluation will always make the object simpler. > 2. The evaluation is very cheap in every case. > 3. The evaluation is so trivial that no one will ever not want it done. > > For example, we auto-simplify exp(x)*exp(x) to exp(2*x), but we leave > exp(x)*exp(y) alone, because if we auto-combined it, it would be impossible > to actually get exp(x)*exp(y) instead of exp(x + y) (things used to be this > way back in SymPy 0.6.4 until I spent a very headacheful few weeks changing > it last summer). > > (1) is clearly the case for turning inequalities into booleans. (2) will > only be true for the simple case of number < number. I could imagine other mathematical objects that have a clear concept of < and > and that are cheap to find. > Otherwise, even if the assumption for Ask(x - y, Q.positive) is True for x > > y, we should leave it alone in Gt.__new__ and leave the work to refine(). > Actually, even if this were cheap, I would still want to leave it alone > because of (3). > Yes, I agree that refine should be used in this cases. > Also, should we prevent bool(relational) from working otherwise, much like > the TypeError you get when you do 1j < 1? The problem with this is that there is little different between bool(x) and bool(x<0). > I would rather have bool(x<y) raise an error than mislead me by returning > True (misleading in the sense that bool(x>y) would also be True). But it would also be misleading that bool(2*x) is True, but bool(x<0) raises an exception. > Semantically speaking, relational.__nonzero__ should be True unless the > relational is explicitly False, and relational.__bool__ should be either the > explicit truth value of the relational or raise TypeError if there is none, > but I do not know the actual implementation difference between these two in > Python. > Yes, there is this issue as well. > > In [69]: e = Ge(x,0) > > > > In [70]: e.subs(x,1) > > Out[70]: 0 <= 1 # Just Ge(1,0)! > > > > Thus. it is common and easy to get Relational classes that should > evaluate to > > a boolean but don't. This behavior also affects boolean logic classes > > like And/Or, etc. as well as Interval: > > > > In [71]: e = And(x>0,x<1) > > > > In [72]: e.subs(x,0.5) > > Out[72]: And(0 < 0.5, 0.5 < 1) > > > > The problem is that the __new__ method of Relational does NOT actually > > try to compare the lhs and rhs. That is, Ge.__new__(lhs, rhs) doesn't > actually > > try lhs >= rhs. But, we can't have it try that or it will generate an > > infinite loop! Resolving this will be quite subtle. > > This should at least work with refine: > > In [17]: refine(e.subs(x,0.5)) > Out[17]: And(0 < 0.5, 0.5 < 1) > Not sure what you mean by this. Are you saying you *should* get this: In [17]: refine(e.subs(x,0.5)) Out[17]: True > I wonder if internally, x > y should be represented as Assume(x - y, > Q.positive) and x >= y as Assume(x - y, Q.nonnegative) (except there doesn't > seem to be a Q.nonnegative yet for some reason), except that it would also > have to keep track of what the original kind of inequality it was and what > terms were on what side. Anyway, Ask(x - y, Q.positive) is the proper way > to evaluate x < y, not checking x>=y, etc. > > Not sure about using Assume for all of this. Inequalities seem different than assumptions to me... Brian > Aaron Meurer > > > > Cheers, > > > > Brian > > > > > > > > -- > > You received this message because you are subscribed to the Google Groups > "sympy" group. > > To post to this group, send email to [email protected]. > > To unsubscribe from this group, send email to > [email protected] <sympy%[email protected]>. > > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected] <sympy%[email protected]>. > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. > > -- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
