Basic Boolean classes and the SingletonRegistry

18 views
Skip to first unread message

Sean Vig

unread,
Feb 8, 2012, 8:48:39 PM2/8/12
to sy...@googlegroups.com
Hi,

So in conjunction with a pull of mine to rework some of the Piecewise framework [1], I'm trying to implement classes to represent Booleans (True,False,None) that subclass Basic, as reported in this issue [2]. As suggested in the issue, I started with classes named like BooleanTrue (so as to not clobber True), however, there doesn't seem to be any way to add these to the SingletonRegistry (the classes accessible by S.*) as S.True rather than S.BooleanTrue, which would be more convenient. Does anyone know of a way to do this or a way to modify the existing code to allow this?

As a second note, when I asked Aaron about this or IRC, he mentioned it may not be possible at all to have something with an attribute named None, as would be the case for something like S.None going to BooleanNone. If this is the case, could this be hacked in somehow (Aaron suggested possibly working with __getattr__), or would it be better to name it something different so this isn't an issue? If so, are there any suggestions for what it should be called?

Thanks,
Sean

Matthew Rocklin

unread,
Feb 8, 2012, 9:04:36 PM2/8/12
to sy...@googlegroups.com
There are a number of decent alternative names. "none" "NULL" come to mind. 

Additionally, SymPy tends to use None to stand for Maybe. Would there be any use for S.Maybe as an additional Boolean Singleton?

--
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.

Aaron Meurer

unread,
Feb 9, 2012, 12:38:46 AM2/9/12
to sy...@googlegroups.com
I think it should be possible to get it to work.  Anyway, S.None isn't a syntax error. I'll play with it later. 

Aaron Meurer
--

Joachim Durchholz

unread,
Feb 9, 2012, 2:33:43 AM2/9/12
to sy...@googlegroups.com
Am 09.02.2012 02:48, schrieb Sean Vig:
> As a second note, when I asked Aaron about this or IRC, he mentioned it may
> not be possible at all to have something with an attribute named None, as
> would be the case for something like S.None going to BooleanNone. If this
> is the case, could this be hacked in somehow (Aaron suggested possibly
> working with __getattr__), or would it be better to name it something
> different so this isn't an issue? If so, are there any suggestions for what
> it should be called?

A quick scan of the English and German Wikipedia pages on three-valued
logic turned up a whole lot of different logic systems, with different
truth tables. The meaning of the third value could be things like:
- indeterminate/unknown
- irrelevant
- both
- neither
- nonsensical/paradox

Is "none"/"no value" the right terminology for the kind of logic that's
being discussed here?
What's the truth table - does it match an existing three-valued logic?
If yes, I'd take the terminology from there.

Aaron Meurer

unread,
Feb 9, 2012, 2:58:38 PM2/9/12
to sy...@googlegroups.com

Actually, "no value" is pretty close. None means that we don't know
the answer, ether because it could be either True or False, or because
we don't have sufficient algorithms to compute it (we don't
differentiate between the two). So for example, if x is assumed to be
positive, x > 2 would have the logical value of None, because we don't
have enough information to determine if x is in the interval (0, 2] or
(2, oo). On the other hand, something like (pi + E).is_irrational
would be None, because this fact is not known for sure by anyone.

As far as the truth table, the logical operands short-circuit as you
would expect, but otherwise, an operand with None gives None again.
So for example, True & None would be True, but False & None would be
None. Not None would also be None. Note that Python's two valued
logic assigns to None the boolean value of False. This is useful,
because you can check for truth using the two valued logic (e.g., "if
x.is_positive" will be correct for True, False, or None), but you have
to be careful when checking for falsity. In that case, you have to
check something like "if x.is_positive is False" instead of "if not
x.is_positive", or you will get the wrong answer if x.is_positive is
None. Better would be to have something like x.is_nonpositive, which
would do the three-valued logic for you.

But that's off topic. The point is that I think None is actually an OK name.

As far as putting it in S, it turns out I was wrong. You can't do
"S.None = something", because that's a syntax error (I tested it
wrong). You also can't do it with True or False, as that's a syntax
error in Python 3. Furthermore, S.True, S.False, and S.None are all
SyntaxErrors in Python 3, so even __setattr__ wouldn't work (this
could work in Python 2, where that is not a syntax error, but we have
to support both).

The Singleton registry is built to assign the exact name of the class
to the attributes automatically (you just have to add "__metaclass__ =
Singleton" to the top of the class definition). But you can define
any additional attribute, and it seems to work. So you can just do

S.Whatever = BooleanNone

and so on, and it will work (or at least it worked in my tests).

So we need to come up with good shortcut names. Here are some options:

- S.T, S.F, and S.N? Those are easy to type, though they could be a
little confusing.

- S.true, S.false, S.none

- Instead of None, use a name more indicative of what it means, like
"maybe" or "unknown" (this option is independent of the others).

- Don't have any shortcut names. If you want it, you can do
S.BooleanTrue, etc., or just S(True).

I'm slightly leaning toward the last option, though not too strongly.

Aaron Meurer

Ronan Lamy

unread,
Feb 10, 2012, 3:35:47 AM2/10/12
to sy...@googlegroups.com
Le jeudi 09 février 2012 à 12:58 -0700, Aaron Meurer a écrit :
> On Thu, Feb 9, 2012 at 12:33 AM, Joachim Durchholz <j...@durchholz.org> wrote:
> > Am 09.02.2012 02:48, schrieb Sean Vig:
> >
> >> As a second note, when I asked Aaron about this or IRC, he mentioned it
> >> may
> >> not be possible at all to have something with an attribute named None, as
> >> would be the case for something like S.None going to BooleanNone. If this
> >> is the case, could this be hacked in somehow (Aaron suggested possibly
> >> working with __getattr__), or would it be better to name it something
> >> different so this isn't an issue? If so, are there any suggestions for
> >> what
> >> it should be called?
> >
> >
> > A quick scan of the English and German Wikipedia pages on three-valued logic
> > turned up a whole lot of different logic systems, with different truth
> > tables. The meaning of the third value could be things like:
> > - indeterminate/unknown
> > - irrelevant
> > - both
> > - neither
> > - nonsensical/paradox
> >
> > Is "none"/"no value" the right terminology for the kind of logic that's
> > being discussed here?
> > What's the truth table - does it match an existing three-valued logic? If
> > yes, I'd take the terminology from there.

Also, Boolean logic is two-valued. If you add None, you get a
non-Boolean logic (aka multi-valued logic), so "BooleanNone" is a
contradiction that makes about as much sense as "RealI" or "RationalPi".


>
> Actually, "no value" is pretty close. None means that we don't know
> the answer, ether because it could be either True or False, or because
> we don't have sufficient algorithms to compute it (we don't
> differentiate between the two). So for example, if x is assumed to be
> positive, x > 2 would have the logical value of None, because we don't
> have enough information to determine if x is in the interval (0, 2] or
> (2, oo). On the other hand, something like (pi + E).is_irrational
> would be None, because this fact is not known for sure by anyone.
>
> As far as the truth table, the logical operands short-circuit as you
> would expect, but otherwise, an operand with None gives None again.
> So for example, True & None would be True, but False & None would be
> None. Not None would also be None. Note that Python's two valued
> logic assigns to None the boolean value of False. This is useful,
> because you can check for truth using the two valued logic (e.g., "if
> x.is_positive" will be correct for True, False, or None), but you have
> to be careful when checking for falsity. In that case, you have to
> check something like "if x.is_positive is False" instead of "if not
> x.is_positive", or you will get the wrong answer if x.is_positive is
> None. Better would be to have something like x.is_nonpositive, which
> would do the three-valued logic for you.

You are confusing the problem domain with the implementation domain.
BooleanTrue and BooleanFalse are needed to represent and manipulate
boolean formulas. Their (symbolic) behaviour should be dictated by the
definitions and theorems of mathematics and logic.
What bool(<boolean expr>) and ask(<boolean expr>) return is a separate
issue where Python conventions and implementation details matter. I
think that if bool(Symbol('x') > 2) raises an exception,
bool(BooleanTrue()) should raise the same exception. On the other hand,
ask() handles the conversion of Boolean expression into one of the
Python builtins True, False and None and it's only after it has been
called that we need to deal with that cumbersome 3-valued logic
operating on True, False and None.


>
> But that's off topic. The point is that I think None is actually an OK name.
>
> As far as putting it in S, it turns out I was wrong. You can't do
> "S.None = something", because that's a syntax error (I tested it
> wrong). You also can't do it with True or False, as that's a syntax
> error in Python 3. Furthermore, S.True, S.False, and S.None are all
> SyntaxErrors in Python 3, so even __setattr__ wouldn't work (this
> could work in Python 2, where that is not a syntax error, but we have
> to support both).
>
> The Singleton registry is built to assign the exact name of the class
> to the attributes automatically (you just have to add "__metaclass__ =
> Singleton" to the top of the class definition). But you can define
> any additional attribute, and it seems to work. So you can just do
>
> S.Whatever = BooleanNone
>
> and so on, and it will work (or at least it worked in my tests).

Yes, doing it manually should work without any problem (but be careful
to set the instance, not the class, on the attribute). The Singleton
metaclass effectively runs "S.BooleanTrue = BooleanTrue()".


>
> So we need to come up with good shortcut names. Here are some options:
>
> - S.T, S.F, and S.N? Those are easy to type, though they could be a
> little confusing.
>
> - S.true, S.false, S.none

We could also use S.True_/S.False_ or S.TRUE/S.FALSE.


>
> - Instead of None, use a name more indicative of what it means, like
> "maybe" or "unknown" (this option is independent of the others).
>
> - Don't have any shortcut names. If you want it, you can do
> S.BooleanTrue, etc., or just S(True).
>
> I'm slightly leaning toward the last option, though not too strongly.

Are you suggesting that sympify(True) should return BooleanTrue()? That
seems reasonable to me, but it has interesting side-effects on the
distinction between sympify() and _sympify()

Aaron Meurer

unread,
Feb 12, 2012, 1:07:40 AM2/12/12
to sy...@googlegroups.com

So perhaps the class structure should represent a little better the
disconnect between two-valued and three-valued logic. It seems to me
that perhaps BooleanTrue and BooleanFalse could be considered as part
of both, as the three-valued logic deriving purely from those two is
exactly the same as two-valued logic.

Yes.

How would you quantify the distinction between sympify() and
_sympify()? From what I understand, the disconnect exists so that we
don't necessarily automatically convert strings into SymPy objects in
some places.

The whole point of creating these objects is so that we can have
boolean types in .args (in particular, in Piecewise(evaluate=False); I
suppose things like And(evaluate=False) would also be possible now as
well). So whichever of sympify() or _sympify() is responsible for
sympifying .args would have to do it. I think S(True) is a lot cleaner
than S.true, S.TRUE, and so on.

Aaron Meurer

Reply all
Reply to author
Forward
0 new messages