# Pivoted Cholesky: Why is rank a private field/property?

**URL:** <https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971>\
**Category:** Numerics\
**Tags:** linearalgebra\
**Created:** [November 22, 2024, 6:24pm UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971 "2024-11-22T18:24:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ajinkya-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ajinkya-k/32/213627_2.png) [@ajinkya-k](https://discourse.julialang.org/u/ajinkya-k)\
**Post date:** [November 22, 2024, 6:24pm UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971/1 "2024-11-22T18:24:35Z")

</div>

Hello! I am posting for the first time so please forgive me if this is naive.

I am using the `cholesky` function with pivoting to (1) factorize a positive semidefinite matrix, (2) get its rank, and (3) do some follow-up computations. When I ran `propertynames` on the `CholeskyPivoted` object, it did not show `rank` as a property. Eventually I figured out that rank can still be accessed by doing `Achol.rank`. See examples:

```julia
n = 20; r = 5 # dimensions of matrix

X = reshape(randn(n * r), n,r)
A = X*X' # rank deficient symmetric matrix

Achol = cholesky(A, RowMaximum(); check = false, tol=1e-8);

propertynames(Achol)
#output: (:U, :L, :p, :P)

Achol.rank
#output: 5

propertynames(Achol, true)
#output: (:U, :L, :p, :P, :factors, :uplo, :piv, :rank, :tol, :info)

getproperty(Achol, :rank)
#output: 5

```

My question: Why is the rank a private field for the pivoted cholesky?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 22, 2024, 7:06pm UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971/2 "2024-11-22T19:06:39Z")

</div>

> [@ajinkya-k](#):
>
> My question: Why is the rank a private field for the pivoted cholesky?

This is the `rank` return value of the [LAPACK `pstrf` function](https://www.netlib.org/lapack/explore-html-3.6.1/dd/dad/dpstrf_8f_a31cdc13a7f4ad687f4aefebff870e1cc.html) (Cholesky with complete pivoting).

I’m not sure how reliable a rank estimate this is? LU can be an unreliable way to compute rank, even with complete pivoting (see e.g. the [links in this discussion](https://discourse.julialang.org/t/how-to-find-the-linearly-independent-columns-rows-of-a-matrix/109772)), but I’m not sure if complete-pivoted Cholesky has the same issues.

In any case, it would be good if you could simply call `rank(Achol)` on the `CholeskyPivoted` object to access this, similar to how one can call `rank` [on the pivoted QR factorization](https://github.com/JuliaLang/julia/pull/54283) to get a QR-based rank estimate. Want to file an issue, or better yet a PR?

---

<div class="post-metadata">

**Author:** ![ajinkya-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ajinkya-k/32/213627_2.png) [@ajinkya-k](https://discourse.julialang.org/u/ajinkya-k)\
**Post date:** [November 22, 2024, 8:00pm UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971/3 "2024-11-22T20:00:55Z")

</div>

@stevengj Thanks! I think the `rank(Achol)` function already exists, so an issue (or PR) is not needed for that. I was only trying to understand why this is not a public property.

Did you mean I should submit an issue (or PR) to show rank in the list of symbols when `propertynames(Achol)` is called? If so I would be happy to give a PR a shot!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 22, 2024, 8:15pm UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971/4 "2024-11-22T20:15:24Z")

</div>

> [@ajinkya-k](#):
>
> I think the `rank(Achol)` function already exists,

Oh right, and it is even documented in the `CholeskyPivoted` docstring. So nothing to do.

I think that since there is a documented API, and it is the standard `rank` function that is used for other matrices and factorizations, that is preferred to accessing internal fields (which might conceivably change).

---

<div class="post-metadata">

**Author:** ![mstewart](https://avatars.discourse-cdn.com/v4/letter/m/b5a626/32.png) [@mstewart](https://discourse.julialang.org/u/mstewart)\
**Post date:** [November 22, 2024, 8:58pm UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971/5 "2024-11-22T20:58:44Z")

</div>

> [@stevengj](#):
>
> I’m not sure how reliable a rank estimate this is? LU can be an unreliable way to compute rank, even with complete pivoting (see e.g. the [links in this discussion](https://discourse.julialang.org/t/how-to-find-the-linearly-independent-columns-rows-of-a-matrix/109772)), but I’m not sure if complete-pivoted Cholesky has the same issues.

It’s not the SVD and the error bounds do have factors that grow exponentially with rank, but it’s actually reliable enough in practice that you can consider it to be stable at the same level as QR factorization with column pivoting. (And in fact Cholesky with diagonal pivoting on A^T A corresponds to QR with column pivoting on A). This [paper](https://eprints.maths.manchester.ac.uk/1193/1/high90c.pdf) gives an analysis of truncating a pivoted Cholesky factorization. It also includes material on QR factorization with column pivoting and LU with complete pivoting. They are all sort of in the same league of rank determination algorithms that have annoying exponential factors in their error bounds but for which the quantities the exponential factors bound are typically small in practice except on carefully constructed examples. It’s analogous to observing exponential element growth in Gaussian elimination with partial pivoting.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [November 22, 2024, 11:46pm UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971/6 "2024-11-22T23:46:15Z")

</div>

> [@ajinkya-k](#):
>
> My question: Why is the rank a private field for the pivoted cholesky?

In general, _all_ fields of objects are internal and subject to change without notice. Unless explicitly documented, that is. But I would never access an internal field of an object, even when documented as public, unless strictly necessary, and even then only grudgingly.

Public fields in Julia always seem out of place and un-idiomatic (imo), since the language _nearly_ universally promotes functional interfaces to objects. If in this case there is a working `rank` function, it makes perfect sense to hide the internal `rank` field to discourage field access.

---

<div class="post-metadata">

**Author:** ![ajinkya-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ajinkya-k/32/213627_2.png) [@ajinkya-k](https://discourse.julialang.org/u/ajinkya-k)\
**Post date:** [November 23, 2024, 7:06am UTC](https://discourse.julialang.org/t/pivoted-cholesky-why-is-rank-a-private-field-property/122971/7 "2024-11-23T07:06:35Z")

</div>

Thanks for sharing the reference.
