Skip to content

Commit b61183e

Browse files
authored
SymTridiagonal ql (#112)
* Support for SymTridiagonal in ∞-QL * Update Project.toml * Update test_infqr.jl * add tests * more tests * Update test_infqr.jl * Update test_infql.jl
1 parent 6bea340 commit b61183e

File tree

8 files changed

+128
-22
lines changed

8 files changed

+128
-22
lines changed

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ MatrixFactorizations = "a3b82374-2e81-5b9e-98ce-41277c0e4c87"
1717
SemiseparableMatrices = "f8ebbe35-cbfb-4060-bf7f-b10e4670cf57"
1818

1919
[compat]
20-
ArrayLayouts = "0.8.9"
20+
ArrayLayouts = "0.8.11"
2121
BandedMatrices = "0.17"
2222
BlockArrays = "0.16.14"
2323
BlockBandedMatrices = "0.11.5"
2424
DSP = "0.7"
2525
FillArrays = "0.13"
2626
InfiniteArrays = "0.12"
2727
LazyArrays = "0.22"
28-
LazyBandedMatrices = "0.8"
29-
MatrixFactorizations = "0.9"
28+
LazyBandedMatrices = "0.8.1"
29+
MatrixFactorizations = "0.9.2"
3030
SemiseparableMatrices = "0.3"
3131
julia = "1.6"
3232

examples/toeplitz.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ using InfiniteLinearAlgebra, BandedMatrices, PyPlot
1111
# Basic routines for plotting
1212
###
1313

14-
function ℓ11(A,λ; kwds...)
14+
function ℓ11(A,λ; kwds...)
1515
try
1616
abs(ql(A-λ*I; kwds...).L[1,1])
1717
catch DomainError

src/InfiniteLinearAlgebra.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ import FillArrays: AbstractFill, getindex_value, axes_print_matrix_row
1717
import InfiniteArrays: OneToInf, InfUnitRange, Infinity, PosInfinity, InfiniteCardinal, InfStepRange, AbstractInfUnitRange, InfAxes, InfRanges
1818
import LinearAlgebra: matprod, qr, AbstractTriangular, AbstractQ, adjoint, transpose, AdjOrTrans
1919
import LazyArrays: applybroadcaststyle, CachedArray, CachedMatrix, CachedVector, DenseColumnMajor, FillLayout, ApplyMatrix, check_mul_axes, LazyArrayStyle,
20-
resizedata!, MemoryLayout,
20+
resizedata!, MemoryLayout, most,
2121
factorize, sub_materialize, LazyLayout, LazyArrayStyle, layout_getindex,
22-
applylayout, ApplyLayout, PaddedLayout, zero!, MulAddStyle,
23-
LazyArray, LazyMatrix, LazyVector, paddeddata
22+
applylayout, ApplyLayout, PaddedLayout, CachedLayout, cacheddata, zero!, MulAddStyle,
23+
LazyArray, LazyMatrix, LazyVector, paddeddata, arguments
2424
import MatrixFactorizations: ul, ul!, _ul, ql, ql!, _ql, QLPackedQ, getL, getR, getU, reflector!, reflectorApply!, QL, QR, QRPackedQ,
2525
QRPackedQLayout, AdjQRPackedQLayout, QLPackedQLayout, AdjQLPackedQLayout, LayoutQ
2626

src/banded/infqltoeplitz.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ end
123123
mul(A::ProductQ, x::AbstractVector) = _productq_mul(A, x)
124124

125125

126+
127+
mul(Q::ProductQ, X::AbstractMatrix) = ApplyArray(*, Q.Qs...) * X
128+
mul(X::AbstractMatrix, Q::ProductQ) = X * ApplyArray(*, Q.Qs...)
129+
130+
131+
126132
# LQ where Q is a product of orthogonal operations
127133
struct QLProduct{T,QQ<:Tuple,LL} <: Factorization{T}
128134
Qs::QQ

src/infql.jl

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,11 @@ function qltail(Z::Number, A::Number, B::Number)
5252

5353
e = sqrt(n^2 - abs2(B))
5454
d = σ*e*Z/n
55-
56-
Q =
55+
5756
ql!([Z A B; 0 d e])
5857
end
5958

6059

61-
ql(A::SymTriPertToeplitz{T}; kwds...) where T = ql_hessenberg!(BandedMatrix(A, (bandwidth(A,1)+bandwidth(A,2),bandwidth(A,2))); kwds...)
62-
ql(A::SymTridiagonal{T}; kwds...) where T = ql_hessenberg!(BandedMatrix(A, (bandwidth(A,1)+bandwidth(A,2),bandwidth(A,2))); kwds...)
63-
ql(A::TriPertToeplitz{T}; kwds...) where T = ql_hessenberg!(BandedMatrix(A, (bandwidth(A,1)+bandwidth(A,2),bandwidth(A,2))); kwds...)
6460
ql_hessenberg(A::InfBandedMatrix{T}; kwds...) where T = ql_hessenberg!(BandedMatrix(A, (bandwidth(A,1)+bandwidth(A,2),bandwidth(A,2))); kwds...)
6561

6662
toeptail(B::BandedMatrix{T}) where T =
@@ -303,3 +299,78 @@ function materialize!(M::MatLdivVec{<:TriangularLayout{'L','N',BandedColumns{Per
303299
end
304300
b
305301
end
302+
303+
_ql(layout, ::NTuple{2,OneToInf{Int}}, A, args...; kwds...) = error("Not implemented")
304+
305+
_data_tail(::PaddedLayout, a) = paddeddata(a), zero(eltype(a))
306+
_data_tail(::AbstractFillLayout, a) = Vector{eltype(a)}(), getindex_value(a)
307+
_data_tail(::CachedLayout, a) = cacheddata(a), getindex_value(a.array)
308+
function _data_tail(::ApplyLayout{typeof(vcat)}, a)
309+
args = arguments(vcat, a)
310+
dat,tl = _data_tail(last(args))
311+
vcat(most(args)..., dat), tl
312+
end
313+
_data_tail(a) = _data_tail(MemoryLayout(a), a)
314+
315+
function _ql(::SymTridiagonalLayout, ::NTuple{2,OneToInf{Int}}, A, args...; kwds...)
316+
T = eltype(A)
317+
d,d∞ = _data_tail(A.dv)
318+
ev,ev∞ = _data_tail(A.ev)
319+
320+
m = max(length(d), length(ev)+1)
321+
dat = zeros(T, 3, m)
322+
dat[1,2:1+length(ev)] .= ev
323+
dat[1,2+length(ev):end] .= ev∞
324+
dat[2,1:length(d)] .= d
325+
dat[2,1+length(d):end] .= d∞
326+
dat[3,1:length(ev)] .= ev
327+
dat[3,1+length(ev):end] .= ev∞
328+
329+
ql(_BandedMatrix(Hcat(dat, [ev∞,d∞,ev∞] * Ones{T}(1,∞)), ℵ₀, 1, 1), args...; kwds...)
330+
end
331+
332+
333+
334+
# TODO: This should be redesigned as ql(BandedMatrix(A))
335+
# But we need to support dispatch on axes
336+
function _ql(::TridiagonalLayout, ::NTuple{2,OneToInf{Int}}, A, args...; kwds...)
337+
T = eltype(A)
338+
d,d∞ = _data_tail(A.d)
339+
dl,dl∞ = _data_tail(A.dl)
340+
du,du∞ = _data_tail(A.du)
341+
342+
m = max(length(d), length(du)+1, length(dl))
343+
dat = zeros(T, 3, m)
344+
dat[1,2:1+length(du)] .= du
345+
dat[1,2+length(du):end] .= du∞
346+
dat[2,1:length(d)] .= d
347+
dat[2,1+length(d):end] .= d∞
348+
dat[3,1:length(dl)] .= dl
349+
dat[3,1+length(dl):end] .= dl∞
350+
351+
ql(_BandedMatrix(Hcat(dat, [du∞,d∞,dl∞] * Ones{T}(1,∞)), ℵ₀, 1, 1), args...; kwds...)
352+
end
353+
354+
355+
###
356+
# L*Q special case
357+
###
358+
359+
copy(M::Mul{TriangularLayout{'L', 'N', PertToeplitzLayout}, HessenbergQLayout{'L'}}) =
360+
ApplyArray(*, M.A, M.B)
361+
362+
copy(M::Mul{HessenbergQLayout{'L'}, TriangularLayout{'L', 'N', PertToeplitzLayout}}) =
363+
ApplyArray(*, M.A, M.B)
364+
365+
366+
function LazyBandedMatrices._SymTridiagonal(::Tuple{TriangularLayout{'L', 'N', PertToeplitzLayout}, HessenbergQLayout{'L'}}, A)
367+
T = eltype(A)
368+
L,Q = arguments(*, A)
369+
Ldat,L∞ = arguments(hcat, L.data.data)
370+
Qdat, Q∞ = arguments(vcat, Q.q)
371+
372+
m = max(size(Ldat,2)+2, length(Qdat)+1)
373+
dv = [A[k,k] for k=1:m]
374+
ev = [A[k,k+1] for k=1:m-1]
375+
SymTridiagonal([dv; Fill(dv[end],∞)], [ev; Fill(ev[end],∞)])
376+
end

src/infqr.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ end
77

88
function AdaptiveQRData(::Union{SymmetricLayout{<:AbstractBandedLayout},AbstractBandedLayout}, A::AbstractMatrix{T}) where T
99
l,u = bandwidths(A)
10-
data = BandedMatrix{T}(undef,(2l+u+1,0),(l,l+u)) # pad super
11-
AdaptiveQRData(CachedArray(data,A), Vector{T}(), 0)
10+
FT = float(T)
11+
data = BandedMatrix{FT}(undef,(2l+u+1,0),(l,l+u)) # pad super
12+
AdaptiveQRData(CachedArray(data,A), Vector{FT}(), 0)
1213
end
1314

1415
function AdaptiveQRData(::AbstractAlmostBandedLayout, A::AbstractMatrix{T}) where T
@@ -123,8 +124,8 @@ function getindex(F::AdaptiveQRFactors, k::Int, j::Int)
123124
F.data.data[k,j]
124125
end
125126

126-
colsupport(F::QRPackedQ{<:Any,<:AdaptiveQRFactors}, j) = colsupport(F.factors, j)
127-
rowsupport(F::QRPackedQ{<:Any,<:AdaptiveQRFactors}, j) = rowsupport(F.factors, j)
127+
colsupport(F::QRPackedQ{<:Any,<:AdaptiveQRFactors}, j) = 1:last(colsupport(F.factors, j))
128+
rowsupport(F::QRPackedQ{<:Any,<:AdaptiveQRFactors}, j) = first(rowsupport(F.factors, j)):size(F,2)
128129

129130
blockcolsupport(F::QRPackedQ{<:Any,<:AdaptiveQRFactors}, j) = blockcolsupport(F.factors, j)
130131

@@ -349,4 +350,7 @@ ldiv!(F::QR{<:Any,<:AdaptiveQRFactors}, b::LayoutVector; kwds...) = ldiv!(F.R, l
349350

350351

351352
factorize(A::BandedMatrix{<:Any,<:Any,<:OneToInf}) = qr(A)
352-
qr(A::SymTridiagonal{T,<:AbstractFill{T,1,Tuple{OneToInf{Int}}}}) where T = adaptiveqr(A)
353+
qr(A::SymTridiagonal{T,<:AbstractFill{T,1,Tuple{OneToInf{Int}}}}) where T = adaptiveqr(A)
354+
355+
copy(M::Mul{<:QRPackedQLayout{<:AdaptiveLayout}}) = ApplyArray(*, M.A, M.B)
356+
copy(M::Mul{<:Any,<:QRPackedQLayout{<:AdaptiveLayout}}) = ApplyArray(*, M.A, M.B)

test/test_infql.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,22 @@ import BandedMatrices: _BandedMatrix
179179
@test Q[1:10,1:10] Qn[1:10,1:10] * diagm(0 => [1; -Ones(9)] )
180180
@test (Q'A)[1:10,1:10] diagm(0 => [1; -Ones(9)] ) * Ln[1:10,1:10] L[1:10,1:10]
181181
end
182+
183+
@testset "Tridiagonal QL" begin
184+
for A in (LinearAlgebra.SymTridiagonal([[1,2]; Fill(3,∞)], [[1, 2]; Fill(1,∞)]),
185+
LinearAlgebra.Tridiagonal([[1, 2]; Fill(1,∞)], [[1,2]; Fill(3,∞)], [[1, 2]; Fill(1,∞)]),
186+
LazyBandedMatrices.SymTridiagonal([[1,2]; Fill(3,∞)], [[1, 2]; Zeros(∞)]),
187+
LazyBandedMatrices.SymTridiagonal([[1,2]; Fill(3,∞)], [[1, 2]; zeros(∞)]),
188+
LazyBandedMatrices.SymTridiagonal([[1,2]; fill(3,∞)], [[1, 2]; zeros(∞)]))
189+
@test abs.(ql(A).L[1:10,1:10]) abs.(ql(A[1:1000,1:1000]).L[1:10,1:10])
190+
end
191+
192+
A = LazyBandedMatrices.SymTridiagonal([[1,2]; Fill(3,∞)], [[1, 2]; Fill(1,∞)])
193+
Q,L = ql(A)
194+
@test (Q*L)[1:10,1:10] A[1:10,1:10]
195+
196+
@test (L*Q)[1:10,1:10] LazyBandedMatrices.SymTridiagonal(L*Q)[1:10,1:10]
197+
end
198+
199+
@test_throws ErrorException ql(zeros(∞,∞))
182200
end

test/test_infqr.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,23 @@ import SemiseparableMatrices: AlmostBandedLayout, VcatAlmostBandedLayout
4343

4444
@testset "col/rowsupport" begin
4545
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ℵ₀, 1, 1)
46-
F = qr(A);
46+
F = qr(A)
4747
@test MemoryLayout(typeof(F.factors)) isa AdaptiveLayout{BandedColumns{DenseColumnMajor}}
4848
@test bandwidths(F.factors) == (1,2)
4949
@test colsupport(F.factors,1) == 1:2
5050
@test colsupport(F.factors,5) == 3:6
5151
@test rowsupport(F.factors,1) == 1:3
5252
@test rowsupport(F.factors,5) == 4:7
53-
Q,R = F;
53+
Q,R = F
5454
@test MemoryLayout(typeof(R)) isa TriangularLayout
5555
@test colsupport(R,1) == 1:1
5656
@test colsupport(R,5) == 3:5
5757
@test rowsupport(R,1) == 1:3
5858
@test rowsupport(R,5) == 5:7
5959
@test colsupport(Q,1) == 1:2
60-
@test colsupport(Q,5) == 3:6
61-
@test rowsupport(Q,1) == 1:3
62-
@test rowsupport(Q,5) == 4:7
60+
@test colsupport(Q,5) == 1:6
61+
@test rowsupport(Q,1) == 1:
62+
@test rowsupport(Q,5) == 4:
6363
end
6464

6565
@testset "Qmul" begin
@@ -296,4 +296,11 @@ import SemiseparableMatrices: AlmostBandedLayout, VcatAlmostBandedLayout
296296
b = [1; 2; 3; zeros(∞)]
297297
@test (qr(A) \ b) (ul(A) \ b)
298298
end
299+
300+
@testset "SymTridiagonal QR" begin
301+
A = LazyBandedMatrices.SymTridiagonal([[1,2]; Fill(3,∞)], [[1, 2]; Fill(1,∞)])
302+
Q,R = qr(A)
303+
@test (Q*R)[1:10,1:10] A[1:10,1:10]
304+
@test (R*Q)[1:10,1:10] LazyBandedMatrices.SymTridiagonal((R*Q)[1:10,1:10])
305+
end
299306
end

0 commit comments

Comments
 (0)