Implementing a sampler with array eltype

白昼怎懂夜的黑 提交于 2020-07-09 06:49:29

问题


Hooking into rand has been easier in the old days... I think I followed the description in the docs, but it doesn't seem to like a sampler returning an array:

using Random

struct Shell{N}
    r0::Float64
    r1::Float64
end

Base.eltype(::Type{Shell{N}}) where {N} = Array{Float64, N}

function Random.rand(rng::Random.AbstractRNG, d::Random.SamplerTrivial{Shell{N}}) where {N}
    # ignore the correctness of the sampling algorithm for now :)
    shell = d[]
    Δ = shell.r1 - shell.r0
    θ = Δ .* randn(N)
    r = shell.r0 .+ θ .* .√rand(N) 
end

Test:

julia> rand(Shell{2}(0, 1))
2-element Array{Float64,1}:
 0.5165139561555491  
 0.035180151872393726

julia> rand(Shell{2}(0, 1), 2)
ERROR: MethodError: no method matching Array{Float64,2}(::Array{Float64,1})
Closest candidates are:
  Array{Float64,2}(::AbstractArray{S,N}) where {T, N, S} at array.jl:498
  Array{Float64,2}(::UndefInitializer, ::Int64, ::Int64) where T at boot.jl:406
  Array{Float64,2}(::UndefInitializer, ::Int64...) where {T, N} at boot.jl:410
  ...
Stacktrace:
 [1] convert(::Type{Array{Float64,2}}, ::Array{Float64,1}) at ./array.jl:490
 [2] setindex!(::Array{Array{Float64,2},1}, ::Array{Float64,1}, ::Int64) at ./array.jl:782
 [3] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:271 [inlined]
 [4] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:266 [inlined]
 [5] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:279 [inlined]
 [6] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:280 [inlined]
 [7] rand(::Shell{2}, ::Int64) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:283
 [8] top-level scope at REPL[14]:1

What am I missing?


回答1:


Your definition of rand always returns an Array{Float64,1}, yet you declared that it returns Array{Float,N} (via your definition of eltype). This is what the error tells you: to put a freshly produced Vector{Float64} into the result array with eltype Array{Float64,2}, a conversion has to be made, but no such conversion is defined, hence the error.

In this case, it seems that changing the eltype definition to Base.eltype(::Type{<:Shell}} = Array{Float64, 1} would solve your problem.



来源:https://stackoverflow.com/questions/62580541/implementing-a-sampler-with-array-eltype

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!