# Turing.jl: UniformDraw distribution?

Is there a “UniformDraw” distribution in Turing.jl / Distributions.jl, i.e. given an array of element, the distribution selects one of the elements randomly.

Example:

``````x = [1,10,32,100]
val ~ UniformDraw(x)
``````

`val` is then 1, 10, 32, 100 randomly selected.

I can implement it naively like this using `DiscreteUniform` (including a version that takes a list of percentages/weights using `Categorical`).

``````"""
Return a normalized vector, i.e. where the sum is 1.
"""
using Turing

function simplex(v)
return v./sum(v)
end

@model function uniformDrawTest(x,pcts=[1,2,3,4])
# Select value uniformly
function uniformDraw(x)
n = length(x)
ix1 ~ DiscreteUniform(1,n)
return x[ix1]
end
# Select a value based on probabilities in pcts
function uniformDraw(x,pcts)
n = length(x)
ix2 ~ Categorical(simplex(pcts))
return x[ix2]
end
val1 ~ Dirac(uniformDraw(x))
val2 ~ Dirac(uniformDraw(x,pcts)
val3 ~ Dirac(uniformDraw(x))   # will be same as val1
end

x = [1,10,32,100]
pcts = [1,2,3,4]
model = uniformDrawTest(x,pcts)

chns = sample(model, PG(15), 10_000)
display(chns)
``````

There are at least two drawbacks with this:

• I have to wrap the result with `Dirac`.
• But more seriously is that the indices (`ix1` and `ix2`) are both global in the model, so `val1` and `val3` will always be the same value.

It’s already available in Distributions.jl as `DiscreteNonParametric`

``````julia> using Distributions

julia> d = DiscreteNonParametric([1,10,32,100], ones(4) ./ 4);

julia> rand(d)
32

julia> rand(d)
32

julia> rand(d)
100

julia> rand(d)
100

julia> rand(d)
10

julia> logpdf(d, 10)
-1.3862943611198906

julia> logpdf(d, 100)
-1.3862943611198906
``````

If you want, you can define the following constructor:

``````julia> UniformDraw(xs) = DiscreteNonParametric(xs, ones(length(xs)) ./ length(xs))
UniformDraw (generic function with 1 method)

julia> d = UniformDraw([1,10,32,100])
DiscreteNonParametric{Int64, Float64, Vector{Int64}, Vector{Float64}}(support=[1, 10, 32, 100], p=[0.25, 0.25, 0.25, 0.25])

julia> rand(d)
1
``````
2 Likes

Thanks @torfjelde !

That was exactly what I looked for. (I must have search in an old Distribution documentation.)