Skip to content

Commit a156a15

Browse files
author
Pawel Latawiec
committed
Modify program flow to append once finished
1 parent bbeaf85 commit a156a15

File tree

2 files changed

+41
-50
lines changed

2 files changed

+41
-50
lines changed

src/lal.jl

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ Provides an iterable which constructs basis vectors for a Krylov subspace genera
123123
# Keywords
124124
- `vw_normalized=false`: Flag if `v` and `w` passed to function are already normalized. If `false`, normalized `v` and `w` in-place.
125125
- `max_iter=size(A, 2)`: Maximum number of iterations
126-
- `max_block_size=2`: Maximum look-ahead block size to construct. Following [^Freund1994], it is rare for blocks to go beyond size 3. This pre-allocates the block storage for the computation to size `(max_block_size, length(v))`. If a block would be built that exceeds this size, the estimate of `norm(A)` is adjusted to allow the block to close.
126+
- `max_block_size=4`: Maximum look-ahead block size to construct. Following [^Freund1994], it is rare for blocks to go beyond size 3. This pre-allocates the block storage for the computation to size `(max_block_size, length(v))`. If a block would be built that exceeds this size, the estimate of `norm(A)` is adjusted to allow the block to close.
127+
- `max_memory=4`: Maximum memory to store the sequence vectors. This may be greater than the block size.
127128
- `log=false`: Flag determining whether to log history in a [`LookAheadLanczosDecompLog`](@ref)
128129
- `verbose=false`: Flag determining verbosity of output during iteration
129130
@@ -137,7 +138,8 @@ function LookAheadLanczosDecomp(
137138
A, v, w;
138139
vw_normalized=false,
139140
max_iter=size(A, 2),
140-
max_block_size=8,
141+
max_block_size=4,
142+
max_memory=4,
141143
log=false,
142144
verbose=false
143145
)
@@ -153,8 +155,8 @@ function LookAheadLanczosDecomp(
153155
q = similar(v)
154156
= similar(v)
155157
= similar(v)
156-
P = LimitedMemoryMatrix(similar(v, size(v, 1), 0), max_block_size)
157-
Q = LimitedMemoryMatrix(similar(v, size(v, 1), 0), max_block_size)
158+
P = LimitedMemoryMatrix(similar(v, size(v, 1), 0), max_memory)
159+
Q = LimitedMemoryMatrix(similar(v, size(v, 1), 0), max_memory)
158160
Ap = similar(v)
159161
Atq = similar(v)
160162
qtAp = zero(elT)
@@ -163,8 +165,8 @@ function LookAheadLanczosDecomp(
163165

164166
= similar(v)
165167
= similar(v)
166-
V = LimitedMemoryMatrix(copy(v), max_block_size)
167-
W = LimitedMemoryMatrix(copy(w), max_block_size)
168+
V = LimitedMemoryMatrix(copy(v), max_memory)
169+
W = LimitedMemoryMatrix(copy(w), max_memory)
168170
w̃tṽ = zero(elT)
169171

170172
wtv = transpose(w) * v
@@ -276,26 +278,26 @@ function _update_PQ_sequence!(ld)
276278
# Alg. 5.2.3
277279
_update_Flastrow!(ld)
278280
# Alg. 5.2.4
279-
innerp = inner_ok && _is_singular(ld.E)
281+
ld.innerp = inner_ok && _is_singular(ld.E)
280282
# Alg. 5.2.5
281-
_update_U!(ld, innerp)
283+
_update_U!(ld, ld.innerp)
282284
# Alg. 5.2.6
283285
_update_p̂q̂_common!(ld)
284286
# Condition from Alg. 5.2.6
285-
if !innerp
287+
if !ld.innerp
286288
# Alg. 5.2.7
287289
_update_Gnm1!(ld)
288-
innerp = inner_ok && _check_G(ld)
290+
ld.innerp = inner_ok && _check_G(ld)
289291
# Condition from Alg. 5.2.7 - we are confident we can perform a regular step
290-
if !innerp
292+
if !ld.innerp
291293
# Alg. 5.2.8
292294
_update_pq_regular!(ld)
293295
_matvec_pq!(ld)
294296
# Alg. 5.2.9
295297
_update_Gn!(ld)
296-
innerp = inner_ok && _check_G(ld)
298+
ld.innerp = inner_ok && _check_G(ld)
297299
# Condition from Alg. 5.2.9 - One last chance to bail and create an inner step
298-
if !innerp
300+
if !ld.innerp
299301
if islogging(ld)
300302
ld.log.PQ_block_count[_PQ_block_size(ld)] += 1
301303
end
@@ -306,9 +308,10 @@ function _update_PQ_sequence!(ld)
306308
end
307309
else
308310
# Alg. 5.2.11
311+
# re-calculate matrix-vector product and append new result to P, Q seq
309312
isverbose(ld) && @info "Inner P-Q construction, second G check"
310313
_update_pq_inner!(ld)
311-
_matvec_pq!(ld, true)
314+
_matvec_pq!(ld)
312315
end
313316
else
314317
# Alg. 5.2.11
@@ -322,7 +325,7 @@ function _update_PQ_sequence!(ld)
322325
_update_pq_inner!(ld)
323326
_matvec_pq!(ld)
324327
end
325-
ld.innerp = innerp
328+
_append_PQ!(ld)
326329
return ld
327330
end
328331

@@ -338,28 +341,27 @@ function _update_VW_sequence!(ld)
338341
# Alg. 5.2.16
339342
_update_Flastcol!(ld)
340343
# Alg. 5.2.17
341-
innerv = inner_ok && _is_singular(ld.D[ld.nl[ld.l]:end, ld.nl[ld.l]:end])
344+
ld.innerv = inner_ok && _is_singular(ld.D[ld.nl[ld.l]:end, ld.nl[ld.l]:end])
342345
# Alg. 5.2.18
343-
_update_L!(ld, innerv)
346+
_update_L!(ld, ld.innerv)
344347
# Alg. 5.2.19
345348
_update_v̂ŵ_common!(ld)
346349
# Condition from # Alg. 5.2.19
347-
if !innerv
350+
if !ld.innerv
348351
# Alg. 5.2.20
349352
_update_Hn!(ld)
350-
innerv = inner_ok && _check_H(ld)
351-
if !innerv
353+
ld.innerv = inner_ok && _check_H(ld)
354+
if !ld.innerv
352355
# Alg. 5.2.21
353356
_update_vw_regular!(ld)
354357
# also updates γ, ω̃tṽ
355358
ld, terminate_early = _update_ρξ!(ld)
356359
if terminate_early return ld, true end
357360
# Alg. 5.2.22
358361
_update_Hnp1!(ld)
359-
innerv = inner_ok && _check_H(ld)
362+
ld.innerv = inner_ok && _check_H(ld)
360363
# Condition from Alg. 5.2.22
361-
if !innerv
362-
ld.innerv = false
364+
if !ld.innerv
363365
if islogging(ld)
364366
ld.log.VW_block_count[_VW_block_size(ld)] += 1
365367
end
@@ -378,15 +380,13 @@ function _update_VW_sequence!(ld)
378380
# Alg. 5.2.24
379381
isverbose(ld) && @info "Inner V-W construction, first H check"
380382
_update_vw_inner!(ld)
381-
ld.innerv = true
382383
ld, terminate_early = _update_ρξ!(ld)
383384
if terminate_early return ld, true end
384385
end
385386
else
386387
# Alg. 5.2.24
387388
isverbose(ld) && @info "Inner V-W construction, singular D check"
388389
_update_vw_inner!(ld)
389-
ld.innerv = true
390390
ld, terminate_early = _update_ρξ!(ld)
391391
if terminate_early return ld, true end
392392
end
@@ -404,6 +404,7 @@ function _update_D!(ld)
404404
# D[n, n] = wtv
405405

406406
# TODO: closed block
407+
block_start = ld.nl[ld.lstar]
407408
if isone(ld.n)
408409
ld.D = fill(ld.wtv, 1, 1)
409410
else
@@ -548,30 +549,21 @@ function _update_pq_inner!(ld)
548549
return ld
549550
end
550551

551-
function _matvec_pq!(ld, retry=false)
552+
function _matvec_pq!(ld)
552553
# Common part of Alg. 5.2.8, Alg. 5.2.11
553-
# if retry, then this means we have already added data to the vectors, but our
554-
# inner block check failed, so we overwrite what he have. This is the case if
555-
# the check at Alg. 5.2.9 fails
556-
if retry
557-
ld.P[:, end] .= ld.p
558-
ld.Q[:, end] .= ld.q
559-
else
560-
hcat!(ld.P, ld.p)
561-
hcat!(ld.Q, ld.q)
562-
end
563554
mul!(ld.Ap, ld.A, ld.p)
564555
ld.qtAp = transpose(ld.q) * ld.Ap
565-
if retry
566-
ld.normp[end] = norm(ld.p)
567-
ld.normq[end] = norm(ld.q)
568-
else
569-
push!(ld.normp, norm(ld.p))
570-
push!(ld.normq, norm(ld.q))
571-
end
572556
return ld
573557
end
574558

559+
function _append_PQ!(ld)
560+
# adds p, q vector sequence to P, Q
561+
hcat!(ld.P, ld.p)
562+
hcat!(ld.Q, ld.q)
563+
push!(ld.normp, norm(ld.p))
564+
push!(ld.normq, norm(ld.q))
565+
end
566+
575567
# 5.2.4, 5.2.17
576568
_is_singular(A) = !isempty(A) && minimum(svdvals(A)) < eps(real(eltype(A)))
577569

@@ -580,6 +572,7 @@ function _update_E!(ld)
580572
# F = ΓUtinv(Γ)E
581573
# 5.2.14
582574
n = ld.n
575+
block_start = ld.mk[ld.kstar]
583576

584577
if isone(ld.n)
585578
ld.E = fill(ld.qtAp, 1, 1)

test/lal.jl

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ function _iterate_and_collect_lal_intermediates(ld)
4040
# calculations will sparsify and only small vectors will be kept
4141
# Because we don't explicitly construct H and G, we do not attempt collecting them
4242

43-
P = Matrix(ld.P) # size (N, n)
44-
Q = Matrix(ld.Q) # size (N, n)
43+
P = Matrix{eltype(ld.p)}(undef, length(ld.p), 0) # size (N, n)
44+
Q = Matrix{eltype(ld.q)}(undef, length(ld.q), 0) # size (N, n)
4545
W = Matrix(ld.W) # size (N, n+1)
4646
V = Matrix(ld.V) # size (N, n+1)
4747
γ = copy(ld.γ) # size n+1
@@ -169,8 +169,6 @@ end
169169
@test ld.n == 1
170170
@test ld_results.V v
171171
@test ld_results.W w
172-
@show size(ld_results.P)
173-
@show size(ld_results.Q)
174172

175173
test_regular_lal_identities(ld_results, ld.log; early_exit=true)
176174
end
@@ -222,13 +220,13 @@ end
222220
fill!(w, 0)
223221
v[1] = 1.0
224222
w[3] = 1.0
225-
ld = IS.LookAheadLanczosDecomp(A, v, w; log=true, vw_normalized=false, max_block_size=4)
223+
ld = IS.LookAheadLanczosDecomp(A, v, w; log=true, vw_normalized=false, max_block_size=3, max_memory=4)
226224
ld_results = _iterate_and_collect_lal_intermediates(ld)
227225

228226
test_lal_identities(ld_results)
229227
@test ld.log.VW_block_count[3] == 3
230228
@test ld.log.PQ_block_count[2] == 3
231-
@test ld.log.PQ_block_count[1] == 3
229+
@test ld.log.PQ_block_count[1] == 4
232230
end
233231
@testset "Regular V-W, immediate P-Q Block" begin
234232
# v, w chosen s.t (w, v) ≠ 0 and (q, Ap) == (w, Av) == 0
@@ -268,7 +266,7 @@ end
268266
]
269267
v = [rand(rng, size(I1, 1)); fill(0.0, size(Ac, 1) - size(I1, 1))]
270268
w = [rand(rng, size(I1, 1)); fill(0.0, size(Ac, 1) - size(I1, 1))]
271-
ld = IS.LookAheadLanczosDecomp(Ac, v, w; log=true, vw_normalized=false, max_block_size=10, verbose=true)
269+
ld = IS.LookAheadLanczosDecomp(Ac, v, w; log=true, vw_normalized=false, max_block_size=10, max_memory=10, verbose=true)
272270
ld_results = _iterate_and_collect_lal_intermediates(ld)
273271
test_lal_identities(ld_results)
274272
end

0 commit comments

Comments
 (0)