-
Notifications
You must be signed in to change notification settings - Fork 7
Implement reverse Cholesky for symmetric Tridiagonal matrices #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement reverse Cholesky for symmetric Tridiagonal matrices #179
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #179 +/- ##
==========================================
+ Coverage 82.32% 83.03% +0.71%
==========================================
Files 11 12 +1
Lines 1420 1509 +89
==========================================
+ Hits 1169 1253 +84
- Misses 251 256 +5 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are some comments.
I think the unifying the different designs can happen later, separately as a different PR, but it should be on our radar.
I'm leaning towards having the factors be basic types (BandedMatrix
, Bidiagonal
) that wrap a data type that stores the data but probably it needs more thought.
Not sure what's up with the tests failing. I can't reproduce that error locally... |
Oh, I can now reproduce it (actually, a different error?) after upgrading to LazyArrays 2.0.4, e.g. Expression: exp.(T)[2:∞, 3:∞] isa SubArray
MethodError: BroadcastStyle(::Type{SubArray{Float64, 2, LazyBandedMatrices.Tridiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}, Fill{Float64, 1, Tuple{OneToInf{Int64}}}}, Tuple{InfiniteArrays.InfUnitRange{Int64}, InfiniteArrays.InfUnitRange{Int64}}, false}}) is ambiguous.
Candidates:
BroadcastStyle(::Type{<:SubArray{<:Any, 2, <:BandedMatrices.AbstractBandedMatrix, <:Tuple{AbstractUnitRange{Int64}, AbstractUnitRange{Int64}}}})
@ BandedMatrices C:\Users\User\.julia\packages\BandedMatrices\as2PJ\src\generic\broadcast.jl:40
BroadcastStyle(::Type{<:SubArray{<:Any, 2, <:Any, <:Tuple{var"#s2", var"#s1"} where {var"#s2"<:(Union{Base.Slice{OneToInf{T}}, InfiniteArrays.AbstractInfUnitRange{T}, InfiniteArrays.InfStepRange{T}} where T<:Integer), var"#s1"<:(Union{Base.Slice{OneToInf{T}}, InfiniteArrays.AbstractInfUnitRange{T}, InfiniteArrays.InfStepRange{T}} where T<:Integer)}}})
@ InfiniteArrays C:\Users\User\.julia\packages\InfiniteArrays\7v9AI\src\infrange.jl:489
Possible fix, define
BroadcastStyle(::Type{<:SubArray{<:Any, 2, <:BandedMatrices.AbstractBandedMatrix, <:Tuple{var"#s2", var"#s1"} where {var"#s2"<:Union{InfiniteArrays.AbstractInfUnitRange{Int64}, Base.Slice{OneToInf{T}} where T<:Integer}, var"#s1"<:Union{InfiniteArrays.AbstractInfUnitRange{Int64}, Base.Slice{OneToInf{T}} where T<:Integer}}}})
Stacktrace:
[1] combine_styles(c::SubArray{Float64, 2, LazyBandedMatrices.Tridiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}, Fill{Float64, 1, Tuple{OneToInf{Int64}}}}, Tuple{InfiniteArrays.InfUnitRange{Int64}, InfiniteArrays.InfUnitRange{Int64}}, false})
@ Base.Broadcast .\broadcast.jl:460
[2] broadcasted
@ .\broadcast.jl:1341 [inlined]
[3] _broadcastarray2broadcasted
@ C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:73 [inlined]
[4] _broadcastarray2broadcasted
@ C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:79 [inlined]
[5] _broadcasted
@ C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:80 [inlined]
[6] sub_materialize(::LazyArrays.BroadcastLayout{typeof(exp)}, A::SubArray{Float64, 2, BroadcastMatrix{Float64, typeof(exp), Tuple{LazyBandedMatrices.Tridiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}, Fill{Float64, 1, Tuple{OneToInf{Int64}}}}}}, Tuple{InfiniteArrays.InfUnitRange{Int64}, InfiniteArrays.InfUnitRange{Int64}}, false})
@ LazyArrays C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:97
[7] sub_materialize
@ C:\Users\User\.julia\packages\ArrayLayouts\feBnP\src\ArrayLayouts.jl:126 [inlined]
[8] layout_getindex
@ C:\Users\User\.julia\packages\ArrayLayouts\feBnP\src\ArrayLayouts.jl:132 [inlined]
[9] getindex(A::BroadcastMatrix{Float64, typeof(exp), Tuple{LazyBandedMatrices.Tridiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}, Fill{Float64, 1, Tuple{OneToInf{Int64}}}}}}, kr::InfiniteArrays.InfUnitRange{Int64}, jr::InfiniteArrays.InfUnitRange{Int64})
@ ArrayLayouts C:\Users\User\.julia\packages\ArrayLayouts\feBnP\src\ArrayLayouts.jl:147
[10] macro expansion
@ C:\Users\User\.julia\juliaup\julia-1.10.3+0.x64.w64.mingw32\share\julia\stdlib\v1.10\Test\src\Test.jl:669 [inlined]
[11] macro expansion
@ C:\Users\User\.julia\dev\InfiniteLinearAlgebra.jl\test\test_infbanded.jl:66 [inlined]
[12] macro expansion
@ C:\Users\User\.julia\juliaup\julia-1.10.3+0.x64.w64.mingw32\share\julia\stdlib\v1.10\Test\src\Test.jl:1577 [inlined]
[13] macro expansion
@ C:\Users\User\.julia\dev\InfiniteLinearAlgebra.jl\test\test_infbanded.jl:35 [inlined]
[14] macro expansion
@ C:\Users\User\.julia\juliaup\julia-1.10.3+0.x64.w64.mingw32\share\julia\stdlib\v1.10\Test\src\Test.jl:1577 [inlined]
[15] top-level scope
@ C:\Users\User\.julia\dev\InfiniteLinearAlgebra.jl\test\test_infbanded.jl:7
∞-Toeplitz: Error During Test at C:\Users\User\.julia\dev\InfiniteLinearAlgebra.jl\test\test_infbanded.jl:71
Test threw exception
Expression: exp.(B)[2:∞, 3:∞] isa SubArray
MethodError: BroadcastStyle(::Type{SubArray{Float64, 2, LazyBandedMatrices.Bidiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}}, Tuple{InfiniteArrays.InfUnitRange{Int64}, InfiniteArrays.InfUnitRange{Int64}}, false}}) is ambiguous.
Candidates:
BroadcastStyle(::Type{<:SubArray{<:Any, 2, <:BandedMatrices.AbstractBandedMatrix, <:Tuple{AbstractUnitRange{Int64}, AbstractUnitRange{Int64}}}})
@ BandedMatrices C:\Users\User\.julia\packages\BandedMatrices\as2PJ\src\generic\broadcast.jl:40
BroadcastStyle(::Type{<:SubArray{<:Any, 2, <:Any, <:Tuple{var"#s2", var"#s1"} where {var"#s2"<:(Union{Base.Slice{OneToInf{T}}, InfiniteArrays.AbstractInfUnitRange{T}, InfiniteArrays.InfStepRange{T}} where T<:Integer), var"#s1"<:(Union{Base.Slice{OneToInf{T}}, InfiniteArrays.AbstractInfUnitRange{T}, InfiniteArrays.InfStepRange{T}} where T<:Integer)}}})
@ InfiniteArrays C:\Users\User\.julia\packages\InfiniteArrays\7v9AI\src\infrange.jl:489
Possible fix, define
BroadcastStyle(::Type{<:SubArray{<:Any, 2, <:BandedMatrices.AbstractBandedMatrix, <:Tuple{var"#s2", var"#s1"} where {var"#s2"<:Union{InfiniteArrays.AbstractInfUnitRange{Int64}, Base.Slice{OneToInf{T}} where T<:Integer}, var"#s1"<:Union{InfiniteArrays.AbstractInfUnitRange{Int64}, Base.Slice{OneToInf{T}} where T<:Integer}}}})
Stacktrace:
[1] combine_styles(c::SubArray{Float64, 2, LazyBandedMatrices.Bidiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}}, Tuple{InfiniteArrays.InfUnitRange{Int64}, InfiniteArrays.InfUnitRange{Int64}}, false})
@ Base.Broadcast .\broadcast.jl:460
[2] broadcasted
@ .\broadcast.jl:1341 [inlined]
[3] _broadcastarray2broadcasted
@ C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:73 [inlined]
[4] _broadcastarray2broadcasted
@ C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:79 [inlined]
[5] _broadcasted
@ C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:80 [inlined]
[6] sub_materialize(::LazyArrays.BroadcastLayout{typeof(exp)}, A::SubArray{Float64, 2, BroadcastMatrix{Float64, typeof(exp), Tuple{LazyBandedMatrices.Bidiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}}}}, Tuple{InfiniteArrays.InfUnitRange{Int64}, InfiniteArrays.InfUnitRange{Int64}}, false})
@ LazyArrays C:\Users\User\.julia\packages\LazyArrays\MLFsy\src\lazybroadcasting.jl:97
[7] sub_materialize
@ C:\Users\User\.julia\packages\ArrayLayouts\feBnP\src\ArrayLayouts.jl:126 [inlined]
[8] layout_getindex
@ C:\Users\User\.julia\packages\ArrayLayouts\feBnP\src\ArrayLayouts.jl:132 [inlined]
[9] getindex(A::BroadcastMatrix{Float64, typeof(exp), Tuple{LazyBandedMatrices.Bidiagonal{Float64, Fill{Float64, 1, Tuple{OneToInf{Int64}}}, Zeros{Float64, 1, Tuple{OneToInf{Int64}}}}}}, kr::InfiniteArrays.InfUnitRange{Int64}, jr::InfiniteArrays.InfUnitRange{Int64})
@ ArrayLayouts C:\Users\User\.julia\packages\ArrayLayouts\feBnP\src\ArrayLayouts.jl:147
[10] macro expansion
@ C:\Users\User\.julia\juliaup\julia-1.10.3+0.x64.w64.mingw32\share\julia\stdlib\v1.10\Test\src\Test.jl:669 [inlined]
[11] macro expansion
@ C:\Users\User\.julia\dev\InfiniteLinearAlgebra.jl\test\test_infbanded.jl:71 [inlined]
[12] macro expansion
@ C:\Users\User\.julia\juliaup\julia-1.10.3+0.x64.w64.mingw32\share\julia\stdlib\v1.10\Test\src\Test.jl:1577 [inlined]
[13] macro expansion
@ C:\Users\User\.julia\dev\InfiniteLinearAlgebra.jl\test\test_infbanded.jl:35 [inlined]
[14] macro expansion
@ C:\Users\User\.julia\juliaup\julia-1.10.3+0.x64.w64.mingw32\share\julia\stdlib\v1.10\Test\src\Test.jl:1577 [inlined]
[15] top-level scope
@ C:\Users\User\.julia\dev\InfiniteLinearAlgebra.jl\test\test_infbanded.jl:7 |
I guess you figured out that it was fixed on master? a change in lazy arrays triggered an ambiguity error unfortunately |
Yeah, didn't notice that it was updated. I brought the changes in but it didn't merge as I expected so I just applied it again in b4a38a7. |
This PR implements reverse Cholesky for symmetric Tridiagonal matrices. The algorithm is based on Section 3.2 here. In particular, letting
where$\boldsymbol A_N \in \mathbb R^{N \times N}$ and $\boldsymbol E_{ij}$ is the matrix whose only non-zero entry is $e_{ij} = 1$ , we can show that
where$\boldsymbol A_N = \boldsymbol L_N^\top \boldsymbol L_N$ , $\boldsymbol P_n = \mathrm{diag}(\boldsymbol I_n, \boldsymbol 0)$ , $n$ is the size of the finite section we need to access, and
where
Thus, for a given$\varepsilon > 0$ (here I default to $\varepsilon=|b_N|\sqrt{10^{-5}})$ , if $|\boldsymbol \xi_n| < \varepsilon$ then we say that the $n \times n$ finite section has been well approximated and the code for expanding stops. When the factor is indexed at a greater $n$ than previously requested, the factor expands as needed. The reverse Cholesky for finite matrices is computed simply according to
where$\boldsymbol A_{n-1} = \boldsymbol L_{n-1}^\top\boldsymbol L_{n-1}$ .