It’s this issue. I adapted the Categorical
code, but I didn’t make a PR out of it:
""" Provides AnyCategoricals, which is just like Distributions.Categorical, but
can have an arbitrary domain (aka support). """
module AnyCategoricals
export AnyCategorical
importall Distributions
using Distributions: NoArgCheck, @check_args
doc"""
AnyCategorical(support, p)
A *AnyCategorical distribution* is parameterized by a probability vector `p` over a support vector `support` of the same length.
$P(X = k) = p[k] \quad \text{for } k = 1, 2, \ldots, K.$
`p` must be a real vector, of which all components are nonnegative and sum to one.
**Note:** The input vector `p` is directly used as a field of the constructed distribution, without being copied.
External links:
* [Categorical distribution on Wikipedia](http://en.wikipedia.org/wiki/Categorical_distribution)
"""
immutable AnyCategorical{U, T<:Real} <: DiscreteUnivariateDistribution
support::Vector{U}
p::Vector{T}
AnyCategorical(support::Vector{U}, p::Vector{T}, ::NoArgCheck) =
new(support, p)
function AnyCategorical(support::Vector{U}, p::Vector{T})
@assert isprobvec(p) "The given vector $p must sum to 1"
@assert length(support) == length(p) "$support and $p must have the same length"
@assert length(unique(support)) == length(support) "Duplicates in `support`"
new(support, p)
end
end
AnyCategorical{U, T}(support::Vector{U}, p::Vector{T}) =
AnyCategorical{U, T}(support, p)
AnyCategorical{K, V}(di::Associative{K, V}) =
AnyCategorical{K, V}(collect(keys(di)), collect(values(di)))
ncategories(d::AnyCategorical) = length(d.support)
probs(d::AnyCategorical) = d.p
params(d::AnyCategorical) = (d.support, d.p,)
support(d::AnyCategorical) = d.support
@inline partype{T<:Real}(d::AnyCategorical{T}) = T
mode(d::AnyCategorical) = support(d)[indmax(probs(d))]
get_index(d::AnyCategorical, x) = find(y->y==x, d.support)[1]
pdf(d::AnyCategorical) = copy(d.p)
_pdf{U, T}(d::AnyCategorical{U, T}, x) =
insupport(d, x) ? d.p[get_index(d, x)] : zero(T)
pdf(d::AnyCategorical, x) = _pdf(d, x)
insupport(d::AnyCategorical, x) = x in support(d)
# Disambiguations
pdf(d::AnyCategorical, x::Integer) = _pdf(d, x)
pdf(d::AnyCategorical, x::Real) = _pdf(d, x)
insupport(d::AnyCategorical, x::Integer) = x in support(d)
insupport(d::AnyCategorical, x::Real) = x in support(d)
end