SymPy diff () function problem
I am working on implementing various numeric methods in python including reverse Euler. Thus, I decided to implement the fast Newton-Raphson method, which would give me the desired root for the variables of the equations that I would have to deal with with the calculator. Here he is:
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
A code excerpt that includes a function call 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
Where f
is the "sympified" symbol. In my failed test case, it was:f = sympify('(y**2 + t)/(y - t)')
As you can see, I am printing aux
content to keep track of exactly where the diff function is not working. This was the first iteration for y (0) = 1 for h = 0,1, where aux: -y + 1 + 0.1*(y**2 + 0.1)/(y - 0.1)
. Going through aux
both f
in Newton()
and then running diff(f, y)
it gives me:
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
Surprisingly, when I manually 'simpify' the same equation and 'diff' it, it works. Newton's method also works like a plume. However, I don't know what might be wrong.
source to share
It looks like you are using mpmath diff instead of SymPy. Try "from sympy import diff" before you call your routine. You can check which one you are using by asking for help:
>>> help(diff)
Help on method diff in module sympy.mpmath.calculus.differentiation:
against
>>> from sympy import diff
>>> help(diff)
Help on function diff in module sympy.core.function:
When I run your program with SymPy diff, I get
>>> 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]
source to share