2017-01-23 77 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