Skip to content

Commit

Permalink
more general fix for issue #255 (#257)
Browse files Browse the repository at this point in the history
  • Loading branch information
jverzani authored Nov 6, 2021
1 parent c137aae commit c618dad
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 47 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
7 changes: 4 additions & 3 deletions src/find_zero.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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...)
Expand All @@ -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
Expand Down
81 changes: 38 additions & 43 deletions src/order0.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down

2 comments on commit c618dad

@jverzani
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/48303

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.3.7 -m "<description of version>" c618dada2e10d7ff4feca93081765595a5aa6793
git push origin v1.3.7

Please sign in to comment.