Matrices with vectors in elements?

I’m a little puzzled about how to fill vectors into matrix elements… Consider the two attempts below: the first is unsuccessful, the second is successful.

julia> # Unsuccessful strategy
julia> a11 = [1,2];
julia> a12 = [1,-2];
julia> a21 = [1,2,1];
julia> a22 = [1,2,1];

julia> Matrix{Vector}([a11 a12; a21 a22])
ERROR: MethodError: Cannot `convert` an object of type
  Int64 to an object of type
  Array{T,1} where T
Closest candidates are:
  convert(::Type{T}, ::AbstractArray) where T<:Array at array.jl:533
  convert(::Type{T}, ::T) where T<:AbstractArray at abstractarray.jl:14
  convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray at D:\buildbot\worker\package_win64\build\usr\sh
are\julia\stdlib\v1.4\LinearAlgebra\src\factorization.jl:55
  ...
Stacktrace:
 [1] setindex!(::Array{Array{T,1} where T,2}, ::Int64, ::Int64) at .\array.jl:825
 [2] copyto!(::Array{Array{T,1} where T,2}, ::Array{Int64,2}) at .\multidimensional.jl:962
 [3] Array{Array{T,1} where T,2}(::Array{Int64,2}) at .\array.jl:541
 [4] top-level scope at REPL[34]:1

julia> # Successful strategy
julia> A = Matrix{Vector}(undef,2,2)
2×2 Array{Array{T,1} where T,2}:
 #undef  #undef
 #undef  #undef

julia> A[1,1] = a11;
julia> A[1,2] = a12;
julia> A[2,1] = a21;
julia> A[2,2] = a22;

julia> A
2×2 Array{Array{T,1} where T,2}:
 [1, 2]     [1, -2]
 [1, 2, 1]  [1, 2, 1]

Question: is there a way to fill the matrix with vector elements using the first notation? [The first notation is more convenient as an argument in function calls.]

The [ here is lowered as hvcat. MWE for the issue you are experiencing:

julia> a = 1:2
1:2

julia> [a a; a a]
4×2 Array{Int64,2}:
 1  1
 2  2
 1  1
 2  2

I usually work around these with reshape, eg use the equivalent of

julia> reshape([a, a, a, a], 2, :)
2×2 Array{UnitRange{Int64},2}:
 1:2  1:2
 1:2  1:2
1 Like

Neat. I notice I have to list the matrix elements column wise, which makes sense.

You can also wrap each vector in another vector to avoid concatenation:

julia> [[a11] [a12]; [a21] [a22]]
2×2 Array{Array{Int64,1},2}:
 [1, 2]     [1, -2]
 [1, 2, 1]  [1, 2, 1]

Also note that Matrix{Vector} creates a matrix with non-concretely typed elements and accessing elements will not be type stable. You will probably want to specify the element type of the vectors explicitly, like Matrix{Vector{Int}}.

1 Like

Another option:

julia> [[a11, a21] [a12, a22]]
2×2 Array{Array{Int64,1},2}:
 [1, 2]     [1, -2]
 [1, 2, 1]  [1, 2, 1]
2 Likes