diff --git a/Project.toml b/Project.toml index b0ffecbc..04f49563 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Roots" uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" -version = "1.3.6" +version = "1.3.7" [deps] CommonSolve = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" diff --git a/src/find_zero.jl b/src/find_zero.jl index 5023ce21..40948189 100644 --- a/src/find_zero.jl +++ b/src/find_zero.jl @@ -747,8 +747,9 @@ struct ZeroProblem{F,X} end ## The actual iterating object -struct ZeroProblemIterator{M,F,S,O,L} +struct ZeroProblemIterator{M,N,F,S,O,L} M::M + N::N F::F state::S options::O @@ -777,7 +778,7 @@ function init( options = init_options(M, state; kwargs...) l = Tracks(verbose, tracks, state) incfn(l, initial_fncalls(M)) - ZeroProblemIterator(M, F, state, options, l) + ZeroProblemIterator(M, nothing, F, state, options, l) end function init(š‘­š‘æ::ZeroProblem, pā€²=nothing; kwargs...) @@ -792,7 +793,7 @@ function init( options::UnivariateZeroOptions=init_options(M, state), l::AbstractTracks=NullTracks(), ) - ZeroProblemIterator(M, Callable_Function(M, F), state, options, l) + ZeroProblemIterator(M, Nothing, Callable_Function(M, F), state, options, l) end # Optional iteration interface to handle looping diff --git a/src/order0.jl b/src/order0.jl index b2782db2..b0a59c89 100644 --- a/src/order0.jl +++ b/src/order0.jl @@ -23,54 +23,42 @@ superlinear, and relatively robust to non-reasonable starting points. """ struct Order0 <: AbstractSecant end -function find_zero( - fs, - x0, - method::Order0; +# special case Order0 to be hybrid +function init( + š‘­š‘æ::ZeroProblem, + M::Order0, + pā€²=nothing; p=nothing, - tracks::AbstractTracks=NullTracks(), - verbose=false, + verbose::Bool=false, + tracks=NullTracks(), kwargs..., ) - M = Order1() - N = AlefeldPotraShi() - find_zero(fs, x0, M, N; p=p, tracks=tracks, verbose=verbose, kwargs...) + p = pā€² === nothing ? p : pā€² + init(š‘­š‘æ, Secant(), AlefeldPotraShi(); + p=p, verbose=verbose, tracks=tracks, + kwargs...) + end -# todo: consolidate this with find_zero(M,N,f, x0)... -function find_zero( - fs, - x0, +## When passing 2 methods, any parameters must be passed as a named argument through +## the keyword p +function init( + š‘­š‘æ::ZeroProblem, M::AbstractUnivariateZeroMethod, N::AbstractBracketing; p=nothing, - tracks::AbstractTracks=NullTracks(), - verbose=false, + verbose::Bool=false, + tracks=NullTracks(), kwargs..., ) - F = Callable_Function(M, fs, p) - state = init_state(M, F, x0) + F = Callable_Function(M, š‘­š‘æ.F, p) + state = init_state(M, F, š‘­š‘æ.xā‚€) options = init_options(M, state; kwargs...) l = Tracks(verbose, tracks, state) - - xstar = find_zero(M, N, F, state, options, l, verbose) - isnan(xstar) && throw(ConvergenceFailed("Stopped")) - - return xstar + incfn(l, initial_fncalls(M)) + ZeroProblemIterator(M, N, F, state, options, l) end -# give solve interface for Order0 -# XXX should creat iterator object for hybrid, rather than call out to -# this version of find_zero... -function solve!(š™::ZeroProblemIterator{<:Order0}; verbose=false) - F = š™.F - M = Order1() - N = AlefeldPotraShi() - state = š™.state - options = š™.options - find_zero(M,N,F, - š™.state, š™.options, š™.logger, verbose) -end # Robust version using some tricks: idea from algorithm described in @@ -80,15 +68,10 @@ end # * limit steps so as not too far or too near the previous one # * if not decreasing, use a quad step upto 4 times to bounce out of trap, if possible # First uses M, then N if bracket is identified -function find_zero( - M::AbstractUnivariateZeroMethod, - N::AbstractBracketing, - F, - state::AbstractUnivariateZeroState, - options::UnivariateZeroOptions, - l::AbstractTracks=NullTracks(), - verbose=false, -) +function solve!(š™::ZeroProblemIterator{šŒ,š}; verbose=false) where {šŒ,š<:AbstractBracketing} + + M,N,F,state,options,l = š™.M, š™.N, š™.F, š™.state, š™.options, š™.logger + incfn(l, 2) log_step(l, M, state, :init) log_method(l, M) @@ -210,7 +193,19 @@ function find_zero( isnan(Ī±) ? decide_convergence(M, F, state, options, flag) : Ī± end +function find_zero( + fs, x0, + M::AbstractUnivariateZeroMethod, + N::AbstractBracketing; + verbose=false, + kwargs...) + š = ZeroProblem(fs, x0) + solve!(init(š, M, N; verbose=verbose, kwargs...), verbose=verbose) +end + + # Switch to bracketing method +# deprecate soon, not used function run_bisection(N::AbstractBracketing, f, ab, state) steps, fnevals = state.steps, state.fnevals f = Callable_Function(N, f)