I have been using the Diagonal function to take a vector array and produce a matrix with entries of the vector along the diagonal. It used to work fine but now instead of producing a matrix with entries along the diagonal, it now just makes a 1x1 scalar.
I think it has something to do with types? For instance, when it works it is a 3x3 Diagonal{type, Array{type, 1}}, and when it doesn’t it’s a 1x1 Diagoanl{similar}. The weird thing is that I didn’t change my code from last week to this, and it used to work, but now it does not. Any ideas would be most helpful.
I think there may be some state in your session that is not part of your minimal working example, which causes the seemingly different behavior (eg you are overwriting some variables). This should of course be deterministic, and the expected behavior is
Agreed, but if all I’m doing is overwriting some variables, why does that change things? And how can I prevent that from happening?
The problem arises from a 1x3 Array{Int64, 2} vector I’ve defined in my code analogously to my toy example. Furthermore it is defined within a function, which I believe means that it is defined each time I run that function (so I can’t be overwriting it in the REPL). I’ve also tried defining it as a 3x1 Array{Int64,2} to no success. I haven’t updated Julia to the most recent version or anything. I’m still using 1.1.1
For your intended behavior, you should provide a vector (Array{Int64, 1}), not a matrix (Array{Int64, 2}). Diagonal has different methods for these two different types.
help?> Diagonal
search: Diagonal Bidiagonal Tridiagonal SymTridiagonal
Diagonal(A::AbstractMatrix)
Construct a matrix from the diagonal of A.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> A = [1 2 3; 4 5 6; 7 8 9]
3Ă—3 Array{Int64,2}:
1 2 3
4 5 6
7 8 9
julia> Diagonal(A)
3Ă—3 Diagonal{Int64,Array{Int64,1}}:
1 â‹… â‹…
â‹… 5 â‹…
â‹… â‹… 9
-------------------------------------------------------------------------
Diagonal(V::AbstractVector)
Construct a matrix with V as its diagonal.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> V = [1, 2]
2-element Array{Int64,1}:
1
2
julia> Diagonal(V)
2Ă—2 Diagonal{Int64,Array{Int64,1}}:
1 â‹…
â‹… 2
I guess what I would like to highlight is there seem to be some simple errors in how Diagonal is defined. Or perhaps I just don’t understand the usefulness of how it is currently defined. Why does
Because the former is a matrix and the latter a vector (you should in general avoid using 1x3 matrices as vector, unfortunately, a lot of people are doing it).
If you input a matrix to the Diagonal constructor it will just use its diagonal, which for a 1x3 matrix is only a single element.
The key is that [1 2 3] creates a one row matrix, not a vector. Calling Diagonal(::Matrix)extracts the diagonal from the matrix and constructs a new matrix with it. The reason Diagonal(myvec') sometimes works and sometimes doesn’t has to do with where myvec came from.
The sure-fire way to get the behavior you want is to use Diagonal(vec(x)), which will flatten x into a vector and ensure it gets placed on the diagonal.
In addition to what @DNF and @mbauman explained, you can use the introspection/reflection facilities of Julia to investigate problems like this next time you encounter something unexpected. Eg try
…also just typing in an expression and looking what the REPL tells is quite helpful. Like trying out a few construction ways to create arrays/vectors/matrices: