Skip to content

Commit 75b0783

Browse files
authored
Almost banded adaptive QR (#22)
* Add Semiseparable * Update for ArrayLayouts 0.2 * Start almost banded adaptive QR * _qr * update packages * Update Project.toml * Update Project.toml * debug frozen test * Revert "debug frozen test" This reverts commit dc319ff. * Revert "Revert "debug frozen test"" This reverts commit 183c0da.
1 parent 0c91e07 commit 75b0783

File tree

7 files changed

+144
-36
lines changed

7 files changed

+144
-36
lines changed

Project.toml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,19 @@ LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
1313
LazyBandedMatrices = "d7e5e226-e90b-4449-9968-0f923699bf6f"
1414
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1515
MatrixFactorizations = "a3b82374-2e81-5b9e-98ce-41277c0e4c87"
16+
SemiseparableMatrices = "f8ebbe35-cbfb-4060-bf7f-b10e4670cf57"
1617

1718
[compat]
18-
ArrayLayouts = "0.1"
19-
BandedMatrices = "0.14"
20-
BlockArrays = "0.11"
21-
BlockBandedMatrices = "0.7.1"
22-
FillArrays = "0.8.4"
23-
InfiniteArrays = "0.6.1"
24-
LazyArrays = "0.15"
25-
LazyBandedMatrices = "0.2"
26-
MatrixFactorizations = "0.2"
19+
ArrayLayouts = "0.2.1"
20+
BandedMatrices = "0.15.1"
21+
BlockArrays = "0.12"
22+
BlockBandedMatrices = "0.8"
23+
FillArrays = "0.8.6"
24+
InfiniteArrays = "0.7"
25+
LazyArrays = "0.16.4"
26+
LazyBandedMatrices = "0.2.5"
27+
MatrixFactorizations = "0.3.1"
28+
SemiseparableMatrices = "0.0.1"
2729
julia = "1.3"
2830

2931
[extras]

src/InfiniteLinearAlgebra.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
module InfiniteLinearAlgebra
2-
using BlockArrays, BlockBandedMatrices, BandedMatrices, LazyArrays, LazyBandedMatrices,
2+
using BlockArrays, BlockBandedMatrices, BandedMatrices, LazyArrays, LazyBandedMatrices, SemiseparableMatrices,
33
FillArrays, InfiniteArrays, MatrixFactorizations, ArrayLayouts, LinearAlgebra
44

55
import Base: +, -, *, /, \, ^, OneTo, getindex, promote_op, _unsafe_getindex, print_matrix_row, size, axes,
66
AbstractMatrix, AbstractArray, Matrix, Array, Vector, AbstractVector, Slice,
77
show, getproperty, copy, map
88
import Base.Broadcast: BroadcastStyle, Broadcasted, broadcasted
99

10-
import ArrayLayouts: colsupport, rowsupport, triangularlayout, MatLdivVec, triangulardata, TriangularLayout, sublayout
10+
import ArrayLayouts: colsupport, rowsupport, triangularlayout, MatLdivVec, triangulardata, TriangularLayout, sublayout, _qr
1111
import BandedMatrices: BandedMatrix, _BandedMatrix, AbstractBandedMatrix, bandeddata, bandwidths, BandedColumns, bandedcolumns,
1212
_default_banded_broadcast
1313
import FillArrays: AbstractFill, getindex_value
1414
import InfiniteArrays: OneToInf, InfUnitRange, Infinity, InfStepRange, AbstractInfUnitRange, InfAxes
1515
import LinearAlgebra: lmul!, ldiv!, matprod, qr, AbstractTriangular, AbstractQ, adjoint, transpose
1616
import LazyArrays: applybroadcaststyle, CachedArray, CachedMatrix, CachedVector, DenseColumnMajor, FillLayout, ApplyMatrix, check_mul_axes, ApplyStyle, LazyArrayApplyStyle, LazyArrayStyle,
1717
resizedata!, MemoryLayout, mulapplystyle, LmulStyle, RmulStyle,
18-
factorize, sub_materialize, LazyLayout, LazyArrayStyle, lazy_getindex,
18+
factorize, sub_materialize, LazyLayout, LazyArrayStyle, layout_getindex,
1919
@lazymul, applylayout, ApplyLayout, PaddedLayout, materialize!, zero!, MulAddStyle,
2020
LazyArray, LazyMatrix, LazyVector
21-
import MatrixFactorizations: ql, ql!, QLPackedQ, getL, getR, reflector!, reflectorApply!, QL, QR, QRPackedQ
21+
import MatrixFactorizations: ql, ql!, _ql, QLPackedQ, getL, getR, reflector!, reflectorApply!, QL, QR, QRPackedQ
2222

2323
import BlockArrays: AbstractBlockVecOrMat, sizes_from_blocks, _length, BlockedUnitRange
2424

@@ -29,6 +29,7 @@ import LazyBandedMatrices: MulBandedLayout, BroadcastBandedLayout
2929
import BlockBandedMatrices: _BlockSkylineMatrix, _BandedMatrix, _BlockSkylineMatrix, blockstart, blockstride,
3030
BlockSkylineSizes, BlockSkylineMatrix, BlockBandedMatrix, _BlockBandedMatrix, BlockTridiagonal
3131

32+
import SemiseparableMatrices: AbstractAlmostBandedLayout, _almostbanded_qr!
3233

3334
LazyArrays.@lazymul BandedMatrix{<:Any,<:Any,<:OneToInf}
3435
*(A::BandedMatrix{<:Any,<:Any,<:OneToInf}, b::CachedVector) = apply(*,A,b)

src/banded/infbanded.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Diagonal
33
###
44

5-
getindex(D::Diagonal, k::InfAxes, j::InfAxes) = lazy_getindex(D, k, j)
5+
getindex(D::Diagonal, k::InfAxes, j::InfAxes) = layout_getindex(D, k, j)
66

77
const TriToeplitz{T} = Tridiagonal{T,Fill{T,1,Tuple{OneToInf{Int}}}}
88
const ConstRowMatrix{T} = ApplyMatrix{T,typeof(*),<:Tuple{<:AbstractVector,<:AbstractFill{<:Any,2,Tuple{OneTo{Int},OneToInf{Int}}}}}

src/infql.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ end
208208
# BlockTridiagonal
209209
####
210210

211-
function _ql(A::BlockTriPertToeplitz, d, e)
211+
function _blocktripert_ql(A, d, e)
212212
N = max(length(A.blocks.du.args[1])+1,length(A.blocks.d.args[1]),length(A.blocks.dl.args[1]))
213213
c,a,b = A[Block(N+1,N)],A[Block(N,N)],A[Block(N-1,N)]
214214
P,τ = blocktailiterate(c,a,b,d,e)
@@ -226,7 +226,7 @@ function _ql(A::BlockTriPertToeplitz, d, e)
226226
Vcat(F.τ,mortar(Fill(τ,∞)))), P[Block(1,1)], P[Block(1,2)]
227227
end
228228

229-
ql(A::BlockTriPertToeplitz) = _ql(A, A[Block(2,3)], A[Block(3,3)])[1]
229+
ql(A::BlockTriPertToeplitz) = _blocktripert_ql(A, A[Block(2,3)], A[Block(3,3)])[1]
230230

231231
ql(A::Adjoint{T,BlockTriPertToeplitz{T}}) where T = ql(BlockTridiagonal(A))
232232

src/infqr.jl

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,47 @@ function AdaptiveQRData(::AbstractBandedLayout, A::AbstractMatrix{T}) where T
1010
data = BandedMatrix{T}(undef,(2l+u+1,0),(l,l+u)) # pad super
1111
AdaptiveQRData(CachedArray(data,A), Vector{T}(), 0)
1212
end
13+
14+
function AdaptiveQRData(::AbstractAlmostBandedLayout, A::AbstractMatrix{T}) where T
15+
l,u = almostbandwidths(A)
16+
r = almostbandedrank(A)
17+
data = AlmostBandedMatrix{T}(undef,(2l+u+1,0),(l,l+u),r) # pad super
18+
19+
AdaptiveQRData(CachedArray(data,A,(0,0)), Vector{T}(), 0)
20+
end
21+
1322
AdaptiveQRData(A::AbstractMatrix{T}) where T = AdaptiveQRData(MemoryLayout(typeof(A)), A)
1423

1524
function partialqr!(F::AdaptiveQRData{<:Any,<:BandedMatrix}, n::Int)
1625
if n > F.ncols
17-
l,u = bandwidths(F.data.array)
18-
resizedata!(F.data,n+l,n+u+l);
26+
l,u = bandwidths(F.data.data)
27+
resizedata!(F.data,n+l,n+u);
1928
resize!(F.τ,n);
2029
= F.ncols
2130
τ = view(F.τ,ñ+1:n);
2231
if l 0
2332
zero!(τ)
2433
else
25-
factors = view(F.data.data,ñ+1:n+l,ñ+1:n);
26-
_banded_qr!(factors, τ);
27-
# multiply remaining columns
28-
= max(ñ+1,n-l-u+1) # first column interacting with extra data
29-
Q = QRPackedQ(view(F.data.data,n̄:n+l,n̄:n), view(F.τ,n̄:n))
30-
lmul!(Q',view(F.data.data,n̄:n+l,n+1:n+u+l))
34+
factors = view(F.data.data,ñ+1:n+l,ñ+1:n+u);
35+
_banded_qr!(factors, τ, n-ñ)
36+
end
37+
F.ncols = n
38+
end
39+
F
40+
end
41+
42+
function partialqr!(F::AdaptiveQRData{<:Any,<:AlmostBandedMatrix}, n::Int)
43+
if n > F.ncols
44+
l,u = almostbandwidths(F.data.data)
45+
resizedata!(F.data,n+l,n+l+u);
46+
resize!(F.τ,n);
47+
= F.ncols
48+
τ = view(F.τ,ñ+1:n)
49+
if l 0
50+
zero!(τ)
51+
else
52+
factors = view(F.data.data,ñ+1:n+l,ñ+1:n+l+u)
53+
_almostbanded_qr!(factors, τ, n-ñ)
3154
end
3255
F.ncols = n
3356
end
@@ -82,11 +105,17 @@ end
82105
getR(Q::QR, ::Tuple{OneToInf{Int},OneToInf{Int}}) where T = UpperTriangular(Q.factors)
83106

84107

85-
function _banded_qr(::NTuple{2,OneToInf{Int}}, A)
108+
function adaptiveqr(A)
86109
data = AdaptiveQRData(A)
87110
QR(AdaptiveQRFactors(data), AdaptiveQRTau(data))
88111
end
89112

113+
_qr(::AbstractBandedLayout, ::NTuple{2,OneToInf{Int}}, A) = adaptiveqr(A)
114+
_qr(::AbstractAlmostBandedLayout, ::NTuple{2,OneToInf{Int}}, A) = adaptiveqr(A)
115+
116+
partialqr!(F::QR, n) = partialqr!(F.factors, n)
117+
partialqr!(F::AdaptiveQRFactors, n) = partialqr!(F.data, n)
118+
90119
#########
91120
# lmul!
92121
#########
@@ -142,11 +171,12 @@ function lmul!(adjA::Adjoint{<:Any,<:QRPackedQ{<:Any,<:AdaptiveQRFactors}}, B::C
142171

143172
@inbounds begin
144173
while first(jr) < nA
174+
j = first(jr)
145175
cs = colsupport(A.factors, last(jr))
146176
cs_max = maximum(cs)
147-
kr = first(jr):cs_max
177+
kr = j:cs_max
148178
resizedata!(B, min(cs_max,mB))
149-
if (first(jr) > sB && maximum(abs,view(B.data,colsupport(A.factors,first(jr)))) tol)
179+
if (j > sB && maximum(abs,view(B.data,j:last(colsupport(A.factors,j)))) tol)
150180
break
151181
end
152182
partialqr!(A.factors.data, min(cs_max,nA))

test/runtests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ end
6060
end
6161

6262

63-
@testset "Algebra" begin
63+
# @testset "Algebra" begin
6464
@testset "BandedMatrix" begin
6565
A = BandedMatrix(-3 => Fill(7/10,∞), -2 => 1:∞, 1 => Fill(2im,∞))
6666
@test A isa BandedMatrix{ComplexF64}
@@ -170,7 +170,7 @@ end
170170
# BlockTridiagonal(Zeros.(1:∞,2:∞),
171171
# (n -> Diagonal(((n+2).+(0:n)))/ (2n + 2)).(0:∞),
172172
# Zeros.(2:∞,1:∞))
173-
end
173+
# end
174174

175175
include("test_hessenbergq.jl")
176176
include("test_infql.jl")

test/test_infqr.jl

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
using InfiniteLinearAlgebra, LinearAlgebra, BandedMatrices, InfiniteArrays, MatrixFactorizations, LazyArrays, FillArrays, SpecialFunctions, Test
2-
import LazyArrays: colsupport, rowsupport, MemoryLayout, DenseColumnMajor, TriangularLayout, resizedata!
1+
using InfiniteLinearAlgebra, LinearAlgebra, BandedMatrices, InfiniteArrays, MatrixFactorizations, LazyArrays,
2+
FillArrays, SpecialFunctions, Test, SemiseparableMatrices
3+
import LazyArrays: colsupport, rowsupport, MemoryLayout, DenseColumnMajor, TriangularLayout, resizedata!, arguments
34
import LazyBandedMatrices: BroadcastBandedLayout
45
import BandedMatrices: _BandedMatrix, _banded_qr!, BandedColumns
5-
import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout
6+
import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout, adaptiveqr
7+
import SemiseparableMatrices: AlmostBandedLayout, VcatAlmostBandedLayout
68

79

810
@testset "Adaptive QR" begin
@@ -26,7 +28,7 @@ import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout
2628
end
2729

2830
@testset "AdaptiveQRFactors" begin
29-
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
31+
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
3032
F = qr(A);
3133
@test F.factors[1,1] -sqrt(2)
3234
@test F.factors[100,100] qrunblocked(A[1:101,1:100]).factors[100,100]
@@ -39,7 +41,7 @@ import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout
3941
end
4042

4143
@testset "col/rowsupport" begin
42-
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
44+
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
4345
F = qr(A);
4446
@test MemoryLayout(typeof(F.factors)) isa AdaptiveLayout{BandedColumns{DenseColumnMajor}}
4547
@test bandwidths(F.factors) == (1,2)
@@ -60,7 +62,7 @@ import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout
6062
end
6163

6264
@testset "Qmul" begin
63-
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
65+
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
6466
Q,R = qr(A);
6567
b = Vcat([1.,2,3],Zeros(∞))
6668
@test lmul!(Q, Base.copymutable(b)).datasize[1] == 4
@@ -91,7 +93,7 @@ import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout
9193
@test qr(A[1:3000,1:3000]).Q'b[1:3000] (F.Q'b)[1:3000]
9294
@time J = A \ Vcat([besselj(1,z)], Zeros(∞))
9395
@test J[1:2000] [besselj(k,z) for k=0:1999]
94-
96+
9597
z = 10_000; # the bigger z the longer before we see convergence
9698
A = BandedMatrix(0 => -2*(0:∞)/z, 1 => Ones(∞), -1 => Ones(∞))
9799
@time J = A \ Vcat([besselj(1,z)], Zeros(∞))
@@ -132,4 +134,77 @@ import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout
132134
@test F.Q[1:10,1:10] == Eye(10)
133135
@test F.R[1:10,1:10] == A[1:10,1:10]
134136
end
137+
138+
@testset "almost-banded" begin
139+
@testset "one-band" begin
140+
A = Vcat(Ones(1,∞), BandedMatrix(0 => -Ones(∞), 1 => 1:∞))
141+
@test MemoryLayout(typeof(A)) isa VcatAlmostBandedLayout
142+
V = view(A,1:10,1:10)
143+
@test MemoryLayout(typeof(V)) isa VcatAlmostBandedLayout
144+
@test A[1:10,1:10] isa AlmostBandedMatrix
145+
@test AlmostBandedMatrix(V) == Matrix(V) == A[1:10,1:10]
146+
147+
C = cache(A);
148+
@test C[1000,1000] 999.0
149+
F = adaptiveqr(A);
150+
partialqr!(F.factors.data,2);
151+
@test F.factors.data.data[1:3,1:5] qr(A[1:3,1:5]).factors
152+
partialqr!(F.factors.data,3);
153+
@test F.factors.data.data[1:4,1:6] qr(A[1:4,1:6]).factors
154+
155+
F = adaptiveqr(A);
156+
partialqr!(F.factors.data,10);
157+
@test F.factors[1:11,1:10] qr(A[1:11,1:10]).factors
158+
@test F.τ[1:10] qr(A[1:11,1:10]).τ
159+
partialqr!(F.factors.data,20);
160+
@test F.factors[1:21,1:20] qr(A[1:21,1:20]).factors
161+
162+
@test adaptiveqr(A).R[1:10,1:10] qr(A[1:11,1:10]).R
163+
164+
@test qr(A) isa MatrixFactorizations.QR{Float64,<:InfiniteLinearAlgebra.AdaptiveQRFactors}
165+
@test factorize(A) isa MatrixFactorizations.QR{Float64,<:InfiniteLinearAlgebra.AdaptiveQRFactors}
166+
167+
@test (adaptiveqr(A) \ [ℯ; zeros(∞)])[1:1000] (qr(A) \ [ℯ; zeros(∞)])[1:1000] (A \ [ℯ; zeros(∞)])[1:1000] [1/factorial(1.0k) for k=0:999]
168+
end
169+
170+
@testset "two-bands" begin
171+
B = BandedMatrix(0 => -Ones(∞), 2 => (1:∞).* (2:∞))
172+
A = Vcat(Vcat(Ones(1,∞), ((-1).^(0:∞))'), B)
173+
@test MemoryLayout(typeof(A)) isa VcatAlmostBandedLayout
174+
175+
@test qr(A) isa MatrixFactorizations.QR{Float64,<:InfiniteLinearAlgebra.AdaptiveQRFactors}
176+
@test factorize(A) isa MatrixFactorizations.QR{Float64,<:InfiniteLinearAlgebra.AdaptiveQRFactors}
177+
u = qr(A) \ [1; zeros(∞)]
178+
x = 0.1
179+
@test (exp(1 - x)*(-1 + exp(2 + 2x)))/(-1 + exp(4)) dot(u[1:1000], x.^(0:999))
180+
u = qr(A) \ Vcat([ℯ,1/ℯ], zeros(∞))
181+
@test u[1:1000] [1/factorial(1.0k) for k=0:999]
182+
u = qr(A) \ Vcat(ℯ,1/ℯ, zeros(∞))
183+
@test u[1:1000] [1/factorial(1.0k) for k=0:999]
184+
185+
A = Vcat(Ones(1,∞), ((-1.0).^(0:∞))', B)
186+
@test MemoryLayout(typeof(A)) isa VcatAlmostBandedLayout
187+
u = A \ Vcat(ℯ,1/ℯ, zeros(∞))
188+
@test u[1:1000] [1/factorial(1.0k) for k=0:999]
189+
190+
A = Vcat(Ones(1,∞), ((-1).^(0:∞))', B)
191+
u = A \ Vcat(ℯ,1/ℯ, zeros(∞))
192+
@test u[1:1000] [1/factorial(1.0k) for k=0:999]
193+
end
194+
195+
@testset "more bands" begin
196+
L = Vcat(Ones(1,∞), ((-1).^(0:∞))',
197+
BandedMatrix(-1 => Ones(∞), 1 => Ones(∞), 2 => 4:2:∞, 3 => Ones(∞), 5 => Ones(∞)))
198+
F = qr(L).factors.data;
199+
resizedata!(F.data,13,19)
200+
@test F.data.data[2,8] == -1
201+
F = qr(L);
202+
partialqr!(F,10);
203+
@test F.factors[1:10,1:10] qr(L[1:13,1:10]).factors[1:10,1:10]
204+
@test qr(L).factors[1:10,1:10] qr(L[1:13,1:10]).factors[1:10,1:10]
205+
206+
u = L \ [1; 2; zeros(∞)]
207+
@test L[1:1000,1:1000]*u[1:1000] [1; 2; zeros(998)]
208+
end
209+
end
135210
end

0 commit comments

Comments
 (0)