RootFinding.mw

Root-Finding Methods 

Define a function and its true root 

> `:=`(f, proc (x) options operator, arrow; `+`(`*`(`^`(x, 2)), `-`(`*`(`/`(1, 2), `*`(exp(`+`(`-`(x))))))) end proc)
 

proc (x) options operator, arrow; `+`(`*`(`^`(x, 2)), `-`(`*`(`/`(1, 2), `*`(exp(`+`(`-`(x))))))) end proc (1)
 

 

Use Maple's fsolve to compute the root to 20 digit accuracy. 

 

> `:=`(Digits, 20)
 

20 (2)
 

> `:=`(trueroot, fsolve(f(x) = 0, x))
 

.53983527690282004921 (3)
 

 

Use 14 digit arithmetic for testing the methods, and set the tolerance for the stopping criteron. 

 

> `:=`(Digits, 14)
 

14 (4)
 

> `:=`(tol, 0.1e-10)
 

0.1e-10 (5)
 

 

Set the fail-safe maximum number of iterations. 

 

> `:=`(maxiter, 100)
 

100 (6)
 

>
 

Bisection method 

> `:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
`:=`(bisection, proc (`::`(f, procedure), `::`(a, numeric), `::`(b, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xleft, xright, xlist, i, c, fxleft, fc; `:=`(xleft, xright, evalf(a), ev...
 

>
 

> `:=`(a, b, 1.0, .5)
 

1.0, .5 (7)
 

> f(a), f(b)
 

.81606027941428, -0.5326532985632e-1 (8)
 

> `:=`(xlist, bisection(f, a, b, tol, maxiter))
 

[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
[1.0, .5, .75000000000000, .62500000000000, .56250000000000, .53125000000000, .54687500000000, .53906250000000, .54296875000000, .54101562500000, .54003906250000, .53955078125000, .53979492187500, .53...
(9)
 

> `:=`(N, nops(xlist))
 

39 (10)
 

>
 

 

Note: When testing the order of convergence for each of the methods, we choose to run the loop (see below) from 1 to `+`(N, `-`(3)) and therefore the last ratio tested compares the error in xlist[`+`(N, `-`(2))] with the error in xlist[`+`(N, `-`(3))]. 

 

This is because as the iterates near convergence, one would need to compute with a higher setting of Digits in order to get a true reading of the ratios. (This point is particularly relevant for the methods which converge at a faster rate.) 

 

 

Test if the order of convergence is q = 1. 

 

> `:=`(q, 1)
 

1 (11)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

i = 1, ratio = 0.86567428799637e-1
i = 2, ratio = 5.2758444132292
i = 3, ratio = .40522844101576
i = 4, ratio = .26612806656246
i = 5, ratio = .37879469632207
i = 6, ratio = .81997624268446
i = 7, ratio = .10977376413137
i = 8, ratio = 4.0548224018412
i = 9, ratio = .37669003708449
i = 10, ratio = .17264872766506
i = 11, ratio = 1.3960537778767
i = 12, ratio = .14184760793351
i = 13, ratio = 2.0249096356589
i = 14, ratio = .25307540089940
i = 15, ratio = .47569577400347
i = 16, ratio = .55109195221603
i = 17, ratio = .40728960564461
i = 18, ratio = .72762769328812
i = 19, ratio = .18716460988520
i = 20, ratio = 2.1714452236390
i = 21, ratio = .26973860792948
i = 22, ratio = .35364640174434
i = 23, ratio = .91384161561881
i = 24, ratio = 0.47140676438867e-1
i = 25, ratio = 10.106554963832
i = 26, ratio = .45052734206472
i = 27, ratio = .39018944397791
i = 28, ratio = .21857117685557
i = 29, ratio = .78758913233332
i = 30, ratio = .13484268759291
i = 31, ratio = 3.2080245797940
i = 32, ratio = .34414084507042
i = 33, ratio = 0.47147417532946e-1
i = 34, ratio = 9.1059027777778
i = 35, ratio = .44518589132507
i = 36, ratio = .37644539614561 (12)
 

>
 

 

While we don't see a definite limit being reached, the ratios are not tending towards 0 nor towards infinity. 

The bisection method has linear convergence (order q = 1). 

 

More precisely, the stopping criterion used in the bisection method above is based on the length of the current interval [xleft, xright]. Since we start with an initial interval [a, b] which has length abs(`+`(b, `-`(a))) and at each iteration the new interval has length exactly half the preceding interval, it is clear that the ratio of successive interval lengths is exactly `/`(1, 2). This proves that the bisection method has linear convergence. 

 

 

For example, let us test if the order of convergence is q = 2. 

 

> `:=`(q, 2)
 

2 (13)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

i = 1, ratio = .18812269705724
i = 2, ratio = 132.44151474333
i = 3, ratio = 1.9281468128616
i = 4, ratio = 3.1248627000030
i = 5, ratio = 16.712963785081
i = 6, ratio = 95.509586000088
i = 7, ratio = 15.593477558136
i = 8, ratio = 5247.0802207525
i = 9, ratio = 120.21486235944
i = 10, ratio = 146.26933196872
i = 11, ratio = 6850.6008137739
i = 12, ratio = 498.59323517769
i = 13, ratio = 50177.381730246
i = 14, ratio = 3097.0387228100
i = 15, ratio = 23002.554148232
i = 16, ratio = 56019.798730562
i = 17, ratio = 75127.118706071
i = 18, ratio = 329533.29390231
i = 19, ratio = 116494.27775492
i = 20, ratio = 7221143.9885510
i = 21, ratio = 413096.35205810
i = 22, ratio = 2007864.4005474
i = 23, ratio = 14671240.085866
i = 24, ratio = 828172.43446117
i = 25, ratio = 3766450750.6893
i = 26, ratio = 16612965.441403
i = 27, ratio = 31935989.115763
i = 28, ratio = 45848193.698622
i = 29, ratio = 755850950.90483
i = 30, ratio = 164310052.38822
i = 31, ratio = 28989920294.542
i = 32, ratio = 969410831.18429
i = 33, ratio = 385916489.58784
i = 34, ratio = 1580885898919.8
i = 35, ratio = 8487814896.5695
i = 36, ratio = 16121858507.307 (14)
 

>
 

 

This time, the ratios are increasing towards infinity and therefore the hypothesized order q = 2 is too large. 

 

>
 

Fixed point iteration 

> `:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
`:=`(fixedpoint, proc (`::`(g, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter while `<`(tol, abs(`...
 

>
 

> `:=`(g, unapply(`+`(x, `-`(f(x))), x))
 

proc (x) options operator, arrow; `+`(x, `-`(`*`(`^`(x, 2))), `*`(`/`(1, 2), `*`(exp(`+`(`-`(x)))))) end proc (15)
 

> `:=`(x0, 1.0)
 

1.0 (16)
 

> `:=`(xlist, fixedpoint(g, x0, tol, maxiter))
 

[0., 1.0, .18393972058572, .56609887674714, .52949890451207, .54357981007437, .53843372706828, .54035370380524, .53964266286324, .53990672286905, .53980875946697, .53984511672844, .53983162533285, .53...
[0., 1.0, .18393972058572, .56609887674714, .52949890451207, .54357981007437, .53843372706828, .54035370380524, .53964266286324, .53990672286905, .53980875946697, .53984511672844, .53983162533285, .53...
[0., 1.0, .18393972058572, .56609887674714, .52949890451207, .54357981007437, .53843372706828, .54035370380524, .53964266286324, .53990672286905, .53980875946697, .53984511672844, .53983162533285, .53...
[0., 1.0, .18393972058572, .56609887674714, .52949890451207, .54357981007437, .53843372706828, .54035370380524, .53964266286324, .53990672286905, .53980875946697, .53984511672844, .53983162533285, .53...
[0., 1.0, .18393972058572, .56609887674714, .52949890451207, .54357981007437, .53843372706828, .54035370380524, .53964266286324, .53990672286905, .53980875946697, .53984511672844, .53983162533285, .53...
[0., 1.0, .18393972058572, .56609887674714, .52949890451207, .54357981007437, .53843372706828, .54035370380524, .53964266286324, .53990672286905, .53980875946697, .53984511672844, .53983162533285, .53...
(17)
 

> `:=`(N, nops(xlist))
 

28 (18)
 

>
 

 

Test if the order of convergence is q = 1. 

 

> `:=`(q, 1)
 

1 (19)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

i = 1, ratio = .85241691824452
i = 2, ratio = .77340903909738
i = 3, ratio = 0.73795807163491e-1
i = 4, ratio = .39356266665727
i = 5, ratio = .36226763413642
i = 6, ratio = .37429227365072
i = 7, ratio = .36989544691442
i = 8, ratio = .37153557942476
i = 9, ratio = .37092813372166
i = 10, ratio = .37115371586738
i = 11, ratio = .37107002636531
i = 12, ratio = .37110108563082
i = 13, ratio = .37108955904794
i = 14, ratio = .37109383293570
i = 15, ratio = .37109224220093
i = 16, ratio = .37109283605557
i = 17, ratio = .37109260657617
i = 18, ratio = .37109269505296
i = 19, ratio = .37109261533267
i = 20, ratio = .37109399284499
i = 21, ratio = .37108786037374
i = 22, ratio = .37109086431913
i = 23, ratio = .37104622871046
i = 24, ratio = .37108792846498
i = 25, ratio = .37108433734940 (20)
 

>
 

 

These ratios are approaching a nonzero finite constant. 

 

Fixed point iteration has linear convergence (order q = 1), in general. 

 

>
 

Newton's method 

> `:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
`:=`(newton, proc (`::`(f, procedure), `::`(fprime, procedure), `::`(x0, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i; `:=`(xlist, `+`(x0, `-`(1)), x0); for i from 2 to maxiter...
 

>
 

> eval(f)
 

proc (x) options operator, arrow; `+`(`*`(`^`(x, 2)), `-`(`*`(`/`(1, 2), `*`(exp(`+`(`-`(x))))))) end proc (21)
 

> `:=`(fprime, unapply(diff(f(x), x), x))
 

proc (x) options operator, arrow; `+`(`*`(2, `*`(x)), `*`(`/`(1, 2), `*`(exp(`+`(`-`(x)))))) end proc (22)
 

> `:=`(x0, 2.0)
 

2.0 (23)
 

> `:=`(xlist, newton(f, fprime, x0, tol, maxiter))
 

[1.0, 2.0, 1.0332709786444, .63686054270010, .54511924037554, .53985256974508, .53983527708914, .53983527690281, .53983527690282]
[1.0, 2.0, 1.0332709786444, .63686054270010, .54511924037554, .53985256974508, .53983527708914, .53983527690281, .53983527690282]
(24)
 

> `:=`(N, nops(xlist))
 

9 (25)
 

>
 

 

Test if the order of convergence is q = 1. 

 

> `:=`(q, 1)
 

1 (26)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

i = 1, ratio = 3.1731348575993
i = 2, ratio = .33793153192671
i = 3, ratio = .19663203423431
i = 4, ratio = 0.54459665008907e-1
i = 5, ratio = 0.32727028393136e-2
i = 6, ratio = 0.10774400020463e-4 (27)
 

>
 

 

The ratios are decreasing towards 0 and therefore the hypothesized order q = 1 is too small. 

 

 

Test if the order of convergence is q = 2. 

 

> `:=`(q, 2)
 

2 (28)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

i = 1, ratio = 6.8956499669125
i = 2, ratio = .23143384207360
i = 3, ratio = .39849575849557
i = 4, ratio = .56129364409774
i = 5, ratio = .61936515197538
i = 6, ratio = .62305547338420 (29)
 

>
 

 

These ratios appear to be approaching a nonzero finite constant. 

 

Newton's method has quadratic convergence (order q = 2). 

 

>
 

Secant method 

> `:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
`:=`(secant, proc (`::`(f, procedure), `::`(x0, numeric), `::`(x1, numeric), `::`(tol, numeric), `::`(maxiter, integer)) local xlist, i, fx, fxprev; `:=`(xlist, x0, x1); `:=`(fx, f(xlist[1])); for i f...
 

>
 

> `:=`(x0, x1, 2.0, 0.)
 

2.0, 0. (30)
 

> `:=`(xlist, secant(f, x0, x1, tol, maxiter))
 

[2.0, 0., .22561484995794, .74269471761917, .49760551690234, .53494633480234, .53996743772003, .53983487323262, .53983527686958, .53983527690282, .53983527690282]
[2.0, 0., .22561484995794, .74269471761917, .49760551690234, .53494633480234, .53996743772003, .53983487323262, .53983527686958, .53983527690282, .53983527690282]
(31)
 

> `:=`(N, nops(xlist))
 

11 (32)
 

>
 

 

Test if the order of convergence is q = 1. 

 

> `:=`(q, 1)
 

1 (33)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

 

 

i = 1, ratio = .36970847765570
i = 2, ratio = .58206723493071
i = 3, ratio = .64559596805568
i = 4, ratio = .20817251517285
i = 5, ratio = .11577006595407
i = 6, ratio = 0.27032600201386e-1
i = 7, ratio = 0.30543863795771e-2
i = 8, ratio = 0.82344448512672e-4 (34)
 

>
 

 

The ratios are decreasing towards 0 and therefore the hypothesized order q = 1 is too small. 

 

 

Test if the order of convergence is q = 2. 

 

> `:=`(q, 2)
 

2 (35)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

 

 

i = 1, ratio = .25319641805310
i = 2, ratio = 1.0782311935415
i = 3, ratio = 2.0545957954825
i = 4, ratio = 1.0261909154326
i = 5, ratio = 2.7414331967019
i = 6, ratio = 5.5293353134069
i = 7, ratio = 23.111134177717
i = 8, ratio = 203.98941639158 (36)
 

>
 

 

This time, the ratios are increasing towards infinity and therefore the hypothesized order q = 2 is too large. 


We conclude that the secant method has an order of convergence q such that `and`(`<`(1, q), `<`(q, 2)) .
 

 

>
 

 

An analysis of the secant method proves that the order of convergence is the golden ratio: 

 

> `:=`(goldenRatio, `*`(`+`(1, sqrt(5)), `/`(1, 2))); -1
 

>
 

 

Test if the order of convergence is q = goldenRatio. 

 

> `:=`(q, evalf(goldenRatio))
 

1.6180339887499 (37)
 

> for i to `+`(N, `-`(3)) do 'i' = i, ratio = `/`(`*`(abs(`+`(xlist[`+`(i, 1)], `-`(trueroot)))), `*`(`^`(abs(`+`(xlist[i], `-`(trueroot))), q))) end do
 

 

 

 

 

 

 

 

i = 1, ratio = .29258595648953
i = 2, ratio = .85201019959830
i = 3, ratio = 1.3203437977430
i = 4, ratio = .55795643240611
i = 5, ratio = .81848493689569
i = 6, ratio = .72448860258879
i = 7, ratio = .76245520782015
i = 8, ratio = .73676189140157 (38)
 

>
 

 

These ratios appear to be approaching a nonzero finite constant. 

 

The secant method has order of convergence `and`(q = `*`(`+`(1, sqrt(5)), `/`(1, 2)), `≈`(`*`(`+`(1, sqrt(5)), `/`(1, 2)), 1.618)) . 

 

>
 

On the Efficiency of Root-Finding Methods 

For measuring computational efficiency, the important measure is the number of function evaluations required to compute the root to the desired accuracy tolerance. This can be seen by noting that in every method, apart from function evaluations there are only a small number of simple arithmetic operations to be performed in each iteration. 

 

Moreover, in practical applications the cost of evaluating the function may be relatively expensive. 

 

For the root-finding problem considered above, we have the following comparisons. 

 

Bisection method 

> `:=`(Niters, 39)
 

39 (39)
 

> `:=`(EvalsPerIteration, 1)
 

1 (40)
 

> `:=`(Cost, `*`(Niters, `*`(EvalsPerIteration)))
 

39 (41)
 

>
 

Fixed point iteration 

> `:=`(Niters, 28)
 

28 (42)
 

> `:=`(EvalsPerIteration, 1)
 

1 (43)
 

> `:=`(Cost, `*`(Niters, `*`(EvalsPerIteration)))
 

28 (44)
 

>
 

Newton's method 

> `:=`(Niters, 9)
 

9 (45)
 

> `:=`(EvalsPerIteration, 2)
 

2 (46)
 

> `:=`(Cost, `*`(Niters, `*`(EvalsPerIteration)))
 

18 (47)
 

>
 

Secant method 

> `:=`(Niters, 11)
 

11 (48)
 

> `:=`(EvalsPerIteration, 1)
 

1 (49)
 

> `:=`(Cost, `*`(Niters, `*`(EvalsPerIteration)))
 

11 (50)
 

>
 

Conclusion 

Although Newton's method converges a little faster than the secant method, we see that the Cost when measured by the number of function evaluations required to compute the root is significantly lower for the secant method. 

 

Among the methods discussed above, the secant method is the preferred choice. In fact, good software for root-finding generally combines the concept of the bisection method with the secant method. More specifically, a bracketing of the root is maintained throughout the computation (as in the bisection method) to avoid allowing the secant method to diverge away from the bracketing, while accepting secant iterations as long as they are converging to a root. 

 

>