Skip to content

Instantly share code, notes, and snippets.

@dharasim
Created August 25, 2022 11:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dharasim/a230586c53d1fb1f7b1041103daf2297 to your computer and use it in GitHub Desktop.
Save dharasim/a230586c53d1fb1f7b1041103daf2297 to your computer and use it in GitHub Desktop.
using Distributions
using Random: AbstractRNG
using StatsBase: proportionmap
using Test
# Generic categoricals are also known as empirical measures.
struct GenericCategorical{T}
mapping :: Dict{T, Float64}
values :: Vector{T}
probs :: Vector{Float64}
function GenericCategorical(weights::Dict{T, Float64}) where T
mapping = Dict(k => v/sum(values(weights)) for (k,v) in weights)
new{T}(mapping, collect(keys(mapping)), collect(values(mapping)))
end
end
GenericCategorical(xs::AbstractVector) = GenericCategorical(proportionmap(xs))
# We implement the simplest interface for distributions, consisting of
# random sampling and the evaluation of probabilities.
Distributions.logpdf(gc::GenericCategorical, x) = log(gc.mapping[x])
function Base.rand(rng::AbstractRNG, gc::GenericCategorical)
i = rand(rng, Categorical(gc.probs))
gc.values[i]
end
@testset "Generic categorical" begin
gc = GenericCategorical([1, 1, 1, 2, 2, 3])
@test rand(gc) in [1, 2, 3]
@test rand(gc) isa Int
@test logpdf(gc, 1) > logpdf(gc, 2) > logpdf(gc, 3)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment