Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write code to work with 1D matrices in Julia?

Tags:

julia

Consider the following code

function test(m,B)
    @show typeof(B)
    all_u = rand(m,10)
    one_u = all_u[:,1]
    B*one_u
end
# Works
@show test(3, [1 1 1; 2 2 2])
# Works
@show test(2, [1 1; 2 2])
# Fails
@show test(1, [1; 2])

The last line fails with

`*` has no method matching *(::Array{Int64,1}, ::Array{Float64,1})

because B is now a 1-D vector (which is not OK), and so is one_u (which is always the case, and doesn't cause issues).

How can I write test(m,B) to handle the m==1 case that doesn't require actually special casing it for m==1 (i.e. using an if)? I know that for m==1 case I could actually write another method to dispatch on the fact that B is a Vector but that seems terribly wasteful.

like image 325
IainDunning Avatar asked May 14 '15 16:05

IainDunning


1 Answers

Quoting from your follow-up comment:

B is sometimes a matrix, sometimes a vector/1D matrix - that's the problem.

You can convert a vector to a 2D array with the "slicing" operation [:;:]. In other words, if B has type Array{T,1}, then B[:,:] has type Array{T,2}:

julia> B = [1; 2]
2-element Array{Int64,1}:
 1
 2

julia> typeof(B[:, :])
Array{Int64,2}

On the other hand, if B already has type Array{T,2}, then [:;:] is a no-op:

julia> B = [1 1; 2 2]
2x2 Array{Int64,2}:
 1  1
 2  2

julia> typeof(B[:, :])
Array{Int64,2}

julia> B[:, :] == B
true

Therefore, in order to accommodate your function definition for the case m==1 (i.e. convert B to a 2D array when needed), you can simply substitute B[:,:]*one_u for B*one_u:

julia> function test(m, B)
           @show typeof(B)
           all_u = rand(m, 10)
           one_u = all_u[:, 1]
           B[:, :] * one_u
       end
test (generic function with 1 method)

julia> @show test(3, [1 1 1; 2 2 2])
typeof(B) => Array{Int64,2}
test(3,[1 1 1;2 2 2]) => [1.4490640717303116,2.898128143460623]
2-element Array{Float64,1}:
 1.44906
 2.89813

julia> @show test(2, [1 1; 2 2])
typeof(B) => Array{Int64,2}
test(2,[1 1;2 2]) => [0.9245851832116978,1.8491703664233956]
2-element Array{Float64,1}:
 0.924585
 1.84917 

julia> @show test(1, [1; 2])
typeof(B) => Array{Int64,1}
test(1,[1,2]) => [0.04497125985152639,0.08994251970305278]
2-element Array{Float64,1}:
 0.0449713
 0.0899425
like image 192
jub0bs Avatar answered Oct 16 '22 11:10

jub0bs