|
| 1 | +""" |
| 2 | +This is a program for illustrating the convergence of Newton's method |
| 3 | +for solving nonlinear algebraic equations of the form f(x) = 0. |
| 4 | +
|
| 5 | +Usage: |
| 6 | +python Newton_movie.py f_formula df_formula x0 xmin xmax |
| 7 | +
|
| 8 | +where f_formula is a string formula for f(x); df_formula is |
| 9 | +a string formula for the derivative f'(x), or df_formula can |
| 10 | +be the string 'numeric', which implies that f'(x) is computed |
| 11 | +numerically; x0 is the initial guess of the root; and the |
| 12 | +x axis in the plot has extent [xmin, xmax]. |
| 13 | +""" |
| 14 | +from Newton import Newton |
| 15 | +from scitools.std import * |
| 16 | +import matplotlib.pyplot as plt |
| 17 | +plt.xkcd() # cartoon style |
| 18 | +import sys |
| 19 | + |
| 20 | +def line(x0, y0, dydx): |
| 21 | + """ |
| 22 | + Find a and b for a line a*x+b that goes through (x0,y0) |
| 23 | + and has the derivative dydx at this point. |
| 24 | +
|
| 25 | + Formula: y = y0 + dydx*(x - x0) |
| 26 | + """ |
| 27 | + return dydx, y0 - dydx*x0 |
| 28 | + |
| 29 | + |
| 30 | +def illustrate_Newton(info, f, df, xmin, xmax): |
| 31 | + # First make a plot f for the x values that are in info |
| 32 | + xvalues = linspace(xmin, xmax, 401) |
| 33 | + fvalues = f(xvalues) |
| 34 | + ymin = fvalues.min(); ymax = fvalues.max() |
| 35 | + frame_counter = 0 |
| 36 | + |
| 37 | + # Go through all x points (roots) and corresponding values |
| 38 | + # for each iteration and plot a green line from the x axis up |
| 39 | + # to the point (root,value), construct and plot the tangent at |
| 40 | + # this point, then plot the function curve, the tangent, |
| 41 | + # and the green line, |
| 42 | + # repeat this for all iterations and store hardcopies for making |
| 43 | + # a movie. |
| 44 | + |
| 45 | + for root, value in info: |
| 46 | + a, b = line(root, value, df(root)) |
| 47 | + y = a*xvalues + b |
| 48 | + raw_input('Type CR to continue: ') |
| 49 | + plt.figure() |
| 50 | + plt.plot(xvalues, fvalues, 'r-', |
| 51 | + [root, root], [ymin, value], 'g-', |
| 52 | + [xvalues[0], xvalues[-1]], [0,0], 'k--', |
| 53 | + xvalues, y, 'b-') |
| 54 | + plt.legend(['f(x)', 'approx. root', 'y=0', 'approx. line']) |
| 55 | + plt.axis([xmin, xmax, ymin, ymax]) |
| 56 | + plt.title("Newton's method, iter. %d: x=%g; f(%g)=%.3E" % (frame_counter+1, root, root, value)) |
| 57 | + plt.savefig('tmp_root_%04d.pdf' % frame_counter) |
| 58 | + plt.savefig('tmp_root_%04d.png' % frame_counter) |
| 59 | + frame_counter += 1 |
| 60 | + |
| 61 | +try: |
| 62 | + f_formula = sys.argv[1] |
| 63 | + df_formula = sys.argv[2] |
| 64 | + x0 = float(sys.argv[3]) |
| 65 | + xmin = float(sys.argv[4]) |
| 66 | + xmax = float(sys.argv[5]) |
| 67 | +except IndexError: |
| 68 | + print 'f_formula df_formula x0 xmin max' |
| 69 | + sys.exit(1) |
| 70 | + |
| 71 | +# Clean up all plot files |
| 72 | +import glob, os |
| 73 | +for filename in glob.glob('tmp_*.pdf'): |
| 74 | + os.remove(filename) |
| 75 | + |
| 76 | +f = StringFunction(f_formula) |
| 77 | +f.vectorize(globals()) |
| 78 | +if df_formula == 'numeric': |
| 79 | + # Make a numerical differentiation formula |
| 80 | + h = 1.0E-7 |
| 81 | + def df(x): |
| 82 | + return (f(x+h) - f(x-h))/(2*h) |
| 83 | +else: |
| 84 | + df = StringFunction(df_formula) |
| 85 | + df.vectorize(globals()) |
| 86 | +x, info = Newton(f, x0, df, store=True) |
| 87 | +illustrate_Newton(info, f, df, xmin, xmax) |
| 88 | +plt.show() |
0 commit comments