File: Multinomial.hs

package info (click to toggle)
bali-phy 4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 15,392 kB
  • sloc: cpp: 120,442; xml: 13,966; haskell: 9,975; python: 2,936; yacc: 1,328; perl: 1,169; lex: 912; sh: 343; makefile: 26
file content (40 lines) | stat: -rw-r--r-- 1,258 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
module Probability.Distribution.Multinomial where

import Probability.Random
import MCMC
import Probability.Distribution.Binomial

foreign import bpcall "Distribution:multinomial_density" builtin_multinomial_density :: Int -> EVector Double -> EVector Int -> LogDouble

data Multinomial = Multinomial Int [Double]

instance Dist Multinomial where
    type Result Multinomial = [Int]
    dist_name _ = "multinomial"

instance IOSampleable Multinomial where
    sampleIO (Multinomial n ps) = sampleIO $ sample_multinomial n ps

instance HasPdf Multinomial where
    pdf (Multinomial n ps) ks | length ks /= n  = 0
                              | otherwise       = multinomial_density n ps ks

instance HasAnnotatedPdf Multinomial where
    annotated_densities dist = make_densities $ pdf dist

instance Sampleable Multinomial where
    sample (Multinomial n ps) = sample_multinomial n ps

multinomial_density n ps ks = builtin_multinomial_density n ps' ks'
    where ps' = toVector ps
          ks' = toVector ks

sample_multinomial n [] = return []
sample_multinomial n (p:ps) = do
  let normalize xs = map (/sum xs) xs
  m <- sample $ binomial n p
  ms <- sample_multinomial (n-m) (normalize ps)
  return (m:ms)

multinomial ps = Multinomial (length ps) ps