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

Add apply_step! option for Newton method #284

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
Prev Previous commit
Add always_step option to Newton solver
From updated README.md:

If the optional parameter `always_step = false` (the default), no Newton iteration is performed
if the solution is already converged for the supplied initial `x` values,  and the supplied initial `x` is returned
in the `zero` field of `SolverResults`. If `always_step = true`, a Newton step is performed
before testing for convergence.
sjdaines committed Dec 13, 2024
commit b475fd008dc2a022a11eff4b9ae2d3e88d35af07
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -307,12 +307,17 @@ By default, no linesearch is performed.
**Note:** it is assumed that a passed linesearch function will at least update the solution
vector and evaluate the function at the new point.

If `method = :newton` and `linesearch=LineSearches.Static()` (the default), an additional parameter
If `linesearch=LineSearches.Static()` (the default), an additional parameter
`apply_step!` (default value `(x, x_old, newton_step)->(x .= x_old .+ newton_step)`) can be used to
define a problem-specific function to update the `x` value after the Newton iteration.
For example, `apply_step! = (x, x_old, newton_step)->(x .= x_old .+ newton_step; x .= max.(x, 1e-80))`
will enforce a constraint `x[i] >= 1e-80`.

If the optional parameter `always_step = false` (the default), no Newton iteration is performed
if the solution is already converged for the supplied initial `x` values, and the supplied initial `x` is returned
in the `zero` field of `SolverResults`. If `always_step = true`, a Newton step is performed
before testing for convergence.

## Anderson acceleration

This method is selected with `method = :anderson`.
3 changes: 2 additions & 1 deletion src/nlsolve/nlsolve.jl
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ function nlsolve(df::Union{NonDifferentiable, OnceDifferentiable},
linesearch = LineSearches.Static(),
linsolve=(x, A, b) -> copyto!(x, A\b),
apply_step! = (x, x_old, newton_step)->(x .= x_old .+ newton_step),
always_step = false,
factor::Real = one(real(eltype(initial_x))),
autoscale::Bool = true,
m::Integer = 10,
@@ -22,7 +23,7 @@ function nlsolve(df::Union{NonDifferentiable, OnceDifferentiable},
end
if method == :newton
newton(df, initial_x, xtol, ftol, iterations,
store_trace, show_trace, extended_trace, linesearch; linsolve=linsolve, apply_step! =apply_step!)
store_trace, show_trace, extended_trace, linesearch; linsolve=linsolve, apply_step! =apply_step!, always_step=always_step)
elseif method == :trust_region
trust_region(df, initial_x, xtol, ftol, iterations,
store_trace, show_trace, extended_trace, factor,
13 changes: 10 additions & 3 deletions src/solvers/newton.jl
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ function newton_(df::OnceDifferentiable,
linesearch,
linsolve,
apply_step!,
always_step,
cache = NewtonCache(df)) where T
n = length(initial_x)
copyto!(cache.x, initial_x)
@@ -53,7 +54,12 @@ function newton_(df::OnceDifferentiable,
x_converged, f_converged = assess_convergence(initial_x, cache.xold, value(df), NaN, ftol)
stopped = any(isnan, cache.x) || any(isnan, value(df)) ? true : false

converged = x_converged || f_converged
if always_step
converged = false
else
converged = x_converged || f_converged
end

x_ls = copy(cache.x)
tr = SolverTrace()
tracing = store_trace || show_trace || extended_trace
@@ -145,6 +151,7 @@ function newton(df::OnceDifferentiable,
linesearch,
cache = NewtonCache(df);
linsolve=(x, A, b) -> copyto!(x, A\b),
apply_step! = (x, x_old, newton_step)->(x .= x_old .+ newton_step)) where T
newton_(df, initial_x, convert(real(T), xtol), convert(real(T), ftol), iterations, store_trace, show_trace, extended_trace, linesearch, linsolve, apply_step!, cache)
apply_step! = (x, x_old, newton_step)->(x .= x_old .+ newton_step),
always_step::Bool) where T
newton_(df, initial_x, convert(real(T), xtol), convert(real(T), ftol), iterations, store_trace, show_trace, extended_trace, linesearch, linsolve, apply_step!, always_step, cache)
end