# How to get upper triangular Cholesky factor of sparse matrix?

**URL:** <https://discourse.julialang.org/t/how-to-get-upper-triangular-cholesky-factor-of-sparse-matrix/129979>\
**Category:** Numerics\
**Created:** [June 18, 2025, 12:34am UTC](https://discourse.julialang.org/t/how-to-get-upper-triangular-cholesky-factor-of-sparse-matrix/129979 "2025-06-18T00:34:36Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![slwu89](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/slwu89/32/217323_2.png) [@slwu89](https://discourse.julialang.org/u/slwu89)\
**Post date:** [June 18, 2025, 12:34am UTC](https://discourse.julialang.org/t/how-to-get-upper-triangular-cholesky-factor-of-sparse-matrix/129979/1 "2025-06-18T00:34:36Z")

</div>

Hi all. I read the documentation here [Linear Algebra · The Julia Language](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.cholesky) for what is returned when you call `cholesky` on a `SparseMatrixCSC` object but I still can’t figure out how to get back the upper triangular factor of the (non permuted) matrix. The docs say to use `LtP = F.UP` but whatever is returned by the field `UP` is not being converted into what I want by calling `sparse` or `Matrix` on it. Can someone help me figure out how to do this? MWE below:

```julia
A=[ 10.0 2.0 0.0 -2.0 0.0 -4.0 0.0 0.0;
         2.0 2.0 0.0 -2.0 0.0 0.0 0.0 0.0;
         0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0;
        -2.0 -2.0 0.0 6.0 -2.0 -2.0 0.0 0.0;
         0.0 0.0 0.0 -2.0 20.0 8.0 -8.0 -8.0;
        -4.0 0.0 0.0 -2.0 8.0 8.0 -4.0 -4.0;
         0.0 0.0 0.0 0.0 -8.0 -4.0 8.0 0.0;
         0.0 0.0 0.0 0.0 -8.0 -4.0 0.0 8.0];
A = sparse(A)
C = cholesky(A)
sparse(C.UP) # error
Matrix(C.UP) # error

```

---

<div class="post-metadata">

**Author:** ![technocrat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/technocrat/32/220947_2.png) [@technocrat](https://discourse.julialang.org/u/technocrat)\
**Post date:** [June 18, 2025, 4:48am UTC](https://discourse.julialang.org/t/how-to-get-upper-triangular-cholesky-factor-of-sparse-matrix/129979/2 "2025-06-18T04:48:39Z")

</div>

```julia
using SparseArrays, LinearAlgebra

A = sparse([10.0 2.0 0.0 -2.0 0.0 -4.0 0.0 0.0;
            2.0 2.0 0.0 -2.0 0.0 0.0 0.0 0.0;
            0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0;
            -2.0 -2.0 0.0 6.0 -2.0 -2.0 0.0 0.0;
            0.0 0.0 0.0 -2.0 20.0 8.0 -8.0 -8.0;
            -4.0 0.0 0.0 -2.0 8.0 8.0 -4.0 -4.0;
            0.0 0.0 0.0 0.0 -8.0 -4.0 8.0 0.0;
            0.0 0.0 0.0 0.0 -8.0 -4.0 0.0 8.0])

C = cholesky(A)

# Option 1: Upper triangular factor in permuted space
U_permuted = sparse(C.L)' 

# Option 2: Upper triangular factor in original space
perm = C.p
invperm_vec = invperm(perm)
L_original = sparse(C.L)[invperm_vec, invperm_vec]
U_original = L_original'

# Verify the factorizations
P = sparse(1:8, perm, ones(8))

# In permuted space: P*A*P' = L_permuted * U_permuted
println("Error in permuted space: ", norm(P*A*P' - sparse(C.L)*U_permuted))

# In original space: A = L_original * U_original
println("Error in original space: ", norm(A - L_original*U_original))

```

You need to take this with the huge qualification that I’m not even sure that this was covered when I took my maths as an undergrad in the 60s.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [June 18, 2025, 5:26am UTC](https://discourse.julialang.org/t/how-to-get-upper-triangular-cholesky-factor-of-sparse-matrix/129979/3 "2025-06-18T05:26:23Z")

</div>

It’s poorly documented, but `C.L` is the only factor that supports being directly converted to a (sparse) matrix, so you need to do the permutation and transposition yourself, as @technocrat showed. However, you don’t need to permute the second dimension of `L`— it’s contracted over anyway, so its order is irrelevant as long as it’s consistent between the two factors. Thus, what you want is `PtL = sparse(C.L)[invperm(p), :]`, and, if desired, `UP = PtL'`.

```julia-repl
julia> using SparseArrays, LinearAlgebra

julia> A = sparse([10.0 2.0 0.0 -2.0 0.0 -4.0 0.0 0.0;
                   2.0 2.0 0.0 -2.0 0.0 0.0 0.0 0.0;
                   0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0;
                   -2.0 -2.0 0.0 6.0 -2.0 -2.0 0.0 0.0;
                   0.0 0.0 0.0 -2.0 20.0 8.0 -8.0 -8.0;
                   -4.0 0.0 0.0 -2.0 8.0 8.0 -4.0 -4.0;
                   0.0 0.0 0.0 0.0 -8.0 -4.0 8.0 0.0;
                   0.0 0.0 0.0 0.0 -8.0 -4.0 0.0 8.0]);

julia> C = cholesky(A);

julia> L = sparse(C.L);

julia> PtL = L[invperm(C.p), :];

julia> PtL * PtL'
8×8 SparseMatrixCSC{Float64, Int64} with 30 stored entries:
 10.0 2.0 ⋅ -2.0 ⋅ -4.0 ⋅ ⋅
  2.0 2.0 ⋅ -2.0 ⋅ ⋅ ⋅ ⋅
   ⋅ ⋅ 2.0 ⋅ ⋅ ⋅ ⋅ ⋅
 -2.0 -2.0 ⋅ 6.0 -2.0 -2.0 ⋅ ⋅
   ⋅ ⋅ ⋅ -2.0 20.0 8.0 -8.0 -8.0
 -4.0 ⋅ ⋅ -2.0 8.0 8.0 -4.0 -4.0
   ⋅ ⋅ ⋅ ⋅ -8.0 -4.0 8.0 ⋅
   ⋅ ⋅ ⋅ ⋅ -8.0 -4.0 ⋅ 8.0

```

---

<div class="post-metadata">

**Author:** ![slwu89](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/slwu89/32/217323_2.png) [@slwu89](https://discourse.julialang.org/u/slwu89)\
**Post date:** [June 18, 2025, 1:22pm UTC](https://discourse.julialang.org/t/how-to-get-upper-triangular-cholesky-factor-of-sparse-matrix/129979/4 "2025-06-18T13:22:34Z")

</div>

Many thanks to @technocrat and @danielwe.
