{- |

Approach: model a node with k predecessors as a function with k
          parameters

-}
module Numeric.Probability.Example.Bayesian where

import qualified Numeric.Probability.Distribution as Dist
import qualified Numeric.Probability.Transition as Trans
import qualified Numeric.Probability.Monad as MonadExt
import Numeric.Probability.Distribution ((??), (?=<<), )



-- * Abbreviations, smart constructors

type Probability = Rational
type Dist a = Dist.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
event :: forall a. Probability -> a -> STrans a
event Probability
p a
e0 = forall prob a. Num prob => prob -> Change a -> T prob a
Trans.maybe Probability
p (a
e0forall a. a -> [a] -> [a]
:)

happens :: Eq a => SPred a
happens :: forall a. Eq a => SPred a
happens = forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem

network :: [STrans a] -> PState a
network :: forall a. [STrans a] -> PState a
network = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) a. Monad m => [a -> m a] -> a -> m a
MonadExt.compose []


source :: Probability -> a -> STrans a
source :: forall a. Probability -> a -> STrans a
source = forall a. Probability -> a -> STrans a
event

bin :: Eq a =>
   a -> a -> Probability -> Probability -> Probability -> Probability ->
   a -> STrans a
bin :: forall a.
Eq a =>
a
-> a
-> Probability
-> Probability
-> Probability
-> Probability
-> a
-> STrans a
bin a
x a
y Probability
a Probability
b Probability
c Probability
d a
z State a
s | forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem a
x State a
s Bool -> Bool -> Bool
&& forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem a
y State a
s = forall a. Probability -> a -> STrans a
event Probability
a a
z State a
s
                    | forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem a
x State a
s             = forall a. Probability -> a -> STrans a
event Probability
b a
z State a
s
                    | forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem a
y State a
s             = forall a. Probability -> a -> STrans a
event Probability
c a
z State a
s
                    | Bool
otherwise            = forall a. Probability -> a -> STrans a
event Probability
d a
z State a
s


-- | Two possible causes for one effect

data Nodes = A | B | E deriving (Nodes -> Nodes -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Nodes -> Nodes -> Bool
$c/= :: Nodes -> Nodes -> Bool
== :: Nodes -> Nodes -> Bool
$c== :: Nodes -> Nodes -> Bool
Eq,Eq Nodes
Nodes -> Nodes -> Bool
Nodes -> Nodes -> Ordering
Nodes -> Nodes -> Nodes
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
min :: Nodes -> Nodes -> Nodes
$cmin :: Nodes -> Nodes -> Nodes
max :: Nodes -> Nodes -> Nodes
$cmax :: Nodes -> Nodes -> Nodes
>= :: Nodes -> Nodes -> Bool
$c>= :: Nodes -> Nodes -> Bool
> :: Nodes -> Nodes -> Bool
$c> :: Nodes -> Nodes -> Bool
<= :: Nodes -> Nodes -> Bool
$c<= :: Nodes -> Nodes -> Bool
< :: Nodes -> Nodes -> Bool
$c< :: Nodes -> Nodes -> Bool
compare :: Nodes -> Nodes -> Ordering
$ccompare :: Nodes -> Nodes -> Ordering
Ord,Int -> Nodes -> ShowS
[Nodes] -> ShowS
Nodes -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Nodes] -> ShowS
$cshowList :: [Nodes] -> ShowS
show :: Nodes -> String
$cshow :: Nodes -> String
showsPrec :: Int -> Nodes -> ShowS
$cshowsPrec :: Int -> Nodes -> ShowS
Show)

g :: PState Nodes
g :: PState Nodes
g = forall a. [STrans a] -> PState a
network [forall a. Probability -> a -> STrans a
source Probability
0.1 Nodes
A,
             forall a. Probability -> a -> STrans a
source Probability
0.2 Nodes
B,
             forall a.
Eq a =>
a
-> a
-> Probability
-> Probability
-> Probability
-> Probability
-> a
-> STrans a
bin Nodes
A Nodes
B Probability
1 Probability
1 Probability
0.5 Probability
0 Nodes
E]

-- * queries

e, aE, bE :: Probability
e :: Probability
e  = forall a. Eq a => SPred a
happens Nodes
E forall prob a. Num prob => Event a -> T prob a -> prob
??                PState Nodes
g
aE :: Probability
aE = forall a. Eq a => SPred a
happens Nodes
A forall prob a. Num prob => Event a -> T prob a -> prob
?? forall a. Eq a => SPred a
happens Nodes
E forall prob a.
Fractional prob =>
(a -> Bool) -> T prob a -> T prob a
?=<< PState Nodes
g
bE :: Probability
bE = forall a. Eq a => SPred a
happens Nodes
B forall prob a. Num prob => Event a -> T prob a -> prob
?? forall a. Eq a => SPred a
happens Nodes
E forall prob a.
Fractional prob =>
(a -> Bool) -> T prob a -> T prob a
?=<< PState Nodes
g


{-
data State = State {causeA :: Bool, causeB :: Bool, effect :: Bool}
             deriving (Eq,Ord,Show)

nCauseA s = s{causeA=True}
-}

--
-- Wet grass example
--
-- cloudy = true 0.5
--
-- sprinkler c = dep c 0.1 0.5
--
-- rain c = dep c 0.8 0.2
--
-- wetGrass s r = bin s r 0.99 0.9 0.9 0
--
-- c = cloudy
-- s = sprinkler cloudy
-- r = rain cloudy
-- w = wetGrass s r


-- alarm :: Prob -> Prob -> Prob
-- alarm b e = cond b (pTrue 0.8)
--                    (cond e (pTrue 0.1) (pTrue 0.01))
--
-- john :: Prob -> Prob
-- john a = cond a (pTrue 0.7) (pTrue 0.1)
--
-- mary :: Prob -> Prob
-- mary a = cond a (pTrue 0.6) (pTrue 0.2)
--
--
-- maryWhenJohn = mary a ?? john a
--                where a = alarm (pTrue 0.5) (pTrue 0.1)