{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RecordWildCards #-}
module Numeric.Eproc.Bernoulli (
Config
, State
, Verdict(..)
, Bettor(..)
, config
, initial
, update
, decide
, log_wealth
, samples
) where
import Numeric.Eproc.Common (Bettor(..), Verdict(..))
data BetState =
SFixed
| SAdaptive
{-# UNPACK #-} !Double
{-# UNPACK #-} !Double
{-# UNPACK #-} !Int
| SNewton
{-# UNPACK #-} !Double
{-# UNPACK #-} !Double
data Config = Config {
Config -> Bettor
cfg_bettor :: !Bettor
, Config -> Double
cfg_lam_max :: {-# UNPACK #-} !Double
, Config -> Double
cfg_p0 :: {-# UNPACK #-} !Double
, Config -> Double
cfg_alpha :: {-# UNPACK #-} !Double
, Config -> Double
cfg_log_thresh :: {-# UNPACK #-} !Double
}
data State = State {
State -> Int
st_n :: {-# UNPACK #-} !Int
, State -> Double
st_log_w :: {-# UNPACK #-} !Double
, State -> BetState
st_bet :: !BetState
}
init_bet :: Bettor -> BetState
init_bet :: Bettor -> BetState
init_bet Bettor
b = case Bettor
b of
Fixed Double
_ -> BetState
SFixed
Bettor
Adaptive -> Double -> Double -> Int -> BetState
SAdaptive Double
0 Double
0 Int
0
Bettor
Newton -> Double -> Double -> BetState
SNewton Double
0 Double
1.0e-6
{-# INLINE init_bet #-}
bet_lambda :: Bettor -> Double -> BetState -> Double
bet_lambda :: Bettor -> Double -> BetState -> Double
bet_lambda Bettor
b !Double
lam_max !BetState
s = case Bettor
b of
Fixed Double
lam -> Double
lam
Bettor
Adaptive -> case BetState
s of
SAdaptive !Double
sm !Double
sm2 !Int
n
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 -> Double
0
| Bool
otherwise ->
let !nd :: Double
nd = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n
!mu :: Double
mu = Double
sm Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
nd
!mu2 :: Double
mu2 = Double
mu Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
mu
!var :: Double
var = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
0 (Double
sm2 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
nd Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
mu2)
!den :: Double
den = Double
var Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
mu2
!raw :: Double
raw = if Double
den Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 then Double
0 else Double
mu Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
den
in Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
0 (Double -> Double -> Double
forall a. Ord a => a -> a -> a
min Double
lam_max Double
raw)
BetState
_ -> Double
0
Bettor
Newton -> case BetState
s of
SNewton !Double
lam Double
_ -> Double
lam
BetState
_ -> Double
0
{-# INLINE bet_lambda #-}
step_bet :: Bettor -> Double -> BetState -> Double -> BetState
step_bet :: Bettor -> Double -> BetState -> Double -> BetState
step_bet Bettor
b !Double
lam_max !BetState
s !Double
z = case Bettor
b of
Fixed Double
_ -> BetState
SFixed
Bettor
Adaptive -> case BetState
s of
SAdaptive !Double
sm !Double
sm2 !Int
n -> Double -> Double -> Int -> BetState
SAdaptive (Double
sm Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
z) (Double
sm2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
z Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
z) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
BetState
_ -> Double -> Double -> Int -> BetState
SAdaptive Double
z (Double
z Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
z) Int
1
Bettor
Newton -> case BetState
s of
SNewton !Double
lam !Double
acc ->
let !denom :: Double
denom = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
lam Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
z
!g :: Double
g = if Double
denom Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 then Double
0 else Double -> Double
forall a. Num a => a -> a
negate Double
z Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
denom
!acc' :: Double
acc' = Double
acc Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
g Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
g
!lam' :: Double
lam' = Double
lam Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
g Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
acc'
!clp :: Double
clp = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
0 (Double -> Double -> Double
forall a. Ord a => a -> a -> a
min Double
lam_max Double
lam')
in Double -> Double -> BetState
SNewton Double
clp Double
acc'
BetState
_ -> Double -> Double -> BetState
SNewton Double
0 Double
1.0e-6
{-# INLINE step_bet #-}
config
:: Double
-> Double
-> Bettor
-> Config
config :: Double -> Double -> Bettor -> Config
config !Double
alpha !Double
p0 !Bettor
b = Config {
cfg_bettor :: Bettor
cfg_bettor = Bettor
b
, cfg_lam_max :: Double
cfg_lam_max = Double
0.5 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
p0
, cfg_p0 :: Double
cfg_p0 = Double
p0
, cfg_alpha :: Double
cfg_alpha = Double
alpha
, cfg_log_thresh :: Double
cfg_log_thresh = Double -> Double
forall a. Floating a => a -> a
log (Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
alpha)
}
{-# INLINE config #-}
initial :: Config -> State
initial :: Config -> State
initial Config{Double
Bettor
cfg_bettor :: Config -> Bettor
cfg_lam_max :: Config -> Double
cfg_p0 :: Config -> Double
cfg_alpha :: Config -> Double
cfg_log_thresh :: Config -> Double
cfg_bettor :: Bettor
cfg_lam_max :: Double
cfg_p0 :: Double
cfg_alpha :: Double
cfg_log_thresh :: Double
..} = State {
st_n :: Int
st_n = Int
0
, st_log_w :: Double
st_log_w = Double
0
, st_bet :: BetState
st_bet = Bettor -> BetState
init_bet Bettor
cfg_bettor
}
{-# INLINE initial #-}
update :: Config -> State -> Bool -> State
update :: Config -> State -> Bool -> State
update Config{Double
Bettor
cfg_bettor :: Config -> Bettor
cfg_lam_max :: Config -> Double
cfg_p0 :: Config -> Double
cfg_alpha :: Config -> Double
cfg_log_thresh :: Config -> Double
cfg_bettor :: Bettor
cfg_lam_max :: Double
cfg_p0 :: Double
cfg_alpha :: Double
cfg_log_thresh :: Double
..} State{Double
Int
BetState
st_n :: State -> Int
st_log_w :: State -> Double
st_bet :: State -> BetState
st_n :: Int
st_log_w :: Double
st_bet :: BetState
..} !Bool
x =
let !xd :: Double
xd = if Bool
x then Double
1 else Double
0
!z :: Double
z = Double
xd Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
cfg_p0
!lam :: Double
lam = Bettor -> Double -> BetState -> Double
bet_lambda Bettor
cfg_bettor Double
cfg_lam_max BetState
st_bet
!fac :: Double
fac = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
lam Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
z
!logw' :: Double
logw' = Double
st_log_w Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Floating a => a -> a
log Double
fac
!s' :: BetState
s' = Bettor -> Double -> BetState -> Double -> BetState
step_bet Bettor
cfg_bettor Double
cfg_lam_max BetState
st_bet Double
z
in Int -> Double -> BetState -> State
State (Int
st_n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Double
logw' BetState
s'
{-# INLINE update #-}
decide :: Config -> State -> Verdict
decide :: Config -> State -> Verdict
decide Config{Double
Bettor
cfg_bettor :: Config -> Bettor
cfg_lam_max :: Config -> Double
cfg_p0 :: Config -> Double
cfg_alpha :: Config -> Double
cfg_log_thresh :: Config -> Double
cfg_bettor :: Bettor
cfg_lam_max :: Double
cfg_p0 :: Double
cfg_alpha :: Double
cfg_log_thresh :: Double
..} State{Double
Int
BetState
st_n :: State -> Int
st_log_w :: State -> Double
st_bet :: State -> BetState
st_n :: Int
st_log_w :: Double
st_bet :: BetState
..}
| Double
st_log_w Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
cfg_log_thresh = Verdict
Reject
| Bool
otherwise = Verdict
Continue
{-# INLINE decide #-}
log_wealth :: State -> Double
log_wealth :: State -> Double
log_wealth = State -> Double
st_log_w
{-# INLINE log_wealth #-}
samples :: State -> Int
samples :: State -> Int
samples = State -> Int
st_n
{-# INLINE samples #-}