sympy分段函数的lambdification计算每个表达式

时间:2018-06-21 14:49:48

标签: python sympy piecewise lambdify

我正在对一个sympy分段函数进行lambd化,试图做这样的事情:

f = Piecewise((1,(p > -1e-10) & (p < 1e-10)), (1/p, True))
g = lambdify(p,f,"numpy")

>>> f.subs(p,0)
1 

我明白了

>>> g(0)
/usr/lib/python2.7/dist-packages/numpy/__init__.py:1: RuntimeWarning: divide by zero encountered in true_divide
  """ 
array(1.0)

似乎(lambdified?)-Piecewise在返回具有真实条件的表达式之前先评估所有表达式。有办法解决吗?

1 个答案:

答案 0 :(得分:3)

NumPy code printer used by lambdifyPiecewise转换为

numpy.select(conditions, expressions, default=numpy.nan)

这意味着数组expressions是在numpy.select选择该数组的一个元素之前进行完整计算的。解决它的一些方法是:

1)将后端更改为math(或mpmathnumpy以外的任何其他字符),这将导致Piecewise为翻译为nested if statement

g = lambdify(p, f, "math")
g(0)  # 1, no warnings

2)根据最大/最小/绝对/符号来重写公式,该表达式可以表达一些分段函数并易于进行lambdify。并非总是可能的,但就您而言,

f = 0.5 * (sign(p + 1e-10) + sign(p - 1e-10)) / Max(1e-10, Abs(p)) + 0.5 * (sign(p + 1e-10) - sign(p - 1e-10))

完成任务。诀窍是0.5 * (sign(p + 1e-10) + sign(p - 1e-10))在p不太接近0时为sign(p),而在p不太接近0时为0。类似地,如果p不太接近0,则0.5 * (sign(p + 1e-10) - sign(p - 1e-10))为1,当p为0时为{0}。这些因素导致公式从一种模式切换到另一种模式,分母中的Max在任何情况下都避免了零误差除法。

3)Suppress Runtime Warnings