SymPy lambdify引发OverflowError:数学范围错误

时间:2014-09-11 04:48:59

标签: python numpy lambda overflow sympy

所以,我有这个代码

from __future__ import division, print_function
import sympy as sp
import numpy as np
from sympy.utilities.lambdify import *

u = np.random.uniform(4, 6, 500)
w, k = sp.symbols('w k')
f = sp.log((k - w) * sp.exp((k - w)**5))
l = sum(f.subs(dict(k=k)) for k in u)

现在我想将l用作w的函数。所以我知道一些选择

z_lambdify = lambdify(w, l)
z_subs = lambda x: l.subs(w, x)

第一个函数给出错误

>>> z_lambdify(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
OverflowError: math range error
>>> z_lambdify(4)
40.862695278600114

虽然第二个给出答案

>>> z_subs(1)
11469.9130597554
>>> z_subs(4)
40.8626952786003

我会用它,但它很慢。有什么方法可以解决这个问题(修复lamdify错误或使用l作为一个不那么慢的函数的方法)?

版本:Python 2.7.6,NumPy 1.8.1,SymPy 0.7.4.1

1 个答案:

答案 0 :(得分:1)

回答你的问题:

问题在于:

z_lambdify = lambdify(w, l)

告诉新函数使用内置的math函数执行计算,您可以使用cProfile.run('z_lambdify(1)')检查运行情况;在执行z_subs(1)调用sympy函数时。要获得相同的行为,您应该告诉lambdify()使用相同的模块:

 z_lambdify = lambdify(w, l, "sympy")

重要建议:

您应该在其定义中简化您的功能,然后使用NumPy更有效地执行计算。使用一些简单的代数,您的函数可以以“非溢出”格式重写为:

f = lambda k, w: np.log(k - w) + (k - w)**5

这样可以实现您想要的答案:

f(k=u, w=1).sum()

当您执行f(k=u, w=1)时,您会得到一个具有相同形状u的数组,其中每个值表示使用u的每个值计算的函数的结果。您可以使用此功能同时评估f() kw的不同值,即将w作为具有相同形状u的另一个数组传递使用恒定值。