Sympify "<" не возвращает логическое значение в пользовательской функции? - PullRequest
0 голосов
/ 21 октября 2019

Сводка

Мое собственноручное условие if-then-else для sympy не работает для некоторых логических выражений.

Код (Примечание: для меня это не вариант по кусочкам, предлагается здесь 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

, который работает частично, например, с этими тремя логическими значениями:

>>> print(ifte('1+2 and True and 1 != 2', 'b', 'c'))
b

Задача

Почему строка с 0 <1 вычисляется правильно? </p>

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

Все операторы в условии if обычнооцените как логическое значение.

  • Почему это не работает для <,>, <=,> =?
  • Есть ли решение для этого?
  • Как можноЯ уверен, что другие заявления также окажутся в качестве исключения?

1 Ответ

1 голос
/ 21 октября 2019

Проблема возникает во время 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

и связана с type, который получает a. Поскольку это зависит от выражения в a, вы можете наблюдать различные варианты поведения для разных выражений. В частности, для некоторых значений a это будет sympy.logic.boolalg.*. Если это так, то метод __gt__ (который вызывается при использовании оператора >) не определен, и вы получаете ошибку, которую вы наблюдаете. Для некоторых других значений это будет простой bool, для которого определен метод __gt__ и код работает так, как вы ожидаете.

Для решения проблемы просто удалите > 0сравнение, т.е.

from sympy import Function

class ifte(Function):
    nargs = 3

    @classmethod
    def eval(cls, a, b, c):
        if a:
            return b
        else:
            return c

или, еще проще:

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

Обратите внимание, что полученное сообщение об ошибке немного зависит от имеющейся версии SymPy, но принципта же. Например, в версии 1.1.1 я получаю:

TypeError: '>' не поддерживается между экземплярами 'BooleanTrue' и 'int'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...