How to initialize an array of Turing variables?

I am new to Turing and in the process of translating a complex dynamical stochastic model from Stan to Turing. Instead of declaring individual variables (many of them arrays), I would like to include them in a dictionary, and here I am running into issues using the right type. How do I initialize dictionary and array using the correct type?
This short piece of code demonstrates what I would like to achieve without having to declare x:

using Turing

@model function mwe_model()
    # unnecessary declaration of an extra variable to get type
    x ~ Normal(0.0, 1.0)
    T = typeof(x)
    
    stoch = Dict{String, T}();

    stoch["param1"] = Array{T}(undef, 1)
    stoch["param1"][1] ~ Normal(0.0, 1.0)
end

PS: I have tried setting the type explicitly which is less flexible and sometimes results in errors:

import ForwardDiff
using Turing

@model function mwe_model()
    T = ForwardDiff.Dual :: Type
    stoch = Dict{String, T}();

    # this creates an error
    stoch["param1"] = Array{T}(undef, 1)
    stoch["param1"][1] ~ Normal(0.0, 1.0)

    # this works:
    #stoch["param2"] = Array{T}(undef, 1, 1)
    #stoch["param2"][1, 1] ~ Normal(0.0, 1.0)
end

display(sample(mwe_model(), NUTS(), 1_000))

The code above terminates with an error: LoadError: UndefRefError: access to undefined reference. However, it appears to work when using the 2-dimensional array stoch["param2"] instead of stoch["param1"]. This is probably a bug, but I am most interested in a more flexible way to obtain the type without having to hard-code it.

you can either use loop for arraydist:
https://turing.ml/dev/docs/using-turing/guide#constructing-product-distributions-with-arraydist

Thanks for the tip. And – somewhat embarrassingly – for the last few weeks, I thought that the website turing.ml was down, when it just turned out that it is being blocked by my university’s VPN. Turning off the VPN, I found more useful information:

Moreover, if the continuous random variable is to be sampled using a Hamiltonian sampler, the vector’s element type needs to either be: 1. Real to enable auto-differentiation through the model which uses special number types that are sub-types of Real, or 2. Some type parameter T defined in the model header using the type parameter syntax, …

I checked that supertype(ForwardDiff.Dual) is indeed Real and based on that, I would change my example code to something along the lines of:

@model function mwe_model()
    T = Real
    stoch = Dict{String, Array{T}}();

    stoch["param1"] ~ arraydist([Normal(0.0, 1.0) for i in 1:1])
end
1 Like