2017-01-23 76 views
1

我遇到以下问题,首先我会简单解释一下这是怎么回事:lambdified sympy表达式返回不正确的结果

f(x) 
g(x, y) = f(x) - y 

从那里,我们预计

g(x, f(x)) = f(x) - f(x) = 0 

lambdified g(x,y)回报的东西非常接近零,而不是为零。这是一个重现问题的代码。它只有当我把log评估足量到达f(x)

要点:https://gist.github.com/marekyggdrasil/39a24213ebaba6293464d116821cc334

来源:

from sympy import Symbol, pprint, log, lambdify 

# setting symbols 
g1 = Symbol("gamma1") 
g2 = Symbol("gamma2") 
g3 = Symbol("gamma3") 
g4 = Symbol("gamma4") 
rt = Symbol("rt") 

# setting expressions 
criteria = (g1 * log(g1, 2.0))/2.0 
criteria += (g2 * log(g2, 2.0))/2.0 
criteria += (g3 * log(g3, 2.0))/2.0 
criteria += (g4 * log(g4, 2.0))/2.0 
rooteq = criteria - rt 

print "\ncriteria function: " 
pprint(criteria) 

print "\ncriteria function - rt: " 
pprint(rooteq) 

# lambdifying expressions to callable functions 
tsymbols = [g1, g2, g3, g4, rt] 
lambfun_criteria = lambdify(tsymbols, criteria) 
lambfun_rooteq = lambdify(tsymbols, rooteq) 

# example point x 
x = [0.25006462253641376, 2.2501938662000542, 2.2501938662000542, 2.2501938662000542, 0.0] 

# evaluating of criteria on x 
rootval = lambfun_criteria(*x) 

# setting rt to this evaluation 
x[4] = rootval 

print "\nactual evaluation of rooteq: " + str(lambfun_rooteq(*x)) 
print "\nexpected evaluation of rooteq: " + str(- x[4] + lambfun_criteria(*x)) 

输出

$ python lambdifytest.py 

criteria function: 
0.721347520444482⋅γ₁⋅log(γ₁) + 0.721347520444482⋅γ₂⋅log(γ₂) + 0.721347520444482⋅γ₃⋅log(γ₃) + 0.721347520444482⋅γ₄⋅log(γ₄) 

criteria function - rt: 
0.721347520444482⋅γ₁⋅log(γ₁) + 0.721347520444482⋅γ₂⋅log(γ₂) + 0.721347520444482⋅γ₃⋅log(γ₃) + 0.721347520444482⋅γ₄⋅log(γ₄) - rt 

actual evaluation of rooteq: 4.4408920985e-16 

expected evaluation of rooteq: 0.0 
+0

你好,看起来就像是一个[浮动点表示错误](https://docs.python.org/2/tutorial/floatingpoint.html#representation-error),基本上,因为您在浮点上执行操作,所以您累积的近似错误不会累加t 0 0 如果你只是执行'0.4 + 0.3 + 0.2',你会得到'0.8999999999999999' python – JMat

+0

我不认为这是,反对它的论点是它不会积累,只有一个评估在途中,也许我应该提出一个不同的问题:为什么最后和最后一行来源提供不同的结果? – Marek

+0

正如你所看到的'lambfun_rooteq(* x)'和' - x [4] + lambfun_criteria(* x)'在完全相同的值上完全相同的计算,但会产生不同的结果,我认为这是关键问题。 – Marek

回答

0

我发现一个自定义的数学模块可当SymPy表达式被指定时指定。在我的情况下,mpmath帮助。

导入mpmath并设置精密的东西,你找到足够

from mpmath import mp 
mp.dps = 15 

告诉SymPy你希望你的lambda函数使用mpmath处理浮点运算

lambfun_criteria = lambdify(tsymbols, criteria, "mpmath") 
lambfun_rooteq = lambdify(tsymbols, rooteq, "mpmath") 

于是最后我得到的输出

actual evaluation of rooteq: 0.0 
expected evaluation of rooteq: 0.0 

T导致问题的原因如下,创建的lambda函数中使用的默认浮点运算与脚本中用于比较结果的算法不同。

我更新了完整的解决方案文件的要点,如果有人需要复制粘贴

https://gist.github.com/marekyggdrasil/39a24213ebaba6293464d116821cc334#file-lambdify_test_solution-py

编辑:忘了给文档引用

http://docs.sympy.org/dev/modules/utilities/lambdify.html

+1

如果你想使用任意的精度算术,你可能会留在SymPy中,并使用'expr.evalf(precision)',它是一个包围mpmath(但返回一个SymPy表达式)的'expr.evalf(precision)'。 – asmeurer