# Does Roots.jl provide an API to obtain the trace of a root finding algorithm?

I only find that it can print out such information by the kwargs `verbose=true`. But how can I obtain this just like the `Optim.jl` which store all information in the returned value? I want to count the number of evaluations of my function called by each root finding algorithm.

Just increment a counter in your function. (You can use a local variable for the counter via a closure.)

2 Likes

Thanks! But what if I don’t want to modify my funciton (or the function is an external call to the C/C++ funciton?). Do you know any other root finding packages that keeps track of its iteration trace? Besides the number of evaluations, I’d also like to know the `x` and `f(x)` during each iteration.

“You can use a local variable for the counter via a closure.” means to do the following. You can use any function including a function which is an external call to the C function.

``````using Roots

function withcounter(f, n = 0)
c = Ref(n)
F(x...; y...) = (c[] += 1; f(x...; y...))
getcounter() = c[]
setcounter!(n) = c[] = n
F, getcounter, setcounter!
end

f(x::Float64)::Float64 = @ccall sin(x::Float64)::Float64
@show f(1.0);
``````
``````f(1.0) = 0.8414709848078965
``````
``````F, getcounter, setcounter! = withcounter(x -> f(x) - 0.8414709848078965)
@show find_zero(F, 0.9)
@show getcounter();
``````
``````find_zero(F, 0.9) = 1.0
getcounter() = 11
``````
``````setcounter!(0)
@show find_zeros(F, 0, 2π)
@show getcounter();
``````
``````find_zeros(F, 0, 2π) = [1.0, 2.141592653589793]
getcounter() = 1270
``````
6 Likes

In addition to the suggested ways, the state object keeps track of this. It can be accessed different ways, here is one:

``````using Roots
Z = ZeroProblem(sin, (3,4))
prob = init(Z, Roots.Secant()); solve!(prob)
prob.state.fnevals # 7
``````
3 Likes

This solution leads me to explore the source code of `Roots.jl` package. And what I find is the kwargs `tracks` which is exactly what I want! Thanks all!

To track the number of evaluations and all `xs` and `fs`, we just provide a `Tracks` instance to the kwargs, such as

``````using Roots
tracks = Roots.Tracks(Float64[], Float64[])
find_zero(sin, (3,4), Roots.FalsePosition(), tracks=tracks, verbose=true)
``````

Then we can show the tracks

``````Roots.show_tracks(tracks, Roots.FalsePosition())
``````