对于分段函数和numpy模块,sympy.lambdify出错

时间:2022-06-23 20:19:52

In sympy 0.7.6, I had no troubles with the following code for both the modules='sympy' and the modules='numpy' options. Now with sympy v0.1, the evaluation with modules='numpy' raise a ZeroDivisionError:

在第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

Seems like the piecewise functions evaluate before the condition with modules='numpy'.

看起来像在使用modules ='numpy'的条件之前评估的分段函数。

My questions are:

我的问题是:

Is this behavior normal?

这种行为是否正常?

If so, why, and how to define a piecewise expression and evaluate it as fast as with numpy module without the sympy.lambdify procedure?

如果是这样,为什么,以及如何定义分段表达式并使用numpy模块快速评估它而没有sympy.lambdify过程?

EDIT:

编辑:

Found that in my case the solution is theano:

发现在我的情况下解决方案是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

1 个解决方案

#1


2  

I deleted my other answer (in case you already saw it). There is a much simpler solution.

我删除了我的其他答案(如果你已经看过了)。有一个更简单的解决方案。

The ZeroDivisionError comes because the lambdified expression produces, roughly, lambda x, y: select([less(y, -1),less_equal(y, 1),True], [1/x,x,1/x], default=nan). The problem is that passing in x = 0 results in 1/0 being evaluated by Python, which raises the error.

ZeroDivisionError之所以出现是因为lambdified表达式大致产生了lambda x,y:select([less(y,-1),less_equal(y,1),True],[1 / x,x,1 / x],默认值=南)。问题是传入x = 0会导致Python评估1/0,从而引发错误。

But NumPy is just fine with dividing by zero. It will issue a warning, but otherwise works fine (it gives inf), and in this example there is no problem, because the inf is not actually used.

但NumPy除以零就可以了。它会发出警告,但在其他方面工作正常(它给inf),在这个例子中没有问题,因为实际上没有使用inf。

So the solution is to wrap the input to lambdify as numpy arrays, that is, instead of

所以解决方案是将输入包装为lambdify作为numpy数组,即代替

f_numpy(0, 1)

use

使用

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

There is a SymPy issue discussing this if you are interested.

如果您有兴趣,有一个SymPy问题正在讨论这个问题。

#1


2  

I deleted my other answer (in case you already saw it). There is a much simpler solution.

我删除了我的其他答案(如果你已经看过了)。有一个更简单的解决方案。

The ZeroDivisionError comes because the lambdified expression produces, roughly, lambda x, y: select([less(y, -1),less_equal(y, 1),True], [1/x,x,1/x], default=nan). The problem is that passing in x = 0 results in 1/0 being evaluated by Python, which raises the error.

ZeroDivisionError之所以出现是因为lambdified表达式大致产生了lambda x,y:select([less(y,-1),less_equal(y,1),True],[1 / x,x,1 / x],默认值=南)。问题是传入x = 0会导致Python评估1/0,从而引发错误。

But NumPy is just fine with dividing by zero. It will issue a warning, but otherwise works fine (it gives inf), and in this example there is no problem, because the inf is not actually used.

但NumPy除以零就可以了。它会发出警告,但在其他方面工作正常(它给inf),在这个例子中没有问题,因为实际上没有使用inf。

So the solution is to wrap the input to lambdify as numpy arrays, that is, instead of

所以解决方案是将输入包装为lambdify作为numpy数组,即代替

f_numpy(0, 1)

use

使用

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

There is a SymPy issue discussing this if you are interested.

如果您有兴趣,有一个SymPy问题正在讨论这个问题。