Я работаю над реализацией различных численных методов на питоне, включая обратный Эйлер. Таким образом, я решил реализовать быстрый метод Ньютона-Рафсона, который дал бы мне желаемый корень для уравнений с переменными, с которыми придется иметь дело моему калькулятору. Вот:
def Newton(y0, f, tol=1e-10):
y = Symbol('y')
df = diff(f, y)
while f.subs(y, y0) > tol:
y0 -= f.subs(y, y0)/df.subs(y, y0)
return y0
Фрагмент кода, связанный с вызовом функции Newton()
:
def InverseEuler(f, y0, t0, tf, h):
coords = [[t0, y0]]
t, y = symbols('t y')
while round(t0, 7) < round(tf, 7):
aux = sympify(y0 - y + h*f.subs(t, t0 + h))
print aux
y0 = utils.Newton(y0, aux)
t0 += h
coords.append([t0, y0])
return coords
Где f
— это «упрощенная» строка. В моем неудачном тестовом случае это было: f = sympify('(y**2 + t)/(y - t)')
Как видите, я печатаю содержимое aux
, чтобы отследить, где именно происходит сбой функции diff. Это было в первой итерации для y(0) = 1 с h = 0,1, где aux было: -y + 1 + 0.1*(y**2 + 0.1)/(y - 0.1)
. При передаче aux
как f
в Newton()
и последующем запуске diff(f, y)
это дает мне:
Traceback (most recent call last):
File "C:\Users\Gabriel Vasconcelos\Documents\python\Metodos\metodos.py", line 97, in <module>
GPHandler.replot(InverseEuler(f, 1, 0, 4, 0.1))
File "C:\Users\Gabriel Vasconcelos\Documents\python\Metodos\metodos.py", line 31, in InverseEuler
y0 = utils.Newton(y0, aux)
File "C:\Users\Gabriel Vasconcelos\Documents\python\Metodos\utils.py", line 6, in Newton
df = diff(f, y)
File "C:\Python27\lib\site-packages\sympy\mpmath\calculus\differentiation.py", line 188, in diff
values, norm, workprec = hsteps(ctx, f, x, n, prec, **options)
File "C:\Python27\lib\site-packages\sympy\mpmath\calculus\differentiation.py", line 61, in hsteps
values = [f(x+k*h) for k in steps]
TypeError: 'Add' object is not callable
Удивительно, но когда я вручную «упрощаю» это же уравнение и «дифференцирую» его, оно работает. Метод Ньютона также работает как шлейф. Тем не менее, я не знаю, что может быть не так.