AMath 583 Lab 4

Where to find this notebook:

Announcements:

  • Please sit at assigned tables.
  • You may need to hold the shift key while refreshing your browser to load the latest SMC.
  • Today will review some git commands and work more with the notebook for Newton's method.

You do not need to do the next command when using the IPython notebook on SageMathCloud, but it may be needed if you open this notebook on another system where the defaults are set differently. It does "from pylab import *" so numpy and plotting commands are available, and sets it up for plots to appear in the notebook webpage


In [1]:
%pylab inline


Populating the interactive namespace from numpy and matplotlib

Newton's method


In [1]:
def newton(fvals, x0, tol):
    xk = x0
    kmax = 30   # maximum number of iterations
    print "   k               xk                      f(xk)"
    for k in range(kmax):
        
        fxk, fpxk = fvals(xk)  # evaluate f(x) and f'(x)
        print "%4i   %22.15f  %22.15f"  % (k, xk, fxk)

        if abs(fxk) < tol:
            break  #leave the loop if tolerance satisfied
            
        xk = xk - fxk / fpxk  # update xk using Newton's method

    return xk

A function to take a single step of Newton's method and plot the step:

This next function takes as input some value xk (representing $x_k$ in an iteration of Newton's method) and returns $x_{k+1}$. It also plots the function along with the tangent line at xk that is used to define the next iterate. It plots the function and tangent line over an interval including the two points and adds a legend that contains the two values.


In [2]:
def newton_step_plot(xk, fvals):
    fxk, fpxk = fvals(xk)
    xkp1 = xk - fxk / fpxk  # calculate x_{k+1} from x_k
    xdiff = abs(xkp1 - xk)
    xlower = min(xk,xkp1) - xdiff
    xupper = max(xk,xkp1) + xdiff
    x = linspace(xlower,xupper,500)
    fx, fpx = fvals(x)
    tangent_line = fxk + (x-xk)*fpxk
    plot(x, fx, 'b')
    plot(x, tangent_line, 'r')
    plot([xk], [fxk], 'ro', label="x_k = %g" % xk)
    plot([xkp1], [0.], 'go', label="x_{k+1} = %g" % xkp1)
    plot([xlower, xupper], [0,0], 'k')
    legend(loc='best')   # uses the labels specified in the plot commands above
    axis('tight')
    return xkp1

Now experiment...

You might try:

  • See what happens with the previous example if you use different initial conditions. Does it always converge (perhaps with more steps?)
  • Try the function $f(x) =

In [6]:
def fvals(x):
    f = (x**2 - 2)*exp(-0.1*x**2) + 0.5
    fprime = (2*x -0.2*x*(x**2-2)) * exp(-0.1*x**2)
    return f, fprime



# Plot the function over a suitable range to get an idea of where the zeros are:

x = linspace(-10,10,1000)
fx, fpx = fvals(x)
plot(x,fx)
plot(x,zeros(len(x)), 'k')  # x-axis
#ylim(-2,0.5)


Out[6]:
[<matplotlib.lines.Line2D at 0x3d39710>]

In [7]:
xk = newton(fvals, 1., 1e-10)
fxk, fpxk = fvals(xk)
print "At xk = %22.15e,  f(xk) = %22.15e  " % (xk,fxk)


   k               xk                      f(xk)
   0        1.000000000000000      -0.404837418035960
   1        1.203370245891898       0.022503433876258
   2        1.193128381016442       0.000042137532198
   3        1.193109130763237       0.000000000151643
   4        1.193109130693959      -0.000000000000000
At xk =  1.193109130693959e+00,  f(xk) = -2.220446049250313e-16  

In [17]:
def fvals(x):
    f = 2 + 20*sin(x**2) - exp(x) 
    fprime = 40*x*cos(x**2) - exp(x)
    return f, fprime

# Plot the function over a suitable range to get an idea of where the zeros are:

x = linspace(-6,4,1000)
fx, fpx = fvals(x)
plot(x,fx)
plot(x,zeros(len(x)), 'k')  # x-axis
#ylim(-2,0.5)


Out[17]:
[<matplotlib.lines.Line2D at 0x3ec3850>]

Zoom in to look for good initial guesses:


In [19]:
x = linspace(0,4,1000)
fx, fpx = fvals(x)
plot(x,fx)
plot(x,zeros(len(x)), 'k')  # x-axis

figure()
plot(x,fx)
plot(x,zeros(len(x)), 'k')  # x-axis
xlim([2.5, 3.0])
ylim([-10,10])


Out[19]:
(-10, 10)

Try various initial guesses to try to find the three positive zeros:


In [12]:
x0 = 1.  # note this converges to a an xk < 0
xk = newton(fvals, x0, 1e-10)
fxk, fpxk = fvals(xk)
print "At xk = %22.15e,  f(xk) = %22.15e  " % (xk,fxk)


   k               xk                      f(xk)
   0        1.000000000000000      16.111137867698886
   1        0.147279584093039       1.275113632984884
   2       -0.122236669139563       1.413886040218566
   3        0.122640427016665       1.170324286577991
   4       -0.187413390025008       1.873230222316289
   5        0.037707068134118       0.990009450202088
   6       -2.069349649505509     -16.304073426099926
   7       -1.595303191123130      13.033820783745227
   8       -1.843161553225515      -3.215838784590288
   9       -1.797977469384006       0.014281578791279
  10       -1.798177337431642      -0.000000327567254
  11       -1.798177332847609       0.000000000000005
At xk = -1.798177332847609e+00,  f(xk) =  4.524158825347513e-15  

In [13]:
x0 = 2.
xk = newton(fvals, x0, 1e-10)
fxk, fpxk = fvals(xk)
print "At xk = %22.15e,  f(xk) = %22.15e  " % (xk,fxk)


   k               xk                      f(xk)
   0        2.000000000000000     -20.525106005089214
   1        1.656083808535012       4.530801410781863
   2        1.724443106218330      -0.267375592692043
   3        1.720811138308240      -0.000565143439227
   4        1.720803428772618      -0.000000002598783
   5        1.720803428737166       0.000000000000009
At xk =  1.720803428737166e+00,  f(xk) =  8.881784197001252e-15  

In [14]:
x0 = 2.5
xk = newton(fvals, x0, 1e-10)
fxk, fpxk = fvals(xk)
print "At xk = %22.15e,  f(xk) = %22.15e  " % (xk,fxk)


   k               xk                      f(xk)
   0        2.500000000000000     -10.846078291654610
   1        2.623584500613982      -0.492027749088077
   2        2.630340539018377      -0.006798464480951
   3        2.630436570096133      -0.000001430887492
   4        2.630436590316514      -0.000000000000071
At xk =  2.630436590316514e+00,  f(xk) = -7.105427357601002e-14  

In [15]:
x0 = 3.
xk = newton(fvals, x0, 1e-10)
fxk, fpxk = fvals(xk)
print "At xk = %22.15e,  f(xk) = %22.15e  " % (xk,fxk)


   k               xk                      f(xk)
   0        3.000000000000000      -9.843167218352535
   1        2.923944688926137      -1.259530461769195
   2        2.910481684113222      -0.052382376568243
   3        2.909870578351823      -0.000111027378573
   4        2.909869277563181      -0.000000000503633
   5        2.909869277557280       0.000000000000011
At xk =  2.909869277557280e+00,  f(xk) =  1.065814103640150e-14  

New problem:

Find the two points where the circle and line intersect in the plot below. The equation of the circle is $(x-1)^2 + y^2 = 4$ and the curve $y = \cos(x)$. Combine these equations by plugging $\cos(x)$ in for $y$ in the equation for the circle. This gives a single nonlinear equation in $x$ that you can solve using Newton's method.

Try to find both intersections and then replot the circle with these two points as red dots.


In [63]:
theta = linspace(0, 2*pi, 1000)
x = 1 + 2*cos(theta)
y = 2*sin(theta)
plot(x,y,'b')

x = linspace(-2,4,1000)
y = cos(x)
plot(x,y,'b')
axis('scaled')  # so circle looks circular


Out[63]:
(-2.0, 4.0, -2.0, 2.0)

In [ ]: