# LinearAlgebra: rank

**URL:** <https://discourse.julialang.org/t/linearalgebra-rank/67763>\
**Category:** General Usage\
**Tags:** linearalgebra\
**Created:** [September 6, 2021, 4:12pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763 "2021-09-06T16:12:24Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![unhandyandy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/unhandyandy/32/7634_2.png) [@unhandyandy](https://discourse.julialang.org/u/unhandyandy)\
**Post date:** [September 6, 2021, 4:12pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/1 "2021-09-06T16:12:24Z")

</div>

What exactly does the rank function compute? I thought it would give the number of llinearly independent rows in a matrix, but evidently not.

Here `cov` is a 138x138 matrix.

```julia
1|julia> rank(cov[1:20,1:20])
20

1|julia> rank(cov)
13

```

Shouldn’t that be impossible?

---

<div class="post-metadata">

**Author:** ![zdenek\_hurak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zdenek_hurak/32/53118_2.png) [@zdenek\_hurak](https://discourse.julialang.org/u/zdenek_hurak)\
**Post date:** [September 6, 2021, 5:08pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/2 "2021-09-06T17:08:33Z")

</div>

Indeed, this looks weird.

At first I thought that you may have introduced some problems by using the name of the function [cov](https://docs.julialang.org/en/v1/stdlib/Statistics/#Statistics.cov) from the standard [Statistics](https://docs.julialang.org/en/v1/stdlib/Statistics/) library, but unless you import it, you are free to call your matrix `cov`.

Do you think it is possible to share you matrix somehow? Do you generate it through a code? In general, [it is really useful to share a minimum working example](https://discourse.julialang.org/t/please-read-make-it-easier-to-help-you/14757) (including the imports/`using` of the packages) because who knows where you take your function `rank` from. I certainly cannot reproduce the problem with some randomly generated singular matrix.

```julia
julia> using LinearAlgebra: rank

julia> A = rand(13,138);

julia> X = A'*A
138×138 Matrix{Float64}:
 6.37017 3.87032 3.7639 2.93673 3.90856 2.89665 … 3.58424 4.81491 2.77375 3.95746 4.24206
 3.87032 4.4881 3.17356 3.16758 3.26719 2.35837 3.2946 4.02962 2.37569 3.14432 2.57209
 3.7639 3.17356 4.64649 3.36158 2.97343 2.63004 4.15317 4.36145 3.35719 2.9598 4.12072
 2.93673 3.16758 3.36158 3.80284 2.74161 2.42185 3.45357 3.46843 2.79067 2.18312 2.65219
 3.90856 3.26719 2.97343 2.74161 3.84898 2.41936 3.0891 3.70304 2.32024 2.98657 3.03344
 2.89665 2.35837 2.63004 2.42185 2.41936 2.40715 … 2.71721 3.39881 2.12739 2.21862 2.54849
 5.21516 4.57535 4.43188 4.21679 3.69402 3.22894 4.32022 5.20635 3.58125 4.07824 4.01366
 ⋮ ⋮ ⋱ ⋮                 
 4.42637 4.1324 3.98606 3.16609 3.45972 2.20833 3.65279 4.18168 2.93238 3.29186 3.46011
 3.58424 3.2946 4.15317 3.45357 3.0891 2.71721 4.12401 4.17301 3.20623 2.70909 3.51342
 4.81491 4.02962 4.36145 3.46843 3.70304 3.39881 4.17301 5.53489 3.24436 3.89468 4.29279
 2.77375 2.37569 3.35719 2.79067 2.32024 2.12739 … 3.20623 3.24436 2.90164 2.27987 2.93651
 3.95746 3.14432 2.9598 2.18312 2.98657 2.21862 2.70909 3.89468 2.27987 3.79522 3.11997
 4.24206 2.57209 4.12072 2.65219 3.03344 2.54849 3.51342 4.29279 2.93651 3.11997 4.53387

julia> rank(X)
13

julia> rank(X[1:20,1:20])
13

```

---

<div class="post-metadata">

**Author:** ![unhandyandy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/unhandyandy/32/7634_2.png) [@unhandyandy](https://discourse.julialang.org/u/unhandyandy)\
**Post date:** [September 6, 2021, 5:35pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/3 "2021-09-06T17:35:46Z")

</div>

What’s a good way to share a 138x138 matrix?

Btw, could this matrix just be too large for the LinearAlgebra package?

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [September 6, 2021, 6:09pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/4 "2021-09-06T18:09:59Z")

</div>

@unhandyandy: `rank(A)` computes the number of singular values of A that are above a given tolerance.

```julia
help?> rank
search: rank RankDeficientException lowrankupdate lowrankupdate! lowrankdowndate

  rank(A::AbstractMatrix; atol::Real=0, rtol::Real=atol>0 ? 0 : n*ϵ)
  rank(A::AbstractMatrix, rtol::Real)

  Compute the rank of a matrix by counting how many singular values of A have
  magnitude greater than max(atol, rtol*σ₁) where σ₁ is A's largest singular
  value. atol and rtol are the absolute and relative tolerances, respectively.
  The default relative tolerance is n*ϵ, where n is the size of the smallest
  dimension of A, and ϵ is the eps of the element type of A.

```

---

<div class="post-metadata">

**Author:** ![unhandyandy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/unhandyandy/32/7634_2.png) [@unhandyandy](https://discourse.julialang.org/u/unhandyandy)\
**Post date:** [September 6, 2021, 6:22pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/5 "2021-09-06T18:22:22Z")

</div>

> > ![](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/45/5321_2.png "John\_Gibson") | [John\_Gibson](https://discourse.julialang.org/u/john_gibson)  
> > September 6 |
> > 
> > - | - |
> 
> `
> 
> ```julia
> 
> ```
> 
> `
> 
> Try computing the singular values of your 20 x 20 submatrix. I’ll bet seven of them are very close to zero., meaning your matrix is effectively rank 13 in 64-bit floating point artithmetic.

1. Then why did Julia compute the rank to be 20 instead of 13?
2. The default tolerence is zero.

> [@zdenek\_hurak](https://discourse.julialang.org/u/zdenek_hurak): Did you mean to type `A = rand(138,138)` instead of `A = rand(13,138)`?

No, he used A to form A’\*A, which he knew would have rank 13.

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [September 6, 2021, 6:27pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/6 "2021-09-06T18:27:35Z")

</div>

Here’s a simple example illustrating the behavior you see with your `cov` matrix

```julia
julia> A = randn(5,5);

julia> A[1:5,1:3] = 1e-32*randn(5,3);

julia> rank(A)
2

julia> rank(A[1:3,1:3])
3

```

The issue is that the submatrix is well-conditioned but the full matrix is not:

```julia
julia> svdvals(A)
5-element Vector{Float64}:
 2.8403134593841486
 1.883573969215261
 1.5494894381007906e-16
 9.045455141730465e-17
 1.0078154590482648e-32

julia> svdvals(A[1:3,1:3])
3-element Vector{Float64}:
 3.9530622919506925e-32
 1.2513920009022788e-32
 1.9253723883320212e-33

julia> cond(A[1:3,1:3])
20.531416758164323

julia> cond(A)
2.8182872507893575e32

```

Sorry about earlier edits. I misread your original post and didn’t see the issue correcty.

---

<div class="post-metadata">

**Author:** ![unhandyandy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/unhandyandy/32/7634_2.png) [@unhandyandy](https://discourse.julialang.org/u/unhandyandy)\
**Post date:** [September 6, 2021, 6:28pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/7 "2021-09-06T18:28:54Z")

</div>

I see, thank you.

---

<div class="post-metadata">

**Author:** ![zdenek\_hurak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zdenek_hurak/32/53118_2.png) [@zdenek\_hurak](https://discourse.julialang.org/u/zdenek_hurak)\
**Post date:** [September 6, 2021, 7:05pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/8 "2021-09-06T19:05:32Z")

</div>

Perfect. Thanks. I have composed even a tiny bit more explicit example that demonstrates the phenomenon:

```julia
julia> A = [1e-16 0 0; 0 1e-16 0; 0 0 1.0]
3×3 Matrix{Float64}:
 1.0e-16 0.0 0.0
 0.0 1.0e-16 0.0
 0.0 0.0 1.0

julia> rank(A)
1

julia> rank(A[1:2,1:2])
2

```

I confess I have learnt something. Another confirmation that one shouldn’t blindly rely on the (discontinuous) `rank` function – checking the singular values is a good practice.

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [September 6, 2021, 7:56pm UTC](https://discourse.julialang.org/t/linearalgebra-rank/67763/9 "2021-09-06T19:56:07Z")

</div>

That’s even better!
