Hi, as the title says I’m trying to build a simple and fast bisection algorithm. I know the Roots.jl package already implements it, yet I’m doing it both for pedagogical purposes and because I then plan to expand it with different algorithms (I like having full control over what my code can or cannot do).
The way I thought of doing it is very simple: I have a Point
object that stores both coordinates of a point and at each iteration I update one of the two endpoints based on the sign at the midpoint, where the function interval!()
does most of the work.
I tried to strip down the code to its bare minimum:
mutable struct Point
x::Real
y::Real
end
function interval!(f::Function, pl::Point, ph::Point)
xm = (pl.x + ph.x)/2
ym = f(xm)
if ym < 0
(pl.x, pl.y) = (xm, ym)
else
(ph.x, ph.y) = (xm, ym)
end
return (xm, ym)
end
function root_1d(f::Function, x1::Real, x2::Real;
x_tol::Float64 = 1e-6, f_tol::Float64 = 1e-6, max_iter::Int = 3000)
pl = Point(x1,f(x1))
ph = Point(x2,f(x2))
pl.y*ph.y >= 0 && error("the interval provided does not bracket a root")
# Ensures left endpoint evaluates to negative
pl.y > 0 && ((pl, ph) = (ph, pl))
xm = 0
ym = 0
iter = 0
stop = false
while ~stop
iter += 1
(xm, ym) = interval!(f,pl,ph)
# Convergence check
if ph.x - pl.x <= x_tol*(1 + abs(pl.x) + abs(ph.x)) || abs(ym) <= f_tol || iter >= max_iter
stop = true
iter >= max_iter && warn("root_1d did not converge within max_iter")
end
end
return xm, ym
end
Now, one thing I noticed is that the interval!()
function is not type stable. Running
f(x) = x^3
pl = Point(-1, 1)
ph = Point(2, 8)
@code_warntype interval!(f, pl, ph)
tells me the result is of type Tuple{Any,Any}
. From what I understand this comes from the fact that it cannot infer the sum of two reals (???) but this seems a bit weird.
I’m not sure how I should fix this. I tried making Point
a parametric type but then I cannot change it in place because the type of its argument might change from one iteration to the next. At the same time I thought having the Point
object might be nice to reduce memory allocation.
Any help is much appreciated.