Skip to content
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

LU decomposition #272

Open
eschnett opened this issue Sep 29, 2022 · 4 comments
Open

LU decomposition #272

eschnett opened this issue Sep 29, 2022 · 4 comments

Comments

@eschnett
Copy link

I needed to invert large banded matrices, and I found that BandedMatrices.jl didn't support this operation. For example:

julia> using LinearAlgebra
julia> using BandedMatrices

julia> B = brand(Int8, 5, 5, 2, 2)
5×5 BandedMatrix{Int8} with bandwidths (2, 2):
 68  -17   -36         
  2  -88  -118    83    
 83    8   -47    52   83
     -6   -44  -116   98
          57  -104  -87

julia> lu(B)
BandedMatrices.BandedLU{Float64, BandedMatrix{Float64, Matrix{Float64}, Base.OneTo{Int64}}}
L factor:
5×5 Matrix{Float64}:
  1.0           0.0           0.0       0.0        0.0
  0.0240964     1.0           0.0       0.0        0.0
  5.7603e-16   -1.33319e-16   1.0       0.0        0.0
 -3.15648e-16   0.0680328    -0.632442  1.0        0.0
  0.819277      0.267077      0.591554  0.0155523  1.0
U factor:
5×5 BandedMatrix{Float64} with bandwidths (2, 4):
 83.0    8.0      -47.0      52.0     83.0
  0.0  -88.1928  -116.867    81.747   -2.0
  0.0    0.0       57.0    -104.0    -87.0
        0.0        0.0    -187.335   43.1136
                  0.0       0.0    -16.6712

This uses a full matrix to store L, which is not good for me.

Similarly, when using rational numbers, I found that

julia> B = Rational{BigInt}.(brand(Int8, 5, 5, 2, 2))
5×5 BandedMatrix{Rational{BigInt}} with bandwidths (2, 2):
 -128//1  -64//1   74//1             
   27//1  113//1  115//1   -88//1     
  -10//1   87//1   51//1  -106//1  -67//1
          -6//1  -48//1   -43//1  -47//1
                 29//1   -93//1   71//1

julia> lu(B)
ERROR: UndefVarError: banded_lufact! not defined

I have taken the liberty of implementing the functionality that I need outside of BandedMatrices.jl. See here for the functions I implemented.

The respective functionality is good enough for me, but is not quite generic. For example, I implemented \ to solve a linear system, but not an in-place ldiv!. These functions also don't support a banded RHS for \.

I would be happy to contribute this to BandedMatrices.jl. If you are interested, then please let me know how this could/should be integrated into your package. Otherwise, feel free to copy the code I wrote. This code is inspired (copied/translated) from Wikipedia (see the URL above), LAPACK (dtrsm), and the Julia LinearAlgebra package.

@dlfivefifty
Copy link
Member

Yes please! I believe the issue is that LU is currently only implemented in LAPACK so a Julia native implementation would be fantastic

@eschnett
Copy link
Author

eschnett commented Oct 4, 2022

I've looked at the code for LU decomposition in BandedMatrices.jl, and it's not clear to me which part of the code would need to stay and which part should be rewritten. It seems that some LU decomposition functionality is there, but it's not implemented in an ideal way – e.g. it seems the L factor is full instead of banded.

  • Is the type BandedLU necessary? It seems that the Base LU type would suffice.
  • Should the pivot search remain? A pivot search destroys the band structure. One could remove it, and ask people to convert to a full matrix if they want a pivot search.
  • I am interested in supporting types that are not supported by LAPACK. Would it make sense to remove the calls to LAPACK, implementing the respective functions in Julia?
  • A comment in the function lu! states "l of the bands are ignored and overwritten". That seems weird. The problem seems to be that the LAPACK function dgbsv allows (and here requires) over-allocating storage, which is not supported by this package. If there is no functionality to resize banded matrices without de-allocating storage, then filling the extra bands with zeros might be a good approach?

@dlfivefifty
Copy link
Member

I suggest you read the docs on LAPACK's gbtrf:

https://netlib.org/lapack/explore-html/d2/d2d/group__double_g_bcomputational_ga7fc91ba3f250ad3844eba25d59f5d7be.html

Is the type BandedLU necessary? It seems that the Base LU type would suffice.

Yes since gbtrf does not actually permute the rows in memory (as that would destroy banded structure), instead it just records where the pivots were. So it's not the same format as LinearAlgebra.LU.

Should the pivot search remain? A pivot search destroys the band structure. One could remove it, and ask people to convert to a full matrix if they want a pivot search.

Yes because you maintain bandedness if you do what LAPACK does.

I am interested in supporting types that are not supported by LAPACK. Would it make sense to remove the calls to LAPACK, implementing the respective functions in Julia?

No, still use LAPACK for BLAS types. Only use the Julia implementation for general types. You can use BigFloat as a test.

A comment in the function lu! states "l of the bands are ignored and overwritten". That seems weird. The problem seems to be that the LAPACK function dgbsv allows (and here requires) over-allocating storage, which is not supported by this package. If there is no functionality to resize banded matrices without de-allocating storage, then filling the extra bands with zeros might be a good approach?

I don't agree: we do allow overallocating storage, e.g., if the data is a (strided) view of a bigger array.

@j-fu
Copy link

j-fu commented Feb 21, 2023

Hi, FYI: I did some similar job for dgemm etc in sparspak: https://github.com/PetrKryslUCSD/Sparspak.jl/blob/main/src/Utilities/GenericBlasLapackFragments.jl

This was based on the netlib fortran code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants