Skip to content

Commit 6971501

Browse files
committed
Fix more bugs in USYMLQR
1 parent 8637a9d commit 6971501

File tree

5 files changed

+55
-40
lines changed

5 files changed

+55
-40
lines changed

docs/src/preconditioners.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ Methods concerned: [`CGNE`](@ref cgne), [`CRMR`](@ref crmr), [`LNLQ`](@ref lnlq)
119119
|:---------------:|:---------------------:|:--------------------:|:---------------------:|:--------------------:|
120120
| Arguments | `M` with `ldiv=false` | `M` with `ldiv=true` | `N` with `ldiv=false` | `N` with `ldiv=true` |
121121

122+
In the special case of [USYMLQR](@ref usymlqr), $\tau = 1$ and $\nu = 0$.
123+
122124
!!! warning
123125
The preconditioners `M` and `N` must be hermitian and positive definite.
124126

src/usymlq.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ kwargs_usymlq = (:transfer_to_usymcg, :atol, :rtol, :itmax, :timemax, :verbose,
287287
# Compute d̅ₖ.
288288
if iter == 1
289289
# d̅₁ = u₁
290-
kcopy!(n, d̅, uₖ) # d̅ ← vₖ
290+
kcopy!(n, d̅, uₖ) # d̅ ← uₖ
291291
else
292292
# d̅ₖ = s̄ₖ * d̅ₖ₋₁ - cₖ * uₖ
293293
kaxpby!(n, -cₖ, uₖ, conj(sₖ), d̅)

src/usymlqr.jl

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -225,17 +225,17 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
225225
end
226226

227227
(verbose > 0) && @printf(iostream, "%4s %7s %7s %7s\n", "k", "αₖ", "βₖ", "γₖ")
228-
kdisplay(iter, verbose) && @printf(iostream, "%4d %7.1e %7.1e %7.1e\n", iter, αₖ, βₖ, γₖ)
229-
230-
cₖ₋₂ = cₖ₋₁ = cₖ = one(T) # Givens cosines used for the QR factorization of Tₖ₊₁.ₖ
231-
sₖ₋₂ = sₖ₋₁ = sₖ = zero(FC) # Givens sines used for the QR factorization of Tₖ₊₁.ₖ
232-
kfill!(wₖ₋₂, zero(FC)) # Column k-2 of Wₖ = Vₖ(Rₖ)⁻¹
233-
kfill!(wₖ₋₁, zero(FC)) # Column k-1 of Wₖ = Vₖ(Rₖ)⁻¹
234-
ϕbarₖ = βₖ # ϕbarₖ is the last component of f̄ₖ = (Qₖ)ᴴβ₁e₁
235-
kfill!(d̅, zero(FC)) # Last column of D̅ₖ = UₖQₖ
236-
ηₖ₋₁ = ηbarₖ = zero(FC) # ηₖ₋₁ and ηbarₖ are the last components of h̄ₖ = (Rₖ)⁻ᵀγ₁e₁
237-
ηₖ₋₂ = θₖ = zero(FC) # ζₖ₋₂ and θₖ are used to update ηₖ₋₁ and ηbarₖ
238-
δbarₖ₋₁ = δbarₖ = zero(FC) # Coefficients of Rₖ₋₁ and Rₖ modified over the course of two iterations
228+
kdisplay(iter, verbose) && @printf(iostream, "%4d %7s %7.1e %7.1e\n", iter, "✗ ✗ ✗ ✗", βₖ, γₖ)
229+
230+
cₖ₋₂ = cₖ₋₁ = cₖ = one(T) # Givens cosines used for the QR factorization of Tₖ₊₁.ₖ
231+
sₖ₋₂ = sₖ₋₁ = sₖ = zero(FC) # Givens sines used for the QR factorization of Tₖ₊₁.ₖ
232+
kfill!(wₖ₋₂, zero(FC)) # Column k-2 of Wₖ = Vₖ(Rₖ)⁻¹
233+
kfill!(wₖ₋₁, zero(FC)) # Column k-1 of Wₖ = Vₖ(Rₖ)⁻¹
234+
ϕbarₖ = βₖ # ϕbarₖ is the last component of f̄ₖ = (Qₖ)ᴴβ₁e₁
235+
kfill!(d̅, zero(FC)) # Last column of D̅ₖ = UₖQₖ
236+
ηₖ₋₁ = ηbarₖ = zero(FC) # ηₖ₋₁ and ηbarₖ are the last components of h̄ₖ = (Rₖ)⁻ᵀγ₁e₁
237+
ηₖ₋₂ = ωₖ = zero(FC) # ηₖ₋₂ and ωₖ are used to update ηₖ₋₁ and ηbarₖ
238+
δₖ₋₁ = δbarₖ₋₁ = δbarₖ = zero(FC) # Coefficients of Rₖ₋₁ and Rₖ modified over the course of two iterations
239239

240240
# Stopping criterion.
241241
rNorm_LS = bNorm = βₖ
@@ -252,6 +252,7 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
252252
ill_cond = false
253253
user_requested_exit = false
254254
overtimed = false
255+
solved_cg = solved_lq = false
255256

256257
while !(solved || tired || ill_cond || inconsistent || user_requested_exit || overtimed)
257258
# Update iteration index.
@@ -278,8 +279,8 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
278279
MisI || mulorldiv!(M⁻¹uₖ, M, q, ldiv) # βₖ₊₁uₖ₊₁ = MAvₖ - γₖuₖ₋₁ - αₖuₖ
279280
NisI || mulorldiv!(N⁻¹vₖ, N, p, ldiv) # γₖ₊₁vₖ₊₁ = NAᴴuₖ - βₖvₖ₋₁ - ᾱₖvₖ
280281

281-
βₖ₊₁ = knorm_elliptic(m, M⁻¹uₖ, q) # βₖ₊₁ = ‖uₖ₊₁‖_E
282-
γₖ₊₁ = knorm_elliptic(n, N⁻¹vₖ, p) # γₖ₊₁ = ‖vₖ₊₁‖_F
282+
βₖ₊₁ = MisI ? knorm(m, q) : knorm_elliptic(m, M⁻¹uₖ, q) # βₖ₊₁ = ‖uₖ₊₁‖_E
283+
γₖ₊₁ = NisI ? knorm(n, p) : knorm_elliptic(n, N⁻¹vₖ, p) # γₖ₊₁ = ‖vₖ₊₁‖_F
283284

284285
# Update M⁻¹uₖ₋₁ and N⁻¹vₖ₋₁
285286
kcopy!(m, M⁻¹uₖ₋₁, M⁻¹uₖ)
@@ -377,9 +378,9 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
377378
# [δ₁ 0 ] [ η₁ ] = [γ₁]
378379
# [λ₁ δbar₂] [ηbar₂] [0 ]
379380
if iter == 2
380-
ωₖ₋₁ = ηₖ
381-
ηₖ₋₁ = ηₖ₋₁ / δₖ₋₁
382-
ωₖ = -λₖ₋₁ * ζₖ₋₁
381+
ωₖ₋₁ = ωₖ
382+
ηₖ₋₁ = ωₖ₋₁ / δₖ₋₁
383+
ωₖ = -λₖ₋₁ * ηₖ₋₁
383384
end
384385
# [λₖ₋₂ δₖ₋₁ 0 ] [ηₖ₋₂ ] = [0]
385386
# [ϵₖ₋₂ λₖ₋₁ δbarₖ] [ηₖ₋₁ ] [0]
@@ -398,14 +399,14 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
398399
if iter 2
399400
# Compute solution yₖ.
400401
# (yᴸ)ₖ₋₁ ← (yᴸ)ₖ₋₂ + ηₖ₋₁ * dₖ₋₁
401-
kaxpy!(n, ηₖ₋₁ * cₖ, d̅, x)
402-
kaxpy!(n, ηₖ₋₁ * sₖ, uₖ, x)
402+
kaxpy!(n, ηₖ₋₁ * cₖ, d̅, yₖ)
403+
kaxpy!(n, ηₖ₋₁ * sₖ, uₖ, yₖ)
403404
end
404405

405406
# Compute d̅ₖ.
406407
if iter == 1
407408
# d̅₁ = u₁
408-
kcopy!(n, d̅, uₖ) # d̅ ← vₖ
409+
kcopy!(n, d̅, uₖ) # d̅ ← uₖ
409410
else
410411
# d̅ₖ = s̄ₖ * d̅ₖ₋₁ - cₖ * uₖ
411412
kaxpby!(n, -cₖ, uₖ, conj(sₖ), d̅)
@@ -431,12 +432,15 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
431432
end
432433

433434
# Compute zₖ.
434-
kaxpy!(n, -ηₖ, wₖ, zₖ)
435+
if iter 2
436+
kaxpy!(n, -ηₖ₋₁, wₖ₋₁, zₖ)
437+
end
435438

436-
# Compute uₖ₊₁ and vₖ₊₁.
437-
kcopy!(m, uₖ₋₁, uₖ) # uₖ₋₁uₖ
438-
kcopy!(n, vₖ₋₁, vₖ) # vₖ₋₁vₖ
439+
# Update N⁻¹vₖ and M⁻¹uₖ
440+
kcopy!(m, N⁻¹vₖ₋₁, N⁻¹vₖ) # N⁻¹vₖN⁻¹vₖ
441+
kcopy!(n, M⁻¹uₖ₋₁, M⁻¹uₖ) # M⁻¹uₖM⁻¹uₖ
439442

443+
# Compute uₖ₊₁ and vₖ₊₁.
440444
if βₖ₊₁ zero(T)
441445
kdivcopy!(m, uₖ, q, βₖ₊₁) # uₖ₊₁ = q / βₖ₊₁
442446
end
@@ -460,15 +464,16 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
460464
γₖ = γₖ₊₁
461465
βₖ = βₖ₊₁
462466

463-
# Update δbarₖ₋₁.
467+
# Update δbarₖ₋₁ and δₖ₋₁.
464468
δbarₖ₋₁ = δbarₖ
469+
δₖ₋₁ = δₖ
465470

466471
# Update stopping criterion.
467472
iter == 1 &&= atol + rtol * AᴴrNorm)
468473
user_requested_exit = callback(workspace) :: Bool
469474
# ill_cond_lim = one(T) / Acond ≤ ctol
470-
ill_cond_mach = one(T) + one(T) / Acond one(T)
471-
ill_cond = ill_cond_mach || ill_cond_lim
475+
# ill_cond_mach = one(T) + one(T) / Acond ≤ one(T)
476+
# ill_cond = ill_cond_mach || ill_cond_lim
472477
solved = rNorm ε_LS
473478
solved_lq = rNorm_lq ε_LN
474479
solved_cg = transfer_to_usymcg && (abs(δbarₖ) > eps(T)) && (rNorm_cg ε_LN)
@@ -477,8 +482,10 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
477482
tired = iter itmax
478483
timer = time_ns() - start_time
479484
overtimed = timer > timemax_ns
480-
kdisplay(iter, verbose) && @printf(iostream, "%7.1e\n", rNorm_lq)
481-
kdisplay(iter, verbose) && @printf(iostream, "%4d %8.1e %7.1e %7.1e %7.1e %7.1e %7.1e ", iter, αₖ, βₖ, γₖ, Anorm, Acond, rNorm_qr)
485+
Acond = Inf
486+
Anorm = Inf
487+
# kdisplay(iter, verbose) && @printf(iostream, "%7.1e\n", rNorm_lq)
488+
kdisplay(iter, verbose) && @printf(iostream, "%4d %8.1e %7.1e %7.1e %7.1e %7.1e %7.1e ", iter, αₖ, βₖ, γₖ, Anorm, Acond, rNorm)
482489
kdisplay(iter, verbose) && @printf(iostream, "%5d %7.1e %8.1e %.2fs\n", iter, rNorm, AᴴrNorm, ktimer(start_time))
483490
end
484491
(verbose > 0) && @printf(iostream, "\n")
@@ -493,11 +500,11 @@ kwargs_usymlqr = (:transfer_to_usymcg, :M, :N, :ldiv, :atol, :rtol, :itmax, :tim
493500

494501
# Termination status
495502
tired && (status = "maximum number of iterations exceeded")
496-
# solved_lq && (status = "solution xᴸ good enough given atol and rtol")
497-
# solved_cg && (status = "solution xᶜ good enough given atol and rtol")
503+
solved_lq && (status = "solution xᴸ good enough given atol and rtol")
504+
solved_cg && (status = "solution xᶜ good enough given atol and rtol")
498505
solved && (status = "solution good enough given atol and rtol")
499-
ill_cond_mach && (status = "condition number seems too large for this machine")
500-
ill_cond_lim && (status = "condition number exceeds tolerance")
506+
# ill_cond_mach && (status = "condition number seems too large for this machine")
507+
# ill_cond_lim && (status = "condition number exceeds tolerance")
501508
user_requested_exit && (status = "user-requested exit")
502509
overtimed && (status = "time limit exceeded")
503510

test/test_usymlqr.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
N⁻¹ = eye(n)
1010
H⁻¹ = blockdiag(D⁻¹, N⁻¹)
1111

12-
(x, y, stats) = usymlqr(A, b, c, M=D⁻¹)
13-
K = [D A; A' zeros(n, n)]
12+
(x, y, stats) = usymlqr(A, b, c, verbose=1)
13+
K = [eye(m) A; A' zeros(n, n)]
1414
B = [b; c]
1515
r = B - K * [x; y]
16-
resid = sqrt(dot(r, H⁻¹ * r)) / sqrt(dot(B, H⁻¹ * B))
16+
resid = norm(r) / norm(B)
1717
@printf("USYMLQR: Relative residual: %8.1e\n", resid)
1818
@test(resid usymlqr_tol)
1919

20-
(x, y, stats) = usymlqr(A, b, c)
21-
K = [eye(m) A; A' zeros(n, n)]
20+
(x, y, stats) = usymlqr(A, b, c, M=D⁻¹)
21+
K = [D A; A' zeros(n, n)]
2222
B = [b; c]
2323
r = B - K * [x; y]
24-
resid = norm(r) / norm(B)
24+
resid = sqrt(dot(r, H⁻¹ * r)) / sqrt(dot(B, H⁻¹ * B))
2525
@printf("USYMLQR: Relative residual: %8.1e\n", resid)
2626
@test(resid usymlqr_tol)
2727
end

test/test_warm_start.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,16 @@ function test_warm_start(FC)
119119
@test(resid tol)
120120

121121
workspace = UsymlqrWorkspace(A, b)
122-
solve!(workspace, A, b, b, x0, y0)
122+
krylov_solve!(workspace, A, b, b, x0, y0)
123123
r = [b - workspace.x - A * workspace.y; b - A' * workspace.x]
124124
resid = norm(r) / norm([b; b])
125125
@test(resid tol)
126+
127+
# TODO: (z0, z0) should be a solution
128+
krylov_solve!(workspace, J, d, d, z0, z0)
129+
r = [d - workspace.x - J * workspace.y; d - J' * workspace.x]
130+
resid = norm(r) / norm([d; d])
131+
@test(resid tol)
126132
end
127133

128134
# GPMR

0 commit comments

Comments
 (0)