{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module      :  Mcmc.Chain.Link
-- Description :  The state combined with auxiliary variables
-- Copyright   :  2021 Dominik Schrempf
-- License     :  GPL-3.0-or-later
--
-- Maintainer  :  dominik.schrempf@gmail.com
-- Stability   :  unstable
-- Portability :  portable
--
-- Creation date: Wed May 20 09:10:27 2020.
module Mcmc.Chain.Link
  ( Link (..),
  )
where

import Data.Aeson
import Data.Aeson.Types
import Mcmc.Likelihood
import Mcmc.Prior
import Numeric.Log

-- | Link of a Markov chain. For reasons of computational efficiency, each state
-- is associated with the corresponding prior and likelihood.
data Link a = Link
  { -- | The current state in the state space @a@.
    forall a. Link a -> a
state :: a,
    -- | The current prior value.
    forall a. Link a -> Prior
prior :: Prior,
    -- | The current likelihood value.
    forall a. Link a -> Prior
likelihood :: Likelihood
  }
  deriving (Link a -> Link a -> Bool
forall a. Eq a => Link a -> Link a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Link a -> Link a -> Bool
$c/= :: forall a. Eq a => Link a -> Link a -> Bool
== :: Link a -> Link a -> Bool
$c== :: forall a. Eq a => Link a -> Link a -> Bool
Eq, Link a -> Link a -> Bool
Link a -> Link a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Link a)
forall a. Ord a => Link a -> Link a -> Bool
forall a. Ord a => Link a -> Link a -> Ordering
forall a. Ord a => Link a -> Link a -> Link a
min :: Link a -> Link a -> Link a
$cmin :: forall a. Ord a => Link a -> Link a -> Link a
max :: Link a -> Link a -> Link a
$cmax :: forall a. Ord a => Link a -> Link a -> Link a
>= :: Link a -> Link a -> Bool
$c>= :: forall a. Ord a => Link a -> Link a -> Bool
> :: Link a -> Link a -> Bool
$c> :: forall a. Ord a => Link a -> Link a -> Bool
<= :: Link a -> Link a -> Bool
$c<= :: forall a. Ord a => Link a -> Link a -> Bool
< :: Link a -> Link a -> Bool
$c< :: forall a. Ord a => Link a -> Link a -> Bool
compare :: Link a -> Link a -> Ordering
$ccompare :: forall a. Ord a => Link a -> Link a -> Ordering
Ord, Int -> Link a -> ShowS
forall a. Show a => Int -> Link a -> ShowS
forall a. Show a => [Link a] -> ShowS
forall a. Show a => Link a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Link a] -> ShowS
$cshowList :: forall a. Show a => [Link a] -> ShowS
show :: Link a -> String
$cshow :: forall a. Show a => Link a -> String
showsPrec :: Int -> Link a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Link a -> ShowS
Show, ReadPrec [Link a]
ReadPrec (Link a)
ReadS [Link a]
forall a. Read a => ReadPrec [Link a]
forall a. Read a => ReadPrec (Link a)
forall a. Read a => Int -> ReadS (Link a)
forall a. Read a => ReadS [Link a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Link a]
$creadListPrec :: forall a. Read a => ReadPrec [Link a]
readPrec :: ReadPrec (Link a)
$creadPrec :: forall a. Read a => ReadPrec (Link a)
readList :: ReadS [Link a]
$creadList :: forall a. Read a => ReadS [Link a]
readsPrec :: Int -> ReadS (Link a)
$creadsPrec :: forall a. Read a => Int -> ReadS (Link a)
Read)

instance ToJSON a => ToJSON (Link a) where
  toJSON :: Link a -> Value
toJSON (Link a
x (Exp Double
p) (Exp Double
l)) = [Pair] -> Value
object [Key
"s" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= a
x, Key
"p" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
p, Key
"l" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
l]
  toEncoding :: Link a -> Encoding
toEncoding (Link a
x (Exp Double
p) (Exp Double
l)) = Series -> Encoding
pairs (Key
"s" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= a
x forall a. Semigroup a => a -> a -> a
<> Key
"p" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
p forall a. Semigroup a => a -> a -> a
<> Key
"l" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
l)

link :: FromJSON a => Object -> Parser (Link a)
link :: forall a. FromJSON a => Object -> Parser (Link a)
link Object
v = do
  a
s <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"s"
  Double
p <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"p"
  Double
l <- Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"l"
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Prior -> Prior -> Link a
Link a
s (forall a. a -> Log a
Exp Double
p) (forall a. a -> Log a
Exp Double
l)

instance FromJSON a => FromJSON (Link a) where
  parseJSON :: Value -> Parser (Link a)
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Link" forall a. FromJSON a => Object -> Parser (Link a)
link