Opened 4 years ago

Last modified 3 years ago

#17700 new defect

wrong symbolic results in case the answer is not known

Reported by: jakobkroeker Owned by:
Priority: critical Milestone: sage-6.8
Component: symbolics Keywords:
Cc: ​eviatarbach, ​tmonteil, slelievre, vdelecroix Merged in:
Authors: Reviewers:
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: pynac- Stopgaps: todo

Description (last modified by jakobkroeker)

A failing example is taken from

bool( abs(a+b) <= abs(a) + abs(b) ) # False, expected True or 'Unknown'
assert (not False == bool( abs(a+b) <= abs(a) + abs(b) ) ) #fails

The documentation of bool() says "Returns True when the argument x is true, False otherwise."

Formally this includes returning False in case the answer is unknown and it seems that bool() was specified to behave like it does. But I find that is very unfortunate and even improving the documentation (explicitly mention the 'answer is unknown' case) is not sufficient.

see also discussion at

In that thread the exception variant is preferred in case of 'don't know'

Please also take into consideration Tristate variants ( A sandbox for a Tristate class: )

See also!topic/sage-devel/4DUsgt670MA

Change History (12)

comment:1 Changed 4 years ago by jakobkroeker

  • Cc ​tmonteil added

comment:2 Changed 4 years ago by eviatarbach

Thanks for opening this ticket! I think this is a huge problem in Sage symbolics.

I can't remember what I did to change the behaviour so that when a comparison is made and the result can't be determined it raises an exception instead of returning False; I'll try to look into it this weekend.

I like the idea of having a three-valued logic (; unfortunately Python makes this very difficult, as the Tristate class shows. There does not seem to be an elegant solution, so I wonder if it's not just best to stick with exceptions.

comment:3 Changed 4 years ago by rws

I'll gladly do a review of this ticket.

comment:4 Changed 4 years ago by rws

  • Description modified (diff)

comment:5 Changed 4 years ago by jakobkroeker

  • Description modified (diff)

comment:6 Changed 4 years ago by leif

  • Milestone changed from sage-6.5 to sage-6.7

Btw., also the coercion framework occasionally leads to "surprising" results (because silently False is returned upon comparison when no coercion can be established, such that for example a == b and a == c doesn't imply b == c). This and similar has been discussed on sage-devel a couple of times.

comment:7 Changed 4 years ago by rws

The ticket is about symbolics so let's get concrete. It happens that at the moment I'm implementing more logic affecting comparisons/relations/zero tests of expressions in Pynac. The decision process for the logic in Sage is:

Expression.__nonzero__() is called on input of bool. __nonzero__ is the one that should throw an exception for unknown results. In __nonzero__,

  1. first the relations of constants are decided
  2. Pynac's relational_to_bool is called (relational::safe_bool()), it does:
    1. relations with one or two infinities; any result gets returned by __nonzero__ right away
    2. if l.h.s - r.h.s is a Python object (other than Expression) compare it to zero, i.e., delegate to the resp. class
    3. else if relation is >= or <= use positive flag of (l.h.s - r.h.s) or its negative to decide (Pynac-
  3. the previous result may now get changed in case of not-equal; already here Maxima may be called (I think this is wrong, Maxima should always be the last resort)
  4. if no assumptions are needed now is time for test_relation which has some detailed logic and uses interval fields to disprove relations ("interval fields never return false positives"); it already has tristate logic by returning NotImplemented if unsure
  5. if the previous neither returns True/False return what symbolic/ returns
    1. the relation is tested and any True is returned immediately
    2. simplification is attempted before returning the final True/False

EDIT: __nonzero__ is not called by Pynac EDIT: add info about upcoming Pynac snippet

Last edited 4 years ago by rws (previous) (diff)

comment:8 Changed 4 years ago by rws

  • Dependencies set to pynac-
  • Milestone changed from sage-6.7 to sage-6.8

In we implement multistate for item 2 above. The Sage part raises a TypeError with text Undecidable relation: ... if Pynac returns undecidable and continues on with item 3/4 in case of not implemented.

comment:9 Changed 4 years ago by rws

The second issue this ticket depends on concerns the Maxima interface in item 5. There is e.g.:

sage: from sage.symbolic.relation import test_relation_maxima
sage: test_relation_maxima(I>0)

because in Maxima

(%i8) is(%i>0);
(%o8)                               false

so the 'false' result should raise a NotImplementedError in __nonzero__ because Maxima does not distinguish between false, known undecidable, and unknown. This produces hundreds of doctest fails in symbolics alone.

Moreover, trying to snatch this decision functionality from Maxima presupposes an independent assumption framework.

EDIT: I is %i in Maxima

Last edited 4 years ago by rws (previous) (diff)

comment:10 Changed 4 years ago by slelievre

  • Cc slelievre vdelecroix added

comment:11 Changed 3 years ago by eviatarbach

I started doing some work on this. Since Sage already has an Unknown object for representing indeterminate truth values, I thought we could adapt it for use here. Ticket #20920 makes some changes to Unknown to raise an error when attempting to evaluate its truth value with __nonzero__, as well as adding an Undecidable object.

comment:12 Changed 3 years ago by rws

Great. See also #19040.

Note: See TracTickets for help on using tickets.