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

时间:2021-10-18 23:21:46

So, I have this code

所以,我有这个代码

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)

And now I want to use l as a function of w. So I know of some options

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

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

The first function gives an error

第一个函数给出错误

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

While the second gives answers

而第二个给出答案

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

I would just use this, but it is very slow. Any way to get around this (fixing the lamdify error or a way of using l as a function that is not so slow)?

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

Version: Python 2.7.6, NumPy 1.8.1, SymPy 0.7.4.1

版本:Python 2.7.6,NumPy 1.8.1,SymPy 0.7.4.1

1 个解决方案

#1


1  

Answering your question:

The problem is that:

问题是:

z_lambdify = lambdify(w, l)

tells the new function to perform the calculations using the built-in math functions, which you can check running with cProfile.run('z_lambdify(1)'); while doing z_subs(1) calls sympy functions. To get the same behavior you should tell lambdify() to use the same module:

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

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

Important suggestion:

You should simplify your function already at its definition and then useNumPy to perform the calculations much more efficiently. Using some simple algebra your function can be rewritten in a "non-overflowing" format as:

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

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

such that your desired answer can be achieved doing:

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

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

when you do f(k=u, w=1) you get an array with the same shape of u, where each value represents the result of the function evaluated with each value of u. You can use this function to simultaneously evaluate f() for different values of k and w, i.e. passing w as another array with the same shape of u instead of using a constant value.

当你做f(k = u,w = 1)时,你得到一个具有相同u形状的数组,其中每个值代表用u的每个值计算的函数的结果。您可以使用此函数同时为不同的k和w值评估f(),即将w作为另一个具有相同u形状的数组而不是使用常量值。

#1


1  

Answering your question:

The problem is that:

问题是:

z_lambdify = lambdify(w, l)

tells the new function to perform the calculations using the built-in math functions, which you can check running with cProfile.run('z_lambdify(1)'); while doing z_subs(1) calls sympy functions. To get the same behavior you should tell lambdify() to use the same module:

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

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

Important suggestion:

You should simplify your function already at its definition and then useNumPy to perform the calculations much more efficiently. Using some simple algebra your function can be rewritten in a "non-overflowing" format as:

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

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

such that your desired answer can be achieved doing:

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

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

when you do f(k=u, w=1) you get an array with the same shape of u, where each value represents the result of the function evaluated with each value of u. You can use this function to simultaneously evaluate f() for different values of k and w, i.e. passing w as another array with the same shape of u instead of using a constant value.

当你做f(k = u,w = 1)时,你得到一个具有相同u形状的数组,其中每个值代表用u的每个值计算的函数的结果。您可以使用此函数同时为不同的k和w值评估f(),即将w作为另一个具有相同u形状的数组而不是使用常量值。