Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix line search in BFGS #711

Merged
merged 2 commits into from
Nov 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions src/plugins/local_improvement_search.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
# Initial step-length
αₖ = 1.0
# Evaluation counter
evals = Ref(0)
evals = Ref(bfgs.evaluation_limit)
while true
# Search direction. We could be clever here and maintain B⁻¹, but we're
# only ever going to be solving this for very small |x| << 100 problems,
Expand All @@ -98,7 +98,7 @@
elseif _norm(∇fₖ₊₁) < 1e-6
# Zero(ish) gradient. Return what must be a local maxima.
return fₖ₊₁, xₖ + αₖ * pₖ
elseif evals[] > bfgs.evaluation_limit
elseif evals[] <= 0
# We have evaluated the function too many times. Return our current
# best.
return fₖ₊₁, xₖ + αₖ * pₖ
Expand Down Expand Up @@ -127,18 +127,21 @@
α::Float64,
evals::Ref{Int},
) where {F<:Function}
while _norm(α * p) / max(1.0, _norm(x)) > 1e-3
while _norm(α * p) > 1e-3 * max(1.0, _norm(x))
xₖ = x + α * p
ret = f(xₖ)
evals[] += 1
if ret === nothing
α /= 2 # Infeasible. So take a smaller step
evals[] -= 1
if ret === nothing # Infeasible. So take a smaller step
α /= 2
continue
end
fₖ₊₁, ∇fₖ₊₁ = ret
if p' * ∇fₖ₊₁ < 1e-6
# Still a descent direction, so take a step.
return α, fₖ₊₁, ∇fₖ₊₁
elseif isapprox(fₖ + α * p' * ∇fₖ, fₖ₊₁; atol = 1e-8)
# Step is onto a kink
return α, fₖ₊₁, ∇fₖ₊₁

Check warning on line 144 in src/plugins/local_improvement_search.jl

View check run for this annotation

Codecov / codecov/patch

src/plugins/local_improvement_search.jl#L144

Added line #L144 was not covered by tests
end
# Step is an ascent, so use Newton's method to find the intersection
α = (fₖ₊₁ - fₖ - p' * ∇fₖ₊₁ * α) / (p' * ∇fₖ - p' * ∇fₖ₊₁)
Expand Down
Loading