Truncated distributions in Gen

Is there a way to sample from a truncated distribution in Gen? In other words, what should go in ?? below?

using Gen, Distributions

@gen function line_model(xs::Vector{Float64})

    slope = @trace(??, :slope)
    intercept = @trace(normal(0, 2), :intercept)

    for (i, x) in enumerate(xs)
        @trace(normal(slope * x + intercept, 0.1), (:y, i))
    end

end;

xs = [-5., -4., -3., -2., -1., 0., 1., 2., 3., 4., 5.];
trace = Gen.simulate(line_model, (xs,));

I’ve tried:

  1. Distributions.Truncated(normal(0, 1), 0, Inf). I believe this doesn’t work because Gen’s normal(0, 1) returns a float.
  2. I considered implementing this using @dist, but couldn’t formulate truncation as a deterministic transformation:
@dist function truncated_normal(mean, sd, lb, ub)
    max(lb, min(normal(mean, sd), ub))
end

Is there a way to implement Truncated from Distributions.jl for any distribution in Gen?

Thanks.

Found a solution using Genify.

Define:

function truncated_normal(mean, sd, lb, ub)
    d = Distributions.Truncated(Normal(mean, sd), lb, ub)
    x = rand(d)
end

and

gen_truncated_normal = genify(truncated_normal, Real, Real, Real, Real)

Then, modify the line in line_model to:

slope = @trace(gen_truncated_normal(0,1,0,Inf), :slope)

3 Likes

Awesome! For people finding this now, you can also use the new GitHub - probcomp/GenDistributions.jl: Use Distributions.jl distributions from within Gen package to call any Distributions.jl distribution from within a Gen model.

2 Likes

Thanks, thats great!

Sweet! Thanks so much, @Alex_Lew!