2017-01-23 7 views
1

ich folgendes Problem gestoßen, zunächst möchte ich kurz erklären, was los ist:lambdified sympy Ausdruck gibt falsches Ergebnis

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

Von dort wir

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

lambdified g(x,y) kehrt etwas sehr nahe bei Null statt erwarten von Null. Hier ist ein Code, der das Problem reproduziert. Es kommt nur, wenn ich genügend log Auswertungen setzen in f(x)

Kern: https://gist.github.com/marekyggdrasil/39a24213ebaba6293464d116821cc334

Quelle:

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

Ausgang

$ 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

Hallo, schaut zu geben verweisen, wie es eine ist [floating Punktdarstellungsfehler] (https://docs.python.org/2/tutorial/floatingpoint.html#representation-error), im Grunde, weil Sie Operationen an Gleitkommawerten durchführen, akkumulieren Sie Approximationsfehler, die t nicht addieren o 0 Wenn Sie einfach '0.4 + 0.3 + 0.2' ausführen, erhalten Sie' 0.8999999999999999' in python – JMat

+0

Ich glaube nicht, dass es das Argument gegen es wäre, dass es nicht ansammelt, gibt es nur eine Auswertung auf dem Weg, vielleicht sollte ich eine Frage anders stellen: Warum liefern letzte und vorletzte Zeilen der Quelle unterschiedliche Ergebnisse? – Marek

+0

Wie Sie sehen können 'lambfun_rooteq (* x)' und '- x [4] + lambfun_criteria (* x)' sind genau die gleichen Berechnungen auf genau die gleichen Werte, aber liefern unterschiedliche Ergebnisse, ich denke, das ist das Schlüsselproblem. – Marek

Antwort

0

ich, dass eine benutzerdefinierte Mathematikmodul gefunden werden kann angegeben, wenn SymPy Ausdruck Lambda ist. In meinem Fall mpmath geholfen.

Import mpmath und stellen Sie die Präzision zu etwas, das Sie ausreichend

from mpmath import mp 
mp.dps = 15 

Sagen SymPy finden Sie Ihre Lambda-Funktion mpmath für den Umgang mit Fließkommaarithmetik

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

Dann bekomme ich die Ausgabe schließlich zu verwenden

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

T Die Ursache des Problems war die folgende: Die Standard-Fließkomma-Arithmetik, die in der erstellten Lambda-Funktion verwendet wurde, war nicht die gleiche wie die im Skript verwendete, die die Ergebnisse vergleicht.

ich den Kern mit voller Lösung Datei aktualisiert, wenn jemand copy-paste

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

bearbeiten muss: vergessen docs

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

+1

Wenn Sie Arbitrary mit beliebiger Genauigkeit verwenden möchten, können Sie auch einfach in SymPy bleiben und 'expr.evalf (precision)' verwenden, was ein Wrapper um mpmath ist (aber einen SymPy-Ausdruck zurückgibt). – asmeurer