问题
Summary
My self-written if-then-else conditional for sympy does not work for some Booleans.
Code (Note: Piecewise is not an option for me, proposed here https://stackoverflow.com/a/38858444/5626139)
from sympy import Function
class ifte(Function):
nargs = 3
@classmethod
def eval(cls, a, b, c):
if a > 0:
return b
else:
return c
Which works partially, for example with these three booleans:
>>> print(ifte('1+2 and True and 1 != 2', 'b', 'c'))
b
Problem
Why does the line with 0<1 evaluate correctly?
>>> print(ifte('0==1', 'b', 'c'))
b
>>> print(ifte('0<1', 'b', 'c'))
TypeError:
A Boolean argument can only be used in Eq and Ne; all other
relationals expect real expressions.
All the operators in the if-condition usually evaluate to boolean.
- Why does this not work for <, >, <=, >= ?
- Is there a solution to this?
- How can I be sure if other statements also end up as exception?
回答1:
The issue is triggered during the if:
from sympy import Function
class ifte(Function):
nargs = 3
@classmethod
def eval(cls, a, b, c):
if a > 0: # <-- PROBLEM HERE
return b
else:
return c
and it is related to the type that a gets.
Since this depends on the expression in a, you observe different behaviors for different expression.
In particular, for some values of a, this gets to be sympy.logic.boolalg.*.
If that is the case, then the __gt__ method (which is called when the > operator is used) is not defined and you get the error you observe.
For some other values, this gets to be a simple bool, for which the __gt__ method is defined and the code works the way you expect.
To solve the issue, simply remove the > 0 comparison, i.e.
from sympy import Function
class ifte(Function):
nargs = 3
@classmethod
def eval(cls, a, b, c):
if a:
return b
else:
return c
or, even more simply:
from sympy import Function
class ifte(Function):
nargs = 3
@classmethod
def eval(cls, a, b, c):
return b if a else c
print(ifte('1+2 and True and 1 != 2', 'b', 'c'))
# b
print(ifte('1==0', 'b', 'c'))
# c
print(ifte('1>0', 'b', 'c'))
# b
print(ifte('1<0', 'b', 'c'))
# c
Note that the error message you get depends a bit on the SymPy version you have, but the principle is the same.
For example, in version 1.1.1 I get:
TypeError: '>' not supported between instances of 'BooleanTrue' and 'int'
来源:https://stackoverflow.com/questions/58485525/sympify-does-not-return-boolean-in-custom-function