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

lambdification of sympy piecewise function evaluates every expression

我正在对一个 sympy 分段函数进行 lambdifying 尝试做这样的事情:

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 在返回条件为真的表达式之前对所有表达式求值。有解决办法吗?

NumPy code printer used by lambdifyPiecewise 翻译成

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

这意味着数组 expressionsnumpy.select 选择该数组的一个元素之前被完整计算。一些绕过它的方法是:

1) 将后端更改为math(或mpmath,或numpy以外的任何内容),这将导致Piecewise 被翻译成 nested if statement

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

2) 将公式改写为Max/Min/Abs/sign,可以表达一些分段函数,很容易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))

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

3) Suppress Runtime Warnings