Copyright | (c) Casper M. H. Holmgreen |
---|---|
License | MIT |
Maintainer | cholmgreen@gmail.com |
Stability | unstable |
Portability | portable |
Safe Haskell | None |
Language | Haskell98 |
The goal of Carbon is to capture idiomatic usage patterns for Monte Carlo simulations in an easy to use interface. Currently, only one pattern is implemented but more are planned.
There are two main parts to the library:
- The
MonteCarlo
monad for building simulations - The
Result
type family for describing how to aggregate results
Running a simulation will require a basic understanding of how to use both.
Control.Monad.MonteCarlo exports the RandomGen
typeclass for convenience.
- type MonteCarlo g = State g
- experimentS :: (RandomGen g, Result s) => MonteCarlo g (Obs s) -> Int -> g -> s
- experimentP :: (RandomGen g, Result s) => MonteCarlo g (Obs s) -> Int -> Int -> g -> s
- runMC :: RandomGen g => MonteCarlo g a -> g -> (a, g)
- evalMC :: RandomGen g => MonteCarlo g a -> g -> a
- random :: (RandomGen g, Random a) => MonteCarlo g a
- randomR :: (RandomGen g, Random a) => (a, a) -> MonteCarlo g a
- class RandomGen g
Running Simulations
Running simulations should be done using the high level functions provided here.
Monte Carlo simulations are specified by two parts: a MonteCarlo
action and a type annotation describing how to aggregate the results.
See Result
for more information.
type MonteCarlo g = State g Source
The MonteCarlo
monad is just a State
monad in disguise.
This allows us to thread the internal PRNG state through the simulation as we sample new numbers.
experimentS :: (RandomGen g, Result s) => MonteCarlo g (Obs s) -> Int -> g -> s Source
This is a high level function for running a full Monte Carlo simulation.
It takes a MonteCarlo
action, the number of observations to aggregate, and an instance of RandomGen
.
The return value is dictated by the type family Result
; a type annotation is required to specify how observations should be aggregated.
For example, given a MonteCarlo
action, mySim, with type:
mySim :: RandomGen g => MonteCarlo g Bool
We can get radically different results with just a type annotation:
experimentS mySimulation 100 g :: [Bool] experimentS mySimulation 100 g :: BoolSumm
experimentP :: (RandomGen g, Result s) => MonteCarlo g (Obs s) -> Int -> Int -> g -> s Source
This is a high level function for running a full Monte Carlo simulation in parallel.
It is identical to experimentS
except that it takes an additional Int argument representing the chunk size.
Determining a good chunk size is an art, but a good starting point may be to divide the number of runs by 200.
Note: you must compile an executable with the -threaded flag in order for sparks to run in parallel.
Building Simulations
Simulations are built by structuring MonteCarlo
actions over top of eachother, in a manner similar to parser combinators.
This compositional approach makes it very easy to express complex simulations without sacrificing readability.
Additionally, more complex simulations can layer monad transformers overtop of MonteCarlo
to add support for State, RO-environments, etc.
random :: (RandomGen g, Random a) => MonteCarlo g a Source
randomR :: (RandomGen g, Random a) => (a, a) -> MonteCarlo g a Source