I attach reworked patch. Added tests and docstring documenting that 
sympify accepts booleans.

Ondrej Certik wrote:
> Could you please write some tests for this?
> 
> Otherwise +1
> 
> On Wed, Jun 10, 2009 at 9:20 AM, Fabian Pedregosa<fab...@fseoane.net> wrote:
>> Before of this, sympy would convert True --> S.One, False --> S.Zero,
>> but with the logic module with classes inheriting from basic, I need
>> to manipulate boolean expressions, so converting booleans to S.One
>> and S.Zero is in my oppinion wrong because of conceptual reasons
>> and efficiency.
>>
>> The only module that used this behaviour was functions.elementary.piecewise,
>> and was adopted to use the new one.
>> ---
>>  sympy/core/sympify.py                   |    4 ++--
>>  sympy/functions/elementary/piecewise.py |   18 +++++++++++-------
>>  sympy/printing/ccode.py                 |    2 +-
>>  sympy/printing/latex.py                 |    2 +-
>>  sympy/printing/pretty/pretty.py         |    2 +-
>>  sympy/utilities/decorator.py            |    3 ++-
>>  6 files changed, 18 insertions(+), 13 deletions(-)
>>
>> diff --git a/sympy/core/sympify.py b/sympy/core/sympify.py
>> index 8da69d2..b00961b 100644
>> --- a/sympy/core/sympify.py
>> +++ b/sympy/core/sympify.py
>> @@ -57,6 +57,8 @@ def sympify(a, locals=None, convert_xor=True):
>>         return a
>>     if isinstance(a, BasicType):
>>         return a
>> +    elif isinstance(a, bool):
>> +        return a
>>     elif isinstance(a, (int, long)):
>>         return Integer(a)
>>     elif isinstance(a, (float, decimal.Decimal)):
>> @@ -68,8 +70,6 @@ def sympify(a, locals=None, convert_xor=True):
>>         if ireal + iimag*1j == a:
>>             return ireal + iimag*S.ImaginaryUnit
>>         return real + S.ImaginaryUnit * imag
>> -    elif isinstance(a, bool):
>> -        raise NotImplementedError("bool support")
>>     elif isinstance(a, (list,tuple,set)):
>>         return type(a)([sympify(x) for x in a])
>>
>> diff --git a/sympy/functions/elementary/piecewise.py 
>> b/sympy/functions/elementary/piecewise.py
>> index d5afef7..3abbb1f 100644
>> --- a/sympy/functions/elementary/piecewise.py
>> +++ b/sympy/functions/elementary/piecewise.py
>> @@ -147,7 +147,7 @@ def _eval_interval(self, sym, a, b):
>>         #    -  eg x < 1, x < 3 -> [oo,1],[1,3] instead of [oo,1],[oo,3]
>>         # 3) Sort the intervals to make it easier to find correct exprs
>>         for expr, cond in self.args:
>> -            if cond.is_Number:
>> +            if isinstance(cond, bool) or cond.is_Number:
>>                 if cond:
>>                     default = expr
>>                     break
>> @@ -203,15 +203,19 @@ def _eval_derivative(self, s):
>>     def _eval_subs(self, old, new):
>>         if self == old:
>>             return new
>> -        return Piecewise(*[(e._eval_subs(old, new), c._eval_subs(old, new)) 
>> \
>> -                                for e, c in self.args])
>> +        new_args = []
>> +        for e, c in self.args:
>> +            if isinstance(c, bool):
>> +                new_args.append((e._eval_subs(old, new), c))
>> +            else:
>> +                new_args.append((e._eval_subs(old, new), c._eval_subs(old, 
>> new)))
>> +        return Piecewise( *new_args )
>>
>>     @classmethod
>>     def __eval_cond(cls, cond):
>>         """Returns S.One if True, S.Zero if False, or None if undecidable."""
>> -        if type(cond) == bool or cond.is_number:
>> -            return sympify(bool(cond))
>> -        if cond.args[0].is_Number and cond.args[1].is_Number:
>> -            return sympify(bool(cond))
>> +        if type(cond) == bool or cond.is_number or (cond.args[0].is_Number 
>> and cond.args[1].is_Number):
>> +            if cond: return S.One
>> +            return S.Zero
>>         return None
>>
>> diff --git a/sympy/printing/ccode.py b/sympy/printing/ccode.py
>> index a1341b5..7a6ccf6 100644
>> --- a/sympy/printing/ccode.py
>> +++ b/sympy/printing/ccode.py
>> @@ -38,7 +38,7 @@ def _print_Piecewise(self, expr):
>>         ecpairs = ["(%s) {\n%s\n}\n" % (self._print(c), self._print(e)) \
>>                        for e, c in expr.args[:-1]]
>>         last_line = ""
>> -        if expr.args[-1].cond is S.One:
>> +        if expr.args[-1].cond == True:
>>             last_line = "else {\n%s\n}" % self._print(expr.args[-1].expr)
>>         else:
>>             ecpairs.append("(%s) {\n%s\n" % \
>> diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py
>> index 6f2b089..02cdd00 100644
>> --- a/sympy/printing/latex.py
>> +++ b/sympy/printing/latex.py
>> @@ -521,7 +521,7 @@ def _print_Relational(self, expr):
>>     def _print_Piecewise(self, expr):
>>         ecpairs = [r"%s & for %s" % (self._print(e), self._print(c)) \
>>                        for e, c in expr.args[:-1]]
>> -        if expr.args[-1].cond is S.One:
>> +        if expr.args[-1].cond == True:
>>             ecpairs.append(r"%s & \textrm{otherwise}" % \
>>                                self._print(expr.args[-1].expr))
>>         else:
>> diff --git a/sympy/printing/pretty/pretty.py 
>> b/sympy/printing/pretty/pretty.py
>> index 5065d6c..19ffff2 100644
>> --- a/sympy/printing/pretty/pretty.py
>> +++ b/sympy/printing/pretty/pretty.py
>> @@ -318,7 +318,7 @@ def _print_Piecewise(self, pexpr):
>>         P = {}
>>         for n, ec in enumerate(pexpr.args):
>>             P[n,0] = self._print(ec.expr)
>> -            if ec.cond is S.One:
>> +            if ec.cond == True:
>>                 P[n,1] = prettyForm('otherwise')
>>             else:
>>                 P[n,1] = prettyForm(*prettyForm('for 
>> ').right(self._print(ec.cond)))
>> diff --git a/sympy/utilities/decorator.py b/sympy/utilities/decorator.py
>> index 1d022d6..489f781 100644
>> --- a/sympy/utilities/decorator.py
>> +++ b/sympy/utilities/decorator.py
>> @@ -39,6 +39,8 @@ def threaded_proxy(func):
>>         def threaded_decorator(expr, *args, **kwargs):
>>             if isinstance(expr, Matrix):
>>                 return expr.applyfunc(lambda f: func(f, *args, **kwargs))
>> +            elif isinstance(expr, bool):
>> +                    return expr
>>             elif hasattr(expr, '__iter__'):
>>                 return expr.__class__([ func(f, *args, **kwargs) for f in 
>> expr ])
>>             else:
>> @@ -47,7 +49,6 @@ def threaded_decorator(expr, *args, **kwargs):
>>                 if isinstance(expr, Relational):
>>                     lhs = func(expr.lhs, *args, **kwargs)
>>                     rhs = func(expr.rhs, *args, **kwargs)
>> -
>>                     return Relational(lhs, rhs, expr.rel_op)
>>                 elif expr.is_Add and use_add:
>>                     return Add(*[ func(f, *args, **kwargs) for f in 
>> expr.args ])
>> --
>> 1.6.1.2
>>
>>
> 
> > 
> 


-- 
http://fseoane.net/blog/

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sympy-patches" group.
To post to this group, send email to sympy-patches@googlegroups.com
To unsubscribe from this group, send email to 
sympy-patches+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sympy-patches?hl=en
-~----------~----~----~----~------~----~------~--~---

>From 18d9ea5c171bb2a02d7d26d4ba5f9d291ece93a5 Mon Sep 17 00:00:00 2001
From: Fabian Pedregosa <fab...@fseoane.net>
Date: Sun, 31 May 2009 23:47:46 +0200
Subject: [PATCH] Add support for bool types in sympify.

Before of this, sympy would convert True --> S.One, False --> S.Zero,
but with the logic module with classes inheriting from basic, I need
to manipulate boolean expressions, so converting booleans to S.One
and S.Zero is in my oppinion wrong because of conceptual reasons
and efficiency.

The only module that used this behaviour was functions.elementary.piecewise,
and was adopted to use the new one.

Also added tests.
---
 sympy/core/sympify.py                   |    5 +++--
 sympy/core/tests/test_sympify.py        |    6 ++++++
 sympy/functions/elementary/piecewise.py |   18 +++++++++++-------
 sympy/printing/ccode.py                 |    2 +-
 sympy/printing/latex.py                 |    2 +-
 sympy/printing/pretty/pretty.py         |    2 +-
 sympy/utilities/decorator.py            |    3 ++-
 7 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/sympy/core/sympify.py b/sympy/core/sympify.py
index 8da69d2..7fd432a 100644
--- a/sympy/core/sympify.py
+++ b/sympy/core/sympify.py
@@ -25,6 +25,7 @@ def sympify(a, locals=None, convert_xor=True):
            - any object defined in sympy (except maybe matrices [TODO])
            - standard numeric python types: int, long, float, Decimal
            - strings (like "0.09" or "2e-19")
+           - booleans (will leave them unchanged)
 
        If the argument is already a type that sympy understands, it will do
        nothing but return that value. This can be used at the begining of a
@@ -57,6 +58,8 @@ def sympify(a, locals=None, convert_xor=True):
         return a
     if isinstance(a, BasicType):
         return a
+    elif isinstance(a, bool):
+        return a
     elif isinstance(a, (int, long)):
         return Integer(a)
     elif isinstance(a, (float, decimal.Decimal)):
@@ -68,8 +71,6 @@ def sympify(a, locals=None, convert_xor=True):
         if ireal + iimag*1j == a:
             return ireal + iimag*S.ImaginaryUnit
         return real + S.ImaginaryUnit * imag
-    elif isinstance(a, bool):
-        raise NotImplementedError("bool support")
     elif isinstance(a, (list,tuple,set)):
         return type(a)([sympify(x) for x in a])
 
diff --git a/sympy/core/tests/test_sympify.py b/sympy/core/tests/test_sympify.py
index 63094f5..20a15b9 100644
--- a/sympy/core/tests/test_sympify.py
+++ b/sympy/core/tests/test_sympify.py
@@ -35,6 +35,12 @@ def test_sympify3():
     raises(SympifyError, "_sympify('x**3')")
     raises(SympifyError, "_sympify('1/2')")
 
+def test_sympify_bool():
+    """Test that sympify accepts boolean values
+    and that output leaves them unchanged"""
+    assert sympify(True) == True
+    assert sympify(False)== False
+
 def test_sympify4():
     class A:
         def _sympy_(self):
diff --git a/sympy/functions/elementary/piecewise.py b/sympy/functions/elementary/piecewise.py
index d5afef7..3abbb1f 100644
--- a/sympy/functions/elementary/piecewise.py
+++ b/sympy/functions/elementary/piecewise.py
@@ -147,7 +147,7 @@ def _eval_interval(self, sym, a, b):
         #    -  eg x < 1, x < 3 -> [oo,1],[1,3] instead of [oo,1],[oo,3]
         # 3) Sort the intervals to make it easier to find correct exprs
         for expr, cond in self.args:
-            if cond.is_Number:
+            if isinstance(cond, bool) or cond.is_Number:
                 if cond:
                     default = expr
                     break
@@ -203,15 +203,19 @@ def _eval_derivative(self, s):
     def _eval_subs(self, old, new):
         if self == old:
             return new
-        return Piecewise(*[(e._eval_subs(old, new), c._eval_subs(old, new)) \
-                                for e, c in self.args])
+        new_args = []
+        for e, c in self.args:
+            if isinstance(c, bool):
+                new_args.append((e._eval_subs(old, new), c))
+            else:
+                new_args.append((e._eval_subs(old, new), c._eval_subs(old, new)))
+        return Piecewise( *new_args )
 
     @classmethod
     def __eval_cond(cls, cond):
         """Returns S.One if True, S.Zero if False, or None if undecidable."""
-        if type(cond) == bool or cond.is_number:
-            return sympify(bool(cond))
-        if cond.args[0].is_Number and cond.args[1].is_Number:
-            return sympify(bool(cond))
+        if type(cond) == bool or cond.is_number or (cond.args[0].is_Number and cond.args[1].is_Number):
+            if cond: return S.One
+            return S.Zero
         return None
 
diff --git a/sympy/printing/ccode.py b/sympy/printing/ccode.py
index a1341b5..7a6ccf6 100644
--- a/sympy/printing/ccode.py
+++ b/sympy/printing/ccode.py
@@ -38,7 +38,7 @@ def _print_Piecewise(self, expr):
         ecpairs = ["(%s) {\n%s\n}\n" % (self._print(c), self._print(e)) \
                        for e, c in expr.args[:-1]]
         last_line = ""
-        if expr.args[-1].cond is S.One:
+        if expr.args[-1].cond == True:
             last_line = "else {\n%s\n}" % self._print(expr.args[-1].expr)
         else:
             ecpairs.append("(%s) {\n%s\n" % \
diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py
index 6f2b089..02cdd00 100644
--- a/sympy/printing/latex.py
+++ b/sympy/printing/latex.py
@@ -521,7 +521,7 @@ def _print_Relational(self, expr):
     def _print_Piecewise(self, expr):
         ecpairs = [r"%s & for %s" % (self._print(e), self._print(c)) \
                        for e, c in expr.args[:-1]]
-        if expr.args[-1].cond is S.One:
+        if expr.args[-1].cond == True:
             ecpairs.append(r"%s & \textrm{otherwise}" % \
                                self._print(expr.args[-1].expr))
         else:
diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py
index 5065d6c..19ffff2 100644
--- a/sympy/printing/pretty/pretty.py
+++ b/sympy/printing/pretty/pretty.py
@@ -318,7 +318,7 @@ def _print_Piecewise(self, pexpr):
         P = {}
         for n, ec in enumerate(pexpr.args):
             P[n,0] = self._print(ec.expr)
-            if ec.cond is S.One:
+            if ec.cond == True:
                 P[n,1] = prettyForm('otherwise')
             else:
                 P[n,1] = prettyForm(*prettyForm('for ').right(self._print(ec.cond)))
diff --git a/sympy/utilities/decorator.py b/sympy/utilities/decorator.py
index 1d022d6..489f781 100644
--- a/sympy/utilities/decorator.py
+++ b/sympy/utilities/decorator.py
@@ -39,6 +39,8 @@ def threaded_proxy(func):
         def threaded_decorator(expr, *args, **kwargs):
             if isinstance(expr, Matrix):
                 return expr.applyfunc(lambda f: func(f, *args, **kwargs))
+            elif isinstance(expr, bool):
+                    return expr
             elif hasattr(expr, '__iter__'):
                 return expr.__class__([ func(f, *args, **kwargs) for f in expr ])
             else:
@@ -47,7 +49,6 @@ def threaded_decorator(expr, *args, **kwargs):
                 if isinstance(expr, Relational):
                     lhs = func(expr.lhs, *args, **kwargs)
                     rhs = func(expr.rhs, *args, **kwargs)
-
                     return Relational(lhs, rhs, expr.rel_op)
                 elif expr.is_Add and use_add:
                     return Add(*[ func(f, *args, **kwargs) for f in expr.args ])
-- 
1.6.2.2

Reply via email to