Skip to content

Commit c9c78ef

Browse files
update LM solver with possibility of using R2DH as subsolver and with different subsolver criterion stop
1 parent 9109051 commit c9c78ef

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

src/LM_alg.jl

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function LM(
4747
subsolver = R2,
4848
subsolver_options = ROSolverOptions(ϵa = options.ϵa),
4949
selected::AbstractVector{<:Integer} = 1:(nls.meta.nvar),
50+
nonlinear::Bool = true,
5051
) where {H}
5152
start_time = time()
5253
elapsed_time = 0.0
@@ -62,6 +63,7 @@ function LM(
6263
γ = options.γ
6364
θ = options.θ
6465
σmin = options.σmin
66+
σk = options.σk
6567

6668
# store initial values of the subsolver_options fields that will be modified
6769
ν_subsolver = subsolver_options.ν
@@ -85,7 +87,6 @@ function LM(
8587
end
8688

8789
# initialize parameters
88-
σk = max(1 / options.ν, σmin)
8990
xk = copy(x0)
9091
hk = h(xk[selected])
9192
if hk == Inf
@@ -104,13 +105,15 @@ function LM(
104105
k = 0
105106
Fobj_hist = zeros(maxIter)
106107
Hobj_hist = zeros(maxIter)
108+
R = eltype(xk)
109+
sqrt_ξ1_νInv = one(R)
107110
Complex_hist = zeros(Int, maxIter)
108111
Grad_hist = zeros(Int, maxIter)
109112
Resid_hist = zeros(Int, maxIter)
110113

111114
if verbose > 0
112115
#! format: off
113-
@info @sprintf "%6s %8s %8s %8s %7s %7s %8s %7s %7s %7s %7s %1s" "outer" "inner" "f(x)" "h(x)" "ξ1" "√ξ" "ρ" "σ" "‖x‖" "‖s‖" "‖Jₖ‖²" "reg"
116+
@info @sprintf "%6s %8s %8s %8s %7s %7s %8s %7s %7s %7s %7s %1s" "outer" "inner" "f(x)" "h(x)" "(ξ1/ν)" "√ξ" "ρ" "σ" "‖x‖" "‖s‖" "‖Jₖ‖²" "reg"
114117
#! format: on
115118
end
116119

@@ -176,22 +179,24 @@ function LM(
176179
prox!(s, ψ, ∇fk, ν)
177180
ξ1 = fk + hk - mk1(s) + max(1, abs(fk + hk)) * 10 * eps() # TODO: isn't mk(s) returned by subsolver?
178181
ξ1 > 0 || error("LM: first prox-gradient step should produce a decrease but ξ1 = $(ξ1)")
182+
sqrt_ξ1_νInv = ξ1 > 0 ? sqrt(ξ1 * νInv) : 10.
179183

180184
if ξ1 0 && k == 1
181-
ϵ_increment = ϵr * sqrt(ξ1)
185+
ϵ_increment = ϵr * sqrt_ξ1_νInv
182186
ϵ += ϵ_increment # make stopping test absolute and relative
183187
ϵ_subsolver += ϵ_increment
184188
end
185189

186-
if sqrt(ξ1) < ϵ
190+
if sqrt_ξ1_νInv < ϵ
187191
# the current xk is approximately first-order stationary
188192
optimal = true
189193
continue
190194
end
191195

192-
subsolver_options.ϵa = k == 1 ? 1.0e-1 : max(ϵ_subsolver, min(1.0e-2, ξ1 / 10))
196+
# subsolver_options.ϵa = k == 1 ? 1.0e-1 : max(ϵ_subsolver, min(1.0e-2, ξ1 / 10))
197+
subsolver_options.ϵa = k == 1 ? 1.0e-3 : min(sqrt_ξ1_νInv ^ (1.5) , sqrt_ξ1_νInv * 1e-3) # 1.0e-5 default
193198
subsolver_options.ν = ν
194-
subsolver_args = subsolver == TRDH ? (SpectralGradient(1 / ν, nls.meta.nvar),) : ()
199+
subsolver_args = subsolver == R2DH ? (SpectralGradient(νInv, nls.meta.nvar),) : ()
195200
@debug "setting inner stopping tolerance to" subsolver_options.optTol
196201
s, iter, _ = with_logger(subsolver_logger) do
197202
subsolver(φ, ∇φ!, ψ, subsolver_args..., subsolver_options, s)
@@ -221,7 +226,7 @@ function LM(
221226

222227
if (verbose > 0) && (k % ptf == 0)
223228
#! format: off
224-
@info @sprintf "%6d %8d %8.1e %8.1e %7.1e %7.1e %8.1e %7.1e %7.1e %7.1e %7.1e %1s" k iter fk hk sqrt(ξ1) sqrt(ξ) ρk σk norm(xk) norm(s) νInv σ_stat
229+
@info @sprintf "%6d %8d %8.1e %8.1e %7.1e %7.1e %8.1e %7.1e %7.1e %7.1e %7.1e %1s" k iter fk hk sqrt_ξ1_νInv sqrt(ξ) ρk σk norm(xk) norm(s) νInv σ_stat
225230
#! format: off
226231
end
227232

@@ -243,7 +248,10 @@ function LM(
243248
Jk = jac_op_residual(nls, xk)
244249
jtprod_residual!(nls, xk, Fk, ∇fk)
245250

246-
σmax = opnorm(Jk)
251+
# update opnorm if not linear least squares
252+
if nonlinear == true
253+
σmax = opnorm(Jk)
254+
end
247255

248256
Complex_hist[k] += 1
249257
end
@@ -252,6 +260,7 @@ function LM(
252260
σk = σk * γ
253261
end
254262
νInv = (1 + θ) * (σmax^2 + σk) # ‖J'J + σₖ I‖ = ‖J‖² + σₖ
263+
255264
tired = k maxIter || elapsed_time > maxTime
256265
end
257266

@@ -260,9 +269,9 @@ function LM(
260269
@info @sprintf "%6d %8s %8.1e %8.1e" k "" fk hk
261270
elseif optimal
262271
#! format: off
263-
@info @sprintf "%6d %8d %8.1e %8.1e %7.1e %7.1e %8s %7.1e %7.1e %7.1e %7.1e" k 1 fk hk sqrt(ξ1) sqrt(ξ1) "" σk norm(xk) norm(s) νInv
272+
@info @sprintf "%6d %8d %8.1e %8.1e %7.1e %7.1e %8s %7.1e %7.1e %7.1e %7.1e" k 1 fk hk sqrt_ξ1_νInv sqrt(ξ1) "" σk norm(xk) norm(s) νInv
264273
#! format: on
265-
@info "LM: terminating with √ξ1 = $(sqrt(ξ1))"
274+
@info "LM: terminating with √(ξ1/ν) = $(sqrt_ξ1_νInv)"
266275
end
267276
end
268277
status = if optimal
@@ -279,7 +288,7 @@ function LM(
279288
set_status!(stats, status)
280289
set_solution!(stats, xk)
281290
set_objective!(stats, fk + hk)
282-
set_residuals!(stats, zero(eltype(xk)), ξ1 0 ? sqrt(ξ1) : ξ1)
291+
set_residuals!(stats, zero(eltype(xk)), ξ1 0 ? sqrt_ξ1_νInv : ξ1)
283292
set_iter!(stats, k)
284293
set_time!(stats, elapsed_time)
285294
set_solver_specific!(stats, :Fhist, Fobj_hist[1:k])

0 commit comments

Comments
 (0)