2017-01-23 2 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 o 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 вы хотите, чтобы ваша функция лямбда использовать 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 причиной этой проблемы было следующее: арифметика с плавающей запятой по умолчанию, используемая в созданной лямбда-функции, не была такой же, как в сценарии, который сравнивает результаты.

Я обновил суть с полным файлом решения, если кому-то нужно копировать-вставить

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

Edit: забыл дать документы ссылки

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

+1

Если вы хотите использовать арифметику произвольной точности, вы можете просто остаться в SymPy и использовать 'expr.evalf (precision)', который является оберткой вокруг mpmath (но возвращает выражение SymPy). – asmeurer

Смежные вопросы