# Can Not Use Triangular Matrix from Cholesky in Any Way

**URL:** https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207
**Category:** General Usage
**Tags:** linearalgebra
**Created:** [October 11, 2018, 10:00pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207 "2018-10-11T22:00:40Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![mcbro](https://avatars.discourse-cdn.com/v4/letter/m/77aa72/32.png) [@mcbro](https://discourse.julialang.org/u/mcbro)
#### Post date: [October 11, 2018, 10:00pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/1 "2018-10-11T22:00:40Z")

</div>

This is a regression in Julia 1.0. Consider this code

```julia
using LinearAlgebra
Umat = [4.10229+0.0im -0.00360251-2.02412im ; -0.00360251+2.02412im 1.30966+0.0im]
R = cholesky(Umat) ;
display(R)

V = Array(R) ;
display(V)

X = zeros(Complex{Float64}, 2, 2, 2) ;
X[2,:,:] = R ;

```

The output of this in Julia 1.0 is:

Cholesky{Complex{Float64},Array{Complex{Float64},2}}  
U factor:  
2×2 UpperTriangular{Complex{Float64},Array{Complex{Float64},2}}:  
2.02541+0.0im -0.00177866-0.999363im  
⋅ 0.557612+0.0im  
2×2 Array{Complex{Float64},2}:  
4.10229+0.0im -0.00360251-2.02412im  
-0.00360251+2.02412im 1.30966+0.0im  
ERROR: LoadError: MethodError: no method matching setindex\_shape\_check(::Cholesky{Complex{Float64},Array{Complex{Float64},2}}, ::Int64, ::Int64, ::Int64)  
Closest candidates are:  
setindex\_shape\_check(::AbstractArray, ::Integer…) at indices.jl:154  
setindex\_shape\_check(::AbstractArray{#s57,1} where #s57, ::Integer, ::Integer) at indices.jl:196  
setindex\_shape\_check(::AbstractArray{#s57,2} where #s57, ::Integer, ::Integer) at indices.jl:200  
…  
This code works perfectly in Julia 0.6.4 once cholesky is replaced with chol() and the using LinearAlgebra statement is removed.

So it appears that the Array() constructor fails to work with a triangular matrix as an argument. (It worked before). Furthermore there no longer appears to be a working auto-conversion to a dense matrix when I attempt to load the triangular matrix into a dense array.

Even worse, this fails  
convert(Array{ComplexF64,2}, R)  
with:

ERROR: MethodError: no method matching Array{Complex{Float64},2}(::Cholesky{Complex{Float64},Array{Complex{Float64},2}})  
How am I supposed to convert these matrices to regular dense arrays when I need to?

Furthermore no matrix operations work on triangular matrices namely,  
R’ \* R  
R+R  
R \* 2

etc.  
I believe the fact that convert(Array, R) does not work properly, is definitely a bug, but my issue was immediately closed.

This is a big step back in usability, unless there is yet another way to convert to a dense matrix that is somehow hidden in the documentation.

FYI it appears that the conversion routines suggested revert R back to R’ \* R  
thus  
Matrix ( R ) = R’ \* R  
How is this supposed to be helpful? There is no way to use the Cholesky factor at all with this convention.

---

<div class="post-metadata">

### Author: ![alejandromerchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alejandromerchan/32/10500_2.png) [@alejandromerchan](https://discourse.julialang.org/u/alejandromerchan)
#### Post date: [October 11, 2018, 10:17pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/2 "2018-10-11T22:17:42Z")

</div>

The usual response for this type of questions is to run the old code in Julia 0.7 to see the deprecations and try to correct them. If you have a code that works in 0.6.4, and doesn’t run at all in 0.7 without any deprecation warning, then there’s an issue. Most of these issues are due to some big changes in the names of functions and other things like that, I don’t think the functionality disappeared.

Also, try to enclose your code with three backticks (```), that helps readability.

---

<div class="post-metadata">

### Author: ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)
#### Post date: [October 11, 2018, 10:22pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/3 "2018-10-11T22:22:12Z")

</div>

Rather than

> [@mcbro](#):
>
> R = cholesky(Umat)

try

```julia
R = cholesky(Umat).U

```

The `cholesky` function returns a factorisation object from which you can get either the upper triangular part or lower triangular part as desired. See the docs at [https://docs.julialang.org/en/latest/stdlib/LinearAlgebra/#LinearAlgebra.cholesky](https://docs.julialang.org/en/latest/stdlib/LinearAlgebra/#LinearAlgebra.cholesky)

---

<div class="post-metadata">

### Author: ![mcbro](https://avatars.discourse-cdn.com/v4/letter/m/77aa72/32.png) [@mcbro](https://discourse.julialang.org/u/mcbro)
#### Post date: [October 11, 2018, 10:26pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/4 "2018-10-11T22:26:10Z")

</div>

I ran it in 0.7. You get the same problem. All conversions to dense matrices cause upper triangular R to be converted to R’ \* R. That has to be a bug.

The loading into the dense subarray has other issues. It claims that it’s broadcasting but it’s not. In fact X[2,:,:] = V does not complain at all, since V is an ordinary dense array.

---

<div class="post-metadata">

### Author: ![mcbro](https://avatars.discourse-cdn.com/v4/letter/m/77aa72/32.png) [@mcbro](https://discourse.julialang.org/u/mcbro)
#### Post date: [October 11, 2018, 10:29pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/5 "2018-10-11T22:29:27Z")

</div>

Why is the default conversion back to R’ \* R then?  
convert(Array, R) = R’ \* R essentially.

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [October 11, 2018, 10:33pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/6 "2018-10-11T22:33:26Z")

</div>

`cholesky(A)` does not return the upper (or lower) triangular factor. It returns a factorization object, which is just another representation of the original matrix `A`, so it is only natural that `convert(Array, cholesky(A))` returns something that is `==` to the original matrix.  
If you want the upper or lower triangular factor (i.e. what `chol` did in Julia v0.6) then you should use `cholesky(A).U` or `cholesky(A).L` respectively.

---

<div class="post-metadata">

### Author: ![dawbarton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dawbarton/32/215461_2.png) [@dawbarton](https://discourse.julialang.org/u/dawbarton)
#### Post date: [October 11, 2018, 10:41pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/7 "2018-10-11T22:41:49Z")

</div>

I’m not sure what you mean. You can use the upper triangular form in most matrix operations directly or convert it into a regular matrix as you want. For example,

```julia
julia> Umat = [4.10229+0.0im -0.00360251-2.02412im ; -0.00360251+2.02412im 1.30966+0.0im]
2×2 Array{Complex{Float64},2}:
     4.10229+0.0im -0.00360251-2.02412im
 -0.00360251+2.02412im 1.30966+0.0im    

julia> R = cholesky(Umat)
Cholesky{Complex{Float64},Array{Complex{Float64},2}}
U factor:
2×2 UpperTriangular{Complex{Float64},Array{Complex{Float64},2}}:
 2.02541+0.0im -0.00177866-0.999363im
         ⋅ 0.557612+0.0im     

julia> RU = Array(R.U)
2×2 Array{Complex{Float64},2}:
 2.02541+0.0im -0.00177866-0.999363im
     0.0+0.0im 0.557612+0.0im     

julia> RU'*RU ≈ Umat
true

```

---

<div class="post-metadata">

### Author: ![mcbro](https://avatars.discourse-cdn.com/v4/letter/m/77aa72/32.png) [@mcbro](https://discourse.julialang.org/u/mcbro)
#### Post date: [October 11, 2018, 10:46pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/8 "2018-10-11T22:46:26Z")

</div>

Well you’ve helped me inasmuch as I didn’t notice that the Cholesky factorization also became an object similar to the changes in qr(), thus I have to use the .U operation to get what I want.

However the object itself can be converted to a dense matrix. ie in your example one can do

```julia
R = cholesky(Umat)
RU = Array(R)

```

However RU will be R.U’ \* R.U not R. This propagated all sorts of interesting hard to find bugs in my code.

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [October 11, 2018, 10:55pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/9 "2018-10-11T22:55:13Z")

</div>

> [@mcbro](#):
>
> However RU will be R.U’ \* R.U not R.

`R` is basically `R.U' * R.U` and hence also equal to `RU`. That is what I meant with

> [@fredrikekre](#):
>
> It returns a factorization object, which is just another representation of the original matrix `A` , so it is only natural that `convert(Array, cholesky(A))` returns something that is `==` to the original matrix.

so the object is a representation of `A`, not the upper or lower factor. For example, it would be weird if

```julia
cholesky(A)\x

```

was not equal to

```julia
A\x

```

so in this example it is pretty clear that `cholesky(A)` is the same as `A`, but with different underlying storage.

---

<div class="post-metadata">

### Author: ![mcbro](https://avatars.discourse-cdn.com/v4/letter/m/77aa72/32.png) [@mcbro](https://discourse.julialang.org/u/mcbro)
#### Post date: [October 11, 2018, 11:01pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/10 "2018-10-11T23:01:37Z")

</div>

I won’t argue that point due to it’s somewhat pedantic nature, but it was certainly unexpected for me. I think it might have been better for the convert to call an error and perhaps point out the existence of the subfields .U and .L. That would have saved me some time.

Also this was not an error that running under 0.7 would have caught as well. I’ll guess I’ll have to be more careful next time. Thanks for the help.

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [October 11, 2018, 11:04pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/11 "2018-10-11T23:04:44Z")

</div>

> [@mcbro](#):
>
> Also this was not an error that running under 0.7 would have caught as well.

Well, the following message is printed:

```julia
julia> using LinearAlgebra

julia> A = rand(2,2); A = A'A;

julia> R = chol(A)
┌ Warning: `chol(A::AbstractMatrix)` is deprecated, use `(cholesky(A)).U` instead.
│ caller = top-level scope at none:0
└ @ Core none:0
2×2 UpperTriangular{Float64,Array{Float64,2}}:
 0.829981 0.527958
  ⋅ 0.781579

```

---

<div class="post-metadata">

### Author: ![mcbro](https://avatars.discourse-cdn.com/v4/letter/m/77aa72/32.png) [@mcbro](https://discourse.julialang.org/u/mcbro)
#### Post date: [October 11, 2018, 11:06pm UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/12 "2018-10-11T23:06:05Z")

</div>

Well I outsmarted myself because I already knew chol() was deprecated and never saw that LOL.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [October 12, 2018, 7:58am UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/13 "2018-10-12T07:58:12Z")

</div>

> [@mcbro](#):
>
> it was certainly unexpected for me

Perhaps the [manual](https://docs.julialang.org/en/stable/stdlib/LinearAlgebra/#man-linalg-factorizations-1) could mention that all factorizations work this way. Can you make a pull request?

---

<div class="post-metadata">

### Author: ![mcbro](https://avatars.discourse-cdn.com/v4/letter/m/77aa72/32.png) [@mcbro](https://discourse.julialang.org/u/mcbro)
#### Post date: [October 12, 2018, 8:35am UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/14 "2018-10-12T08:35:45Z")

</div>

That would certainly help. However I didn’t find chol() in the v 0.7 deprecated or breaking sections. I looked for it there. It might be a good idea to update the manual there, since that’s where a lot of the surprising changes are first documented. The fact that cholfact becomes cholesky is there, but not mention of chol() itself. I should have read the new cholesky entry more carefully, but I was in a hurry and the wrong conversion made some of my errors go away.

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [October 12, 2018, 10:02am UTC](https://discourse.julialang.org/t/can-not-use-triangular-matrix-from-cholesky-in-any-way/16207/15 "2018-10-12T10:02:46Z")

</div>

> It might be a good idea to update the manual there

Submitting a documentation fix is easy because you can do it in your browser: [Editing files - GitHub Docs](https://help.github.com/articles/editing-files-in-another-user-s-repository/). Give it a shot, @mcbro!
