## Probability Distributions

## Built-In Distributions

`Gen.bernoulli`

— Constant.`bernoulli(prob_true::Real)`

Samples a `Bool`

value which is true with given probability

`Gen.normal`

— Constant.`normal(mu::Real, std::Real)`

Samples a `Float64`

value from a normal distribution.

`Gen.mvnormal`

— Constant.`mvnormal(mu::AbstractVector{T}, cov::AbstractMatrix{U}} where {T<:Real,U<:Real}`

Samples a `Vector{Float64}`

value from a multivariate normal distribution.

`Gen.gamma`

— Constant.`gamma(shape::Real, scale::Real)`

Sample a `Float64`

from a gamma distribution.

`Gen.inv_gamma`

— Constant.`inv_gamma(shape::Real, scale::Real)`

Sample a `Float64`

from a inverse gamma distribution.

`Gen.beta`

— Constant.`beta(alpha::Real, beta::Real)`

Sample a `Float64`

from a beta distribution.

`Gen.categorical`

— Constant.`categorical(probs::AbstractArray{U, 1}) where {U <: Real}`

Given a vector of probabilities `probs`

where `sum(probs) = 1`

, sample an `Int`

`i`

from the set {1, 2, .., `length(probs)`

} with probability `probs[i]`

.

`Gen.uniform`

— Constant.`uniform(low::Real, high::Real)`

Sample a `Float64`

from the uniform distribution on the interval [low, high].

`Gen.uniform_discrete`

— Constant.`uniform_discrete(low::Integer, high::Integer)`

Sample an `Int`

from the uniform distribution on the set {low, low + 1, ..., high-1, high}.

`Gen.poisson`

— Constant.`poisson(lambda::Real)`

Sample an `Int`

from the Poisson distribution with rate `lambda`

.

`Gen.piecewise_uniform`

— Constant.`piecewise_uniform(bounds, probs)`

Samples a `Float64`

value from a piecewise uniform continuous distribution.

There are `n`

bins where `n = length(probs)`

and `n + 1 = length(bounds)`

. Bounds must satisfy `bounds[i] < bounds[i+1]`

for all `i`

. The probability density at `x`

is zero if `x <= bounds[1]`

or `x >= bounds[end]`

and is otherwise `probs[bin] / (bounds[bin] - bounds[bin+1])`

where `bounds[bin] < x <= bounds[bin+1]`

.

`Gen.beta_uniform`

— Constant.`beta_uniform(theta::Real, alpha::Real, beta::Real)`

Samples a `Float64`

value from a mixture of a uniform distribution on [0, 1] with probability `1-theta`

and a beta distribution with parameters `alpha`

and `beta`

with probability `theta`

.

## Defining New Distributions

Probability distributions are singleton types whose supertype is `Distribution{T}`

, where `T`

indicates the data type of the random sample.

`abstract type Distribution{T} end`

By convention, distributions have a global constant lower-case name for the singleton value. For example:

```
struct Bernoulli <: Distribution{Bool} end
const bernoulli = Bernoulli()
```

Distributions must implement two methods, `random`

and `logpdf`

.

`random`

returns a random sample from the distribution:

```
x::Bool = random(bernoulli, 0.5)
x::Bool = random(Bernoulli(), 0.5)
```

`logpdf`

returns the log probability (density) of the distribution at a given value:

```
logpdf(bernoulli, false, 0.5)
logpdf(Bernoulli(), false, 0.5)
```

Distribution values should also be callable, which is a syntactic sugar with the same behavior of calling `random`

:

`bernoulli(0.5) # identical to random(bernoulli, 0.5) and random(Bernoulli(), 0.5)`

A new Distribution type must implement the following methods:

`Gen.random`

— Function.`val::T = random(dist::Distribution{T}, args...)`

Sample a random choice from the given distribution with the given arguments.

`Gen.logpdf`

— Function.`lpdf = logpdf(dist::Distribution{T}, value::T, args...)`

Evaluate the log probability (density) of the value.

`Gen.has_output_grad`

— Function.`has::Bool = has_output_grad(dist::Distribution)`

Return true of the gradient if the distribution computes the gradient of the logpdf with respect to the value of the random choice.

`Gen.logpdf_grad`

— Function.`grads::Tuple = logpdf_grad(dist::Distribution{T}, value::T, args...)`

Compute the gradient of the logpdf with respect to the value, and each of the arguments.

If `has_output_grad`

returns false, then the first element of the returned tuple is `nothing`

. Otherwise, the first element of the tuple is the gradient with respect to the value. If the return value of `has_argument_grads`

has a false value for at position `i`

, then the `i+1`

th element of the returned tuple has value `nothing`

. Otherwise, this element contains the gradient with respect to the `i`

th argument.

A new Distribution type must also implement `has_argument_grads`

.