packages feed

monte-carlo-0.2: examples/Sampling.hs

module Main
    where

import Control.Monad.MC
import Control.Monad
import Data.List( foldl' )
import System.Environment( getArgs )
import Text.Printf( printf )


-- | Sample from a binomial distribution with the given parameters.
binomial :: (MonadMC m) => Int -> Double -> m Int
binomial n p = let
    q     = 1 - p
    probs = map (\i -> (fromIntegral $ n `choose` i) * p^^i * q^^(n-i)) [0..n]
    in sampleIntWithWeights probs (n+1)

-- | Get a sample confidence interval for the mean after @reps@ replications of
-- a binomial with the given parameters.
binomialMean :: (MonadMC m) => Int -> Double -> Int -> m (Double,Double)
binomialMean n p reps =
    liftM (sampleCI 0.95) $ repeatMC reps $ liftM fromIntegral (binomial n p)

-- | Compute @reps@ 95% confidence intervals for the mean of an @(n,p)@
-- binormal based on samples of the given size, and record the number
-- of intervals that contain the true mean.
coverage :: (MonadMC m) => Int -> Double -> Int -> Int -> m Int
coverage n p size reps =
    repeatMCWith
        (\c ci -> if mu `inInterval` ci then c+1 else c)
        0
        reps
        (binomialMean n p size)
  where
    mu = fromIntegral n * p
    x `inInterval` (l,h) = x > l && x < h

main = do
    [reps] <- map read `fmap` getArgs
    main' reps

main' reps =
    let seed = 0
        n    = 10
        p    = 0.2
        size = 500
        c    = evalMC (coverage n p size reps) $ mt19937 seed in
    printf "\nOf %d 95%%-intervals, %d contain the true value.\n" reps c


---------------------------   Utility functions -----------------------------

factorial :: Int -> Int
factorial n | n <= 0    = 1
            | otherwise = n * factorial (n-1)

choose :: Int -> Int -> Int
choose n k = factorial n `div` (factorial (n-k) * factorial k)