0

I am solving a large problem where the location of the root to my equation changes very rapidly from one value to another. However the function is close to 0, and so Newton method thinks there is a root there, but iterates itself out. I would like to be able to ask the root finder to try again, but with a different initial guess if it can not converge the first time, but I am unsure how to handle this error. It is worth noting that I would like to use Newton/Secant method as Bisection method will not be very useful due to the problem I am solving. I have an example below which illustrates my problem.

I have searched on how to handle errors and looked at the documentation for scipy.optimize.newton but cannot find how to handle the error and ask it to try again. I keep having to manually input the new guess.

     from numpy import *
     from scipy import optimize

     # Define a function that passes 1, but grazes it at another point
     def f(x):
         y = log(exp(-0.8*x)*cos(5*x) + 0.62)
         return(y)
     # Try find the root
     root= optimize.newton(f, x0, tol = 1e-7, maxiter=80)

If I run this with some x0 value reasonably close to the true root (~0.2201), it finds it quickly. However, the function approaches 0 quite close around 1.25, but then turns back around. If i put x0 in as 1.25, the root finder fails to converge and the error reads 'Failed to converge after 80 iterations, value is nan'. I just want a way to handle this error and ask it to try again with another guess. I have a root finder as part of a big function which I know has a root, it has just moved. So when I get this error, it just terminates my whole code which I'd like to avoid.

Patrick Lewis
  • 83
  • 1
  • 1
  • 10
  • Are you want to find all roots of your function by starting at X0 without changing X0 or by changing X0 at each step? How you propose all X0's that are near to your function's roots – BarzanHayati Jul 18 '19 at 16:41
  • Your function at x=1.25 has a double root. maybe this be r reason of failing! – BarzanHayati Jul 18 '19 at 16:49

1 Answers1

1

What is happening is that your root finder is throwing an exception and you are not doing anything about it, which is why you see an error message.


From the Python 3.7.4 spec (Section 8.2):

Even if a statement or expression is syntactically correct, it may cause an error
...
Errors detected during execution are called exceptions
...
Most exceptions are not handled ... and result in error messages

From this we can see that the error message is caused because an exception happened and it wasn't handled.
The next section in defines how you should handle errors.

From the Python 3.7.4 spec (Section 8.3):

It is possible to write programs that handle selected exceptions.
...
The try statement works as follows.
• First, the try clause ... is executed.
• If an exception occurs during execution of the try clause, the rest of the clause is skipped. Then if its type matches the exception named after the except keyword, the except clause is executed, [then the program skips the rest of the try clause and continues after the except clause]
• If an exception occurs which does not match the exception named in the except clause, [the exception is thrown and can be caught by try-catch clauses wrapping around the current one]

Using this information, we can solve your problem.


We need to wrap your call to the root finder in a try clause:
try:
    root = optimize.newton(f, x0, tol = 1e-7, maxiter=80)
...

Since root is now local to the scope of the try clause, we need to declare it outside:

root = x0 
try:
    root = optimize.newton(f, x0, tol = 1e-7, maxiter=80)
...

We now need to add the except clause to try it with a different value:

root = x0 
try:
    root = optimize.newton(f, x0, tol = 1e-7, maxiter=80)
except YOUR EXCEPTION:
    root = optimizes.newton(f, other_x0, tol = 1e-7, maxiter=80)

You need to replace YOUR EXCEPTION with the name of the exception that is thrown when you reach the maximum amount of iterations.
Alternatively, you could replace it with Exception to catch any exception that is thrown but this isn't recommended because you might catch another exception that you won't know you have to fix.

Helen
  • 185
  • 11
  • Thank you so much, this makes a lot more sense. I will admit I am not a very strong programmer, so I am unsure what exactly I would put for the exception. When it does not converge all it does is return an error message which says ' RuntimeError: Failed to converge after 80 iterations, value is nan'. I'm unsure how to convert this output to an exception which I can then put in. Thanks – Patrick Lewis Jul 18 '19 at 21:44
  • After looking around, I believe 'YOUR EXCEPTION' becomes 'RuntimeError'. This does what I want it to do - if I am incorrect please let me know. Thank you a lot! – Patrick Lewis Jul 18 '19 at 22:10
  • Sorry for not replying yesterday! You are correct in using 'RuntimeError', the error messages always have the name of the exception at the beginning. I'm glad you were able to look it up and find out though that's like 90% of programming. Good luck! – Helen Jul 20 '19 at 12:39