@@ -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