-2

I am trying to find the roots of an equation using Newton's method. This is probably a very obvious mistake, but I keep getting an error that states: "TypeError: cannot determine truth value of Relational". Is there something I forgot to import/include? Sorry, I am very new to python.

import sympy

from sympy import *
x, y, z = symbols('x y z')
init_printing(use_unicode=True)

def newton(f, n, eps):
    y = f(n)
    delta = diff(eps, x)
    while abs(y) > eps:
        dy = (f(n + delta) - y) / delta
        n = n - y/dy
        y = f(n)
    return n

def f(n):
    return 5 * n + 10

eps = input("input function:")

print(newton(f, 0, eps))
Pidge G.
  • 23
  • 2
  • 2
    note that if your question is good and about python basics, no need to label it as "urgent". You'll get 7 answers in 45 nanoseconds with all the people starving on good questions on this sunday evening :) – Jean-François Fabre Jan 22 '17 at 20:54
  • So you say this is what you have so far but is there a problem with it? Does it raise errors? Does it not produce the correct results? – ayhan Jan 22 '17 at 20:56
  • I see that `print(newtroot(function,t))` is not passing the 3 parameters above, and passing `function` instead of `f`. And what is a function cast as integer??? – Jean-François Fabre Jan 22 '17 at 20:58
  • 1
    What you are doing has nothing to do with Newton's method. You should first read about it: https://en.wikipedia.org/wiki/Newton's_method. You start at some x and then get the function value there. After that you need to get the derivative at that point f'(x_i) and then find the intercept of the tangent line with y=0. Do this until you reach an x_n such that f(x_n) < epsilon. After you understood this you can start thinking about an implementation. :) – Martin Krämer Jan 22 '17 at 21:08
  • Should of course read abs(f(x_n)) < epsilon. – Martin Krämer Jan 22 '17 at 21:14
  • 1
    Evidently there's an implicit requirement to calculate the derivative given only the source of the function ... even if the function is restricted to be a polynomial, this is far beyond newbie level. Looks like the OP should be seeking clarification from the teacher. – John Machin Jan 22 '17 at 21:34
  • 1
    Worse: it asks for the rootS (plural) but only one guess is to be supplied! – John Machin Jan 22 '17 at 21:42
  • I doubt the expectation is symbolic derivation. Usually you just provide the function itself and for the derivative you just estimate f'(x) with (f(x+1e-10)-f(x)/1e-10 or sth similarly small. E.g. for f(x)=0.5*x**2 which would have f'(x)=x with the above method I get f'(3)=3.000000248221113, which is fine for all practical purposes. – Martin Krämer Jan 22 '17 at 21:53
  • And the method also converges only towards the root that the derivative at the guess is pointing to. If you need to find multiple roots it is important to initialize the guesses at the right positions. – Martin Krämer Jan 22 '17 at 21:57
  • @MartinKrämer (1) do you mean `estimate f'(x)` (2) with – John Machin Jan 22 '17 at 22:04
  • @JohnMachin Yes, exactly. f'(x) is approximately (f(x + epsilon) - f(x)) / epsilon. Mathematically the limit of epsilon going to zero would make the statement above equal to f'(x). Practically we just plug a small number in numerical code and are fine with it usually. :) – Martin Krämer Jan 22 '17 at 22:07

2 Answers2

1

Your code is not implementing Newton's method. You want to estimate the tangent line at an initial guess, intercept it with y=0 to get a new guess and keep doing that until the function at the guess value is close enough to 0. See the code below.

def newton(f, x, eps=1e-50):
    y = f(x)
    delta = 1e-10
    while abs(y) > eps:
        dy = (f(x+delta) - y) / delta
        x = x - y/dy
        y = f(x)
    return x

def f(x):
    return 5 * x + 10

newton(f, 0) # outputs -2.0

User-supplied functions via text are not easily doable. What we are usually doing is providing a numerical implementation of the function as above.

If you want to operate on the symbolical level you need to parse the string and construct a suitable function in your code, which is not really trivial. You may want to check whether libraries are available for that.

In practice you probably want to implement a maximum number of iterations in case someone runs it on a function without a root.

Martin Krämer
  • 559
  • 4
  • 17
  • Thank you a lot! For a user-defined function, would it be a smart idea to use Sympy and possibly diff(func, var)? – Pidge G. Jan 22 '17 at 22:40
  • Yeah, sympy could be fine for parsing. I would not do symbolic differentiation. There is probably no measurable benefit and it is pretty slow compared to calculating dy as above. – Martin Krämer Jan 22 '17 at 22:41
  • You can generally use sympy to find the root analytically anyway; the point of Newton's method is to find roots fast numerically. :) – Martin Krämer Jan 22 '17 at 22:43
  • sorry this is probably a really obvious mistake, but I put SymPy into your code but I keep getting an error that states: "TypeError: cannot determine truth value of Relational". Is there something I forgot to import from SymPy? I will put what am currently working with in the main part of the question. – Pidge G. Jan 23 '17 at 00:38
  • No idea. I never used sympy. Just aware of its existence. – Martin Krämer Jan 25 '17 at 17:22
  • +1 "If you want to operate on the symbolical level you need to parse the string and construct a suitable function in your code, which is not really trivial. You may want to check whether libraries are available for that." – Jack Sep 24 '17 at 02:34
1

Summary: A user-defined function can be formulated in SymPy, whose derivatives can be obtained almost automatically, and numerical functions for the objective function and its derivatives can be retrieved by lambdify. By using lambdifyed Python function, you do not trade efficience due to symbolic evaluation. Also, we can make use of SciPy optimization package which contains Newton method.

scipy.optimize.minimize offers Newton method. You can feed it with your objective function and its derivative and get the result.

The use of symbolic math in your original code does not makes sense to me as it deals with a specific math formula. Use NumPy and you get better execution performance.

If you are thinking of offering a general math interface to various math formulae, SymPy is great because we can enjoy its derivative functionality.

Several months ago, I have played with the combination of SymPy and SciPy optimize to do a physical model of spring-connected bodies.

https://github.com/wakita/symdoc/blob/master/kk.ipynb

  • The formula of the objective function is given in In[9].
  • A Python function that corresponds to the objective function is obtained in In[10].
  • Derivatives of the objective function is obtained in In[14].
  • Newton-based Minimization is performed in In[19]. It makes use of the first- and second-order derivatives of the objective function.

The beauty of using SymPy is that as you see in my example, I do not mess with complex calculation of derivatives at all and for another, the solution deals with any formula that is expressed in SymPy.

ken
  • 323
  • 2
  • 10