I am constructing some structural (economic) model. This requires me to write something (a simple version for illustration) like
using Parameters
@with_kw struct test_model @deftype Float64
β = 0.98
end
struct test{M}
A::Array{Float64, 3}
B::Matrix{Vector{Float64}}
C::M
end
test(C::test_model) = test(fill(0.0, (131, 51, 21)),
fill([], (131, 21* 51)),
C);
model = test_model()
alloc = test(model)
This gives error
ERROR: MethodError: no method matching test(::Array{Float64, 3}, ::Matrix{Vector{Any}}, ::test_model)
I think the error comes from B
from test
. I did the same exercise without B
, and it doesn’t spit error. However, when I do another exercise:
struct test2
B1::Matrix{Vector{Float64}}
B2::Matrix{Vector{Float64}}
end
test2() = test2(fill([], (131, 21* 51)),
fill([], (131, 21* 51)))
alloc2 = test2();
This doesn’t give error. What does make this difference? How can I deal with this issue?
lmiq
June 20, 2024, 11:44am
2
Sihyun_Kim:
[]
This is a vector of elements of Any
type. Use Float64[]
for an empty vector that will contain Float64
numbers (or Vector{Float64}()
). That will solve the initialization error. The second I think does not error because it is performing an implicit conversion of the two empty matrices.
But there is a deeper problem there, which is that fill(Float64[], (2,2))
will put the same array of floats in every position in the matrix:
julia> m = fill(Float64[], (2,2))
2×2 Matrix{Vector{Float64}}:
[] []
[] []
julia> push!(m[1], 1.0)
1-element Vector{Float64}:
1.0
julia> m
2×2 Matrix{Vector{Float64}}:
[1.0] [1.0]
[1.0] [1.0]
To have independent vectors at each position, you need a comprehension:
julia> m = [ Float64[] for i in 1:2, j in 1:2 ]
2×2 Matrix{Vector{Float64}}:
[] []
[] []
julia> push!(m[1], 1.0)
1-element Vector{Float64}:
1.0
julia> m
2×2 Matrix{Vector{Float64}}:
[1.0] []
[] []
1 Like
lmiq
June 20, 2024, 11:50am
3
A minimal example of what you are seeing there is:
julia> struct test3
B1::Matrix{Vector{Float64}}
x::Float64
end
julia> test3(fill([], (2,2)), 1.0) # converts [] to Float64[] automatically
test3([Float64[] Float64[]; Float64[] Float64[]], 1.0)
julia> struct test4{T}
B1::Matrix{Vector{Float64}}
x::T
end
julia> test4(fill([], (2,2)), 1.0) # does not convert automatically
ERROR: MethodError: no method matching test4(::Matrix{Vector{Any}}, ::Float64)
julia> test4(fill(Float64[], (2,2)), 1.0)
test4{Float64}([Float64[] Float64[]; Float64[] Float64[]], 1.0)
I’m not sure if I like the fact that in test3
the automatic conversion occurs.
2 Likes