Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does LDLt function from LinearAlgebra package only work with SymTriDiagonal matrices?

I am studying LDL^t factorization of a symmetric matrix. My own code works correctly, however, when I want to use LDLt function from LinearAlgebra package, the following code does not work

using LinearAlgebra

A = [5.0 1 0 0 0; 1 5 1 0 0; 0 1 5 1 0; 0 0 1 5 1; 0 0 0 1 5]

ldltS = LDLt(A)

display(ldltS)

Julia reports the error "ERROR: LoadError: type Array has no field dv".

If instead of A as in the above code, I build A with SymTriDiagonal, then the code above works.

like image 414
Nick Avatar asked Nov 23 '25 23:11

Nick


1 Answers

your code works, try:

ldltS = LDLt(A);

However the documentation for LDLt reads:

Matrix factorization type of the LDLt factorization of a real SymTridiagonal matrix S

If you want to force it to work with regular matrices the problem is that show displays the object assuming it to be a SymTridiagonal matrix. See the getproperty method in LinearAlgebra\src\ldlt.jl:

function getproperty(F::LDLt, d::Symbol)      
    Fdata = getfield(F, :data)                
    if d === :d                               
        return Fdata.dv                       
    elseif d === :D                           
        return Diagonal(Fdata.dv)             
    elseif d === :L                           
        return UnitLowerTriangular(Fdata)     
    elseif d === :Lt                          
        return UnitUpperTriangular(Fdata)     
    else                                      
        return getfield(F, d)                 
    end                                       
end

The line:

return Diagonal(Fdata.dv)             

could be replaced with

return Diagonal(Fdata)             

You could just overwrite this function:

julia> function Base.getproperty(F::LDLt, d::Symbol)
           Fdata = getfield(F, :data)
           if d === :d
               return Fdata.dv
           elseif d === :D
               return Diagonal(Fdata)
           elseif d === :L
               return UnitLowerTriangular(Fdata)
           elseif d === :Lt
               return UnitUpperTriangular(Fdata)
           else
               return getfield(F, d)
           end
       end

now it works (with regards that algebra in LDLt assumes that this is a SymTridiagonal matrix) :

julia> ldltS
LDLt{Float64, Matrix{Float64}}
L factor:
5×5 UnitLowerTriangular{Float64, Matrix{Float64}}:
 1.0   ⋅    ⋅    ⋅    ⋅
 1.0  1.0   ⋅    ⋅    ⋅
 0.0  1.0  1.0   ⋅    ⋅
 0.0  0.0  1.0  1.0   ⋅
 0.0  0.0  0.0  1.0  1.0
D factor:
5×5 Diagonal{Float64, Vector{Float64}}:
 5.0   ⋅    ⋅    ⋅    ⋅
  ⋅   5.0   ⋅    ⋅    ⋅
  ⋅    ⋅   5.0   ⋅    ⋅
  ⋅    ⋅    ⋅   5.0   ⋅
  ⋅    ⋅    ⋅    ⋅   5.0
like image 178
Przemyslaw Szufel Avatar answered Nov 26 '25 20:11

Przemyslaw Szufel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!