在第0.7.6节中,对于modules ='sympy'和modules ='numpy'选项,我对以下代码没有任何麻烦。现在使用sympy v0.1,使用modules ='numpy'进行评估会引发ZeroDivisionError:
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
似乎在使用modules ='numpy'的条件之前评估分段函数。
我的问题是:
这种行为是否正常?
如果是这样,为什么以及如何定义分段表达式并使用numpy模块快速评估它而不使用sympy.lambdify过程?
编辑:
发现在我的情况下解决方案是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
答案 0 :(得分:2)
我删除了我的其他答案(如果你已经看过了)。有一个更简单的解决方案。
ZeroDivisionError之所以出现是因为lambdified表达式大致产生lambda x, y: select([less(y, -1),less_equal(y, 1),True], [1/x,x,1/x], default=nan)
。问题是传入x = 0会导致Python评估1/0
,从而引发错误。
但NumPy除以零就可以了。它会发出警告,但在其他方面工作正常(它给出inf
),在这个例子中没有问题,因为实际上没有使用inf
。
所以解决方案是将输入包装为lambdify
作为numpy数组,即代替
f_numpy(0, 1)
使用
f_numpy(array(0), array(1))
如果您有兴趣,可以SymPy issue讨论这个问题。