diff --git a/src/linesearch.jl b/src/linesearch.jl index e16b8cb..d67287c 100644 --- a/src/linesearch.jl +++ b/src/linesearch.jl @@ -63,18 +63,36 @@ function strong_backtracking!( nbracket_max = 200 @logmsg LSLogLevel "==BRACKETING THE MINIMUM==" for nbracket in 1:nbracket_max - y, grad = fdf(x0, α, d) + local y, grad + while true + try + y, grad = fdf(x0, α, d) + break + catch err + if err isa DomainError + α_new = (α + α_prev) / 2 + if α_new == α_prev || α_new == α + @warn "==BRACKETING FAIL, LAST STEP VALUE RETURNED==" α + @logmsg LSLogLevel "==LINEAR SEARCH INTERRUPTED==" + return zero(α) + end + α = α_new + else + rethrow(err) + end + end + end g = dot(grad, d) Δyp = (g + g0) * α / 2 # parabolic approximation if abs(Δyp) < ϵ - @logmsg LSLogLevel "" """ + @logmsg LSLogLevel """ Δyp = $(Δyp) (*) Δy = $(y-y0) """ Δy = Δyp else Δy = y - y0 - @logmsg LSLogLevel "" """ + @logmsg LSLogLevel """ Δyp = $(Δyp) Δy = $(Δy) (*) """ diff --git a/src/optimize.jl b/src/optimize.jl index 65e39e9..67a4bef 100644 --- a/src/optimize.jl +++ b/src/optimize.jl @@ -191,6 +191,7 @@ function solver( maxcalls=nothing, constrain_step=nothing, ) + x0 = argumentvec(M) grad_tol = (isnothing(gtol) || gtol < 0) ? zero(eltype(x0)) : gtol convcond = isnothing(convcond) ? stopbygradient(grad_tol) : convcond iter_limit = (isnothing(maxiter) || maxiter < 0) ? typemax(Int) : convert(Int, maxiter) diff --git a/test/interface.jl b/test/interface.jl index 7ba3e81..7ec7c85 100644 --- a/test/interface.jl +++ b/test/interface.jl @@ -40,5 +40,12 @@ end ) @test optimize!(rosenbrock!, opt, init_vec) isa NamedTuple end + + @testset "$(typeof(descent).name) (default parameters)" for descent in descent_methods + opt = Downhill.solver( + descent, + ) + @test optimize!(rosenbrock!, opt, init_vec) isa NamedTuple + end end end diff --git a/test/linesearch.jl b/test/linesearch.jl index c954d68..9b5870b 100644 --- a/test/linesearch.jl +++ b/test/linesearch.jl @@ -70,3 +70,13 @@ end @test isapprox(α, α₀, rtol=0.05) end end + +@testset "Limited domain" begin + function fdf(x, α, d) + z = x[] + α * d[] + return z - sqrt(z), [1 - 0.5 / sqrt(z)] + end + + α = Downhill.strong_backtracking!(fdf, [0.5], [-1.0]) + @test isapprox(α, 0.25, rtol=0.05) +end