From 827a53535dfc3b2d189994989d808f322c4a49f7 Mon Sep 17 00:00:00 2001 From: Patrick Kofod Mogensen Date: Fri, 12 Jun 2020 14:04:17 +0200 Subject: [PATCH 1/2] Better convergence assessment. --- src/nlsolve/utils.jl | 7 ++----- src/solvers/anderson.jl | 3 ++- src/solvers/broyden.jl | 11 +++++------ src/solvers/newton.jl | 7 ++++--- src/solvers/trust_region.jl | 6 ++++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/nlsolve/utils.jl b/src/nlsolve/utils.jl index 5beb1d3..b46de92 100644 --- a/src/nlsolve/utils.jl +++ b/src/nlsolve/utils.jl @@ -8,17 +8,14 @@ function assess_convergence(x, xtol, ftol) x_converged, f_converged = false, false - if !any(isnan, x_previous) && norm(x-x_previous) <= xtol + if any(isnan, x) || norm(x-x_previous) <= xtol x_converged = true end - if maximum(abs, f) <= ftol f_converged = true end - converged = x_converged || f_converged - - return x_converged, f_converged, converged + return x_converged, f_converged end function check_isfinite(x::AbstractArray) diff --git a/src/solvers/anderson.jl b/src/solvers/anderson.jl index 87a798e..e5db13f 100644 --- a/src/solvers/anderson.jl +++ b/src/solvers/anderson.jl @@ -96,7 +96,8 @@ end end # check convergence - x_converged, f_converged, converged = assess_convergence(cache.g, cache.x, fx, xtol, ftol) + x_converged, f_converged = assess_convergence(cache.g, cache.x, fx, xtol, ftol) + converged = x_converged || f_converged converged && break # update current iterate diff --git a/src/solvers/broyden.jl b/src/solvers/broyden.jl index 08fc21e..acb3795 100644 --- a/src/solvers/broyden.jl +++ b/src/solvers/broyden.jl @@ -46,13 +46,11 @@ function broyden_(df::Union{NonDifferentiable, OnceDifferentiable}, Jinv = Matrix{T}(I, n, n) check_isfinite(value(df)) it = 0 - x_converged, f_converged, converged = assess_convergence(value(df), ftol) - - # FIXME: How should this flag be set? - mayterminate = false + x_converged, f_converged = assess_convergence(x, xold, value(df), NaN, ftol) + converged = x_converged || f_converged # Maintain a cache for line search results - # lsr = LineSearches.LineSearchResults(T) + # lsr = LineSearches.LineSearchResults(T) tr = SolverTrace() tracing = store_trace || show_trace || extended_trace @@ -99,7 +97,8 @@ function broyden_(df::Union{NonDifferentiable, OnceDifferentiable}, end if !maybe_stuck - x_converged, f_converged, converged = assess_convergence(x, xold, value(df), xtol, ftol) + x_converged, f_converged = assess_convergence(x, xold, value(df), xtol, ftol) + converged = x_converged || f_converged end maybe_stuck = false diff --git a/src/solvers/newton.jl b/src/solvers/newton.jl index 7edd2a1..8f27573 100644 --- a/src/solvers/newton.jl +++ b/src/solvers/newton.jl @@ -49,7 +49,8 @@ function newton_(df::OnceDifferentiable, check_isfinite(value(df)) vecvalue = vec(value(df)) it = 0 - x_converged, f_converged, converged = assess_convergence(value(df), ftol) + x_converged, f_converged = assess_convergence(initial_x, cache.xold, value(df), NaN, ftol) + converged = x_converged || f_converged x_ls = copy(cache.x) tr = SolverTrace() tracing = store_trace || show_trace || extended_trace @@ -117,8 +118,8 @@ function newton_(df::OnceDifferentiable, end # fvec is here also updated in the linesearch so no need to call f again. copyto!(cache.x, x_ls) - x_converged, f_converged, converged = assess_convergence(cache.x, cache.xold, value(df), xtol, ftol) - + x_converged, f_converged = assess_convergence(cache.x, cache.xold, value(df), xtol, ftol) + converged = x_converged || f_converged newtontrace(sqeuclidean(cache.x, cache.xold), tracing, extended_trace, cache, df, it, tr, store_trace, show_trace) end return SolverResults("Newton with line-search", diff --git a/src/solvers/trust_region.jl b/src/solvers/trust_region.jl index de8520e..0b6c43b 100644 --- a/src/solvers/trust_region.jl +++ b/src/solvers/trust_region.jl @@ -121,7 +121,8 @@ function trust_region_(df::OnceDifferentiable, check_isfinite(cache.r) it = 0 - x_converged, f_converged, converged = assess_convergence(value(df), ftol) + x_converged, f_converged = assess_convergence(initial_x, cache.xold, value(df), NaN, ftol) + converged = x_converged || f_converged delta = convert(real(T), NaN) rho = convert(real(T), NaN) if converged @@ -187,7 +188,8 @@ function trust_region_(df::OnceDifferentiable, end end - x_converged, f_converged, converged = assess_convergence(cache.x, cache.xold, cache.r, xtol, ftol) + x_converged, f_converged = assess_convergence(cache.x, cache.xold, cache.r, xtol, ftol) + converged = x_converged || f_converged else cache.x .-= cache.p x_converged, converged = false, false From 220172b838f82d5d0a7d3b365d518c91617b37b7 Mon Sep 17 00:00:00 2001 From: Patrick Kofod Mogensen Date: Fri, 12 Jun 2020 14:28:31 +0200 Subject: [PATCH 2/2] Move nan-check out of assess. --- src/nlsolve/utils.jl | 2 +- src/solvers/anderson.jl | 3 +++ src/solvers/broyden.jl | 5 ++++- src/solvers/newton.jl | 6 +++++- src/solvers/trust_region.jl | 6 +++++- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/nlsolve/utils.jl b/src/nlsolve/utils.jl index b46de92..d0c7869 100644 --- a/src/nlsolve/utils.jl +++ b/src/nlsolve/utils.jl @@ -8,7 +8,7 @@ function assess_convergence(x, xtol, ftol) x_converged, f_converged = false, false - if any(isnan, x) || norm(x-x_previous) <= xtol + if norm(x-x_previous) <= xtol x_converged = true end if maximum(abs, f) <= ftol diff --git a/src/solvers/anderson.jl b/src/solvers/anderson.jl index e5db13f..f8fe098 100644 --- a/src/solvers/anderson.jl +++ b/src/solvers/anderson.jl @@ -97,6 +97,9 @@ end # check convergence x_converged, f_converged = assess_convergence(cache.g, cache.x, fx, xtol, ftol) + if any(isnan, cache.x) || any(isnan, value(df)) + break + end converged = x_converged || f_converged converged && break diff --git a/src/solvers/broyden.jl b/src/solvers/broyden.jl index acb3795..a697715 100644 --- a/src/solvers/broyden.jl +++ b/src/solvers/broyden.jl @@ -47,6 +47,8 @@ function broyden_(df::Union{NonDifferentiable, OnceDifferentiable}, check_isfinite(value(df)) it = 0 x_converged, f_converged = assess_convergence(x, xold, value(df), NaN, ftol) + stopped = any(isnan, x) || any(isnan, value(df)) ? true : false + converged = x_converged || f_converged # Maintain a cache for line search results @@ -59,7 +61,7 @@ function broyden_(df::Union{NonDifferentiable, OnceDifferentiable}, maybe_stuck = false max_resets = 3 resets = 0 - while !converged && it < iterations + while !stopped && !converged && it < iterations it += 1 @@ -100,6 +102,7 @@ function broyden_(df::Union{NonDifferentiable, OnceDifferentiable}, x_converged, f_converged = assess_convergence(x, xold, value(df), xtol, ftol) converged = x_converged || f_converged end + stopped = any(isnan, x) || any(isnan, value(df)) ? true : false maybe_stuck = false @broydentrace sqeuclidean(x, xold) diff --git a/src/solvers/newton.jl b/src/solvers/newton.jl index 8f27573..4c2ae86 100644 --- a/src/solvers/newton.jl +++ b/src/solvers/newton.jl @@ -50,6 +50,8 @@ function newton_(df::OnceDifferentiable, vecvalue = vec(value(df)) it = 0 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 x_ls = copy(cache.x) tr = SolverTrace() @@ -80,7 +82,7 @@ function newton_(df::OnceDifferentiable, end dfo = OnceDifferentiable(fo, go!, fgo!, cache.x, zero(real(T))) - while !converged && it < iterations + while !stopped && !converged && it < iterations it += 1 @@ -119,6 +121,8 @@ function newton_(df::OnceDifferentiable, # fvec is here also updated in the linesearch so no need to call f again. copyto!(cache.x, x_ls) x_converged, f_converged = assess_convergence(cache.x, cache.xold, value(df), xtol, ftol) + stopped = any(isnan, cache.x) || any(isnan, value(df)) ? true : false + converged = x_converged || f_converged newtontrace(sqeuclidean(cache.x, cache.xold), tracing, extended_trace, cache, df, it, tr, store_trace, show_trace) end diff --git a/src/solvers/trust_region.jl b/src/solvers/trust_region.jl index 0b6c43b..d09e8e0 100644 --- a/src/solvers/trust_region.jl +++ b/src/solvers/trust_region.jl @@ -122,6 +122,8 @@ function trust_region_(df::OnceDifferentiable, it = 0 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 delta = convert(real(T), NaN) rho = convert(real(T), NaN) @@ -161,7 +163,7 @@ function trust_region_(df::OnceDifferentiable, eta = convert(real(T), 1e-4) - while !converged && it < iterations + while !stopped && !converged && it < iterations it += 1 # Compute proposed iteration step @@ -193,6 +195,7 @@ function trust_region_(df::OnceDifferentiable, else cache.x .-= cache.p x_converged, converged = false, false + end @trustregiontrace euclidean(cache.x, cache.xold) @@ -205,6 +208,7 @@ function trust_region_(df::OnceDifferentiable, elseif rho >= 0.5 delta = max(delta, 2 * wnorm(cache.d, cache.p)) end + stopped = any(isnan, cache.x) || any(isnan, value(df)) ? true : false end name = "Trust-region with dogleg"