newton_conv_est.mws

A Procedure for Newton's Method in R^n

Version 0.8

This worksheet:

1. contains a proceudre to do n iterations of Newtons method for solving f=0 where
f:R^n->R^n is given as a liast of expressions

2. optionally show the function values at each iteration.

3. optionally show an estimate |f| |D2f| |Df^(-1)|^2 used in checking the convergence

of Newton's method near this point, where the norms are sums of squares of entries.

If the quantity (replacing the second derivative term by a second derivative norm

bound in a suitable ball) is smaller than 1/2 then convergence is guaranteed.

4. will be available at the URL http://www.mathlab.cornell.edu/local_maple/newton_conv_est.mws when completed.

> restart;

> with(linalg):

Warning, the protected names norm and trace have been redefined and unprotected

> with(plots):

Warning, the name changecoords has been redefined

Change this value if you'd like a different floating point accuracy. More digits are fine.

> Digits:=10;

This error tolerance is used to decide if a matrix is too close to 0 (as measured by its det) to be considered invertible. Reduce it if you like.

> tol := 10.0^(-8);

Change this to false and re-execute the line if you don't want to see function values.

> show_f_val := true;

Change this between true and false and re-execute the line depending on whether you want to see the test for f convergence for the Newton's method near this point.

> show_conv_estimate := true;

Typical Usage: newton([x^2-y^2-16, 2*x*y-30], [x,y], [4,4],10);

to do 10 iterations of Newton's method for solving

x^2-y^2-16 = 0
2*x*y-30 = 0
using the variables [x,y] and starting with the point [4,4].
The sequence of iterations are maintained as p[0], p[1], ... in a global table p.

> newton := proc(f,vars,p0,n)
local i, j, m, u, f_val, Df, Df_val, Df_detval, Df_invval,var_subs_set, err_found,q,q_pre, rad_est, H2f, H2f_val, D2f_norm;
p:= 'p';
p[0] := eval(p0):
q:= map(evalf,p0);
m:= nops(vars);
Df := jacobian(f,vars);
var_subs_set := {seq(vars[j]=q[j],j=1..m)};
f_val := map(evalf,map2(subs,var_subs_set,f));
Df_val := map(evalf,map2(subs,var_subs_set,Df));
Df_detval := det(Df_val);
err_found := evalb(abs(Df_detval) < tol);
printf(`Iteration starts with %a.\n`,convert(q,list));
if (show_f_val) then
printf(`\t\tThe function value here is %a.\n`, f_val);
fi:
if (show_conv_estimate) then
H2f:=[seq(hessian(f[i],vars),i=1..m)];
H2f_val:= map2(subs,var_subs_set,H2f):
Df_invval := inverse(Df_val);
printf(`\t\tThe convergence estimate here is %a.\n`, evalf(rad_est));
fi:
printf(`\n`);
q_pre := eval(q);
for i from 1 to n while (not err_found) do
q := map(evalf,evalm(q_pre - Df_val^(-1) &* f_val));
u := evalm(q - q_pre);
d := sqrt(1.0*dotprod(u,u));
printf(`Iteration %d gives %a, a distance %g from the previous.\n`,i,convert(q,list),d);
var_subs_set := {seq(vars[j]=q[j],j=1..m)};
f_val := map(evalf,map2(subs,var_subs_set,f));
if (show_f_val) then
printf(`\t\tThe function value here is %a.\n`, f_val);
fi:
Df_val := map(evalf,map2(subs,var_subs_set,Df));
Df_detval := det(Df_val);
if (show_conv_estimate) then
H2f_val:= map2(subs,var_subs_set,H2f):
Df_invval := inverse(Df_val);
printf(`\t\tThe convergence estimate here is %a.\n`, rad_est);
fi:
err_found := evalb(abs(Df_detval) < tol);
q_pre := eval(q);
p[i] := convert(eval(q_pre),list);
printf(`\n`);
od:
eval(q);
end:

Enter your function as a list of expressions.

> f := [x^2-y^2-16,2*x*y-30];

> newton(f,[x,y],[4,4],10);

Iteration starts with [4., 4.].

The function value here is [-16., 2.].

The convergence estimate here is .1574659717e-1.

Iteration 1 gives [4.875000000, 2.875000000], a distance 1.425219 from the previous.

The function value here is [-.50000000, -1.96875000].

The convergence estimate here is .7919095779e-2.

Iteration 2 gives [5.001402439, 3.002378049], a distance .179451 from the previous.

The function value here is [-.24759e-3, .3220180e-1].

The convergence estimate here is .1112429410e-3.

Iteration 3 gives [5.000000023, 3.000000653], a distance .002760 from the previous.

The function value here is [-.369e-5, .666e-5].

The convergence estimate here is .2634571979e-7.

Iteration 4 gives [5.000000000, 3.000000001], a distance 6.524055e-07 from the previous.

The function value here is [-.1e-7, 0.].

The convergence estimate here is .3460207611e-10.

Iteration 5 gives [5.000000001, 3.000000001], a distance 1.000000e-09 from the previous.

The function value here is [0., .2e-7].

The convergence estimate here is .6920415222e-10.

Iteration 6 gives [5.000000000, 3.000000000], a distance 1.414214e-09 from the previous.

The function value here is [0., 0.].

The convergence estimate here is 0..

Iteration 7 gives [5.000000000, 3.000000000], a distance 0 from the previous.

The function value here is [0., 0.].

The convergence estimate here is 0..

Iteration 8 gives [5.000000000, 3.000000000], a distance 0 from the previous.

The function value here is [0., 0.].

The convergence estimate here is 0..

Iteration 9 gives [5.000000000, 3.000000000], a distance 0 from the previous.

The function value here is [0., 0.].

The convergence estimate here is 0..

Iteration 10 gives [5.000000000, 3.000000000], a distance 0 from the previous.

The function value here is [0., 0.].

The convergence estimate here is 0..

> p[3];

> pts := [seq(p[i],i=0..10)];

> plot(pts,`sequence of points in the plane`,thickness=3);

>

>

>