Skip to content

Instantly share code, notes, and snippets.

@atcol
Last active July 31, 2019 07:21
Show Gist options
  • Save atcol/1dbcbaeafbde48be3dc48a8dabeb794d to your computer and use it in GitHub Desktop.
Save atcol/1dbcbaeafbde48be3dc48a8dabeb794d to your computer and use it in GitHub Desktop.
A simple tri-state Markov Chain generator. I think.
#!/usr/bin/env stack
-- stack --resolver lts-13.30 script --package random
import Control.Monad (foldM)
import Data.List (elemIndex, minimumBy)
import Data.Maybe (fromMaybe)
import Debug.Trace (trace)
import System.IO (getLine)
import System.Random (randomIO, randomRIO)
data State = A | B | C
deriving (Eq, Read, Show)
type StateF = (State, [Double])
type Table = [StateF]
-- | The mapping from a state to the probability of the other states
table :: Table
table = [(A, [0.3, 0.5, 0.2])
,(B, [0.7, 0.3, 0.0])
,(C, [0.2, 0.7, 0.1])]
-- | Find the next state in @Table@ according to the current @State@ and the given probability
step :: State -> Table -> Double -> State
step cs t x = do
let r = fst $ t !! ns
trace ("\nState: ns=" ++ show ns ++ ", sp=" ++ show sp ++ ", pr=" ++ show pr ++ ", x=" ++ show x) r
where pr = minimumBy (closestTo x) sp -- the smallest probability closest to x
sp = head $ map snd $ filter ((==) cs . fst) t -- the prob table for cs
ns = fromMaybe 0 (elemIndex pr sp) -- Our index in @t@ for the next element
closestTo :: (Ord a, Num a) => a -> a -> a -> Ordering
closestTo x = (\a b -> compare (abs $ x - a) (abs $ x - b))
main :: IO ()
main = do
print $ "Enter a state from " ++ show (map fst table) ++ "> "
cs <- getLine
se <- loop (read cs) 5 []
print se
where loop _ 0 x = return x
loop cs c x = do
n <- randomIO
let ne = step cs table n
loop ne (c - 1) $ x ++ [cs]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment