Skip to content

Commit f7d1a66

Browse files
committed
Adaptive QR works!
2 parents 69a53cf + 49694bd commit f7d1a66

File tree

4 files changed

+127
-48
lines changed

4 files changed

+127
-48
lines changed

src/InfiniteLinearAlgebra.jl

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,45 @@
11
module InfiniteLinearAlgebra
22
using BlockArrays, BlockBandedMatrices, BandedMatrices, LazyArrays, FillArrays, InfiniteArrays, MatrixFactorizations, LinearAlgebra
33

4-
import Base: +, -, *, /, \, OneTo, getindex, promote_op, _unsafe_getindex, print_matrix_row, size,
4+
import Base: +, -, *, /, \, ^, OneTo, getindex, promote_op, _unsafe_getindex, print_matrix_row, size, axes,
55
AbstractMatrix, AbstractArray, Matrix, Array, Vector, AbstractVector,
66
show, getproperty
7+
import Base.Broadcast: BroadcastStyle
8+
79
import InfiniteArrays: OneToInf, InfUnitRange, Infinity, InfStepRange
810
import FillArrays: AbstractFill
911
import BandedMatrices: BandedMatrix, _BandedMatrix, bandeddata
10-
import LinearAlgebra: lmul!, ldiv!, matprod, qr, QRPackedQ, AbstractTriangular, AbstractQ, adjoint, transpose,
11-
QR
12-
import LazyArrays: CachedArray, DenseColumnMajor, FillLayout, ApplyMatrix, check_mul_axes
13-
import MatrixFactorizations: ql, ql!, QLPackedQ, getL, reflector!, reflectorApply!,
14-
QL
12+
import LinearAlgebra: lmul!, ldiv!, matprod, qr, AbstractTriangular, AbstractQ, adjoint, transpose
13+
import LazyArrays: CachedArray, DenseColumnMajor, FillLayout, ApplyMatrix, check_mul_axes, ApplyStyle, LazyArrayApplyStyle, LazyArrayStyle,
14+
CachedMatrix, CachedArray, resizedata!, MemoryLayout
15+
import MatrixFactorizations: ql, ql!, QLPackedQ, getL, getR, reflector!, reflectorApply!, QL, QR, QRPackedQ
1516

1617
import BlockArrays: BlockSizes, cumulsizes, _find_block, AbstractBlockVecOrMat, sizes_from_blocks
1718

18-
import BandedMatrices: BandedMatrix, bandwidths
19+
import BandedMatrices: BandedMatrix, bandwidths, AbstractBandedLayout, _banded_qr!
1920

2021
import BlockBandedMatrices: _BlockSkylineMatrix, _BandedMatrix, AbstractBlockSizes, cumulsizes, _BlockSkylineMatrix, BlockSizes, blockstart, blockstride,
2122
BlockSkylineSizes, BlockSkylineMatrix, BlockBandedMatrix, _BlockBandedMatrix, BlockTridiagonal
2223

2324

25+
# Fix ∞ BandedMatrix
26+
ApplyStyle(::typeof(*), ::Type{<:BandedMatrix{<:Any,<:Any,<:OneToInf}}, _::Type{<:AbstractArray}...) =
27+
LazyArrayApplyStyle()
28+
29+
# BroadcastStyle(::Type{<:BandedMatrix{<:Any,<:Any,<:OneToInf}}) = LazyArrayStyle{2}()
30+
31+
^(A::BandedMatrix{T,<:Any,<:OneToInf}, p::Integer) where T =
32+
if p < 0
33+
inv(A)^(-p)
34+
elseif p == 0
35+
Eye{T}(∞)
36+
elseif p == 1
37+
copy(A)
38+
else
39+
A*A^(p-1)
40+
end
41+
42+
2443
if VERSION < v"1.2-"
2544
import Base: has_offset_axes
2645
require_one_based_indexing(A...) = !has_offset_axes(A...) || throw(ArgumentError("offset arrays are not supported but got an array with index other than 1"))

src/infqr.jl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
mutable struct AdaptiveQRData{T,DM<:AbstractMatrix{T},M<:AbstractMatrix{T}}
3+
data::CachedMatrix{T,DM,M}
4+
τ::Vector{T}
5+
ncols::Int
6+
end
7+
8+
function AdaptiveQRData(::AbstractBandedLayout, A::AbstractMatrix{T}) where T
9+
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)
12+
end
13+
AdaptiveQRData(A::AbstractMatrix{T}) where T = AdaptiveQRData(MemoryLayout(typeof(A)), A)
14+
15+
function partialqr!(F::AdaptiveQRData{<:Any,<:BandedMatrix}, n::Int)
16+
if n > F.ncols
17+
l,u = bandwidths(F.data.array)
18+
resizedata!(F.data,n+l,n+u+l)
19+
resize!(F.τ,n)
20+
= F.ncols
21+
factors = view(F.data.data,ñ+1:n+l,ñ+1:n)
22+
τ = view(F.τ,ñ+1:n)
23+
_banded_qr!(factors, τ)
24+
# multiply remaining columns
25+
= max(ñ+1,n-l-u+1) # first column interacting with extra data
26+
Q = QRPackedQ(view(F.data.data,n̄:n+l,n̄:n), view(F.τ,n̄:n))
27+
lmul!(Q',view(F.data.data,n̄:n+l,n+1:n+u+l))
28+
F.ncols = n
29+
end
30+
F
31+
end
32+
33+
struct AdaptiveQRFactors{T,DM<:AbstractMatrix{T},M<:AbstractMatrix{T}} <: AbstractMatrix{T}
34+
data::AdaptiveQRData{T,DM,M}
35+
end
36+
37+
size(F::AdaptiveQRFactors) = size(F.data.data)
38+
function getindex(F::AdaptiveQRFactors, k::Int, j::Int)
39+
partialqr!(F.data, j)
40+
F.data.data[k,j]
41+
end
42+
43+
struct AdaptiveQRTau{T,DM<:AbstractMatrix{T},M<:AbstractMatrix{T}} <: AbstractVector{T}
44+
data::AdaptiveQRData{T,DM,M}
45+
end
46+
47+
size(F::AdaptiveQRTau) = (size(F.data.data,1),)
48+
49+
function getindex(F::AdaptiveQRTau, j::Int)
50+
partialqr!(F.data, j)
51+
F.data.τ[j]
52+
end
53+
54+
getR(Q::QR, ::Tuple{OneToInf{Int},OneToInf{Int}}) where T = UpperTriangular(Q.factors)
55+
56+
57+
function qr(A::BandedMatrix{<:Any,<:Any,<:OneToInf})
58+
data = AdaptiveQRData(A)
59+
QR(AdaptiveQRFactors(data), AdaptiveQRTau(data))
60+
end

test/runtests.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ import BandedMatrices: bandeddata, _BandedMatrix
4040
At = BandedMatrix(transpose(A))
4141
@test Ac[1:10,1:10] (A')[1:10,1:10] A[1:10,1:10]'
4242
@test At[1:10,1:10] transpose(A)[1:10,1:10] transpose(A[1:10,1:10])
43+
44+
A = _BandedMatrix(Fill(1,4,∞),∞,1,2)
45+
@test A*A isa ApplyArray
46+
@test (A^2)[1:10,1:10] == (A*A)[1:10,1:10] == (A[1:100,1:100]^2)[1:10,1:10]
47+
@test (A^3)[1:10,1:10] == (A*A*A)[1:10,1:10] == (A[1:100,1:100]^3)[1:10,1:10]
4348
end
49+
4450
include("test_hessenbergq.jl")
4551
include("test_infql.jl")
4652

test/test_infqr.jl

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,38 @@
11
using InfiniteLinearAlgebra, LinearAlgebra, BandedMatrices, InfiniteArrays, MatrixFactorizations, LazyArrays, FillArrays
2-
import BandedMatrices: _BandedMatrix, colsupport
3-
import MatrixFactorizations: QR
4-
import LazyArrays: CachedMatrix
5-
6-
struct AdaptiveQRFactors{T,DM<:CachedMatrix{T}} <: AbstractMatrix{T}
7-
factors::DM
8-
τ::Vector{T}
9-
end
10-
11-
struct AdaptiveQRTau{T,DM<:CachedMatrix{T}} <: AbstractMatrix{T}
12-
factors::DM
13-
τ::Vector{T}
2+
import BandedMatrices: _BandedMatrix, _banded_qr!, colsupport, BandedColumns
3+
import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData
4+
5+
6+
@testset "Adaptive QR" begin
7+
@testset "test partialqr!" begin
8+
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
9+
l,u = bandwidths(A)
10+
F = AdaptiveQRData(A);
11+
@test bandwidths(F.data) == (1,2)
12+
n = 3
13+
partialqr!(F,n);
14+
= qrunblocked(Matrix(A[1:n+l,1:n]))
15+
@test.factors F.data[1:n+l,1:n]
16+
@test.τ F.τ
17+
@test triu!(F.data[1:n+1,1:n+2]) .Q'*A[1:n+1,1:n+2] # test extra columns have been modified
18+
n = 6
19+
partialqr!(F,n);
20+
= qrunblocked(Matrix(A[1:n+l,1:n]))
21+
@test.factors F.data[1:n+l,1:n]
22+
@test.τ F.τ
23+
@test triu!(F.data[1:n+1,1:n+2]) .Q'*A[1:n+1,1:n+2] # test extra columns have been modified
24+
end
25+
26+
@testset "AdaptiveQRFactors" begin
27+
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
28+
F = qr(A);
29+
@test F.factors[1,1] -sqrt(2)
30+
@test F.factors[100,100] qrunblocked(A[1:101,1:100]).factors[100,100]
31+
@test F.τ[1] 1+sqrt(2)/2
32+
@test F.τ[100] qrunblocked(A[1:101,1:100]).τ[100]
33+
Q,R = F;
34+
35+
end
1436
end
1537

16-
17-
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
18-
C = cache(A)
19-
20-
21-
V = view(C.data,1:10,1:11)
22-
V isa BandedMatrices.BandedSubBandedMatrix
23-
qr!(V)
24-
qr!(C.data)
25-
26-
F = QR(
27-
28-
29-
vierwC.data
30-
31-
@test C[100_000,100_000] === 100_000.0
32-
33-
@time C[100_000,100_000]
34-
M =
35-
@time F = qr!(C.data)
36-
37-
@which C[1:100,1:100]
38-
39-
@which bandwidths(C)
40-
41-
@which cache(A)
42-
C.data
43-
44-
2
38+

0 commit comments

Comments
 (0)