2

我正在对一个 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 ?) - 在返回具有真实条件的表达式之前,分段计算所有表达式。有没有解决的办法?

4

1 回答 1

3

lambdify 使用的NumPy 代码打印机转换Piecewise

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

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

1)将后端更改math(或mpmath,或除 以外的任何内容numpy),这将导致Piecewise被翻译为嵌套的 if 语句

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))

做这项工作。诀窍是,0.5 * (sign(p + 1e-10) + sign(p - 1e-10))当 p 不太接近 0 时为 sign(p),当它接近 0 时为 0。类似地,0.5 * (sign(p + 1e-10) - sign(p - 1e-10))如果 p 不太接近 0,则为 1,而当 p 接近 0 时,则为 0。这些因素导致公式从一种模式切换到另一种模式,并且Max在分母中无论如何都避免了除以零误差。

3)抑制运行时警告

于 2018-06-21T15:32:21.393 回答