2014-11-06 3 views
3

Я работаю над реализацией различных числовых методов на python, включая обратный Эйлер. Таким образом, я решил реализовать быстрый метод Ньютона-Рафсона, который дал бы мне искомый корень для переменных уравнений, с которыми мне придется иметь дело с калькулятором. Вот оно:Проблема с функцией SymPy diff()

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 является 'sympified' строка. В моем неудачном тестовом случае это было: 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 

Удивительно, но когда я вручную «simpify» что такое же уравнение, и «Diff» это, она работает. Метод Ньютона также работает как плюм. Тем не менее, я не знаю, что может быть неправильно.

ответ

4

Похоже, вы используете mpmath diff вместо SymPy. Попробуйте «от sympy import diff», прежде чем вы вызовете свою рутину. Вы можете проверить, какие из них вы используете, прося помощи:

>>> help(diff) 
Help on method diff in module sympy.mpmath.calculus.differentiation: 

против

>>> from sympy import diff 
>>> help(diff) 
Help on function diff in module sympy.core.function: 

Когда я запускаю программу с дифф SymPy, я получить

>>> InverseEuler(f,1, 0, 1, 0.1)[-1] 
-y + 1 + 0.1*(y**2 + 0.1)/(y - 0.1) 
-y + 1.13404207225556 + 0.1*(y**2 + 0.2)/(y - 0.2) 
-y + 1.30637177730098 + 0.1*(y**2 + 0.3)/(y - 0.3) 
-y + 1.52036600337727 + 0.1*(y**2 + 0.4)/(y - 0.4) 
-y + 1.77886566311632 + 0.1*(y**2 + 0.5)/(y - 0.5) 
-y + 2.08466045990054 + 0.1*(y**2 + 0.6)/(y - 0.6) 
-y + 2.44089877798719 + 0.1*(y**2 + 0.7)/(y - 0.7) 
-y + 2.85134771320082 + 0.1*(y**2 + 0.8)/(y - 0.8) 
-y + 3.32053168504081 + 0.1*(y**2 + 0.9)/(y - 0.9) 
-y + 3.85380349564978 + 0.1*(y**2 + 1.0)/(y - 1.0) 
[0.99999999999999989, 4.45738956363267] 
+0

Спасибо! Мне нужно привыкнуть к этим конфликтам ... Естественно, переключение позиций, в которых я импортировал sympy, и где я импортировал mpmath, заставил его работать отлично! –

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