-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Probabilistic Functional Programming -- -- The Library allows exact computation with discrete random variables in -- terms of their distributions by using a monad. The monad is similar to -- the List monad for non-deterministic computations, but extends the -- List monad by a measure of probability. Small interface to R plotting. @package probability @version 0.2.4 -- | Collection of some shapes of distribution. module Numeric.Probability.Shape -- | A shape is a mapping from the interval [0,1] to non-negative -- numbers. They need not to be normalized (sum up to 1) because this is -- done by subsequent steps. (It would also be impossible to normalize -- the function in a way that each discretization is normalized as well.) type T prob = prob -> prob linear :: Fractional prob => T prob uniform :: Fractional prob => T prob negExp :: Floating prob => T prob normal :: Floating prob => T prob normalCurve :: Floating prob => prob -> prob -> prob -> prob -- | Deterministic and probabilistic values module Numeric.Probability.Distribution type Event a = a -> Bool oneOf :: Eq a => [a] -> Event a just :: Eq a => a -> Event a -- | Probability disribution -- -- The underlying data structure is a list. Unfortunately we cannot use a -- more efficient data structure because the key type must be of class -- Ord, but the Monad class does not allow constraints for -- result types. The Monad instance is particularly useful because many -- generic monad functions make sense here, monad transformers can be -- used and the monadic design allows to simulate probabilistic games in -- an elegant manner. -- -- We have the same problem like making Data.Set an instance of -- Monad, see -- http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros -- -- If you need efficiency, you should remove redundant elements by -- norm. norm converts to Map and back internally -- and you can hope that the compiler fuses the lists with the -- intermediate Map structure. -- -- The defined monad is equivalent to WriterT (Product prob) [] -- a. See -- http://www.randomhacks.net/articles/2007/02/21/refactoring-probability-distributions. newtype T prob a Cons :: [(a, prob)] -> T prob a decons :: T prob a -> [(a, prob)] certainly :: Num prob => a -> T prob a errorMargin :: RealFloat prob => prob -- | Check whether two distributions are equal when neglecting rounding -- errors. We do not want to put this into an Eq instance, since -- it is not exact equivalence and it seems to be too easy to mix it up -- with liftM2 (==) x y. approx :: (RealFloat prob, Ord a) => T prob a -> T prob a -> Bool lift :: Num prob => ([(a, prob)] -> [(a, prob)]) -> T prob a -> T prob a size :: T prob a -> Int check :: (RealFloat prob, Show prob) => T prob a -> T prob a -- | can fail because of rounding errors, better use fromFreqs cons :: (RealFloat prob, Show prob) => [(a, prob)] -> T prob a sumP :: Num prob => [(a, prob)] -> prob sortP :: Ord prob => [(a, prob)] -> [(a, prob)] sortElem :: Ord a => [(a, prob)] -> [(a, prob)] norm :: (Num prob, Ord a) => T prob a -> T prob a norm' :: (Num prob, Ord a) => [(a, prob)] -> [(a, prob)] norm'' :: (Num prob, Ord a) => [(a, prob)] -> [(a, prob)] -- | pretty printing pretty :: (Ord a, Show a, Num prob, Ord prob) => (prob -> String) -> T prob a -> String (//%) :: (Ord a, Show a) => T Rational a -> () -> IO () equal :: (Num prob, Eq prob, Ord a) => T prob a -> T prob a -> Bool -- | distribution generators type Spread prob a = [a] -> T prob a choose :: Num prob => prob -> a -> a -> T prob a enum :: Fractional prob => [Int] -> Spread prob a -- | Give a list of frequencies, they do not need to sum up to 1. relative :: Fractional prob => [prob] -> Spread prob a shape :: Fractional prob => (prob -> prob) -> Spread prob a linear :: Fractional prob => Spread prob a uniform :: Fractional prob => Spread prob a negExp :: Floating prob => Spread prob a normal :: Floating prob => Spread prob a -- | extracting and mapping the domain of a distribution extract :: T prob a -> [a] -- | fmap with normalization map :: (Num prob, Ord b) => (a -> b) -> T prob a -> T prob b -- | unfold a distribution of distributions into one distribution, this is -- join with normalization. unfold :: (Num prob, Ord a) => T prob (T prob a) -> T prob a -- | conditional distribution cond :: Num prob => T prob Bool -> T prob a -> T prob a -> T prob a truth :: Num prob => T prob Bool -> prob -- | conditional probability, identical to filter (?=<<) :: Fractional prob => (a -> Bool) -> T prob a -> T prob a -- | filter in infix form. Can be considered an additional monadic -- combinator, which can be used where you would want guard -- otherwise. (>>=?) :: Fractional prob => T prob a -> (a -> Bool) -> T prob a -- | filtering distributions data Select a Case :: a -> Select a Other :: Select a above :: (Num prob, Ord prob, Ord a) => prob -> T prob a -> T prob (Select a) fromFreqs :: Fractional prob => [(a, prob)] -> T prob a filter :: Fractional prob => (a -> Bool) -> T prob a -> T prob a mapMaybe :: Fractional prob => (a -> Maybe b) -> T prob a -> T prob b -- | selecting from distributions selectP :: (Num prob, Ord prob) => T prob a -> prob -> a scanP :: (Num prob, Ord prob) => prob -> [(a, prob)] -> a (??) :: Num prob => Event a -> T prob a -> prob -- | expectation value expected :: Num a => T a a -> a -- | statistical analyses variance :: Num a => T a a -> a stdDev :: Floating a => T a a -> a instance Eq a => Eq (Select a) instance Ord a => Ord (Select a) instance Show a => Show (Select a) instance (Num prob, Ord prob, Ord a, Fractional a) => Fractional (T prob a) instance (Num prob, Ord prob, Ord a, Num a) => Num (T prob a) instance Eq (T prob a) instance (Num prob, Ord prob, Show prob, Ord a, Show a) => Show (T prob a) instance Functor (T prob) instance Num prob => Applicative (T prob) instance Num prob => Monad (T prob) -- | Deterministic and probabilistic generators module Numeric.Probability.Transition -- | deterministic generator type Change a = a -> a -- | probabilistic generator type T prob a = a -> T prob a id :: Num prob => T prob a -- | map maps a change function to the result of a transformation -- (map is somehow a lifted form of map) The restricted -- type of f results from the fact that the argument to -- t cannot be changed to b in the result T -- type. map :: (Num prob, Ord a) => Change a -> T prob a -> T prob a -- | unfold a distribution of transitions into one transition -- -- NOTE: The argument transitions must be independent unfold :: (Num prob, Ord a) => T prob (T prob a) -> T prob a -- | Composition of transitions similar to compose but with -- intermediate duplicate elimination. compose :: (Num prob, Ord a) => [T prob a] -> T prob a untilLeft :: (Num prob, Ord a, Ord b) => (a -> T prob (Either b a)) -> T prob a -> T prob b -- | In fix $ go a -> do ...; go xy any action after a -- go is ignored. fix :: (Num prob, Ord a, Ord b) => ((a -> EitherT a (T prob) b) -> (a -> EitherT a (T prob) b)) -> T prob a -> T prob b -- | functions to convert a list of changes into a transition type SpreadC prob a = [Change a] -> T prob a apply :: Num prob => Change a -> T prob a maybe :: Num prob => prob -> Change a -> T prob a lift :: Spread prob a -> SpreadC prob a uniform :: Fractional prob => SpreadC prob a linear :: Fractional prob => SpreadC prob a normal :: Floating prob => SpreadC prob a enum :: RealFloat prob => [Int] -> SpreadC prob a relative :: RealFloat prob => [prob] -> SpreadC prob a -- | functions to convert a list of transitions into a transition type SpreadT prob a = [T prob a] -> T prob a liftT :: (Num prob, Ord a) => Spread prob (T prob a) -> SpreadT prob a uniformT :: (Fractional prob, Ord a) => SpreadT prob a linearT :: (Fractional prob, Ord a) => SpreadT prob a normalT :: (Floating prob, Ord a) => SpreadT prob a enumT :: (RealFloat prob, Ord a) => [Int] -> SpreadT prob a relativeT :: (RealFloat prob, Ord a) => [prob] -> SpreadT prob a module Numeric.Probability.Example.Alarm type Probability = Rational type Dist a = T Probability a type PBool = T Probability Bool flp :: Probability -> PBool -- | prior burglary 1% b :: PBool -- | prior earthquake 0.1% e :: PBool -- | conditional probability of alarm given burglary and earthquake a :: Bool -> Bool -> PBool -- | conditional probability of john calling given alarm j :: Bool -> PBool -- | conditional probability of mary calling given alarm m :: Bool -> PBool -- | calculate the full joint distribution data Burglary B :: Bool -> Bool -> Bool -> Bool -> Bool -> Burglary burglary :: Burglary -> Bool earthquake :: Burglary -> Bool alarm :: Burglary -> Bool john :: Burglary -> Bool mary :: Burglary -> Bool bJoint :: Dist Burglary -- | what is the probability that mary calls given that john calls? pmj :: Probability instance Eq Burglary instance Ord Burglary instance Show Burglary -- | Approach: model a node with k predecessors as a function with k -- parameters module Numeric.Probability.Example.Bayesian type Probability = Rational type Dist a = T Probability a type State a = [a] type PState a = Dist (State a) type STrans a = State a -> PState a type SPred a = a -> State a -> Bool event :: Probability -> a -> STrans a happens :: Eq a => SPred a network :: [STrans a] -> PState a source :: Probability -> a -> STrans a bin :: Eq a => a -> a -> Probability -> Probability -> Probability -> Probability -> a -> STrans a -- | Two possible causes for one effect data Nodes A :: Nodes B :: Nodes E :: Nodes g :: PState Nodes e, bE, aE :: Probability instance Eq Nodes instance Ord Nodes instance Show Nodes -- | Consider a family of two children. Given that there is a boy in the -- family, what is the probability that there are two boys in the family? module Numeric.Probability.Example.Boys type Probability = Rational type Dist a = T Probability a data Child Boy :: Child Girl :: Child type Family = (Child, Child) birth :: Dist Child family :: Dist Family allBoys :: Event Family existsBoy :: Event Family familyWithBoy :: Dist Family twoBoys :: Probability countBoy :: Child -> Int countBoys :: Family -> Int numBoys :: Dist Int instance Eq Child instance Ord Child instance Show Child -- | You take part in a screening test for a disease that you have with a -- probability pDisease. The test can fail in two ways: If you are -- ill, the test says with probability pFalseNegative that you are -- healthy. If you are healthy, it says with probability -- pFalsePositive that you are ill. -- -- Now consider the test is positive - what is the probability that you -- are indeed ill? module Numeric.Probability.Example.Diagnosis type Probability = Rational type Dist a = T Probability a data State Healthy :: State Ill :: State data Finding Negative :: Finding Positive :: Finding pDisease, pFalsePositive, pFalseNegative :: Probability dist :: Dist (State, Finding) -- | Alternative way for computing the distribution. It is usually more -- efficient because we do not need to switch on the healthy state. distAlt :: Dist (State, Finding) p :: Probability instance Eq State instance Ord State instance Show State instance Enum State instance Eq Finding instance Ord Finding instance Show Finding instance Enum Finding module Numeric.Probability.Example.Dice type Die = Int type Probability = Rational type Dist = T Probability die :: Dist Die -- | product of independent distributions twoDice :: Dist (Die, Die) dice :: Int -> Dist [Die] twoSixes :: Probability -- | sixes p n computes the probability of getting p sixes -- (>1, ==2, ...) when rolling n dice sixes :: (Int -> Bool) -> Int -> Probability droll :: Dist Die g3 :: Probability addTwo :: Dist Die -- | Ceneralization of Numeric.Probability.Example.Boys -- -- Consider a family of n children. Given that there are k boys in the -- family, what is the probability that there are m boys in the family? module Numeric.Probability.Example.NBoys type Family = [Child] family :: Int -> Dist Family countBoys :: Family -> Int boys :: Int -> Event Family nBoys :: Int -> Int -> Int -> Probability numBoys :: Int -> Int -> Dist Int -- | only boys in a family that has one boy onlyBoys1 :: Int -> Probability -- | The newspaper Sueddeutsche asked their readers what professions -- 16 persons have, by only showing the photographies of them and three -- choices. -- -- Their statistics was: 22% readers had 0 to 5 correct answers (category -- 0) 75% readers had 6 to 11 correct answers (category 1) 3% readers had -- 12 to 16 correct answers (category 2) -- -- Can this statistics be explained with random guessing, or is there -- some information in the photographies that the readers could utilize? -- -- I got 6 correct answers. module Numeric.Probability.Example.Profession type Probability = Double type Dist a = T Probability a correctAnswers :: Dist Int categories :: Dist Int -- | Randomized values module Numeric.Probability.Random -- | Random values newtype T a Cons :: State StdGen a -> T a decons :: T a -> State StdGen a randomR :: Random a => (a, a) -> T a -- | Run random action in IO monad. run :: T a -> IO a -- | Run random action without IO using a seed. runSeed :: StdGen -> T a -> a print :: Show a => T a -> IO () pick :: (Num prob, Ord prob, Random prob) => T prob a -> T a -- | Randomized distribution type Distribution prob a = T (T prob a) above :: (Num prob, Ord prob, Ord a) => prob -> Distribution prob a -> Distribution prob (Select a) -- | dist converts a list of randomly generated values into a -- distribution by taking equal weights for all values. Thus dist -- (replicate n rnd) simulates rnd n times and -- returns an estimation of the distribution represented by rnd. dist :: (Fractional prob, Ord a) => [T a] -> Distribution prob a -- | random change type Change a = a -> T a change :: (Num prob, Ord prob, Random prob) => T prob a -> Change a -- | random transition type Transition prob a = a -> Distribution prob a type ApproxDist a = T [a] instance Applicative T instance Functor T instance Monad T -- | Tracing module Numeric.Probability.Trace type Trace a = [a] type Walk a = a -> Trace a type Space prob a = Trace (T prob a) type Expand prob a = a -> Space prob a -- | walk is a bounded version of the predefined function iterate walk :: Int -> Change a -> Walk a type RTrace a = T (Trace a) type RWalk a = a -> RTrace a type RSpace prob a = T (Space prob a) type RExpand prob a = a -> RSpace prob a -- | merge converts a list of RTraces into a list of -- randomized distributions, i.e., an RSpace, by creating a -- randomized distribution for each list position across all traces merge :: (Fractional prob, Ord a) => [RTrace a] -> RSpace prob a zipListWith :: ([a] -> b) -> [[a]] -> [b] -- | Number type based on Float with formatting in percents. module Numeric.Probability.Percentage newtype T Cons :: Float -> T percent :: Float -> T showPfix :: (RealFrac prob, Show prob) => Int -> prob -> String roundRel :: RealFrac a => Int -> a -> a -- | Print distribution as table with configurable precision. (//) :: (Ord a, Show a) => Dist a -> Int -> IO () (//*) :: (Ord a, Show a) => Dist a -> (Int, Int) -> IO () liftP :: (Float -> Float) -> T -> T liftP2 :: (Float -> Float -> Float) -> T -> T -> T type Dist a = T T a type Spread a = [a] -> Dist a type RDist a = T (Dist a) type Trans a = a -> Dist a type Space a = Trace (Dist a) type Expand a = a -> Space a type RTrans a = a -> RDist a type RSpace a = T (Space a) type RExpand a = a -> RSpace a instance Eq T instance Ord T instance Random T instance Floating T instance Fractional T instance Num T instance Show T module Numeric.Probability.Expectation class ToFloat a toFloat :: ToFloat a => a -> Float class FromFloat a fromFloat :: FromFloat a => Float -> a class Expected a expected :: Expected a => a -> Float floatDist :: (ToFloat prob, Expected a) => T prob a -> T Float Float -- | statistical analyses variance :: Expected a => Dist a -> Float stdDev :: Expected a => Dist a -> Float instance (ToFloat prob, Expected a) => Expected (T prob a) instance Expected a => Expected [a] instance Expected Integer instance Expected Int instance Expected Float instance FromFloat Integer instance FromFloat Int instance FromFloat Float instance ToFloat T instance ToFloat Integer instance ToFloat Int instance ToFloat Float -- | Simulation module Numeric.Probability.Simulation -- | Simulation means to repeat a Rnd.change change many times and to -- accumulate all results into a distribution. Therefore, simulation can -- be regarded as an approximation of distributions through -- randomization. -- -- The Sim class allows the overloading of simulation for different kinds -- of generators, namely transitions and Rnd.change changes: -- -- class C c (~.) :: (C c, Fractional prob, Ord prob, Random prob, Ord a) => Int -> (a -> c a) -> Transition prob a (~..) :: (C c, Fractional prob, Ord prob, Random prob, Ord a) => (Int, Int) -> (a -> c a) -> RExpand prob a (~*.) :: (C c, Fractional prob, Ord prob, Random prob, Ord a) => (Int, Int) -> (a -> c a) -> Transition prob a instance C T instance (Num prob, Ord prob, Random prob) => C (T prob) module Numeric.Probability.Example.MontyHall data Door A :: Door B :: Door C :: Door doors :: [Door] data State Doors :: Door -> Door -> Door -> State prize :: State -> Door chosen :: State -> Door opened :: State -> Door -- | initial configuration of the game status start :: State -- | Steps of the game: -- --
    --
  1. hide the prize
  2. --
  3. choose a door
  4. --
  5. open a non-open door, not revealing the prize
  6. --
  7. apply strategy: switch or stay
  8. --
hide :: Trans State choose :: Trans State open :: Trans State type Strategy = Trans State switch :: Strategy stay :: Strategy game :: Strategy -> Trans State data Outcome Win :: Outcome Lose :: Outcome result :: State -> Outcome eval :: Strategy -> Dist Outcome simEval :: Int -> Strategy -> RDist Outcome firstChoice :: Dist Outcome switch' :: Trans Outcome type StrategyM = Door -> Door -> Door stayM :: StrategyM switchM :: StrategyM evalM :: StrategyM -> Dist Outcome instance Eq Door instance Ord Door instance Show Door instance Eq State instance Ord State instance Show State instance Eq Outcome instance Ord Outcome instance Show Outcome -- | Abstract interface to probabilistic objects like random generators and -- probability distributions. It allows to use the same code both for -- computing complete distributions and for generating random values -- according to the distribution. The latter one is of course more -- efficient and may be used for approximation of the distribution by -- simulation. -- -- Maybe a better name is Experiment. module Numeric.Probability.Object class Monad obj => C prob obj | obj -> prob fromFrequencies :: C prob obj => [(a, prob)] -> obj a type Spread obj a = [a] -> obj a shape :: (C prob obj, Fractional prob) => (prob -> prob) -> Spread obj a linear :: (C prob obj, Fractional prob) => Spread obj a uniform :: (C prob obj, Fractional prob) => Spread obj a negExp :: (C prob obj, Floating prob) => Spread obj a normal :: (C prob obj, Floating prob) => Spread obj a enum :: (C prob obj, Floating prob) => [Int] -> Spread obj a -- | Give a list of frequencies, they do not need to sum up to 1. relative :: (C prob obj, Floating prob) => [prob] -> Spread obj a instance C prob obj => C prob (EitherT b obj) instance Fractional prob => C prob (T prob) instance C Double T -- | Model: -- -- one server serving customers from one queue module Numeric.Probability.Example.Queuing type Time = Int -- | (servingTime, nextArrival) type Profile = (Time, Time) type Event a = (a, Profile) -- | customers and their individual serving times type Queue a = [(a, Time)] -- | (customers waiting,validity period of that queue) type State a = (Queue a, Time) type System a = [([a], Time)] type Events a = [Event a] event :: Time -> Events a -> Queue a -> [State a] system :: Events a -> System a -- | multiple servers mEvent :: Int -> Time -> Events a -> Queue a -> [State a] -- | decrease served customers remaining time by specified amount mServe :: Int -> Int -> Queue a -> Queue a -- | time until next completion mTimeStep :: Int -> Queue a -> Int mSystem :: Int -> Events a -> System a type RProfile = (Dist Time, Trans Time) type REvent a = (a, RProfile) type REvents a = [REvent a] rSystem :: Int -> REvents a -> T (System a) rBuildEvents :: REvents a -> T (Events a) rmSystem :: Ord a => Int -> Int -> REvents a -> RDist (System a) evalSystem :: (Ord a, Ord b) => Int -> Int -> REvents a -> (System a -> b) -> RDist b unit :: b -> ((), b) maxQueue :: Ord a => System a -> Int allWaiting :: Ord a => Int -> System a -> [a] countWaiting :: Ord a => Int -> System a -> Int waiting :: Int -> System a -> Time inSystem :: System a -> Time total :: System a -> Time server :: Int -> System a -> Time idle :: Int -> System a -> Time idleAvgP :: Int -> System a -> Float module Numeric.Probability.Example.Barber custServ :: Dist Time nextCust :: Trans Time barbers :: Int customers :: Int runs :: Int barberEvent :: ((), (Dist Time, Time -> Dist Time)) barberEvents :: [((), (Dist Time, Time -> Dist Time))] barberSystem :: Ord b => (System () -> b) -> RDist b data Category ThreeOrLess :: Category FourToTen :: Category MoreThanTen :: Category cat :: Time -> Category perc :: Float -> String -- | avg barber idle time barberIdle :: RDist String -- | avg customer waiting time (unserved customers) customerWait :: RDist Category instance Eq Category instance Ord Category instance Show Category module Numeric.Probability.Example.Collection type Collection a = [a] type Probability = Rational selectOne :: Fractional prob => StateT (Collection a) (T prob) a select1 :: Fractional prob => Collection a -> T prob a select2 :: Fractional prob => Collection a -> T prob (a, a) select :: Fractional prob => Int -> Collection a -> T prob [a] data Marble R :: Marble G :: Marble B :: Marble bucket :: Collection Marble jar :: Collection Marble pRGB :: Probability pRG :: Probability data Suit Club :: Suit Spade :: Suit Heart :: Suit Diamond :: Suit data Rank Plain :: Int -> Rank Jack :: Rank Queen :: Rank King :: Rank Ace :: Rank type Card = (Rank, Suit) plains :: [Rank] faces :: [Rank] isFace :: Card -> Bool isPlain :: Card -> Bool ranks :: [Rank] suits :: [Suit] deck :: Collection Card -- | mini-blackjack: draw 2 cards, and if value is less than 14, continue -- drawing until value equals or exceeds 14. if values exceeds 21, you -- lose, otherwise you win. value :: Card -> Int totalValue :: Collection Card -> Int draw :: Fractional prob => ([Card], Collection Card) -> T prob ([Card], Collection Card) drawF :: ([Card], Collection Card) -> Dist ([Card], Collection Card) drawTo16 :: T ([Card], Collection Card) win :: ([Card], b) -> Bool chanceWin :: (Fractional prob, Ord prob, Random prob) => T (T prob Bool) instance Eq Marble instance Ord Marble instance Show Marble instance Eq Suit instance Ord Suit instance Show Suit instance Enum Suit instance Eq Rank instance Ord Rank instance Show Rank -- | We play the following game: We roll a die until we stop or we get -- three spots. In the first case we own all spots obtained so far, in -- the latter case we own nothing. -- -- What is the strategy for maximizing the expected score? module Numeric.Probability.Example.DiceAccum type Score = Int die :: Fractional prob => T prob Die roll :: Fractional prob => T prob (Maybe Score) continue :: Score -> Bool -- | optimal strategy strategy :: Fractional prob => T prob (Maybe Score) -- | distribution of the scores that are achieved with the optimal strategy game :: Fractional prob => T prob (Maybe Score) walk :: Int -> IO (Trace (Maybe Score)) -- | Given a row of n (~50) dice and two players starting with a random -- dice within the first m (~5) dice. Every players moves along the row, -- according the pips on the dice. They stop if a move would exceed the -- row. What is the probability that they stop at the same die? (It is -- close to one.) -- -- Wuerfelschlange (german) -- http:faculty.uml.edurmontenegroresearchkruskal_countkruskal.html -- -- Kruskal's trick -- http:www.math.deexponatewuerfelschlange.html/ module Numeric.Probability.Example.Kruskal type Die = Int type Probability = Rational type Dist = T Probability die :: (C prob experiment, Fractional prob) => Score -> experiment Die type Score = Int -- | We reformulate the problem to the following game: There are two -- players, both of them collect a number of points. In every round the -- player with the smaller score throws a die and adds the pips to his -- score. If the two players somewhen get the same score, then the game -- ends and the score is the result of the game (Just score). If -- one of the players exceeds the maximum score n, then the game stops -- and players lose (Nothing). game :: (C prob experiment, Fractional prob) => Score -> Score -> (Score, Score) -> experiment (Maybe Score) gameRound :: Score -> Score -> Dist (Either (Maybe Score) (Score, Score)) -> Dist (Either (Maybe Score) (Score, Score)) gameFast :: Score -> Score -> Dist (Score, Score) -> Dist (Maybe Score) gameFastEither :: Score -> Score -> Dist (Score, Score) -> Dist (Maybe Score) -- | This version could be generalized to both Random and Distribution -- monad while remaining efficient. gameFastFix :: Score -> Score -> Dist (Score, Score) -> Dist (Maybe Score) -- | In gameFastFix we group the scores by rounds. This leads to a -- growing probability distribution, but we do not need the round number. -- We could process the game in a different way: We only consider the -- game states where the lower score matches the round number. gameLeastScore :: Score -> Score -> Dist (Score, Score) -> Dist (Maybe Score) -- | gameLeastScore can be written in terms of a matrix power. For n -- pips we need a n² × n² matrix. Using symmetries, we reduce it to a -- square matrix with size n·(n+1)/2. -- -- p[n+1,(n+1,n+1)] \ p[n,(n+0,n+0)] \ | p[n+1,(n+1,n+2)] | | -- p[n,(n+0,n+1)] | | p[n+1,(n+1,n+3)] | | p[n,(n+0,n+2)] | | ... | | ... -- | | p[n+1,(n+1,n+6)] | = M/6 · | p[n,(n+0,n+5)] | | p[n+1,(n+2,n+2)] | -- | p[n,(n+1,n+1)] | | ... | | ... | | p[n+1,(n+2,n+6)] | | -- p[n,(n+1,n+5)] | | ... | | ... | p[n+1,(n+6,n+6)] \ p[n,(n+5,n+5)] -- -- -- M[(n+1,(x,y)),(n,(x,y))] = 6 -- -- M[(n+1,(min y (n+d), max y (n+d))), (n,(n,y))] = 1 -- -- M[(n+1,(x1,y1)),(n,(x0,y0))] = 0 flattenedMatrix :: Score -> [Int] startVector :: Score -> [Int] compareMaybe :: Ord a => Maybe a -> Maybe a -> Ordering cumulate :: Ord a => Dist (Maybe a) -> [(Maybe a, Probability)] runExact :: Score -> IO () trace :: Score -> [Score] -> [Score] chop :: [Score] -> [[Score]] meeting :: [Score] -> [Score] -> Maybe Score -- | This is a bruteforce implementation of the original game: We just roll -- the die maxScore times and then jump from die to die -- according to the number of pips. bruteforce :: Score -> Score -> (Score, Score) -> T (Maybe Score) runSimulation :: Score -> IO () latexDie :: Score -> String latexMarkedDie :: Score -> String latexFromChain :: [Score] -> String latexChoppedFromChain :: [Score] -> String makeChains :: IO () module Numeric.Probability.Visualize -- | global settings for one figure data FigureEnv FE :: String -> String -> String -> String -> FigureEnv fileName :: FigureEnv -> String title :: FigureEnv -> String xLabel :: FigureEnv -> String yLabel :: FigureEnv -> String -- | default settings for figure environment figure :: FigureEnv data Color Black :: Color Blue :: Color Green :: Color Red :: Color Brown :: Color Gray :: Color Purple :: Color DarkGray :: Color Cyan :: Color LightGreen :: Color Magenta :: Color Orange :: Color Yellow :: Color White :: Color Custom :: Int -> Int -> Int -> Color data LineStyle Solid :: LineStyle Dashed :: LineStyle Dotted :: LineStyle DotDash :: LineStyle LongDash :: LineStyle TwoDash :: LineStyle type PlotFun = Float -> Float -- | settings for individual plots data Plot Plot :: [Float] -> [Float] -> Color -> LineStyle -> Int -> String -> Plot ys :: Plot -> [Float] xs :: Plot -> [Float] color :: Plot -> Color lineStyle :: Plot -> LineStyle lineWidth :: Plot -> Int label :: Plot -> String -- | default plotting environment plot :: Plot colors :: [Color] setColor :: Plot -> Color -> Plot autoColor :: [Plot] -> [Plot] -- | create a plot from a distribution plotD :: ToFloat a => Dist a -> Plot plotRD :: ToFloat a => RDist a -> IO Plot -- | create a plot from a function plotF :: (FromFloat a, ToFloat b) => (Float, Float, Float) -> (a -> b) -> Plot -- | create a plot from a list plotL :: ToFloat a => [a] -> Plot plotRL :: ToFloat a => T [a] -> IO Plot yls :: [Float] -> Plot -> Plot metaTuple :: [Float] -> [(Float, Float)] -> [(Float, Float)] -- | we want to increase the bounds absolutely, account for negative -- numbers incr, decr :: (Ord a, Fractional a) => a -> a -- | Visualization output type Vis = IO () fig :: [Plot] -> Vis figP :: FigureEnv -> [Plot] -> Vis showParams :: Show a => [a] -> [String] -> String legend :: Float -> Float -> [Plot] -> String drawy :: ToFloat a => Int -> Plot -> [a] -> String vec :: Show a => [a] -> String out0 :: FilePath -> String -> IO () out1 :: FilePath -> String -> IO () instance Show FigureEnv instance Eq Color instance Eq LineStyle instance Show LineStyle instance Show Color -- | Lotka-Volterra predator-prey model -- -- parameters -- -- module Numeric.Probability.Example.Predator g, e, s, d :: Float v0 :: Float p0 :: Float dv :: (Float, Float) -> Float dp :: (Float, Float) -> Float dvp :: (Float, Float) -> (Float, Float) vp :: [(Float, Float)] vs :: [Float] ps :: [Float] fig1 :: Int -> Vis module Numeric.Probability.Example.TreeGrowth type Height = Int data Tree Alive :: Height -> Tree Hit :: Height -> Tree Fallen :: Tree grow :: Trans Tree hit :: Trans Tree fall :: Trans Tree evolve :: Trans Tree -- | tree growth simulation: start with seed and run for n generations seed :: Tree -- | tree n : tree distribution after n generations tree :: Int -> Tree -> Dist Tree -- | hist n : history of tree distributions for n generations hist :: Int -> Expand Tree -- | Since '(*.)' is overloaded for Trans and RChange, we can run the -- simulation ~. directly to n *. live. simTree :: Int -> Int -> RTrans Tree simHist :: Int -> Int -> RExpand Tree t2 :: Dist Tree h2 :: Space Tree sh2, st2 :: IO () height :: Tree -> Int p1, p6, p5, p4, p3, p2 :: Vis heightAtTime :: Int -> Plot heightCurve :: (Int, Color) -> Plot done :: Tree -> Bool ev5 :: Tree -> Dist Tree instance Ord Tree instance Eq Tree instance Show Tree