# Implementing a custom Sampler in Distributions.jl

**URL:** https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066
**Category:** Statistics
**Tags:** first-steps
**Created:** [June 9, 2020, 1:00pm UTC](https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066 "2020-06-09T13:00:40Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![nluetts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nluetts/32/24967_2.png) [@nluetts](https://discourse.julialang.org/u/nluetts)
#### Post date: [June 9, 2020, 1:00pm UTC](https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066/1 "2020-06-09T13:00:40Z")

</div>

I am trying to implement my own Sampler for a [scaled and shifted](https://en.wikipedia.org/wiki/Beta_distribution#Four_parameters) Beta distribution with support in some arbitrary range [a, b]:

```julia
using Distributions: Beta, Sampleable, Continuous, Univariate

struct ScaledShiftedBetaSampler <: Sampleable{Univariate, Continuous}
    distribution::Beta
    a::Float64
    b::Float64
end

function Base.rand(d::ScaledShiftedBetaSampler)
    sample = rand(d.distribution)
    return sample * (d.b - d.a) + d.a
end

```

According to the [Distributions.jl docs](https://juliastats.org/Distributions.jl/stable/extends/#Univariate-Sampler-1) it is sufficient to implement the function `rand(d::ScaledShiftedBetaSampler)` that returns a single random number while vectorised versions are already predefined:

> The package already implements a vectorized version of `rand!` and `rand` that repeatedly calls the he scalar version to generate multiple samples.

Drawing a single sample works fine:

```julia
julia> using Random: seed!; seed!(42)
Random.MersenneTwister(UInt32[0x0000002a], ...

julia> splr = ScaledShiftedBetaSampler(Beta(2,2), 3.0, 6.0)
ScaledShiftedBetaSampler(Beta{Float64}(α=2.0, β=2.0), 3.0, 6.0)

julia> rand(splr)
4.106660698978913

julia> using Plots: histogram; histogram([rand(splr) for _ in 1:100000])

```

 ![grafik](https://global.discourse-cdn.com/julialang/original/3X/3/8/3843f3c08f40012c1a62a271a1dd915413fa9797.png)

However, drawing several samples throws an error:

```julia
julia> rand(splr, 100000)
ERROR: ArgumentError: Sampler for this object is not defined
Stacktrace:
 [1] Random.Sampler(::Type{Random.MersenneTwister}, ::Random.SamplerTrivial{ScaledShiftedBetaSampler,Float64}, ::Val{1}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/Random/src/Random.jl:145
 [2] Random.Sampler(::Random._GLOBAL_RNG, ::Random.SamplerTrivial{ScaledShiftedBetaSampler,Float64}, ::Val{1}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/Random/src/Random.jl:139
 [3] rand(::Random._GLOBAL_RNG, ::Random.SamplerTrivial{ScaledShiftedBetaSampler,Float64}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/Random/src/Random.jl:253 (repeats 2 times)
 [4] rand! at /Users/Nils/.julia/packages/Distributions/RAeyY/src/univariates.jl:165 [inlined]
 [5] rand at /Users/Nils/.julia/packages/Distributions/RAeyY/src/univariates.jl:158 [inlined]
 [6] rand(::ScaledShiftedBetaSampler, ::Int64) at /Users/Nils/.julia/packages/Distributions/RAeyY/src/genericrand.jl:24
 [7] top-level scope at REPL[12]:1

```

From my understanding of the docs, I was expecting this to work. What am I missing?

My versions:

```julia
julia> import Pkg; Pkg.status("Distributions")
Status `~/.julia/environments/v1.4/Project.toml`
  [31c24e10] Distributions v0.23.4

julia> versioninfo()
Julia Version 1.4.2
Commit 44fa15b150* (2020-05-23 18:35 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin18.7.0)
  CPU: Intel(R) Core(TM) i5-5250U CPU @ 1.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.1 (ORCJIT, broadwell)

```

---

<div class="post-metadata">

### Author: ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)
#### Post date: [June 9, 2020, 8:25pm UTC](https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066/2 "2020-06-09T20:25:16Z")

</div>

I think the documentation is outdated. Most of the distributions in the package implement `rand(rng::AbstractRNG, s::T)` for their type T.

Try implementing only this:

```julia
function Base.rand(rng::AbstractRNG, d::ScaledShiftedBetaSampler)
    sample = rand(rng, d.distribution)
    return sample * (d.b - d.a) + d.a
end

```

I think the rest of the machinery you want will delegate to this method, including methods that use the global rng.

---

<div class="post-metadata">

### Author: ![johnczito](https://avatars.discourse-cdn.com/v4/letter/j/53a042/32.png) [@johnczito](https://discourse.julialang.org/u/johnczito)
#### Post date: [June 9, 2020, 9:25pm UTC](https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066/3 "2020-06-09T21:25:08Z")

</div>

Just as a heads up, `Distributions` already [provides](https://github.com/JuliaStats/Distributions.jl/issues/1072) this functionality, if a bit covertly.

---

<div class="post-metadata">

### Author: ![nluetts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nluetts/32/24967_2.png) [@nluetts](https://discourse.julialang.org/u/nluetts)
#### Post date: [June 10, 2020, 5:31am UTC](https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066/4 "2020-06-10T05:31:44Z")

</div>

@contradict Yes, it seems the docs are not up to date. Defining `Base.rand(rng::AbstractRNG, d::ScaledShiftedBetaSampler)` does the trick, thank you very much!

@johnczito [`LocationScale`](https://juliastats.org/Distributions.jl/stable/univariate/#Distributions.LocationScale) does what I want and seems like the best option here, thanks for pointing me to it!

Problem solved 👍

---

<div class="post-metadata">

### Author: ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)
#### Post date: [June 10, 2020, 2:14pm UTC](https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066/5 "2020-06-10T14:14:59Z")

</div>

> [@nluetts](#):
>
> Problem solved 👍

Not quite, until the documentation has been fixed 😉 Would you mind filing an issue with Distributions.jl?

---

<div class="post-metadata">

### Author: ![nluetts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nluetts/32/24967_2.png) [@nluetts](https://discourse.julialang.org/u/nluetts)
#### Post date: [June 11, 2020, 5:53am UTC](https://discourse.julialang.org/t/implementing-a-custom-sampler-in-distributions-jl/41066/6 "2020-06-11T05:53:23Z")

</div>

> [@sijo](#):
>
> Not quite, until the documentation has been fixed 😉 Would you mind filing an issue with Distributions.jl?

You are right — I created an [issue](https://github.com/JuliaStats/Distributions.jl/issues/1132).
