2016-06-26 2 views
3

В sympy 0.7.6 у меня не было проблем со следующим кодом как для модулей = 'sympy', так и для модулей = 'numpy'. Теперь с SymPy v0.1, оценка с «NumPy» модулей = поднять ZeroDivisionError:Ошибка с sympy.lambdify для кусочных функций и numpy-модуля

import sympy 

x, y = sympy.symbols(['x', 'y']) 
expr = sympy.Piecewise((1/x, y < -1), (x, y <= 1), (1/x, True)) 

f_sympy = sympy.lambdify([x, y], expr, modules='sympy') 
f_numpy = sympy.lambdify([x, y], expr, modules='numpy') 

print f_sympy(0, 1) # performs well 

print f_numpy(0, 1) # issue: ZeroDivisionError 

Похоже кусочно функции оценки до состояния с модулями = «NumPy».

Мои вопросы:

Это обычное поведение?

Если да, то почему и как определить кусочное выражение и оценить его так же быстро, как с numpy-модулем без процедуры sympy.lambdify?

EDIT:

Найдено, что в моем случае решение Theano:

import sympy 

x, y = sympy.symbols(['x', 'y']) 
f = sympy.Piecewise((1/x, y < -1), (x, y <= 1), (1/x, True)) 

from sympy.printing.theanocode import theano_function 
f_theano = theano_function([x, y], [f]) 

print f_theano(0, 1) # OK, return 0 

ответ

2

Я удалил мой другой ответ (в случае, если вы уже видели его). Существует гораздо более простое решение.

ZeroDivisionError происходит потому, что выраженное выражение выражается примерно lambda x, y: select([less(y, -1),less_equal(y, 1),True], [1/x,x,1/x], default=nan). Проблема в том, что передача в x = 0 приводит к тому, что 1/0 оценивается Python, что вызывает ошибку.

Но NumPy просто отлично с делением на ноль. Он выдаст предупреждение, но в остальном работает нормально (он дает inf), и в этом примере нет проблем, потому что inf фактически не используется.

Таким образом, решение является обертывание вход в lambdify в качестве Numpy массивов, то есть, вместо

f_numpy(0, 1) 

использования

f_numpy(array(0), array(1)) 

Существует В SymPy issue обсуждали это, если вы заинтересованы.

+0

спасибо. Теперь это намного яснее. Я попробую решение 'numpy.array'. На данный момент я использую это обходное решение, которое вызывает «lambdarepr» и (к сожалению) «eval»: https://gist.github.com/A-Falaize/ff2fafd5ab19f88c478f7494e340a619 Это работает для меня, но не очень " вещий. Каковы недостатки такого решения? – Toht

+0

Я не вижу, как решается этот вопрос, как ягненок вашего бедняка. Из того, что я могу сказать, все, что делает ваша функция, 'sympy.lambdify' также делает, но' sympy.lambdify' также делает намного больше, поэтому я бы рекомендовал просто использовать его. – asmeurer

Смежные вопросы