# demo of various rootfinding methods using Printf using ForwardDiff function bisection(f,a,b,tol; maxit=1000) if f(a)*f(b) > 0 print("There may not be a root in this interval") return NaN,NaN,NaN end c = 0.5*(a+b) k = 1 chist = [] while abs(f(c))>tol && k < maxit @printf("Bisection c, |f(x)| at iterate %2d: %18.14f %10.7e\n", k, c, abs(f(c))) if f(c)*f(a)<0 b = c else a = c end c = 0.5*(a+b) push!(chist,c) k += 1 end return c,k,chist end function regula_falsi(f,a,b,tol; maxit=1000) # evaluate f at the bracket endpoints fa = f(a) fb = f(b) c = .5*(a+b) k = 0 fc = Inf # start with f(c) = inf to enter loop xhist = [] while abs(fc)>tol && k < maxit c = (a*fb - b*fa)/(fb-fa) # generate new root estimate fc = f(c) # evaluate function at new root estimate @printf("Regula falsi error/f(x) at iterate %2d: %18.14f %10.7e\n", k, c, abs(f(c))) if fa*fc < 0 b=c fb=fc # update new bracket else a=c fa=fc end k += 1 push!(xhist,c) end return c, k, xhist end function newton(f,df,x0,tol; maxit=1000) k = 1 @printf("Newton error/f(x) at iterate %3d: %20.14f %10.7e\n", k, x0, f(x0)) xhist = [] while abs(f(x0))>tol && ktol && k < maxit @printf("Secant error at iterate %3d: %20.14f %10.7e\n", k, x0, abs(f(x0))) x = x1 - f1*(x1-x0)/(f1-f0) # generate new root estimate x0 = x1 x1 = x f0 = f1 f1 = f(x1) k += 1 push!(xhist,x) end x = x1 return x, k, xhist end # things to try: function with zero derivative at the root # - bisection can't find change in sign # - Newton slows # # f(x) = x^2 # df(x) = 2*x # example showing Newton is sensitive to the starting guess: f'(x^*) = 0, f''(x^*) != 0 # - if 1/3 < x0 != 1/2, converge but slow # - if x0 < 1/3, failure # - if x0 = 1/2, converges in two iterates! # # bisection also fails due to multiple roots # # f(x) = x.*(1-x).^2 # df(x) = -2*x.*(1 - x) + (1-x).^2