using Iterators
multEval(x::Vector{Int}, n::Int, p::Vector{Float64}) = (factorial(n) / prod(gamma(x+1))) * prod(p.^x)
# multinomial entropy
function multEnt(n::Int, p::Vector{Float64})
@assert n >= 0
multientropy = 0
for par in partitions(n)
if length(par) <= length(p)
point = vcat(par, zeros(Int, max(0, length(p)-length(par))))
for perm in Set(permutations(point))
multientropy -= multEval(perm, n, p) * log(multEval(perm, n, p))
end
end
end
return multientropy
end
# efficient multinomial entropy
function func(n::Int, p::Vector{Float64})
@assert n >= 0
multientropy = (-log(factorial(n)) - n*sum(p.*log(p))
+ sum([sum([binomial(n, x) * p[i]^x * (1 - p[i])^(n - x) * log(factorial(x)) for x in 0:n]) for i in 1:length(p)]))
return multientropy
end