module ELynx.Simulate.MarkovProcess
( ProbMatrix,
State,
probMatrix,
jump,
)
where
import Control.Monad.Primitive
import ELynx.Data.MarkovProcess.RateMatrix
import Numeric.LinearAlgebra
import System.Random.MWC
import System.Random.MWC.Distributions
type ProbMatrix = Matrix R
type State = Int
probMatrix :: RateMatrix -> Double -> ProbMatrix
probMatrix :: RateMatrix -> Double -> RateMatrix
probMatrix RateMatrix
q Double
t
| Double
t Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 =
if RateMatrix -> Int
forall t. Matrix t -> Int
rows RateMatrix
q Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== RateMatrix -> Int
forall t. Matrix t -> Int
cols RateMatrix
q
then Int -> RateMatrix
forall a. (Num a, Element a) => Int -> Matrix a
ident (RateMatrix -> Int
forall t. Matrix t -> Int
rows RateMatrix
q)
else [Char] -> RateMatrix
forall a. HasCallStack => [Char] -> a
error [Char]
"probMatrix: Matrix is not square."
| Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0 = [Char] -> RateMatrix
forall a. HasCallStack => [Char] -> a
error [Char]
"probMatrix: Time is negative."
| Bool
otherwise = RateMatrix -> RateMatrix
forall t. Field t => Matrix t -> Matrix t
expm (RateMatrix -> RateMatrix) -> RateMatrix -> RateMatrix
forall a b. (a -> b) -> a -> b
$ Double -> RateMatrix -> RateMatrix
forall t (c :: * -> *). Linear t c => t -> c t -> c t
scale Double
t RateMatrix
q
jump :: (PrimMonad m) => State -> ProbMatrix -> Gen (PrimState m) -> m State
jump :: Int -> RateMatrix -> Gen (PrimState m) -> m Int
jump Int
i RateMatrix
p = Vector Double -> Gen (PrimState m) -> m Int
forall g (m :: * -> *) (v :: * -> *).
(StatefulGen g m, Vector v Double) =>
v Double -> g -> m Int
categorical (RateMatrix
p RateMatrix -> Int -> Vector Double
forall c t. Indexable c t => c -> Int -> t
! Int
i)