From be4a77c9b51a47442b56f112e720f73f6e069943 Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Fri, 10 May 2019 08:39:38 +0200 Subject: [PATCH 1/4] fix typos, clarify what methods should be defined. This was missed in #31787. --- stdlib/Random/docs/src/index.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/stdlib/Random/docs/src/index.md b/stdlib/Random/docs/src/index.md index c81946fc2a2de..32f5f5be8d4c1 100644 --- a/stdlib/Random/docs/src/index.md +++ b/stdlib/Random/docs/src/index.md @@ -84,13 +84,20 @@ Generating random values for some distributions may involve various trade-offs. The `Random` module defines a customizable framework for obtaining random values that can address these issues. Each invocation of `rand` generates a *sampler* which can be customized with the above trade-offs in mind, by adding methods to `Sampler`, which in turn can dispatch on the random number generator, the object that characterizes the distribution, and a suggestion for the number of repetitions. Currently, for the latter, `Val{1}` (for a single sample) and `Val{Inf}` (for an arbitrary number) are used, with `Random.Repetition` an alias for both. -The object returned by `Sampler` is then used to generate the random values, by a method of `rand` defined for this purpose. Samplers can be arbitrary values, but for most applications the following predefined samplers may be sufficient: +The object returned by `Sampler` is then used to generate the random values. When implementing the random generation interface for a value `X::T` that can be sampled from, the implementor should define the method -1. `SamplerType{T}()` can be used for implementing samplers that draw from type `T` (e.g. `rand(Int)`). +```julia +rand(rng, sampler) +``` +for the particular sampler returned by `Sampler(rng, X, repetition)` + +Samplers can be arbitrary values that implement `rand(rng, sampler)`, but for most applications the following predefined samplers may be sufficient: + +1. `SamplerType{T}()` can be used for implementing samplers that draw from type `T` (e.g. `rand(Int)`). This is the default returned by `Sampler` for *types*. -2. `SamplerTrivial(self)` is a simple wrapper for `self`, which can be accessed with `[]`. This is the recommended sampler when no pre-computed information is needed (e.g. `rand(1:3)`). +2. `SamplerTrivial(self)` is a simple wrapper for `self`, which can be accessed with `[]`. This is the recommended sampler when no pre-computed information is needed (e.g. `rand(1:3)`), and is the default returned by `Sampler` for *values*. -3. `SamplerSimple(self, data)` also contains the additional `data` field, which can be used to store arbitrary pre-computed values. +3. `SamplerSimple(self, data)` also contains the additional `data` field, which can be used to store arbitrary pre-computed values, which should be computed in a *custom method* of `Sampler`. We provide examples for each of these. We assume here that the choice of algorithm is independent of the RNG, so we use `AbstractRNG` in our signatures. @@ -185,7 +192,7 @@ is defined to return `SamplerTrivial` with a `Random.CloseOpen01{T}}` type defin #### An optimized sampler with pre-computed data -Consider a discrete distribution, where numbers `1:n` are drawn with given probabilities that some to one. When many values are needed from this distribution, the fastest method if using an [alias table](https://en.wikipedia.org/wiki/Alias_method). We don't provide the algorithm for building such a table here, but suppose it is available in `make_alias_table(probabilities)` instead, and `draw_number(rng, alias_table)` can be used to draw a random number from it. +Consider a discrete distribution, where numbers `1:n` are drawn with given probabilities that sum to one. When many values are needed from this distribution, the fastest method is using an [alias table](https://en.wikipedia.org/wiki/Alias_method). We don't provide the algorithm for building such a table here, but suppose it is available in `make_alias_table(probabilities)` instead, and `draw_number(rng, alias_table)` can be used to draw a random number from it. Suppose that the distribution is described by ```julia From 229bf3eafd204881836d411961d07d497262b959 Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Fri, 10 May 2019 09:30:31 +0200 Subject: [PATCH 2/4] remove example for `Random.CloseOpen01{T}}` it is just confusing at this stage. --- stdlib/Random/docs/src/index.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/stdlib/Random/docs/src/index.md b/stdlib/Random/docs/src/index.md index 32f5f5be8d4c1..68470c5ce1387 100644 --- a/stdlib/Random/docs/src/index.md +++ b/stdlib/Random/docs/src/index.md @@ -181,15 +181,6 @@ julia> rand(Die(4), 3) Given a collection type `S`, it's currently assumed that if `rand(::S)` is defined, an object of type `eltype(S)` will be produced. In the last example, a `Vector{Any}` is produced; the reason is that `eltype(Die) == Any`. The remedy is to define `Base.eltype(::Type{Die}) = Int`. -A `SamplerTrivial` does not have to wrap the original object. For example, in `Random`, `AbstractFloat` types are special-cased, because by default random values are not produced in the whole type domain, but rather in `[0,1)`. - -Consequently, a method -```julia -Sampler(::Type{RNG}, ::Type{T}, n::Repetition) where {RNG<:AbstractRNG,T<:AbstractFloat} = - Sampler(RNG, CloseOpen01(T), n) -``` -is defined to return `SamplerTrivial` with a `Random.CloseOpen01{T}}` type defined for this purpose, which has an appropriate `rand` method defined for it. - #### An optimized sampler with pre-computed data Consider a discrete distribution, where numbers `1:n` are drawn with given probabilities that sum to one. When many values are needed from this distribution, the fastest method is using an [alias table](https://en.wikipedia.org/wiki/Alias_method). We don't provide the algorithm for building such a table here, but suppose it is available in `make_alias_table(probabilities)` instead, and `draw_number(rng, alias_table)` can be used to draw a random number from it. From f27c3e319fbe370a7e68fafbbe96b5e85e5aa42a Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Sat, 11 May 2019 10:51:50 +0200 Subject: [PATCH 3/4] punctuation fixes, add back subsection on AbstractFloat --- stdlib/Random/docs/src/index.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stdlib/Random/docs/src/index.md b/stdlib/Random/docs/src/index.md index 68470c5ce1387..2ac5fff71e0b7 100644 --- a/stdlib/Random/docs/src/index.md +++ b/stdlib/Random/docs/src/index.md @@ -89,7 +89,7 @@ The object returned by `Sampler` is then used to generate the random values. Whe ```julia rand(rng, sampler) ``` -for the particular sampler returned by `Sampler(rng, X, repetition)` +for the particular `sampler` returned by `Sampler(rng, X, repetition)`. Samplers can be arbitrary values that implement `rand(rng, sampler)`, but for most applications the following predefined samplers may be sufficient: @@ -181,6 +181,10 @@ julia> rand(Die(4), 3) Given a collection type `S`, it's currently assumed that if `rand(::S)` is defined, an object of type `eltype(S)` will be produced. In the last example, a `Vector{Any}` is produced; the reason is that `eltype(Die) == Any`. The remedy is to define `Base.eltype(::Type{Die}) = Int`. +#### Generating values for an `AbstractFloat` type + +`AbstractFloat` types are special-cased, because by default random values are not produced in the whole type domain, but rather in `[0,1)`. The following method should be implemented for `T <: AbstractFloat`: `Random.rand(::AbstractRNG, ::Random.SamplerTrivial{Random.CloseOpen01{T}})` + #### An optimized sampler with pre-computed data Consider a discrete distribution, where numbers `1:n` are drawn with given probabilities that sum to one. When many values are needed from this distribution, the fastest method is using an [alias table](https://en.wikipedia.org/wiki/Alias_method). We don't provide the algorithm for building such a table here, but suppose it is available in `make_alias_table(probabilities)` instead, and `draw_number(rng, alias_table)` can be used to draw a random number from it. From ca3530282dd1b9d5ecd2e82466c5c56ef96f8389 Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Sun, 12 May 2019 09:57:20 +0200 Subject: [PATCH 4/4] remove the type designation (unused in the text) --- stdlib/Random/docs/src/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Random/docs/src/index.md b/stdlib/Random/docs/src/index.md index 2ac5fff71e0b7..6f23ea2686645 100644 --- a/stdlib/Random/docs/src/index.md +++ b/stdlib/Random/docs/src/index.md @@ -84,7 +84,7 @@ Generating random values for some distributions may involve various trade-offs. The `Random` module defines a customizable framework for obtaining random values that can address these issues. Each invocation of `rand` generates a *sampler* which can be customized with the above trade-offs in mind, by adding methods to `Sampler`, which in turn can dispatch on the random number generator, the object that characterizes the distribution, and a suggestion for the number of repetitions. Currently, for the latter, `Val{1}` (for a single sample) and `Val{Inf}` (for an arbitrary number) are used, with `Random.Repetition` an alias for both. -The object returned by `Sampler` is then used to generate the random values. When implementing the random generation interface for a value `X::T` that can be sampled from, the implementor should define the method +The object returned by `Sampler` is then used to generate the random values. When implementing the random generation interface for a value `X` that can be sampled from, the implementor should define the method ```julia rand(rng, sampler)