Skip to content

Commit bf3d347

Browse files
committed
Update for 2 cases of -ve direction
1 parent 8c953b3 commit bf3d347

File tree

4 files changed

+76
-61
lines changed

4 files changed

+76
-61
lines changed

src/cr.jl

+18-5
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ M also indicates the weighted norm in which residuals are measured.
5151
* `M`: linear operator that models a Hermitian positive-definite matrix of size `n` used for centered preconditioning;
5252
* `ldiv`: define whether the preconditioner uses `ldiv!` or `mul!`;
5353
* `radius`: add the trust-region constraint ‖x‖ ≤ `radius` if `radius > 0`. Useful to compute a step in a trust-region method for optimization;
54-
* `linesearch`: if `true`, indicate that the solution is to be used in an inexact Newton method with linesearch. If `linesearch` is true and nonpositive curvature is detected, the solution depends on the iteration: at iteration k = 0, the right-hand side is returned with `solver.npc_dir` as the preconditioned initial residual; at iteration k > 0, the solution from iteration k-1 is returned with `solver.npc_dir` as the most recent residual;
54+
* `linesearch`: if `true` and nonpositive curvature is detected, behavior depends on the iteration.
55+
– At k = 0, return the right-hand side with `solver.npc_dir` set to the preconditioned initial residual.
56+
– At k > 0, return the solution from iteration k–1 with `solver.npc_dir` set to the detected nonpositive-curvature direction—either the previous search direction if the search-direction test fails, or the latest residual if the residual-curvature test fails. If both test fails, set `solver.npc_dir` to the current residual, update `solver.p` to the most recent search direction, and record the number of negative-curvature directions in `stats.num_neg_dir`;
5557
* `γ`: tolerance to determine that the curvature of the quadratic model is nonpositive;
5658
* `atol`: absolute stopping tolerance based on the residual norm;
5759
* `rtol`: relative stopping tolerance based on the residual norm;
@@ -216,7 +218,6 @@ kwargs_cr = (:M, :ldiv, :radius, :linesearch, :γ, :atol, :rtol, :itmax, :timema
216218
overtimed = false
217219

218220
while ! (solved || tired || user_requested_exit || overtimed)
219-
linesearch && kcopy!(n, npc_dir , r) # npc_dir ← r; contain the last residual
220221
if linesearch
221222
if (pAp γ * pNorm²) || γ * rNorm²)
222223
npcurv = true
@@ -226,6 +227,8 @@ kwargs_cr = (:M, :ldiv, :radius, :linesearch, :γ, :atol, :rtol, :itmax, :timema
226227
stats.inconsistent = false
227228
stats.timer = start_time |> ktimer
228229
stats.status = "nonpositive curvature"
230+
kcopy!(n, npc_dir , r) # npc_dir ← r; contain the last residual
231+
stats.num_neg_dir = 2
229232
iter == 0 && kcopy!(n, x, b) # x ← b
230233
solver.warm_start = false
231234
stats.indefinite = true
@@ -262,6 +265,7 @@ kwargs_cr = (:M, :ldiv, :radius, :linesearch, :γ, :atol, :rtol, :itmax, :timema
262265
else # case 2
263266
(verbose > 0) && @printf(iostream, "r is a direction of nonpositive curvature: %8.1e\n", ρ)
264267
α = tr
268+
#TODO what to do in this case?
265269
end
266270
else
267271
# q_p = q(x + α_p * p) - q(x) = -α_p * rᴴp + ½ (α_p)² * pᴴAp
@@ -292,6 +296,10 @@ kwargs_cr = (:M, :ldiv, :radius, :linesearch, :γ, :atol, :rtol, :itmax, :timema
292296
elseif pAp > 0 && ρ < 0
293297
npcurv = true
294298
(verbose > 0) && @printf(iostream, "pᴴAp = %8.1e > 0 and rᴴAr = %8.1e < 0\n", pAp, ρ)
299+
if linesearch
300+
kcopy!(n, npc_dir , r) # npc_dir ← r; contain the last residual
301+
stats.num_neg_dir = 1
302+
end
295303
# q_p is minimal for α_p = rᴴp / pᴴAp
296304
α = descent ? min(t1, pr / pAp) : max(t2, pr / pAp)
297305
Δ = -α * pr + tr * rNorm² +^2 * pAp - (tr)^2 * ρ) / 2
@@ -308,6 +316,10 @@ kwargs_cr = (:M, :ldiv, :radius, :linesearch, :γ, :atol, :rtol, :itmax, :timema
308316
elseif pAp < 0 && ρ > 0
309317
npcurv = true
310318
(verbose > 0) && @printf(iostream, "pᴴAp = %8.1e < 0 and rᴴAr = %8.1e > 0\n", pAp, ρ)
319+
if linesearch
320+
kcopy!(n, npc_dir , p) # npc_dir ← r; contain the last residual
321+
stats.num_neg_dir = 1
322+
end
311323
α = descent ? t1 : t2
312324
tr = min(tr, rNorm² / ρ)
313325
Δ = -α * pr + tr * rNorm² +^2 * pAp - (tr)^2 * ρ) / 2
@@ -323,6 +335,10 @@ kwargs_cr = (:M, :ldiv, :radius, :linesearch, :γ, :atol, :rtol, :itmax, :timema
323335

324336
elseif pAp < 0 && ρ < 0
325337
npcurv = true
338+
if linesearch
339+
kcopy!(n, npc_dir , r) # npc_dir ← r; contain the last residual
340+
stats.num_neg_dir = 2
341+
end
326342
(verbose > 0) && @printf(iostream, "negative curvatures along p and r. pᴴAp = %8.1e and rᴴAr = %8.1e\n", pAp, ρ)
327343
α = descent ? t1 : t2
328344
Δ = -α * pr + tr * rNorm² +^2 * pAp - (tr)^2 * ρ) / 2
@@ -415,9 +431,6 @@ kwargs_cr = (:M, :ldiv, :radius, :linesearch, :γ, :atol, :rtol, :itmax, :timema
415431
npcurv && (status = "nonpositive curvature")
416432
on_boundary && (status = "on trust-region boundary")
417433

418-
if npcurv && linesearch
419-
stats.indefinite = true
420-
end
421434
# Update x
422435
warm_start && kaxpy!(n, one(FC), Δx, x)
423436
solver.warm_start = false

0 commit comments

Comments
 (0)