should bool(x > 0) be False or an exception?

185 views
Skip to first unread message

Carl Witty

unread,
Apr 9, 2008, 10:18:48 PM4/9/08
to sage-devel
I'd like to reopen discussion of #2781, "bool() for SymbolicEquation
should raise an error when it doesn't know the answer". Jason created
a prototype patch to implement this, but gave up on it and closed the
ticket when he was convinced that "this is not pythonic".

I like the "raise an exception" behavior, because it would eliminate
questions asking why form1 and form2 below are different (from this
sage-support thread http://groups.google.com/group/sage-support/browse_thread/thread/79d0d6d94cfe9526#).
(I have seen this exact problem at least twice on sage-support.) What
do you think?

f(x)=x;
def g(x):
if (x>=0):
return f(x)
else:
return f(-x);

show(plot(g(x),(x,-1,1))) #form1
show(plot(g,-1,1)) #form2

Carl

didier deshommes

unread,
Apr 9, 2008, 11:16:42 PM4/9/08
to sage-...@googlegroups.com
On Wed, Apr 9, 2008 at 10:18 PM, Carl Witty <cwi...@newtonlabs.com> wrote:
>
> I'd like to reopen discussion of #2781, "bool() for SymbolicEquation
> should raise an error when it doesn't know the answer". Jason created
> a prototype patch to implement this, but gave up on it and closed the
> ticket when he was convinced that "this is not pythonic".
>
> I like the "raise an exception" behavior, because it would eliminate
> questions asking why form1 and form2 below are different (from this
> sage-support thread http://groups.google.com/group/sage-support/browse_thread/thread/79d0d6d94cfe9526#).
> (I have seen this exact problem at least twice on sage-support.) What
> do you think?

-1
I like bool(x>0) to be False by default if the answer is not known.
mhansen raised this great point that we rely so much on things like :
if (condition on x):
do something

that it would be cumbersome to surround this statement with a try,catch block.

I'm only opposing this because it is unpythonic but I don't see any
reason not to define methods that have the same functionality for
SymbolicEquation but *can* raise an exception when appropriate.

didier

Chris Chiasson

unread,
Apr 9, 2008, 11:31:23 PM4/9/08
to sage-devel
Since x>=0 returns unevaluated, the problem seems like it is with the
if statement, which is turning "maybe" into false. In Mathematica, the
if statement would return unevaluated (for symbolic input into g).

On Apr 9, 9:18 pm, Carl Witty <cwi...@newtonlabs.com> wrote:
> I'd like to reopen discussion of #2781, "bool() for SymbolicEquation
> should raise an error when it doesn't know the answer". Jason created
> a prototype patch to implement this, but gave up on it and closed the
> ticket when he was convinced that "this is not pythonic".
>
> I like the "raise an exception" behavior, because it would eliminate
> questions asking why form1 and form2 below are different (from this
> sage-support threadhttp://groups.google.com/group/sage-support/browse_thread/thread/79d0...).

Carl Witty

unread,
Apr 10, 2008, 12:27:37 AM4/10/08
to sage-devel
On Apr 9, 8:16 pm, "didier deshommes" <dfdes...@gmail.com> wrote:
> On Wed, Apr 9, 2008 at 10:18 PM, Carl Witty <cwi...@newtonlabs.com> wrote:
>
> > I'd like to reopen discussion of #2781, "bool() for SymbolicEquation
> > should raise an error when it doesn't know the answer". Jason created
> > a prototype patch to implement this, but gave up on it and closed the
> > ticket when he was convinced that "this is not pythonic".
>
> > I like the "raise an exception" behavior, because it would eliminate
> > questions asking why form1 and form2 below are different (from this
> > sage-support threadhttp://groups.google.com/group/sage-support/browse_thread/thread/79d0...).
> > (I have seen this exact problem at least twice on sage-support.) What
> > do you think?
>
> -1
> I like bool(x>0) to be False by default if the answer is not known.
> mhansen raised this great point that we rely so much on things like :
> if (condition on x):
> do something
>
> that it would be cumbersome to surround this statement with a try,catch block.
>
> I'm only opposing this because it is unpythonic but I don't see any
> reason not to define methods that have the same functionality for
> SymbolicEquation but *can* raise an exception when appropriate.

Conversely, we could have __nonzero__ (as used by bool() and if:)
raise an exception and have another method (I suggest "known_true")
that does not raise an exception; there would be no need for try/
except.

In my opinion, the current behavior is too confusing (especially for
non-expert users) to be worth keeping, even if it is occasionally
useful. I'd guess that the majority of Sage scripts that use a
SymbolicEquation as the condition in an if: statement do so
incorrectly, as in the example from sage-support that I quoted above;
even if it is used correctly, it's still going to be very confusing to
a reader who may not be familiar with the unknown->False mapping.

Also, I'm curious: when is it actually useful to use a
SymbolicEquation as the condition of an if: statement (with the
current meaning)? I hope I've never used this construct in my own
code (I've certainly never done so intentionally, and I hope I haven't
done so by accident).

> didier

Carl

Simon King

unread,
Apr 10, 2008, 4:41:36 AM4/10/08
to sage-devel
On Apr 10, 4:18 am, Carl Witty <cwi...@newtonlabs.com> wrote:
> I like the "raise an exception" behavior, because it would eliminate
> questions asking why form1 and form2 below are different (from this
> sage-support threadhttp://groups.google.com/group/sage-support/browse_thread/thread/79d0...).
> (I have seen this exact problem at least twice on sage-support.) What
> do you think?

I guess what i suggest wouldn't solve the plot-issue. However, i think
if one doesn't know whether an inequality holds, or if the inequality
simply makes no sense (such as in the case of an unordered field) then
bool() should neither raise an exception nor return False but return
None. I think it is much simpler to have
if bool(x>0) == True:
bla1
elif bool(x>0)==None:
bla2
else:
bla3
than catching exceptions.

Perhaps it would even make sense to have a new type UnknownBool. This
could be returned if the inequality may be true, whereas None could be
returned if the inequality simply makes no sense. I don't like at all
what happens for complex numbers or finite fields!

Here are some examples.
sage: bool(x>0)
False # i think it should be None, or better UnknownBool or so
sage: assume(x>0)
sage: bool(x>-1)
True # fine
sage: bool(x>ComplexNumber(0,0))
True # ??? The complex field is not ordered. So, the answer "True"
doesn't make sense!
sage: bool(x>GF(2)(0))
False # Again, ">" does not apply. So, to get "False" or "True" isn't
quite correct.
sage: bool(x>ComplexNumber(-1,0))
True # --"--
sage: bool(x>ComplexNumber(-1,1))
False # --"--

Yours
Simon



Carl Witty

unread,
Apr 12, 2008, 11:24:54 AM4/12/08
to sage-devel
On Apr 10, 1:41 am, Simon King <k...@mathematik.uni-jena.de> wrote:
> On Apr 10, 4:18 am, Carl Witty <cwi...@newtonlabs.com> wrote:
>
> > I like the "raise an exception" behavior, because it would eliminate
> > questions asking why form1 and form2 below are different (from this
> > sage-support threadhttp://groups.google.com/group/sage-support/browse_thread/thread/79d0...).
> > (I have seen this exact problem at least twice on sage-support.) What
> > do you think?
>
> I guess what i suggest wouldn't solve the plot-issue. However, i think
> if one doesn't know whether an inequality holds, or if the inequality
> simply makes no sense (such as in the case of an unordered field) then
> bool() should neither raise an exception nor return False but return
> None. I think it is much simpler to have

bool() is a Python builtin that cannot return None. bool(x) calls
x.__nonzero__(); but if you try to make __nonzero__() return None, you
get:
<type 'exceptions.TypeError'>: __nonzero__ should return an int

Chris's suggestion of making if: sometimes return an "unevaluated if"
is also impossible in Python.

Of course, we can (and probably should) make a new method on
SymbolicEquation that returns True/False/None; we could also add
support for a symbolic "unevaluated if" if we wanted. But since we
use Python, we're stuck with: bool(x > 0) must return True, False, or
raise an exception; and this controls what "if x > 0:" will do.

Carl

Jason Grout

unread,
Apr 12, 2008, 11:58:56 AM4/12/08
to sage-...@googlegroups.com

The reason why I eventually decided that throwing an exception was
unpythonic was that I could not find a single case of current python
code which did that. Actually, the one reference I did find was a
bugfix to a project (I think SQLAlchemy), in which they changed
__nonzero__ to not raise an exception since it was inconsistent with
other behavior.

That, and the fact that Python by default returns True for objects
instead of raising exceptions, tells me that raising exceptions would
also raise an exceptional number of eyebrows and probably voices too.

I think we ought to have a different function for testing true/false and
would return a third value (None? an exception?) if the value was not known.

Jason

Carl Witty

unread,
Apr 12, 2008, 8:33:59 PM4/12/08
to sage-devel
On Apr 12, 8:58 am, Jason Grout <jason-s...@creativetrax.com> wrote:
> Carl Witty wrote:
> > On Apr 10, 1:41 am, Simon King <k...@mathematik.uni-jena.de> wrote:
> >> On Apr 10, 4:18 am, Carl Witty <cwi...@newtonlabs.com> wrote:
>
> >>> I like the "raise an exception" behavior, because it would eliminate
> >>> questions asking why form1 and form2 below are different (from this
> >>> sage-support threadhttp://groups.google.com/group/sage-support/browse_thread/thread/79d0...).
> >>> (I have seen this exact problem at least twice on sage-support.) What
> >>> do you think?
> >> I guess what i suggest wouldn't solve the plot-issue. However, i think
> >> if one doesn't know whether an inequality holds, or if the inequality
> >> simply makes no sense (such as in the case of an unordered field) then
> >> bool() should neither raise an exception nor return False but return
> >> None. I think it is much simpler to have
> The reason why I eventually decided that throwing an exception was
> unpythonic was that I could not find a single case of current python
> code which did that. Actually, the one reference I did find was a
> bugfix to a project (I think SQLAlchemy), in which they changed
> __nonzero__ to not raise an exception since it was inconsistent with
> other behavior.
>
> That, and the fact that Python by default returns True for objects
> instead of raising exceptions, tells me that raising exceptions would
> also raise an exceptional number of eyebrows and probably voices too.

I agree that raising an exception is somewhat unpythonic, but I don't
think that's an automatic veto on the idea. Sage does lots of
unpythonic stuff already, and I think we should at least consider
adding one more unpythonic behavior in this case.

I still think that most of the times people write "if x > 0:", they
will be implicitly wanting an unevaluated, symbolic conditional that
we can't automatically provide; in these cases, I think raising an
exception is much better than silently giving a result quite different
than what's desired.

For the few cases where people actually understand the issues (and the
issues are complicated, involving two very different kinds of
variables and two very different kinds of evaluation), and write "if x
> 0:" wanting the current behavior, an exception is slightly worse
than the current behavior; but if the exception points at a simple
workaround (by having "Use the .known_true() method to evaluate
unknown conditions to False" as part of the exception text) then the
cost is very small.

So according to this analysis, raising the exception is a large
benefit (doesn't silently give the wrong answer) for a larger number
of novice users, and a small cost for a smaller number of expert
users. If this is correct, then I think we should raise the
exception.

Carl

William Stein

unread,
Apr 12, 2008, 8:39:24 PM4/12/08
to sage-...@googlegroups.com

I vote +1 to Carl's proposal.

William

Chris Chiasson

unread,
Apr 13, 2008, 12:37:13 AM4/13/08
to sage-devel
+1 for Carl's proposal with the addition that it should mention the
"unevaluated if" functionality if/when it becomes available in sage
(heck, maybe it should just point to the relevant threads or trac
tickets in the interim...)

kro...@uni-math.gwdg.de

unread,
Jul 31, 2013, 5:33:30 AM7/31/13
to sage-...@googlegroups.com, wst...@gmail.com
Am Sonntag, 13. April 2008 02:39:24 UTC+2 schrieb William Stein:

Dear sagemath-developers,


the issue with unexpected behaviour of bool(SymbolicExpression)
seems still unresolved (at least in versions <= 5.8);
see http://ask.sagemath.org/question/2853/testing-inequalities-in-sage

I vote for returning an exception in case the algorithm cannot decide if the expression is True or False;
alternatively ( in my opinion ) bool() should NOT be applicable to symbolic expressions for which a natural answer is at least tri-state, even if it breaks a lot of code.


Best,


Jack

Jesus Torrado

unread,
Aug 1, 2013, 8:57:02 AM8/1/13
to sage-...@googlegroups.com
+1 to the exception.

With respect to "pythonism", I would say that this is more pythonic than creating a 3-state boolean type.

And I would like to raise attention this current, related sage-support discussion: https://groups.google.com/forum/#!topic/sage-support/JOA8JqgXJQA

Eviatar

unread,
Aug 1, 2013, 1:03:55 PM8/1/13
to sage-...@googlegroups.com
Maxima does have an unknown answer for comparisons. I'm in favour of the exception.

"Jakob Kröker"

unread,
Aug 2, 2013, 6:15:50 AM8/2/13
to sage-...@googlegroups.com
Dear Eviatar,


could you provide some arguments for your choice?

By the way, 'Unknown' is not usable for fixing this issue, because a
value, that is neither True nor False should not be convertible to a
boolean or integer or whatever is accepted by the 'if'-statement, but
'if' seems to accept Unknown :

if not Unknown : print "if should fail, but it succeeds"

is valid code...


Jack
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "sage-devel" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/sage-devel/vNxnHSeRBW4/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> sage-devel+...@googlegroups.com. To post to this group, send email
> to sage-...@googlegroups.com. Visit this group at
> http://groups.google.com/group/sage-devel.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>
>


Volker Braun

unread,
Aug 2, 2013, 10:04:42 AM8/2/13
to sage-...@googlegroups.com, wst...@gmail.com
I tend to be in favor of the True/False/raise Exception model for testing equality, but has anybody looked into what would be involved to transition the Sage ilbrary? I imagine we would have to adapt a lot of code. 

TB

unread,
Aug 3, 2013, 9:06:01 AM8/3/13
to sage-...@googlegroups.com, Eviatar
On 01/08/2013 20:03, Eviatar wrote:
> Maxima does have an unknown answer for comparisons. I'm in favour of the
> exception.
>
> On Wednesday, 9 April 2008 19:18:48 UTC-7, Carl Witty wrote:
>
> I'd like to reopen discussion of #2781, "bool() for SymbolicEquation
> should raise an error when it doesn't know the answer". Jason created
> a prototype patch to implement this, but gave up on it and closed the
> ticket when he was convinced that "this is not pythonic".
>
> I like the "raise an exception" behavior, because it would eliminate
> questions asking why form1 and form2 below are different (from this
> sage-support thread
> http://groups.google.com/group/sage-support/browse_thread/thread/79d0d6d94cfe9526#
> <http://groups.google.com/group/sage-support/browse_thread/thread/79d0d6d94cfe9526#>).
>
> (I have seen this exact problem at least twice on sage-support.) What
> do you think?
>
> f(x)=x;
> def g(x):
> if (x>=0):
> return f(x)
> else:
> return f(-x);
>
> show(plot(g(x),(x,-1,1))) #form1
> show(plot(g,-1,1)) #form2
>
> Carl
>
> --
> You received this message because you are subscribed to the Google
> Groups "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to sage-devel+...@googlegroups.com.
> To post to this group, send email to sage-...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sage-devel.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
FWIW, I am too in favour of raising an exception when converting a
symbolic expression to a boolean.

But I would like to note that it is not that convenient to use
"try:...except:..." at the prompt. Can we also add a method to symbolic
expressions, tentatively called truth_value(), that would return 3-state
value:
* True if the expression is always true (tautology)
* False if the expression is always false (negation of tautology)
* None otherwise

Then code might use

if some_exp.truth_value() is not None:
# some_exp is either always true or always false.

and when you want to make sure that some_exp is always true you can use

if some_exp.truth_value():
# some_exp is always true.


TB

chris wuthrich

unread,
Aug 4, 2013, 5:43:33 AM8/4/13
to sage-...@googlegroups.com

I am not against the exception.

The question is what quantifiers we use for variables, isn't it? Antoher approach would be to implement it such that the quatifier is always "forall" for all variables in the expression, i.e. it only returns True if for all possible values of x, y, .. it is True. Otherwise it returns False. That would be another consistent approach.

I don't know which one I favour, I only know that the current state is very bad.

Chris.

Eviatar

unread,
Aug 9, 2013, 6:04:32 PM8/9/13
to sage-...@googlegroups.com, wst...@gmail.com
I changed the code to return an exception if the truth value is unknown and ran `sage -testall`. Here are the results:

sage -t devel/sage/sage/tensor/differential_form_element.py  # 43 doctests failed                   
sage -t devel/sage/sage/tensor/differential_forms.py  # 1 doctest failed                            
sage -t devel/sage/sage/calculus/tests.py  # 4 doctests failed                                      
sage -t devel/sage/sage/calculus/calculus.py  # 10 doctests failed                                  
sage -t devel/sage/sage/calculus/desolvers.py  # 8 doctests failed                                  
sage -t devel/sage/sage/calculus/wester.py  # 3 doctests failed                                     
sage -t devel/sage/sage/symbolic/assumptions.py  # 8 doctests failed                                
sage -t devel/sage/sage/symbolic/expression.pyx  # Killed due to segmentation fault                 
sage -t devel/sage/sage/symbolic/units.py  # Killed due to segmentation fault                       
sage -t devel/sage/sage/symbolic/relation.py  # 2 doctests failed                                   
sage -t devel/sage/sage/matrix/matrix_symbolic_dense.pyx  # 2 doctests failed                       
sage -t devel/sage/sage/doctest/forker.py  # 1 doctest failed                                       
sage -t devel/sage/sage/misc/functional.py  # 2 doctests failed                                     
sage -t devel/sage/sage/misc/cachefunc.pyx  # 1 doctest failed                                      
sage -t devel/sage/sage/combinat/tutorial.py  # 9 doctests failed                                   
sage -t devel/sage/sage/tests/french_book/recequadiff.py  # 25 doctests failed

Many of the failed tests are due to dependence on variables which would have been assigned in previous tests, but failed due to the exception. I might be willing to fix these tests when I have time.

Jakob Kroeker

unread,
Feb 26, 2015, 12:44:02 PM2/26/15
to sage-...@googlegroups.com, wst...@gmail.com
>I changed the code to return an exception if the truth value is unknown and ran `sage -testall`.

Did you upload the patch to somewhere? Where this change has to be made?


> I might be willing to fix these tests when I have time.

It seems that nothing happens for more than a year,
so maybe someone else has time to fix this?

I opened a ticket :
http://trac.sagemath.org/ticket/17700


Jakob
Reply all
Reply to author
Forward
0 new messages