Skip to content

Commit ce154a7

Browse files
committed
inf QR Q mul
1 parent 172d7db commit ce154a7

File tree

4 files changed

+105
-6
lines changed

4 files changed

+105
-6
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,21 @@
22

33
A Julia repository for linear algebra with infinite banded and block-banded matrices
44

5-
This currently implements the infinite-dimensional QL decomposition for perturbations of Toeplitz operators. Here is an example:
5+
6+
## Infinite-dimensional QR factorization
7+
8+
This currently supports the infinite-dimensional QR factorization for banded matrices, also known as the adaptive QR decomposition as the entries of the QR decomposition are determined lazily.
9+
10+
## Infinite-dimensional QL factorization
11+
12+
13+
This currently supports the infinite-dimensional QL factorization for perturbations of Toeplitz operators. Here is an example:
614
```julia
715
# Bull head matrix
816
A = BandedMatrix(-3 => Fill(7/10,∞), -2 => Fill(1,∞), 1 => Fill(2im,∞))
917
ql(A - 5*I)
1018
```
11-
The infinite-dimensional QL decomposition is a subtly thing: its defined when the operator has non-positive Fredholm index, and if the Fredholm index is not zero, it may not be unique. For the Bull head matrix `A`, here are plots of `ql(A-λ*I).L[1,1]` alongside the image of the symbol `A`, which depicts the essential spectrum of `A` and where the Fredholm index changes. Note we have two plots as the regions with negative Fredholm index have multiple QL decompositions. Where the Fredholm index is positive, the QL decomposition doesn't exist and is depected in black.
19+
The infinite-dimensional QL factorization is a subtly thing: its defined when the operator has non-positive Fredholm index, and if the Fredholm index is not zero, it may not be unique. For the Bull head matrix `A`, here are plots of `ql(A-λ*I).L[1,1]` alongside the image of the symbol `A`, which depicts the essential spectrum of `A` and where the Fredholm index changes. Note we have two plots as the regions with negative Fredholm index have multiple QL factorizations. Where the Fredholm index is positive, the QL factorization doesn't exist and is depected in black.
1220

1321
<img src=https://github.com/JuliaMatrices/InfiniteLinearAlgebra.jl/raw/master/images/ql1.png width=500 height=400>
1422
<img src=https://github.com/JuliaMatrices/InfiniteLinearAlgebra.jl/raw/master/images/ql2.png width=500 height=400>

src/InfiniteLinearAlgebra.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import InfiniteArrays: OneToInf, InfUnitRange, Infinity, InfStepRange
1010
import FillArrays: AbstractFill
1111
import BandedMatrices: BandedMatrix, _BandedMatrix, bandeddata, bandwidths
1212
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, mulapplystyle, LmulStyle, RmulStyle
13+
import LazyArrays: CachedArray, CachedMatrix, CachedVector, DenseColumnMajor, FillLayout, ApplyMatrix, check_mul_axes, ApplyStyle, LazyArrayApplyStyle, LazyArrayStyle,
14+
CachedMatrix, CachedArray, resizedata!, MemoryLayout, mulapplystyle, LmulStyle, RmulStyle,
15+
colsupport, rowsupport, triangularlayout
1516
import MatrixFactorizations: ql, ql!, QLPackedQ, getL, getR, reflector!, reflectorApply!, QL, QR, QRPackedQ
1617

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

src/infqr.jl

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,36 @@ struct AdaptiveQRFactors{T,DM<:AbstractMatrix{T},M<:AbstractMatrix{T}} <: Abstra
3434
data::AdaptiveQRData{T,DM,M}
3535
end
3636

37+
struct AdaptiveLayout{M} <: MemoryLayout end
38+
MemoryLayout(::Type{AdaptiveQRFactors{T,DM,M}}) where {T,DM,M} = AdaptiveLayout{typeof(MemoryLayout(DM))}()
39+
triangularlayout(::Type{Tri}, ::ML) where {Tri, ML<:AdaptiveLayout} = Tri{ML}()
40+
3741
size(F::AdaptiveQRFactors) = size(F.data.data)
3842
bandwidths(F::AdaptiveQRFactors) = bandwidths(F.data.data)
43+
function colsupport(F::AdaptiveQRFactors, j)
44+
partialqr!(F.data, j)
45+
colsupport(F.data.data, j)
46+
end
47+
48+
function rowsupport(F::AdaptiveQRFactors, j)
49+
partialqr!(F.data, j+bandwidth(F,2))
50+
rowsupport(F.data.data, j)
51+
end
52+
3953
function getindex(F::AdaptiveQRFactors, k::Int, j::Int)
4054
partialqr!(F.data, j)
4155
F.data.data[k,j]
4256
end
4357

58+
colsupport(F::QRPackedQ{<:Any,<:AdaptiveQRFactors}, j) = colsupport(F.factors, j)
59+
rowsupport(F::QRPackedQ{<:Any,<:AdaptiveQRFactors}, j) = rowsupport(F.factors, j)
60+
61+
62+
Base.replace_in_print_matrix(A::AdaptiveQRFactors, i::Integer, j::Integer, s::AbstractString) =
63+
i in colsupport(A,j) ? s : Base.replace_with_centered_mark(s)
64+
Base.replace_in_print_matrix(A::UpperTriangular{<:Any,<:AdaptiveQRFactors}, i::Integer, j::Integer, s::AbstractString) =
65+
i in colsupport(A,j) ? s : Base.replace_with_centered_mark(s)
66+
4467
struct AdaptiveQRTau{T,DM<:AbstractMatrix{T},M<:AbstractMatrix{T}} <: AbstractVector{T}
4568
data::AdaptiveQRData{T,DM,M}
4669
end
@@ -58,4 +81,37 @@ getR(Q::QR, ::Tuple{OneToInf{Int},OneToInf{Int}}) where T = UpperTriangular(Q.fa
5881
function qr(A::BandedMatrix{<:Any,<:Any,<:OneToInf})
5982
data = AdaptiveQRData(A)
6083
QR(AdaptiveQRFactors(data), AdaptiveQRTau(data))
84+
end
85+
86+
87+
function lmul!(A::QRPackedQ{<:Any,<:AdaptiveQRFactors}, B::CachedVector{T,Vector{T},<:Zeros{T,1}}) where T
88+
require_one_based_indexing(B)
89+
mA, nA = size(A.factors)
90+
sB = length(B.data)
91+
mB = length(B)
92+
if mA != mB
93+
throw(DimensionMismatch("matrix A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)"))
94+
end
95+
Afactors = A.factors
96+
97+
resizedata!(B, maximum(colsupport(A,sB)))
98+
b = B.data
99+
100+
sB_2 = length(b)
101+
102+
@inbounds begin
103+
for k = sB:-1:1
104+
cs = colsupport(Afactors,k)
105+
vBj = b[k]
106+
for i = (k+1:sB_2) cs
107+
vBj += conj(Afactors[i,k])*b[i]
108+
end
109+
vBj = A.τ[k]*vBj
110+
b[k] -= vBj
111+
for i = (k+1:sB_2) cs
112+
b[i] -= Afactors[i,k]*vBj
113+
end
114+
end
115+
end
116+
B
61117
end

test/test_infqr.jl

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using InfiniteLinearAlgebra, LinearAlgebra, BandedMatrices, InfiniteArrays, MatrixFactorizations, LazyArrays, FillArrays
2-
import BandedMatrices: _BandedMatrix, _banded_qr!, colsupport, BandedColumns
3-
import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData
2+
import LazyArrays: colsupport, rowsupport, MemoryLayout, DenseColumnMajor, TriangularLayout
3+
import BandedMatrices: _BandedMatrix, _banded_qr!, BandedColumns
4+
import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData, AdaptiveLayout
45

56

67
@testset "Adaptive QR" begin
@@ -35,6 +36,39 @@ import InfiniteLinearAlgebra: partialqr!, AdaptiveQRData
3536
@test size(R) == (∞,∞)
3637
@test R[1,1] == -sqrt(2)
3738
end
39+
40+
@testset "col/rowsupport" begin
41+
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
42+
F = qr(A);
43+
@test MemoryLayout(typeof(F.factors)) isa AdaptiveLayout{BandedColumns{DenseColumnMajor}}
44+
@test bandwidths(F.factors) == (1,2)
45+
@test colsupport(F.factors,1) == 1:2
46+
@test colsupport(F.factors,5) == 3:6
47+
@test rowsupport(F.factors,1) == 1:3
48+
@test rowsupport(F.factors,5) == 4:7
49+
Q,R = F;
50+
@test MemoryLayout(typeof(R)) isa TriangularLayout
51+
@test colsupport(R,1) == 1:1
52+
@test colsupport(R,5) == 3:5
53+
@test rowsupport(R,1) == 1:3
54+
@test rowsupport(R,5) == 5:7
55+
@test colsupport(Q,1) == 1:2
56+
@test colsupport(Q,5) == 3:6
57+
@test rowsupport(Q,1) == 1:3
58+
@test rowsupport(Q,5) == 4:7
59+
end
60+
61+
@testset "Qmul" begin
62+
A = _BandedMatrix(Vcat(Ones(1,∞), (1:∞)', Ones(1,∞)), ∞, 1, 1)
63+
Q,R = qr(A);
64+
b = Vcat([1.,2,3],Zeros(∞))
65+
@test lmul!(Q, Base.copymutable(b)).data qr(A[1:4,1:3]).Q*[1,2,3]
66+
@test Q[1,1] -1/sqrt(2)
67+
@test Q[200_000,200_000] -1.0
68+
@test Q[1:101,1:100] qr(A[1:101,1:100]).Q[:,1:100]
69+
70+
# lmul!(Q', Base.copymutable(b))
71+
end
3872
end
3973

4074

0 commit comments

Comments
 (0)