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:
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'.
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?
EDIT:
Found that in my case the solution is 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
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.
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.
So the solution is to wrap the input to lambdify
as numpy arrays, that is, instead of
f_numpy(0, 1)
use
f_numpy(array(0), array(1))
There is a SymPy issue discussing this if you are interested.