packages feed

hbayes 0.4.1 → 0.5

raw patch · 20 files changed

+1450/−91 lines, 20 filesdep +gammadep +mwc-randomdep +statisticsdep ~QuickCheckdep ~arraydep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: gamma, mwc-random, statistics

Dependency ranges changed: QuickCheck, array, base, containers, mtl, pretty

API changes (from Hackage documentation)

- Bayes.BayesianNetwork: instance Instantiable d v => Testable d v
- Bayes.InfluenceDiagram: instance Instantiable DEV Int
+ Bayes: class FunctorWithVertex g
+ Bayes: fmapWithVertex :: FunctorWithVertex g => (Vertex -> a -> b) -> g c a -> g c b
+ Bayes: fmapWithVertexM :: (FunctorWithVertex g, Monad m) => (Vertex -> a -> m b) -> g c a -> m (g c b)
+ Bayes: instance FunctorWithVertex (SimpleGraph local)
+ Bayes: markovBlanket :: DirectedGraph g => g a b -> Vertex -> [Vertex]
+ Bayes.BayesianNetwork: instance Instantiable d v DVI => Testable d v
+ Bayes.Continuous: (=:) :: Instantiable d v r => d -> v -> r
+ Bayes.Continuous: beta :: VariableName s => s -> DN -> DN -> CNMonad DN
+ Bayes.Continuous: beta' :: VariableName s => s -> DN -> DN -> CNMonad DN
+ Bayes.Continuous: class BayesianVariable v
+ Bayes.Continuous: class InstantiationValue i v | i -> v
+ Bayes.Continuous: class VariableName m
+ Bayes.Continuous: continuousMCMCSampler :: ContinuousNetwork -> [CVI] -> Sampler DirectedSG CVI
+ Bayes.Continuous: data CV
+ Bayes.Continuous: data CVI
+ Bayes.Continuous: data DN
+ Bayes.Continuous: data Distri
+ Bayes.Continuous: evalCN :: CNMonad a -> a
+ Bayes.Continuous: execCN :: CNMonad a -> ContinuousNetwork
+ Bayes.Continuous: exponential :: VariableName s => s -> DN -> CNMonad DN
+ Bayes.Continuous: histogram :: Int -> [Double] -> [(Double, Double, Double)]
+ Bayes.Continuous: instance BayesianVariable DN
+ Bayes.Continuous: instance Fractional DN
+ Bayes.Continuous: instance Fractional RN
+ Bayes.Continuous: instance Instantiable DN Double CVI
+ Bayes.Continuous: instance Monoid (DistributionSupport (Double, Double))
+ Bayes.Continuous: instance Num DN
+ Bayes.Continuous: instance Num RN
+ Bayes.Continuous: instance VariableName ()
+ Bayes.Continuous: instance VariableName String
+ Bayes.Continuous: instantiationValue :: InstantiationValue i v => i -> v
+ Bayes.Continuous: mkVariable :: VariableName m => m -> CNMonad CV
+ Bayes.Continuous: normal :: VariableName s => s -> DN -> DN -> CNMonad DN
+ Bayes.Continuous: runCN :: CNMonad a -> (a, ContinuousNetwork)
+ Bayes.Continuous: runSampling :: (DirectedGraph g, FunctorWithVertex g) => Int -> Int -> Sampler g a -> IO [Sample g a]
+ Bayes.Continuous: samplingHistograms :: (InstantiationValue i v, BayesianVariable i, FunctorWithVertex g, Graph g) => Int -> [Sample g i] -> Sample g [(Double, Double, Double)]
+ Bayes.Continuous: toDouble :: InstantiationValue i v => i -> Double
+ Bayes.Continuous: type CNMonad a = GraphMonad DirectedSG () Distri a
+ Bayes.Continuous: type ContinuousNetwork = SBN Distri
+ Bayes.Continuous: type ContinuousSample = SBN CVI
+ Bayes.Continuous: uniform :: VariableName s => s -> DN -> DN -> CNMonad DN
+ Bayes.Continuous: vertex :: BayesianVariable v => v -> Vertex
+ Bayes.EM: learnEM :: (FunctorWithVertex g, NamedGraph g, FoldableWithVertex g, DirectedGraph g) => [[DVI]] -> BayesianNetwork g CPT -> BayesianNetwork g CPT
+ Bayes.Examples.ContinuousSampling: debugcn :: IO ()
+ Bayes.Examples.ContinuousSampling: nbSensors :: Int
+ Bayes.Examples.ContinuousSampling: sensor :: DN -> CNMonad DN
+ Bayes.Examples.ContinuousSampling: test :: ([DN], ContinuousNetwork)
+ Bayes.Examples.EMTest: emTest :: IO ()
+ Bayes.Examples.Sampling: testSampling :: IO ()
+ Bayes.Factor: class BayesianVariable v
+ Bayes.Factor: class InstantiationValue i v | i -> v
+ Bayes.Factor: toDouble :: InstantiationValue i v => i -> Double
+ Bayes.InfluenceDiagram: instance BayesianVariable DEV
+ Bayes.InfluenceDiagram: instance BayesianVariable PorD
+ Bayes.InfluenceDiagram: instance Instantiable DEV Int DVI
+ Bayes.Sampling: D :: !CV -> !DistributionF DirectedSG (Double, Double) CVI -> Distri
+ Bayes.Sampling: Sampler :: !b -> !GenIO -> IO (Sample g a) -> !GenIO -> SamplerGraph g a -> !SamplingScheme g b a -> Sampler g a
+ Bayes.Sampling: continuousMCMCSampler :: ContinuousNetwork -> [CVI] -> Sampler DirectedSG CVI
+ Bayes.Sampling: data Distri
+ Bayes.Sampling: data Sampler g a
+ Bayes.Sampling: discreteAncestralSampler :: (Factor f, FunctorWithVertex g, DirectedGraph g) => BayesianNetwork g f -> Sampler g DVI
+ Bayes.Sampling: gibbsMCMCSampler :: (Factor f, FunctorWithVertex g, DirectedGraph g) => BayesianNetwork g f -> [DVI] -> Sampler g DVI
+ Bayes.Sampling: gibbsSampler :: (Factor f, FunctorWithVertex g, DirectedGraph g) => BayesianNetwork g f -> [DVI] -> Sampler g DVI
+ Bayes.Sampling: histogram :: Int -> [Double] -> [(Double, Double, Double)]
+ Bayes.Sampling: instance Graph g => Show (Sample g CVI)
+ Bayes.Sampling: instance Graph g => Show (Sample g [(Double, Double, Double)])
+ Bayes.Sampling: instance Graph g => Show (Sample g [DVI])
+ Bayes.Sampling: instance SampleGeneration CV CVI (Double, Double) Double
+ Bayes.Sampling: instance SampleGeneration DV DVI DV Int
+ Bayes.Sampling: instance SamplingBounds (Double, Double) Double
+ Bayes.Sampling: instance SamplingBounds DV Int
+ Bayes.Sampling: runSampling :: (DirectedGraph g, FunctorWithVertex g) => Int -> Int -> Sampler g a -> IO [Sample g a]
+ Bayes.Sampling: samplingHistograms :: (InstantiationValue i v, BayesianVariable i, FunctorWithVertex g, Graph g) => Int -> [Sample g i] -> Sample g [(Double, Double, Double)]
+ Bayes.Sampling: topologicalOrder :: DirectedGraph g => g a b -> [Vertex]
+ Bayes.Sampling: type ContinuousNetwork = SBN Distri
+ Bayes.Sampling: type ContinuousSample = SBN CVI
+ Bayes.Sampling: type Sample g a = BayesianNetwork g a
- Bayes.Factor: (=:) :: Instantiable d v => d -> v -> DVI
+ Bayes.Factor: (=:) :: Instantiable d v r => d -> v -> r
- Bayes.Factor: class BayesianDiscreteVariable v
+ Bayes.Factor: class BayesianVariable v => BayesianDiscreteVariable v
- Bayes.Factor: instantiationValue :: DVI -> Int
+ Bayes.Factor: instantiationValue :: InstantiationValue i v => i -> v
- Bayes.Factor: vertex :: BayesianDiscreteVariable v => v -> Vertex
+ Bayes.Factor: vertex :: BayesianVariable v => v -> Vertex
- Bayes.FactorElimination: posterior :: (BayesianDiscreteVariable dv, Factor f, IsBucketItem f) => JunctionTree f -> dv -> Maybe f
+ Bayes.FactorElimination: posterior :: (BayesianDiscreteVariable dv, Factor f, IsBucketItem f) => JunctionTree f -> [dv] -> Maybe f
- Bayes.InfluenceDiagram: (=:) :: Instantiable d v => d -> v -> DVI
+ Bayes.InfluenceDiagram: (=:) :: Instantiable d v r => d -> v -> r
- Bayes.InfluenceDiagram: class Instantiable d v
+ Bayes.InfluenceDiagram: class Instantiable d v r | d -> r

Files

Bayes.hs view
@@ -2,17 +2,23 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-}-{- | Discrete Bayesian Network Library.+{- | Bayesian Network Library.  It is a very preliminary version. It has only been tested on very simple examples where it worked. It should be considered as experimental and not used in any production work. -Look at the "Bayes.Examples" and "Bayes.Examples.Tutorial" in this package +* Look at the "Bayes.Examples" and "Bayes.Examples.Tutorial" in this package  to see how to use the library. -In "Bayes.Examples.Influence" you'll find additional examples about influence diagrams.+* In "Bayes.Examples.Influence" you'll find additional examples about influence diagrams. +* In "Bayes.Examples.Sampling" there are some explanations about the samplers for discrete networks.++* "Bayes.Examples.EMTest" is explaining learning with expectation / maximization.++* "Bayes.Examples.ContinuousSampling" is showing an example of sampling with a continuous network.+ -} module Bayes(   -- * Graph@@ -21,6 +27,7 @@   , UndirectedGraph(..)   , DirectedGraph(..)   , FoldableWithVertex(..)+  , FunctorWithVertex(..)   , NamedGraph(..)   -- ** Graph Monad   , GraphMonad@@ -35,6 +42,7 @@   , rootNode   , parentNodes   , childrenNodes+  , markovBlanket   -- ** Support functions for Graph constructions   , Vertex   , Edge @@ -86,9 +94,8 @@ -- | An implementation of the BayesianNetwork using the simple graph and no value for the edges type SBN f = DirectedSG () f --- | Bayesian network. g must be a directed graph and f a factor-type BayesianNetwork g f = g () f + instance Arbitrary (DirectedSG String String) where   arbitrary = do      let createVertex g i = do @@ -279,6 +286,16 @@     ingoing :: g a b -> Vertex -> Maybe [Edge]     outgoing :: g a b -> Vertex -> Maybe [Edge] ++-- | Return the Markov blanket of a node +markovBlanket :: DirectedGraph g => g a b -> Vertex -> [Vertex]+markovBlanket g c = +  let p = parentNodes g c+      children = childrenNodes g c +      parentOfChildrens = concatMap (parentNodes g) children +  in +  nub (c:p ++ children ++ parentOfChildrens)+ -- | Return the parents of a node parentNodes :: DirectedGraph g => g a b -> Vertex -> [Vertex] parentNodes g v = maybe [] id $ do @@ -418,6 +435,23 @@  instance Functor (SimpleGraph local edge) where    fmap f (SP em vm nm) = SP em (IM.map (\(l,d) -> (l, f d)) vm) nm++class FunctorWithVertex g where +   fmapWithVertex :: (Vertex -> a -> b) -> g c a -> g c b +   fmapWithVertexM :: Monad m => (Vertex -> a -> m b) -> g c a -> m (g c b) +++instance FunctorWithVertex (SimpleGraph local) where +    fmapWithVertex f (SP em vm nm) = SP em (IM.mapWithKey (\k (l,d) -> (l, f (Vertex k) d)) vm) nm+    fmapWithVertexM f (SP em vm nm) = do +      let l = IM.toList vm+          g f (k,(l,d)) = do +            r <- f (Vertex k) d +            return (k,(l,r))+      rl <- mapM (g f) $ l+      let vm' = IM.fromList rl+      return $ SP em vm' nm+  instance F.Foldable (SimpleGraph local edge) where   foldr f c (SP _ vm _) = IM.foldr (\(_,d) s -> f d s) c vm
Bayes/BayesianNetwork.hs view
@@ -142,7 +142,7 @@   -- an enumeration   (.==.) :: d -> v -> LE  -instance Instantiable d v => Testable d v where +instance Instantiable d v DVI => Testable d v where    (.==.) a b = LETest (a =: b)  infixl 8 .==.
+ Bayes/Continuous.hs view
@@ -0,0 +1,330 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{- Bayesian Networks with continuous variables++-}+module Bayes.Continuous(+    -- * Types +    -- ** For the graph description+      CNMonad(..)+    , CV+    , DN+    , VariableName(..)+    , BayesianVariable(..)+    -- ** For the sampling +    , Distri +    , ContinuousNetwork(..) +    , ContinuousSample(..)+    , InstantiationValue(..)+    , CVI +    -- * Network creation functions+    , uniform +    , normal+    , beta+    , beta'+    , exponential+    , execCN+    , runCN +    , evalCN+    -- * Sampling functions+    , runSampling +    , continuousMCMCSampler+    , (=:)+    -- * Result statistics+    , histogram+    , samplingHistograms +    ) where++import Bayes.Sampling+import Bayes+import Data.Monoid+import Control.Applicative+import Bayes.PrivateTypes+import Bayes.Network(NetworkMonad(..),runGraph,execGraph,evalGraph)+import Control.Monad.State.Strict+import Data.Maybe(fromJust)+import Control.Monad+import Control.Monad.Reader +import Bayes.Sampling(runSampling, samplingHistograms,gibbsMCMCSampler, ContinuousNetwork(..), ContinuousSample(..)) +import Math.Gamma(gamma)++-- | The Bayesian monad+type CNMonad a = GraphMonad DirectedSG () Distri a+++instance Monoid (DistributionSupport (Double,Double)) where +    mempty = BoundedSupport (0.0,0.0)+    (BoundedSupport (xa,ya)) `mappend` (BoundedSupport (xb,yb)) = BoundedSupport (min xa xb, max ya yb)+    (BoundedSupport _) `mappend` (Unbounded a) = Unbounded a +    (Unbounded a) `mappend` (BoundedSupport _) = Unbounded a +    (Unbounded a) `mappend` (Unbounded b) = Unbounded (a+b)++newtype RN = RN (Reader (Sample DirectedSG CVI) Double) ++instance Num RN where +   (RN a) + (RN b) = RN $ liftA2 (+) a b+   (RN a) - (RN b) = RN $ liftA2 (-) a b+   (RN a) * (RN b) = RN $ liftA2 (*) a b+   abs (RN a) = RN $ liftA abs a +   signum (RN a) = RN $ liftA signum a +   fromInteger a = RN (return (fromInteger a))++instance Fractional RN where +   (RN a) / (RN b) = RN $ liftA2 (/) a b+   fromRational a = RN (return (fromRational a))++-- | An expression which can be a constant, variable or formula.+-- In case it is a variable, it can be used as a 'BayesianVariable'+-- or instantiated as an 'Instantiable' type.+-- Otherwise you'll get an error+data DN = DN !([CV]) !RN++instance BayesianVariable DN where +    vertex (DN [] _) = error "No vertex for this expression"+    vertex (DN (v:[]) _) = vertex v +    vertex (DN l _) = error "Too many vertices for this expression"++dependencies :: DN -> [CV]+dependencies (DN l _) = l ++instance Instantiable DN Double CVI where +  (=:) (DN [] _) x = error "No variable is related to this expression"+  (=:) (DN (a:[]) _) x = a =: x+  (=:) (DN l _) x = error "Too many variables are related to this expression"++value :: DN -> Reader (Sample DirectedSG CVI) Double +value (DN _ (RN v)) = v++instance Num DN where +    (DN da na) + (DN db nb) = DN (da `mappend`db) (na + nb)+    (DN da na) - (DN db nb) = DN (da `mappend`db) (na - nb)+    (DN da na) * (DN db nb) = DN (da `mappend`db) (na * nb)+    abs (DN a b) = DN a (abs b)+    signum (DN a b) = DN a (signum b)+    fromInteger i = DN [] (fromInteger i)++instance Fractional DN where+    (DN da na) / (DN db nb) = DN (da `mappend`db) (na / nb)+    fromRational i = DN [] (fromRational i)+++{-++Graph creation++-}++-- | This class is used to simplify the network description. Variable+-- names can be optional. In that later case, () must be used instead of a name.+class VariableName m where +    mkVariable :: m -> CNMonad CV ++instance VariableName String where +    mkVariable = variable ++instance VariableName () where +    mkVariable _ = unamedVariable++-- | Create a new named Bayesian variable if not found.+-- Otherwise, return the found one.+addVariableIfNotFound :: String -> CNMonad Vertex+addVariableIfNotFound vertexName = graphNode vertexName (D (CV (Vertex 0)) (Distri (return mempty) (\s -> return 0.0)))++-- | Create a new unamed variable+unamedVariable :: CNMonad CV+unamedVariable = do +  ((namemap,count),g) <- get +  let vertexName = "unamed" ++ show count+  va <- addVariableIfNotFound vertexName+  return (CV va)+++whenJust Nothing _ = return ()+whenJust (Just i) f = f i >> return ()++-- | Set the node of a bayesian network under creation+setBayesianNode :: CV -> Distri -> CNMonad ()+setBayesianNode (CV v) newValue = do+  (aux,oldGraph) <- get+  let newGraph = changeVertexValue v newValue oldGraph+ +  whenJust newGraph $ \nvm -> do+     put $! (aux, nvm)++-- | Create an edge between two vertex of the Bayesian network+(<--) :: CV -> CV -> CNMonad ()+(CV va) <-- (CV vb) = newEdge vb va mempty++++node :: CV -> DN+node v = DN [v] (RN $ do +    r <- ask +    return . instantiationValue . fromJust . vertexValue r $ (vertex v)+    )++-- | Define a Bayesian variable (name and bounds)+variable :: String -- ^ Variable name+         -> CNMonad CV+variable name = do+  va <- addVariableIfNotFound name+  return (CV va)++cpt :: CV -> [CV] -> CNMonad CV+cpt node conditions = do+  mapM_ (node <--) (reverse conditions)+  return node++{-++Distributions++-}++-- | Exponential distribution +exponential :: VariableName s +            => s +            -> DN +            -> CNMonad DN +exponential s na = do +    v <- mkVariable s+    let la = dependencies na +    cpt v la +    let bound = do +           lambda <- value na+           return (Unbounded (1.0 / lambda))+        result = D v (Distri bound $ \inst -> do +                    lambda <- value na+                    let x = instantiationValue inst +                    if x < 0+                      then +                        return 0.0 +                      else +                        return $ lambda * exp(-lambda * x)+                    )+    setBayesianNode v result +    return (node v)++-- | Beta distribution +beta :: VariableName s +     => s +     -> DN +     -> DN +     -> CNMonad DN +beta s na nb = do +    v <- mkVariable s+    let la = dependencies na +        lb = dependencies nb +    let l = la ++ lb+    cpt v l+    let bound = return (BoundedSupport (0.0,0.1) )+        result = D v (Distri bound $ \inst -> do +                    a <- value na+                    b <- value nb+                    let x = instantiationValue inst +                    return $ gamma(a+b)/gamma(a)/gamma(b)*x**(a-1)*(1-x)**(b-1)+                    )+    setBayesianNode v result +    return (node v)++-- | Beta' distribution +beta' :: VariableName s +     => s +     -> DN +     -> DN +     -> CNMonad DN +beta' s na nb = do +    v <- mkVariable s+    let la = dependencies na +        lb = dependencies nb +    let l = la ++ lb+    cpt v l+    let bound = do +              a <- value na+              b <- value nb+              let std = a * (a + b - 1) -- Not really the standard deviation but related to it+                                        -- enough for generating new samples+              return (Unbounded std)+        result = D v (Distri bound $ \inst -> do +                    a <- value na+                    b <- value nb+                    let x = instantiationValue inst +                    if x <= 0 +                      then +                        return 0.0+                      else+                        return $ gamma(a+b)/gamma(a)/gamma(b)*x**(a-1)*(1+x)**(-a-b)+                    )+    setBayesianNode v result +    return (node v)++-- | Uniform dstribution+uniform :: VariableName s +        => s -- ^ Variable name+        -> DN -- ^ Min bound+        -> DN -- ^ Max bound+        -> CNMonad DN+uniform s na nb = do +    v <- mkVariable s+    let la = dependencies na +        lb = dependencies nb +    let l = la ++ lb+    cpt v l+    let bound = do +        a <- value na +        b <- value nb +        return (BoundedSupport (a,b) )+    let result = D v (Distri bound $ \inst -> do +                    a <- value na+                    b <- value nb+                    let d = 1.0 / (b - a)+                    if instantiationValue inst < a || instantiationValue inst > b then return 0.0 else return d)+    setBayesianNode v result +    return (node v)+++-- | Normal distribution+normal :: VariableName s +       => s -- ^ Variable name+       -> DN -- ^ Average+       -> DN -- ^ Standard deviation+       -> CNMonad DN+normal s mean std = do+    v <- mkVariable s+    let la = dependencies mean +        lb = dependencies std +    let l = la ++ lb+    cpt v l+    let bound = do +        s <- value std +        return (Unbounded s )+    let result = D v (Distri bound $ \inst -> do +                    m <- value mean+                    s <- value std+                    let x = instantiationValue inst +                    return (1.0 / (sqrt (2 * pi)*s) * exp(-(x-m)*(x-m)/(2*s*s))+                           ))+    setBayesianNode v result +    return (node v)++{-+ +Graph creation from the Monad.  ++-}++-- | Create a  network using the simple graph implementation+-- The initialized nodes are replaced by the value.+-- Returns the monad values and the built graph.+runCN :: CNMonad a -> (a,ContinuousNetwork)+runCN = runGraph++-- | Create a  network but only returns the monad value.+-- Mainly used for testing.+execCN :: CNMonad a -> ContinuousNetwork+execCN = execGraph++-- | Create a bayesian network but only returns the monad value.+-- Mainly used for testing.+evalCN :: CNMonad a -> a+evalCN = evalGraph
+ Bayes/EM.hs view
@@ -0,0 +1,65 @@+{- | Expectation / Maximization to learn Bayesian network values++-}+module Bayes.EM( +    -- * Learning function+      learnEM+    ) where ++import Bayes+import Bayes.Factor +import Bayes.Sampling +import Bayes.Factor.CPT+import Bayes.FactorElimination+import Data.Maybe(fromJust)+++sumG :: (FunctorWithVertex g, Graph g) +     => Sample g (CPT,CPT) +     -> Sample g (CPT,CPT) +     -> Sample g (CPT,CPT)+sumG ga gb = +  let sumNode vertex (xa,xb) = +        let (ya,yb) = fromJust . vertexValue gb $ vertex +        in +        (cptSum [xa,ya], cptSum [xb,yb])+  in +  fmapWithVertex sumNode ga ++divideG :: Vertex +        -> (CPT,CPT) +        -> CPT+divideG _ (a,b) = cptDivide a b ++-- | Learn network values from samples using the expectation / maximization algorithm.+learnEM :: (FunctorWithVertex g, NamedGraph g, FoldableWithVertex g, DirectedGraph g) +        => [[DVI]] -- ^ Samples+        -> BayesianNetwork g CPT -- ^ Start network+        -> BayesianNetwork g CPT -- ^ Network with new values learnt from the samples+learnEM samples startG = +    let jt = createJunctionTree nodeComparisonForTriangulation startG +        results = map (computeSample startG jt) samples+    in +    fmapWithVertex divideG (foldl1 sumG results)++computeSample :: (FunctorWithVertex g, Graph g) +              => BayesianNetwork g CPT +              -> JunctionTree CPT +              -> [DVI] +              -> Sample g (CPT,CPT)+computeSample startG jt s = fmapWithVertex (computeNode startG jt s) startG++computeNode :: Graph g +            => BayesianNetwork g CPT +            -> JunctionTree CPT +            -> [DVI] +            -> Vertex +            -> CPT +            -> (CPT,CPT)+computeNode g jt samples vertex _ = +    let jt' = changeEvidence samples jt+        f@(main:l) = factorVariables (fromJust . vertexValue g $ vertex)+        a = fromJust $ posterior jt' f +        b = if null l then factorFromScalar 1.0 else fromJust $ posterior jt' l +    in +    (a,b)
+ Bayes/Examples/ContinuousSampling.hs view
@@ -0,0 +1,118 @@+{- | Sampling example with continuous distributions++Continuous networks can't be handled by any of the functions defined for the discrete networks.+So, instead of using exact inference algorithms like the junction trees, sampling method have to be used.++In this example, we want to estimate a parameter which is measured by noisy sensors.++There are 'nbSensors' available. They are described with a 'normal' distribution centered on the value of+the unknown parameters and with a standard deviation of 0.1.++The unknown parameter is described with a 'uniform' distribution bounded by 1.0 and 2.0.++First, we describe the sensor:++@+sensor :: 'DN' -> 'CNMonad' 'DN' +sensor p = do +    'normal' () p 0.1 +@++It is just a 'normal' distribution. The mean of this distribution is the parameters p. This parameter has special type 'DN'.+All expressions used to build the continuous bayesian network are using values of type 'DN'. A value of type 'DN' can either+represent a constant, a variable or an expression.++If the sensor was biased, we could write:++@+    'normal' ()  (p + 0.2) 0.1+@++The Bayesian network describing the measurement process is given by:++@+    test = 'runCN' $ do+      a <- 'uniform' \"a\" 1.0 2.0 -- Unknown parameter+      sensors <- sequence (replicate 'nbSensors' (sensor a))+      return (a:sensors)+@++We are connecting 'nbSensors' nodes corresponding to the 'nbSensors' measurements.  In real life it can either be different sensors+or the same one used several times (assuming the value of the parameter is not dependent on time).++Now, as usual in all the examples of this package, we get the bayesian graph and a list of variables used+to compute some posterior or define some evidences++@+    debugcn = do +        let ((a:sensors), testG) = test+@++Then, we generate some random measurements and create the evidences++@+    g <- create +    measurements <- sequence . replicate  nbSensors $ (MWC.normal 1.5 0.1 g)+    let evidence = zipWith (=:) sensors measurements+@++Evidence has type 'CVI' and is created with the assigment operator '=:' .++Now, we generate some samples to estimate the posterior distributions.++@+    n <- 'runSampling' 10000 200 ('continuousMCMCSampler' testG evidence)+@++This function is generating a sequence of graphs ! We are not interested in the sensor values. They are known and fixed+since they have been measured. So, we extract the value of the parameter.++@+    let samples = map (\g -> 'instantiationValue' . fromJust . 'vertexValue' g $ ('vertex' a)) n+@++And with the samples for the parameters we can compute an histogram and get an approximation of the posterior.++@+    let samples = map (\g -> 'instantiationValue' . fromJust . 'vertexValue' g $ ('vertex' a)) n+        h = 'histogram' 6 samples +    print h+@++We see in the histogram that the estimated value is around 1.5.++-}+module Bayes.Examples.ContinuousSampling(+	  nbSensors +	, sensor +	, test +	, debugcn+	) where+import Bayes+import Bayes.Continuous +import qualified System.Random.MWC.Distributions as MWC(normal)+import System.Random.MWC(GenIO,create)+import Data.Maybe(fromJust)++nbSensors = 10 ++sensor :: DN -> CNMonad DN +sensor p = do +    normal () p 0.1 ++test = runCN $ do+  a <- uniform "a" 1.0 2.0 -- Unknown parameter+  sensors <- sequence (replicate nbSensors (sensor a))+  return (a:sensors)++debugcn = do +    let ((a:sensors), testG) = test+    g <- create +    measurements <- sequence . replicate  nbSensors $ (MWC.normal 1.5 0.1 g)+    let evidence = zipWith (=:) sensors measurements+    n <- runSampling 10000 200 (continuousMCMCSampler testG evidence)+    let samples = map (\g -> instantiationValue . fromJust . vertexValue g $ (vertex a)) n+        h = histogram 6 samples +    print h++
+ Bayes/Examples/EMTest.hs view
@@ -0,0 +1,118 @@+{- | Test of learning++In this example, two networks are used : 'simple' which is the reference and 'wrong' which is a wrong start.+The goal is to use test patterns to learn the right 'simple' network from 'wrong'. Only the values are learnt.+The topology of both networks is the same.++@+simple :: (['TDV' Bool],'SBN' 'CPT')+simple = 'runBN' $ do +    a <- 'variable' \"a\" ('t' :: Bool)+    b <- 'variable' \"b\" ('t' :: Bool) +--    +    'proba' a '~~' [0.4,0.6]+    'cpt' b [a] '~~' [0.8,0.2,0.2,0.8]+--+    return [a,b]+@++and 'wrong' where the probability for a is wrong.++@+wrong :: (['TDV' Bool],'SBN' 'CPT')+wrong = 'runBN' $ do +    a <- 'variable' \"a\" ('t' :: Bool)+    b <- 'variable' \"b\" ('t' :: Bool) +--    +    'proba' a '~~' [0.2,0.8]+    'cpt' b [a] '~~' [0.8,0.2,0.2,0.8]+--+    return [a,b]+@++So, the first thing to do is generate test patterns. We are using the 'discreteAncestralSampler' for this. This function is+generating a sequence of graphs. We are just interested in the values. So, we get the values with 'allVertexValues'.++@+generatePatterns :: IO [[DVI]]+generatePatterns = do +    let (vars\@[a,b],exampleG) = simple+    r <- 'runSampling' 5000 0 ('discreteAncestralSampler' exampleG)+    return (map 'allVertexValues' r)+@++Once we have the data, we can try to learn the network:++@+emTest = do +  samples <- generatePatterns +  let (_,simpleG) = simple +      (_,wrongG) = wrong +  print simpleG +  'printGraphValues' simpleG+  'printGraphValues' wrongG+--+  'printGraphValues' ('learnEM' samples wrongG)+@++First, we display the topology of the graph and the values for the reference graph and the wrong one.+Then, we use the 'learnEM' function to learn a new network from the samples. And, we print the new values to check.++-}+module Bayes.Examples.EMTest(+    -- * Test function+    emTest+  ) where+++import Bayes.Sampling +import System.Random.MWC.CondensedTable+import qualified Data.Vector as V+import Bayes.Factor+import Bayes+import Bayes.FactorElimination+import Data.Maybe(fromJust)+import Bayes.BayesianNetwork+import Bayes.Factor.CPT+import Statistics.Sample.Histogram+import Bayes.EM++simple :: ([TDV Bool],SBN CPT)+simple = runBN $ do +    a <- variable "a" (t :: Bool)+    b <- variable "b" (t :: Bool) +    +    proba a ~~ [0.4,0.6]+    cpt b [a] ~~ [0.8,0.2,0.2,0.8]++    return [a,b]++wrong :: ([TDV Bool],SBN CPT)+wrong = runBN $ do +    a <- variable "a" (t :: Bool)+    b <- variable "b" (t :: Bool) +    +    proba a ~~ [0.2,0.8]+    cpt b [a] ~~ [0.8,0.2,0.2,0.8]++    return [a,b]++setJust vertex v = Just v ++generatePatterns :: IO [[DVI]]+generatePatterns = do +    let (vars@[a,b],exampleG) = simple+    r <- runSampling 5000 0 (discreteAncestralSampler exampleG)+    return (map allVertexValues r)++emTest = do +  samples <- generatePatterns +  let (_,simpleG) = simple +      (_,wrongG) = wrong +  print simpleG +  printGraphValues simpleG+  printGraphValues wrongG++  +  printGraphValues (learnEM samples wrongG)+ 
+ Bayes/Examples/Sampling.hs view
@@ -0,0 +1,98 @@+{- | Example of sampling++Two samplers are availables : the 'discreteAncestralSampler' and the 'gibbsSampler'.+Only the 'gibbsSampler' can be used with evidence.++In this example, we have a very simple network.++@+    simple :: (['TDV' Bool],'SBN' 'CPT')+    simple = 'runBN' $ do +        a <- 'variable' \"a\" ('t' :: Bool)+        b <- 'variable' \"b\" ('t' :: Bool) +--        +        'proba' a '~~' [0.4,0.6]+        'cpt' b [a] '~~' [0.8,0.2,0.2,0.8]+--    +        return [a,b]+@++This network is representing a sensor b. We observe the value of b and we want to infer the value of a.++We use the 'gibbsSampler' for this with an initial period of 200 samples which are dropped. The 'gibbsSampler' is+generate a stream of samples. From this stream, we need to compute a probability distribution. For this, we use+the 'samplingHistograms' histogram function which is generating a list : the probability values of each vertex.++@+    let (vars\@[a,b],exampleG) = simple+    n <- 'runSampling' 5000 200 ('gibbsSampler' exampleG [b '=:' True])+    let h = 'samplingHistograms' n+    print $ h+@++Then, we compare this result with the exact one we get with a junction tree.++@+    let jt = 'createJunctionTree' 'nodeComparisonForTriangulation' exampleG+        jt' = 'changeEvidence' [b '=:' True] jt+    mapM_ (\x -> print . 'posterior' jt' $ [x]) vars+@++We can also use the 'discreteAncestralSampler' to compute the posterior but it is not supporting the use of evidence in this+version. The syntax is similar.++@+    n <- 'runSampling' 500 ('discreteAncestralSampler' exampleG)+@++-}+module Bayes.Examples.Sampling(+    -- * Test function+	  testSampling+) where++import Bayes.Sampling +import System.Random.MWC.CondensedTable+import qualified Data.Vector as V+import Bayes.Factor+import Bayes+import Bayes.FactorElimination+import Data.Maybe(fromJust)+import Bayes.BayesianNetwork+import Bayes.Factor.CPT+import Statistics.Sample.Histogram+++simple :: ([TDV Bool],SBN CPT)+simple = runBN $ do +    a <- variable "a" (t :: Bool)+    b <- variable "b" (t :: Bool) +    +    proba a ~~ [0.4,0.6]+    cpt b [a] ~~ [0.8,0.2,0.2,0.8]++    return [a,b]+++testSampling = do+    let (vars@[a,b],exampleG) = simple+        jt = createJunctionTree nodeComparisonForTriangulation exampleG+    --n <- runSampling 500 (discreteAncestralSampler exampleG)+    putStrLn "The bayesian network"+    print exampleG+    putStrLn "\nThe values of the Bayesian network"+    printGraphValues exampleG++    n <- runSampling 5000 200 (gibbsSampler exampleG [b =: True])+    let h = samplingHistograms 2 n+    putStrLn "\nThe result of the sampling"+    print $ h++    n <- runSampling 5000 200 (gibbsMCMCSampler exampleG [b =: True])+    let h = samplingHistograms 2 n+    putStrLn "\nThe result of the sampling with MCMC"+    print $ h++    let jt' = changeEvidence [b =: True] jt+    putStrLn "\nThe result of the junction tree inference"+    mapM_ (\x -> print . posterior jt' $ [x]) vars
Bayes/Examples/Tutorial.hs view
@@ -67,7 +67,7 @@ Once the junction tree has been computd, it can be used to compute several marginals:  @-    'posterior' jt rain+    'posterior' jt [rain] @  The function is called posterior and will compute posterior only when solme evidence has@@ -77,7 +77,7 @@  @     let jt' = 'updateEvidence' [wet '=:' True] jt -    'posterior' jt' rain+    'posterior' jt' [rain] @  If you want to compute the posterior for a combination of variables, you have two possibilities : either going back to the@@ -99,12 +99,12 @@ @     let jt4 = 'changeEvidence' [wet '=:' True] jt      print \"Posterior Marginal : probability of rain and road slippery if grass wet\"-    let m = 'posterior' jt4 roadandrain+    let m = 'posterior' jt4 [roadandrain]     print m --     let jt5 = 'changeEvidence' [wet '=:' True, sprinkler '=:' False] jt      print \"Posterior Marginal : probability of rain and road slippery if grass wet and srinkler not used\"-    let m = 'posterior' jt5 roadandrain+    let m = 'posterior' jt5 [roadandrain] @  /Inferences with an imported network/@@ -146,11 +146,11 @@ @     let jtcancer = 'createJunctionTree' 'nodeComparisonForTriangulation' cancer ---    mapM_ (\x -> putStrLn (show x) >> (print . 'posterior' jtcancer $ x)) [varA,varB,varC,varE]+    mapM_ (\x -> putStrLn (show x) >> (print . 'posterior' jtcancer $ [x])) [varA,varB,varC,varE] --     print \"UPDATED EVIDENCE\"     let jtcancer' = 'updateEvidence' [varD '=:' Present] jtcancer -    mapM_ (\x -> putStrLn (show x) >> (print . 'posterior' jtcancer' $ x)) [varA,varB,varC,varE]+    mapM_ (\x -> putStrLn (show x) >> (print . 'posterior' jtcancer' $ [x])) [varA,varB,varC,varE] @  The '=:' operator will check that the assignment is type compatible because varD is a typed discrete variable of type 'TDV' Coma.@@ -208,13 +208,13 @@  @     print \"Sensor 90%\"-    print $ posterior ('changeFactor' (theNewFactor 0.9) jt') a+    print $ posterior ('changeFactor' (theNewFactor 0.9) jt') [a] --     print \"Sensor 50%\"-    print $ posterior ('changeFactor' (theNewFactor 0.5) jt') a+    print $ posterior ('changeFactor' (theNewFactor 0.5) jt') [a] --     print \"Sensor 10%\"-    print $ posterior ('changeFactor' (theNewFactor 0.1) jt') a+    print $ posterior ('changeFactor' (theNewFactor 0.1) jt') [a] @  -}@@ -257,7 +257,7 @@   (varmap,perso) <- exampleDiabete   let jtperso = createJunctionTree nodeComparisonForTriangulation perso       cho0 = fromJust . Map.lookup "cho_0" $ varmap-  print $ posterior jtperso cho0+  print $ posterior jtperso [cho0] #endif  miscTest s = do @@ -270,7 +270,7 @@   print "FACTOR ELIMINATION"   let post (v,name) = do          putStrLn name -        print $ posterior jtperso v+        print $ posterior jtperso [v]   mapM_ post  (zip l names)    print "VARIABLE ELIMINATION"@@ -294,15 +294,15 @@     let [varA,varB,varC,varE] = fromJust $ mapM (flip Map.lookup varmap) ["A","B","C","E"]         jtcancer = createJunctionTree nodeComparisonForTriangulation cancer         varD = tdv (fromJust $ Map.lookup "D" varmap) :: TDV Coma-    mapM_ (\x -> putStrLn (show x) >> (print . posterior jtcancer $ x)) [varA,varB,varC,varE]+    mapM_ (\x -> putStrLn (show x) >> (print . posterior jtcancer $ [x])) [varA,varB,varC,varE]      print "UPDATED EVIDENCE : Coma present"     let jtcancer' = changeEvidence [varD =: Present] jtcancer -    mapM_ (\x -> putStrLn (show x) >> (print . posterior jtcancer' $ x)) [varA,varB,varC,varE]+    mapM_ (\x -> putStrLn (show x) >> (print . posterior jtcancer' $ [x])) [varA,varB,varC,varE]      print "UPDATED EVIDENCE : Coma absent"     let jtcancer' = changeEvidence [varD =: Absent] jtcancer -    mapM_ (\x -> putStrLn (show x) >> (print . posterior jtcancer' $ x)) [varA,varB,varC,varE]+    mapM_ (\x -> putStrLn (show x) >> (print . posterior jtcancer' $ [x])) [varA,varB,varC,varE] #endif   -- | Display of factors generated by the logical keyword@@ -322,13 +322,13 @@         theNewFactor x = fromJust $ se seNode a x -- x % success for the sensor         jt' = changeEvidence [seNode =: True] jt     print "Sensor 90%"-    print $ posterior (changeFactor (theNewFactor 0.9) jt') a+    print $ posterior (changeFactor (theNewFactor 0.9) jt') [a]      print "Sensor 50%"-    print $ posterior (changeFactor (theNewFactor 0.5) jt') a+    print $ posterior (changeFactor (theNewFactor 0.5) jt') [a]      print "Sensor 10%"-    print $ posterior (changeFactor (theNewFactor 0.1) jt') a+    print $ posterior (changeFactor (theNewFactor 0.1) jt') [a]  -- | Inferences with the standard network inferencesOnStandardNetwork = do@@ -360,38 +360,38 @@     print "FACTOR ELIMINATION"     putStrLn ""     print "Prior Marginal : probability of rain"-    let m = posterior jt rain+    let m = posterior jt [rain]     print m     putStrLn ""      let jt' = changeEvidence [wet =: True] jt       print "Posterior Marginal : probability of rain if grass wet"-    let m = posterior jt' rain+    let m = posterior jt' [rain]     print m     putStrLn ""      let jt'' = changeEvidence [] jt'     print "Prior Marginal : probability of rain"-    let m = posterior jt rain+    let m = posterior jt [rain]     print m     putStrLn ""      let jt3 = changeEvidence [wet =: True, sprinkler =: True] jt'     print "Posterior Marginal : probability of rain if grass wet and sprinkler used"-    let m = posterior jt3 rain+    let m = posterior jt3 [rain]     print m     putStrLn ""      let jt4 = changeEvidence [wet =: True] jt      print "Posterior Marginal : probability of rain and road slippery if grass wet"-    let m = posterior jt4 roadandrain+    let m = posterior jt4 [roadandrain]     print m     putStrLn ""      let jt5 = changeEvidence [wet =: True, sprinkler =: False] jt      print "Posterior Marginal : probability of rain and road slippery if grass wet and srinkler not used"-    let m = posterior jt5 roadandrain+    let m = posterior jt5 [roadandrain]     print m     putStrLn "" 
Bayes/Factor.hs view
@@ -16,6 +16,7 @@  -- * Set of variables   , Set(..)  , BayesianDiscreteVariable(..)+ , BayesianVariable(..)  -- * Implementation  , Vertex(..)  -- ** Discrete variables and instantiations@@ -24,10 +25,10 @@  , DVSet(..)  , DVI  , DVISet+ , InstantiationValue(..)  , tdvi  , tdv  , setDVValue- , instantiationValue  , instantiationVariable  , variableVertex  , (=:)
Bayes/Factor/CPT.hs view
@@ -111,7 +111,6 @@     mkValue = id     scale = (*)     multiply = (*)-    elementUnit = 1.0     divide _ 0 = 0     divide a b = a / b      elementSum = (+)@@ -136,18 +135,32 @@          evidenceFrom = _evidenceFrom -    factorProduct = _factorProduct multiply+    factorProduct = _factorProduct (Op (factorFromScalar 1.0) 1.0 multiply)          factorProjectOut _ f@(Scalar v) = f     factorProjectOut s f= cptFactorProjectOutWith (sum . map fst) s f  --  Divie two CPT cptDivide :: CPT -> CPT -> CPT-cptDivide a b = _factorProduct divide [a, b]+cptDivide a b   | isScalarFactor a && isScalarFactor b = +                    let va = factorValue a [] +                        vb = factorValue b [] +                    in +                    factorFromScalar (divide va vb)+                | isScalarFactor a = +                    let va = factorValue a [] +                    in +                    factorScale va b +                | isScalarFactor b = +                    let vb = factorValue b [] +                    in +                    if vb == 0.0 then factorFromScalar 0.0 else factorScale (1.0 / vb) a +                | otherwise =+                    _factorProduct (Op (factorFromScalar 1.0) 1.0 divide) [b,a]   cptSum :: [CPT] -> CPT-cptSum = _factorProduct elementSum+cptSum = _factorProduct (Op (factorFromScalar 0.0) 0.0 elementSum)  instance IsBucketItem CPT where      scalarItem = isScalarFactor
Bayes/Factor/MaxCPT.hs view
@@ -29,7 +29,6 @@     multiply (da,[]) (db,lb) = (da*db,lb)     multiply (da,la) (db,[]) = (da*db,la)     multiply (da,la) (db,lb) = (da*db,[xa ++ xb | xa <- la, xb <- lb])-    elementUnit = (1.0,[])     divide _ _ = error "It does not make sense to divide MAXCPT elements"     elementSum _ _ = error "It does not make sense to sum MAXCPT elements" @@ -37,7 +36,7 @@ instantiationProba (a,b) = fst a   maximization :: [((Double,PossibleInstantiations), DVISet)] -> (Double,PossibleInstantiations)-maximization [] = elementUnit +maximization [] = (1.0, [])  maximization l =      let ((d,possible),newInst) = maximumBy (compare `on` instantiationProba) l         addTo [] l = l@@ -65,7 +64,7 @@      evidenceFrom = _evidenceFrom -    factorProduct = _factorProduct multiply+    factorProduct = _factorProduct (Op (factorFromScalar 1.0) (1.0,[]) multiply)          factorProjectOut _ f@(Scalar v) = f     factorProjectOut s f = cptFactorProjectOutWith maximization s f
Bayes/Factor/PrivateCPT.hs view
@@ -11,6 +11,7 @@    -- ** Private functions    , FactorElement(..)    , DecisionFactor(..)+   , Operator(..)    , _emptyFactor    , _factorVariables    , _isScalarFactor@@ -130,7 +131,6 @@     multiply :: a -> a -> a     divide :: a -> a -> a     elementSum ::  a -> a -> a-    elementUnit :: a  _isUsingSameVariablesAs :: PrivateCPT v a -> PrivateCPT v a -> Bool _isUsingSameVariablesAs (Table va _ _) (Table vb _ _) = va == vb@@ -210,17 +210,19 @@ {-# INLINE _factorValue #-} _factorValue f d = doubleValue (privateFactorValue f d) +data Operator f a = Op f a (a -> a -> a)+ _factorProduct :: (FactorElement a, GV.Vector v a, Factor (PrivateCPT v a)) -               => (a -> a -> a)+               => Operator (PrivateCPT v a) a                -> [PrivateCPT v a]                 -> PrivateCPT v a-_factorProduct _ [] = factorFromScalar 1.0-_factorProduct op l = +_factorProduct (Op fUnit opUnit op) [] = fUnit+_factorProduct (Op fUnit opUnit op) l =      let nakedVars = L.foldr1 union . map factorVariables $ l         allVars = DVSet nakedVars         (scalars,cpts) = partition isScalarFactor l         stridesFromCPT (Table d _ _) = indexStridesFor (DVSet d) allVars-        elementProduct [] = elementUnit+        elementProduct [] = opUnit         elementProduct l = foldr1 op l         ps = elementProduct . map (flip privateFactorValue undefined) $ scalars         cptsStrides = map stridesFromCPT cpts
Bayes/FactorElimination.hs view
@@ -308,10 +308,12 @@   -- | Compute the marginal posterior (if some evidence is set on the junction tree)-  -- otherwise compute just the marginal prior.-posterior :: (BayesianDiscreteVariable dv, Factor f, IsBucketItem f) => JunctionTree f -> dv -> Maybe f+-- otherwise compute just the marginal prior. The set of variables must be included inside a cluster+-- for thr algorithm to work. So, most of the cases, it will be used to compute the posterior of just+-- one variable.+posterior :: (BayesianDiscreteVariable dv, Factor f, IsBucketItem f) => JunctionTree f -> [dv] -> Maybe f posterior t someDv = -  let v = dv someDv+  let v = map dv someDv   in   case snd $ traverseTree (findClusterFor v) Nothing t of      Nothing -> Nothing@@ -319,19 +321,19 @@                   d = maybe (factorFromScalar 1.0) id $ downMessage t =<< (nodeParent t c)                   u = map (upMessage t) (nodeChildren t c)                   allFactors = d:u ++ f ++ e-                  variablesToRemove = (nub (concatMap factorVariables allFactors)) \\ [v]-                  unNormalized = marginal allFactors variablesToRemove [v] []+                  variablesToRemove = (nub (concatMap factorVariables allFactors)) \\ v+                  unNormalized = marginal allFactors variablesToRemove v []               in                Just $ factorDivide unNormalized (factorNorm unNormalized)  -- | Find a cluster containing the variable-findClusterFor :: DV +findClusterFor :: [DV]                -> Maybe Cluster                -> Cluster -- ^ Current cluster                -> NodeValue f -- ^ Current value                -> Action (Maybe Cluster) (NodeValue f) findClusterFor dv s c@(Cluster sc) v = -  case Set.member dv sc of +  case Set.isSubsetOf (Set.fromList dv) sc of      False -> Skip s      True -> Stop (Just c) 
Bayes/InfluenceDiagram.hs view
@@ -269,12 +269,14 @@ instance Show DEV where     show (DEV v d) = "D" ++ show v ++ "(" ++ show d ++ ")" +instance BayesianVariable DEV where +  vertex (DEV v _) = v+ instance BayesianDiscreteVariable DEV where    dimension (DEV _ d) = d    dv (DEV v d) = DV v d -  vertex (DEV v _) = v -instance Instantiable DEV Int where +instance Instantiable DEV Int DVI where    (=:) d@(DEV v dim) value = DVI (dv d) value  data PorD = P DV | D DEV deriving(Eq)@@ -288,13 +290,16 @@ instance ChanceVariable (TDV s) where    toDV = dv +instance BayesianVariable PorD where +    vertex (D d) = vertex d+    vertex (P p) = vertex p+ instance BayesianDiscreteVariable PorD where     dimension (D d) = dimension d     dimension (P p) = dimension p     dv (D x) = dv x     dv (P x) = dv x-    vertex (D d) = vertex d-    vertex (P p) = vertex p+  -- | Used to mix decision and chance variables and a same list p :: ChanceVariable c => c -> PorD
Bayes/Network.hs view
@@ -22,6 +22,9 @@ 	, runNetwork 	, execNetwork 	, evalNetwork+  , runGraph+  , execGraph+  , evalGraph 	, getCpt 	) where  
Bayes/PrivateTypes.hs view
@@ -5,10 +5,13 @@ -} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-} module Bayes.PrivateTypes(   -- * Classes and types    BayesianDiscreteVariable(..)+ , BayesianVariable(..)  , Set(..)+ , BayesianNetwork(..)  -- * Variables  , DV(..)  , DVSet(..)@@ -16,11 +19,13 @@  , TDV  , tdv  , tdvi+ , CV(..)+ , CVI(..)  -- * Instantiations  , Instantiable(..)+ , InstantiationValue(..)  , DVI(..)  , setDVValue- , instantiationValue  , instantiationVariable  , fromDVSet  -- * Vertices, Graph@@ -38,6 +43,10 @@  , instantiationDetails  , instantiation  , allInstantiationsForOneVariable+ -- * For sampling + , Sample(..)+ , DistributionSupport(..)+ , DistributionF(..)  -- * Tests   , instantiationProp  ) where@@ -50,9 +59,32 @@ import System.Random(Random) import qualified Data.IntMap as IM import qualified Data.Map as M+import Control.Monad.Reader  +-- | Bayesian network. g must be a directed graph and f a factor+type BayesianNetwork g f = g () f +{-+For sampling+-} +++-- | A sample (graph of instantiations)+type Sample g a = BayesianNetwork g a++-- | Support of the distributiob p(x | abc ...) for x depending on the value of a,b,c ...+data DistributionSupport a = BoundedSupport !a +                           | Unbounded !Double -- ^ Standard deviation+                           deriving(Eq)++-- | Distribution function with a possible bound for the function target+-- The bound may depend on the current sample (because for unbounded we need a variance to be able+-- to cover enough of the support)+data DistributionF g bound inst = Distri !(Reader (Sample g inst) (DistributionSupport bound)) !(inst -> Reader (Sample g inst) Double)+++ {- 	Set -}@@ -128,24 +160,44 @@ instance Show Vertex where      show (Vertex v) = "v" ++ show v +-- | A Bayesian Variable is a variable part of Bayesian network and so which knows+-- its position : the vertex.+class BayesianVariable v where +  vertex :: v -> Vertex + -- | A discrete variable has a number of levels which is required to size the factors-class BayesianDiscreteVariable v where+class BayesianVariable v => BayesianDiscreteVariable v where     dimension :: v -> Int      dv :: v -> DV-    vertex :: v -> Vertex  -- | Get the minimum bound for a type getMinBound :: Bounded a => a -> a  getMinBound _ = minBound --+instance BayesianVariable Vertex where +  vertex v = v +   {-  Variables 	 -} +-- | A continuous variable+data CV = CV !Vertex deriving(Eq,Ord)++instance Show CV where +  show (CV v) = show v++instance BayesianVariable CV where +  vertex (CV v) = v ++-- | A continuous variable instantiation +data CVI = CVI !CV !Double deriving(Eq,Ord,Show)++instance BayesianVariable CVI where +  vertex (CVI v _) = vertex v+ -- | A discrete variable data DV = DV !Vertex !Int deriving(Eq,Ord) @@ -160,10 +212,12 @@ instance Show DV where     show (DV v d) = show v ++ "(" ++ show d ++ ")" +instance BayesianVariable DV where +    vertex (DV v _) = v+ instance BayesianDiscreteVariable DV where     dimension (DV _ d) = d     dv = id-    vertex (DV v _) = v  -- | A typed discrete variable data TDV s = TDV !Vertex !Int deriving(Eq,Ord)@@ -171,10 +225,12 @@ instance Show (TDV s) where     show (TDV v d) = show v +instance BayesianVariable (TDV s) where +    vertex (TDV v _) = v+ instance BayesianDiscreteVariable (TDV s) where     dimension (TDV _ d) = d     dv (TDV v nb) = DV v nb-    vertex (TDV v _) = v  -- | Typed discrete variable tdv :: DV -> TDV s @@ -228,16 +284,32 @@    -- | A set of variable instantiations type DVISet = [DVI] -class Instantiable d v where +class InstantiationValue i v | i -> v where +  instantiationValue :: i -> v +  toDouble :: i -> Double++instance InstantiationValue DVI Int where +  -- | Extract value of the instantiation+  instantiationValue (DVI _ v) = v+  toDouble (DVI _ v) = fromIntegral v++instance InstantiationValue CVI Double where +  -- | Extract value of the instantiation+  instantiationValue (CVI _ v) = v+  toDouble (CVI _ v) = v++class Instantiable d v r | d -> r where    -- | Create a variable instantiation using values from   -- an enumeration-  (=:) :: d -> v -> DVI +  (=:) :: d -> v -> r  +instance Instantiable CV Double CVI where +  (=:) c x = CVI c x -instance (Bounded b, Enum b) => Instantiable DV b where+instance (Bounded b, Enum b) => Instantiable DV b DVI where   (=:) a b = setDVValue a (fromEnum b - fromEnum (getMinBound b)) -instance (Bounded b, Enum b) => Instantiable (TDV b) b where+instance (Bounded b, Enum b) => Instantiable (TDV b) b DVI where   (=:) (TDV v nb) b = setDVValue (DV v nb) (fromEnum b - fromEnum (getMinBound b))  @@ -246,18 +318,18 @@ setDVValue v a = DVI v a  +instance BayesianVariable DVI where +    vertex (DVI dv _) = vertex dv  instance BayesianDiscreteVariable DVI where     dimension (DVI v _) = dimension v     dv = instantiationVariable-    vertex (DVI dv _) = vertex dv  -- | Get the variables and their values with a type constraint instantiationDetails :: [DVI] -> (DVSet s, MultiIndex s) instantiationDetails l = (DVSet $ map instantiationVariable l, MultiIndex . V.fromList . map (instantiationValue) $ l) --- | Extract value of the instantiation-instantiationValue (DVI _ v) = v+  -- | Discrete variable from the instantiation instantiationVariable (DVI dv _) = dv
+ Bayes/Sampling.hs view
@@ -0,0 +1,490 @@+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FunctionalDependencies #-}+{- | Sampling++Samplers for Bayesian network inferences++-}+module Bayes.Sampling(+  -- * Types +     Sampler(..)+   , Sample(..)+  -- * Sampling+   , runSampling+   , topologicalOrder+  -- * Sampling schemes+   , discreteAncestralSampler+   , gibbsSampler+   , gibbsMCMCSampler+  -- * Sampling results+   , samplingHistograms+   , histogram+  -- * For continuous distributions +   , ContinuousNetwork(..) +   , ContinuousSample(..)+   , Distri(..)+   , continuousMCMCSampler+) where +++import Bayes+import Bayes.Factor+import Control.Monad.Reader +import Data.Maybe(fromJust)+import Bayes.PrivateTypes+import System.Random.MWC.CondensedTable+import System.Random.MWC.Distributions(normal)+import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as UV+import qualified Data.Vector.Unboxed.Mutable as MV(write,read)++import System.Random.MWC(GenIO,create,withSystemRandom,asGenIO,uniformR,Variate)++--import Debug.Trace ++--debug s a = trace ("DEBUG:\n" ++ s ++ show a ++ "\n") a++-- | A graph of sampling functions (parental sampler or markov blanket sampler)+-- It is used to generate new samples.+-- The vertex is implicit in the function definition+-- Which means that if a function is for updating vertex V then it will be the value of vertex+-- V in the sampler graph.+type SamplerGraph g a = BayesianNetwork g (Sample g a -> IO a)++-- | Sampling function for a graph.+-- Generate a new sample and update the state. +type SamplingScheme g b a = GenIO -> SamplerGraph g a -> b -> Sample g a -> IO (b,Sample g a)++-- | Sampler defining the behavior of a sampling algorithms (init value,+-- sample generation, how to select nodes in the grapg)+data Sampler g a = forall b . Sampler !b !(GenIO -> IO (Sample g a)) !(GenIO -> SamplerGraph g a) !(SamplingScheme g b a)+++data Distri = D !CV !(DistributionF DirectedSG (Double,Double) CVI)++type ContinuousNetwork = SBN Distri++type ContinuousSample = SBN CVI++-- | Get current value of function using current network values+distributionOnNetwork ::(DistributionF DirectedSG (Double,Double) CVI) -> Vertex -> Reader (Sample DirectedSG CVI) Double +distributionOnNetwork (Distri _ f) v = do +  r <- ask +  let inst = fromJust . vertexValue r $ v +  f inst++instance Graph g => Show (Sample g [DVI]) where +    show = show . allNodes++instance Graph g => Show (Sample g CVI) where +    show = show . allNodes++instance Graph g => Show (Sample g [(Double,Double,Double)]) where +    show = show . allNodes++{-++Ancestral sampling ++-}++-- | Return the vertices in topological order+topologicalOrder :: DirectedGraph g => g a b -> [Vertex] +topologicalOrder g = _topologicalOrder g [] + where+  _topologicalOrder g current = case rootNode g of +    Nothing -> reverse current+    Just r -> _topologicalOrder (removeVertex r g) (r:current)++-- | Generate a new sample for vertex based upon the sampler functions+-- and the current sample+generateNewSample :: Graph g => SamplerGraph g a  -> Sample g a -> Vertex -> IO (Sample g a)+generateNewSample sampler sample theVertex = do+   let vertexSampler = fromJust $ vertexValue sampler theVertex +   newValue <- vertexSampler sample +   return . fromJust . changeVertexValue theVertex newValue $ sample ++-- | Update all vertices in the current sample and generate a new sample.+-- It is done using ancestral sampling+ancestralSampling :: DirectedGraph g => SamplingScheme g [Vertex] a+ancestralSampling gen sampler nodes s  = do +  r <- foldM (generateNewSample sampler) s nodes+  return (nodes,r)++-- | Select a vertex and generate a new sample using gibbs sampling+gibbsSampling :: DirectedGraph g => SamplingScheme g (CondensedTable V.Vector Vertex) a+gibbsSampling gen samplerGraph table s = do +  aVertex <- genFromTable table gen +  r <- generateNewSample samplerGraph s aVertex+  return (table,r)++-- | Sequence a list of the SAME graphs but with different node values+sequenceG :: (FunctorWithVertex g, Graph g) => [g a b] -> g a [b]+sequenceG [] = error "Can't sequence an empty list of graphs"+sequenceG l@(h:_) = +  let setVertexList vertex oldValue = map (\g -> fromJust . vertexValue g $ vertex) l+  in +  fmapWithVertex setVertexList h ++_range :: Double -> Double -> [Double] -> (Double,Double)+_range mi ma [] = (mi,ma) +_range mi ma (h:t) | h < mi = _range h ma t +                   | h > ma = _range mi h t +                   | otherwise = _range mi ma t ++range :: [Double] -> (Double,Double)+range = _range (1/0) (-1/0)++-- | Compute the histogram of values+histogram :: Int -- ^ Bins +          -> [Double] -- ^ Samples +          -> [(Double,Double,Double)] -- ^ Histogram  (minBound,maxBound, value)+histogram bins values | bins <= 0 = error "Bins must be >= 1" +                      | bins == 1 =+  let (bmin,bmax) = range values +  in +  [(bmin,bmax,1.0)]+                      | otherwise = +  let (bmin,bmax) = range values +  in+  if bmax == bmin +    then +      [(bmin,bmax,1.0)]+    else +      let delta = (bmax - bmin) / fromIntegral bins+          v = UV.replicate bins 0.0+          orMAX a | a >= bins = bins - 1 +                  | otherwise = a+          countSample value = UV.modify (\s -> do +            --when (isNaN value) $ error "NaN"+            let index = orMAX $ floor ((value - bmin) / delta) +            --when (index < 0) $ error ("index == " ++ show index ++ show " " ++ show value) +            --when (index >= bins) $ error ("index == " ++ show index ++ show " " ++ show value)+            d <- MV.read s index +            MV.write s index (d+1)) +          v' = foldr countSample v values+          t = UV.sum v'+          scaled = UV.map (/ t) v'+          addBounds value i = (bmin + delta * i ,bmin + delta + delta*i,value)+      in +      zipWith addBounds (UV.toList scaled) [0..]++-- | Generate a graph of sampling histogram for each variable+-- So, for a vertex v we have the posterior values p(v)+samplingHistograms :: (InstantiationValue i v,BayesianVariable i, FunctorWithVertex g, Graph g) +                   => Int -- ^ Number of bins+                   -> [Sample g i] -- ^ Samples+                   -> Sample g [(Double,Double,Double)] -- ^ Histogram with start bins and bin content+samplingHistograms bins g' = +  let g = sequenceG g' +  in+  fmapWithVertex (createHistogram bins g) g+ where +  createHistogram bins g vertex l =  histogram bins . map toDouble $ l++-- | Sample a bayesian network using a given sampling scheme+runSampling :: (DirectedGraph g, FunctorWithVertex g) +            => Int -- ^ Number of used samples+            -> Int -- ^ Burnin samples before the used samples+            -> Sampler g a -- ^ Sampler+            -> IO [Sample g a] -- ^ List of generated samples+runSampling n b (Sampler initState startSample sampler samplingScheme) = do +    withSystemRandom . asGenIO $ \gen -> do+       start <- startSample gen+       l <- _runAncestralSampling gen (n+b) initState start []+       return (drop b $ l)+  where +    _runAncestralSampling gen n istate i r | n <= 1 = return $ reverse (i:r)+                                           | otherwise = do+                                               (newState,i') <- samplingScheme gen (sampler gen)  istate i+                                               _runAncestralSampling gen (n-1) newState i' (i':r)  +++{-++Discrete variable sampling++-}  ++-- | Gibbs sampling+gibbsSampler :: (Factor f, FunctorWithVertex g, DirectedGraph g) +             => BayesianNetwork g f -- ^ Bayesian network+             -> [DVI] -- ^ Evidence+             -> Sampler g DVI -- ^ Sampler+gibbsSampler g evidence = +  let isEvidence v = v `elem` (map vertex evidence)+      v = filter (not . isEvidence) (allVertices g)+      t = tableFromWeights $ V.fromList $ zip v (repeat 1.0)+  in+  Sampler t (gibbsInitValue evidence g) (gibbsGraphSampler g)  gibbsSampling++-- | Gibbs sampling+gibbsMCMCSampler :: (Factor f, FunctorWithVertex g, DirectedGraph g) +                 => BayesianNetwork g f -- ^ Bayesian network+                 -> [DVI] -- ^ Evidence+                 -> Sampler g DVI -- ^ Sampler+gibbsMCMCSampler g evidence = +  let isEvidence v = v `elem` (map vertex evidence)+      v = filter (not . isEvidence) (allVertices g)+      t = tableFromWeights $ V.fromList $ zip v (repeat 1.0)+  in+  Sampler t (gibbsInitValue evidence g) (gibbsMCMCGraphSampler g)  gibbsSampling++-- | Gibbs sampling for continuous network +continuousMCMCSampler :: ContinuousNetwork -- ^ Bayesian network+                      -> [CVI] -- ^ Evidence+                      -> Sampler DirectedSG CVI-- ^ Sampler+continuousMCMCSampler g evidence = +  let isEvidence v = v `elem` (map vertex evidence)+      v = filter (not . isEvidence) (allVertices g)+      t = tableFromWeights $ V.fromList $ zip v (repeat 1.0)+  in+  Sampler t (continuousInitValue evidence g) (gibbsContinuousMCMCGraphSampler g)  gibbsSampling++-- | Ancestral sampler which does not support evidence+discreteAncestralSampler :: (Factor f, FunctorWithVertex g, DirectedGraph g) => BayesianNetwork g f -> Sampler g DVI+discreteAncestralSampler g = +  let nodes = topologicalOrder g+  in+  Sampler nodes (discreteInitValue [] g) (discreteSampler g)  ancestralSampling+++-- | Distribution function from a factor+-- When we compute the distribution P(x | abc...), abc are given by the graph+-- but x is varied so we must not take its value fromthe graph.+-- So, x is an argument. +distributionFromFactor :: (DirectedGraph g,Factor f) => f -> DistributionF g DV DVI +distributionFromFactor f = +    let vars@(main:_) = factorVariables f+    in +    Distri (return $ BoundedSupport main) $ \current -> do +      sample <- ask+      let currentV = vertex main+          sample' = fromJust . changeVertexValue currentV current $ sample+      return $ factorValue f (variableInstantiations sample' vars)++-- | Distribution function from  markov blanket but not normalized+distributionFromMarkovBlanket :: (DirectedGraph g,Factor f) => BayesianNetwork g f -> f -> DistributionF g DV DVI +distributionFromMarkovBlanket g f = +  let vars@(main:_) = factorVariables f+    in +    Distri (return $ BoundedSupport main) $ \current -> do +      sample <- ask+      let currentV = vertex main +          sample' = fromJust . changeVertexValue currentV current $ sample+          children = childrenNodes sample currentV+          childrenF = map (fromJust . vertexValue g) children +          values = map (\aFactor -> factorValue aFactor (variableInstantiations sample' (factorVariables aFactor))) (f:childrenF)+      return $ product values++continuousDistributionFromMarkovBlanket :: ContinuousNetwork +                                        -> Distri +                                        -> DistributionF DirectedSG (Double,Double) CVI+continuousDistributionFromMarkovBlanket g (D cv d@(Distri b distri)) = Distri b $ \current -> do +      sample <- ask+      let currentV = vertex cv +          children = childrenNodes sample currentV+          dist (D _ d) = d+          childrenF = map (dist . fromJust . vertexValue g) children +      local (fromJust . changeVertexValue currentV current) $ do+        s' <- ask+        values <- mapM (uncurry distributionOnNetwork) ((d,currentV):zip childrenF children)+        return $ product $ values++-- | Value of distribution functions for all range values+forAllRange :: Graph g => Sample g DVI -> DistributionF g DV DVI -> [Double] +forAllRange g (Distri bound r) = +  let range = allInstantiationsForOneVariable theBound +  in +  map (flip runReader g . r) range+ where +  BoundedSupport theBound = runReader bound g+++-- | Value of distribution on Sample+distributionValue :: Graph g => DistributionF g bounds inst -> Sample g inst -> inst -> Double +distributionValue (Distri bound r) g v = runReader (r v) g+++-- | Probability distribution of A given some values for the parents in P(A | parents)+distribution :: Graph g => Sample g DVI -> DistributionF g DV DVI  -> CondensedTableV Int+distribution g f = +  let notNullProba (i,p) = p /= 0.0+      values = forAllRange g f+  in+  tableFromWeights $ V.fromList  $ filter notNullProba $ zip [0..] values++-- | Get the values of factor variables on the current instantiation+variableInstantiations :: (DirectedGraph g, BayesianVariable v) => Sample g a -> [v] -> [a]+variableInstantiations g vars = +  let vertices = map vertex vars+  in+  map (fromJust . vertexValue g) vertices++-- | Force the value of the vertex if it is part of the evidence otherwise+-- use the function+withEvidence :: (Monad m, BayesianVariable v, BayesianVariable vb) => [v] -> vb -> (vb -> m v) -> m v+withEvidence e v f = +  if (vertex v) `elem` (map vertex e) +    then +      return . head . filter (\x -> vertex v == vertex x) $ e+    else +      f v+++-- | Null instantiations (min bound for each variable)+nullInstantiation :: Factor f => [DVI] -> Vertex -> f -> DVI+nullInstantiation evidence v f  = setDVValue (factorMainVariable f) 0 ++-- | Random instantiation for a variable +randomInstantiation :: Factor f => GenIO -> [DVI] -> Vertex -> f -> IO DVI +randomInstantiation gen evidence vertex f = withEvidence evidence vertex $ \v -> do +  let main = factorMainVariable f+      t = tableFromWeights $ V.fromList $ zip [0..dimension main - 1] (repeat 1.0)+  r <- genFromTable t gen +  return (setDVValue main r)++continuousRandomInstantiation :: GenIO -> [CVI] -> Vertex -> Distri -> IO CVI +continuousRandomInstantiation gen evidence vertex (D cv (Distri b _)) = withEvidence evidence vertex $ \v -> do +   value <- uniformR (-10.0,10.0) gen :: IO Double+   return (cv =: value)++-- | Update one vertex in the current sample+updateOneSample :: (DirectedGraph g,Factor f) => GenIO -> Vertex -> f -> (Sample g DVI -> IO DVI)+updateOneSample gen v f = \s -> do+    let d = distributionFromFactor f+    newVal <- genFromTable (distribution s d) gen +    let v = factorMainVariable f +    return (setDVValue v newVal)++-- | Update one vertex in the current sample using gibbs transitions+gibbsUpdateOneSample :: (DirectedGraph g,Factor f) => BayesianNetwork g f -> GenIO -> Vertex -> f -> (Sample g DVI -> IO DVI)+gibbsUpdateOneSample g gen v f = +    let d = distributionFromMarkovBlanket g f+        v = factorMainVariable f +    in +    \s -> do+        newVal <- genFromTable (distribution s d) gen +        return (setDVValue v newVal)+++class SamplingBounds bound inter | bound -> inter where +  samplingBounds :: Num inter => bound -> (inter,inter)++class SamplingBounds bound inter => SampleGeneration var inst bound inter | var -> inst, var -> bound, var -> inter where+  generateSample :: Instantiable var inter inst => Sample g inst -> DistributionF g bound inst -> GenIO -> var -> IO inst++instance SamplingBounds DV Int where +  samplingBounds dv = (0, dimension dv - 1)++instance SampleGeneration DV DVI DV Int where+  generateSample s (Distri b _) gen var = do +      let theBound = runReader b s+      case theBound of +        BoundedSupport s -> do+            let (sa,sb) = samplingBounds s+            u <- uniformR (sa,sb) gen+            return $ setDVValue var u+        Unbounded v -> error "DVI are bounded"++instance SamplingBounds (Double,Double) Double where +  samplingBounds (sa,sb) = (sa,sb)++instance SampleGeneration CV CVI (Double,Double) Double where+  generateSample s (Distri b _) gen var = do +     let theBound = runReader b s+     case theBound of +       BoundedSupport s -> do +                let (sa,sb) = samplingBounds s+                u <- uniformR (sa,sb) gen+                return $ var =: u+       Unbounded sigma -> do +                n <- normal 0.0 sigma gen+                return $ var =: n++gibbsMCMCUpdateOneSample :: (DirectedGraph g,Factor f) +                         => BayesianNetwork g f +                         -> GenIO +                         -> Vertex +                         -> f +                         -> (Sample g DVI -> IO DVI)+gibbsMCMCUpdateOneSample g gen v f = +  let d = distributionFromMarkovBlanket g f+      main = factorMainVariable f+      v = vertex main+  in +  _gibbsMCMCUpdateOneSample d gen v main++gibbsContinuousMCMCUpdateOneSample :: ContinuousNetwork +                                   -> GenIO +                                   -> Vertex +                                   -> Distri+                                   -> (ContinuousSample -> IO CVI)+gibbsContinuousMCMCUpdateOneSample g gen v distri@(D cv _) = +  let d = continuousDistributionFromMarkovBlanket g distri+      v = vertex cv+  in +  _gibbsMCMCUpdateOneSample d gen v cv++-- | Generate a sample using MCMC method.+-- | Update one vertex in the current sample using gibbs transitions+_gibbsMCMCUpdateOneSample :: (DirectedGraph g,BayesianVariable var, Instantiable var inter inst, SampleGeneration var inst bound inter) +                          => DistributionF g bound inst+                          -> GenIO+                          -> Vertex+                          -> var+                          -> (Sample g inst -> IO inst)+_gibbsMCMCUpdateOneSample d@(Distri _ _)  gen v var = \s -> do+        newSample <- generateSample s d gen var+        let oldSample = fromJust . vertexValue s $ v+            oldProbaValue = distributionValue d s oldSample+            newProbaValue = distributionValue d s newSample+        if oldProbaValue == 0.0+          then +            return newSample +          else +            let r = newProbaValue / oldProbaValue +            in+            if (r >= 1.0) +              then +                return newSample +              else do +                z <- uniformR (0.0, 1.0)  gen+                if z < r +                  then +                    return newSample +                  else +                    return oldSample++++-- | Sampler graph where each vertex know how to update its value+discreteSampler :: (FunctorWithVertex g, Factor f, DirectedGraph g) => BayesianNetwork g f -> GenIO -> SamplerGraph g DVI+discreteSampler g gen = fmapWithVertex (updateOneSample gen) g++-- | Sampler graph where each vertex know how to update its value+gibbsGraphSampler :: (FunctorWithVertex g, Factor f, DirectedGraph g) => BayesianNetwork g f -> GenIO -> SamplerGraph g DVI+gibbsGraphSampler g gen = fmapWithVertex (gibbsUpdateOneSample g gen) g++-- | Sampler graph where each vertex know how to update its value+gibbsMCMCGraphSampler :: (FunctorWithVertex g, Factor f, DirectedGraph g) => BayesianNetwork g f -> GenIO -> SamplerGraph g DVI+gibbsMCMCGraphSampler g gen = fmapWithVertex (gibbsMCMCUpdateOneSample g gen) g++gibbsContinuousMCMCGraphSampler :: ContinuousNetwork+                                -> GenIO +                                -> SamplerGraph DirectedSG CVI+gibbsContinuousMCMCGraphSampler g gen = fmapWithVertex (gibbsContinuousMCMCUpdateOneSample g gen) g++-- | Start value+discreteInitValue :: (FunctorWithVertex g, Factor f, DirectedGraph g) => [DVI] -> BayesianNetwork g f -> GenIO -> IO (Sample g DVI) +discreteInitValue evidences g gen = fmapWithVertexM (randomInstantiation gen evidences) g++-- | Start value+gibbsInitValue :: (FunctorWithVertex g, Factor f, DirectedGraph g) => [DVI] -> BayesianNetwork g f -> GenIO -> IO (Sample g DVI) +gibbsInitValue = discreteInitValue++continuousInitValue ::[CVI] -> ContinuousNetwork -> GenIO -> IO ContinuousSample+continuousInitValue evidences g gen = fmapWithVertexM (continuousRandomInstantiation gen evidences) g
Bayes/Test/CompareEliminations.hs view
@@ -46,20 +46,20 @@     -- We then update the values to the right ones by using the right factor         jt = changeFactor theNewFactor jt' -    compareFactors "PRIOR FOR RAIN" (posterior jt rain) (priorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain])+    compareFactors "PRIOR FOR RAIN" (posterior jt [rain]) (priorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain])      let jt1 = changeEvidence [wet =: True] jt          jt2 = changeEvidence [wet =: True, sprinkler =: True] jt1  -    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt1 rain) +    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt1 [rain])           (posteriorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain]  [wet =: True])-    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt2 rain) +    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt2 [rain])           (posteriorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain]  [wet =: True, sprinkler =: True]) -    compareFactors "PRIOR FOR WINTER" (posterior jt winter) (priorMarginal exampleG [sprinkler,wet,road,rain,roadandrain] [winter])-    compareFactors "PRIOR FOR SPRINKLER" (posterior jt sprinkler) (priorMarginal exampleG [winter,wet,road,rain,roadandrain] [sprinkler])-    compareFactors "PRIOR FOR WET" (posterior jt wet) (priorMarginal exampleG [winter,sprinkler,road,rain,roadandrain] [wet])-    compareFactors "PRIOR FOR ROAD" (posterior jt road) (priorMarginal exampleG [winter,sprinkler,wet,rain,roadandrain] [road])+    compareFactors "PRIOR FOR WINTER" (posterior jt [winter]) (priorMarginal exampleG [sprinkler,wet,road,rain,roadandrain] [winter])+    compareFactors "PRIOR FOR SPRINKLER" (posterior jt [sprinkler]) (priorMarginal exampleG [winter,wet,road,rain,roadandrain] [sprinkler])+    compareFactors "PRIOR FOR WET" (posterior jt [wet]) (priorMarginal exampleG [winter,sprinkler,road,rain,roadandrain] [wet])+    compareFactors "PRIOR FOR ROAD" (posterior jt [road]) (priorMarginal exampleG [winter,sprinkler,wet,rain,roadandrain] [road])   -- | Compare that variable elemination and factor elimination are giving@@ -68,18 +68,18 @@ compareVariableFactor = do      let ([winter,sprinkler,rain,wet,road,roadandrain],exampleG) = example         jt = createJunctionTree nodeComparisonForTriangulation exampleG-    compareFactors "PRIOR FOR RAIN" (posterior jt rain) (priorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain])+    compareFactors "PRIOR FOR RAIN" (posterior jt [rain]) (priorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain])      let jt1 = changeEvidence [wet =: True] jt          jt2 = changeEvidence [wet =: True, sprinkler =: True] jt1  -    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt1 rain) +    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt1 [rain])           (posteriorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain]  [wet =: True])-    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt2 rain) +    compareFactors "POSTERIOR RAIN FOR WET" (posterior jt2 [rain])           (posteriorMarginal exampleG [winter,sprinkler,wet,road,roadandrain] [rain]  [wet =: True, sprinkler =: True]) -    compareFactors "PRIOR FOR WINTER" (posterior jt winter) (priorMarginal exampleG [sprinkler,wet,road,rain,roadandrain] [winter])-    compareFactors "PRIOR FOR SPRINKLER" (posterior jt sprinkler) (priorMarginal exampleG [winter,wet,road,rain,roadandrain] [sprinkler])-    compareFactors "PRIOR FOR WET" (posterior jt wet) (priorMarginal exampleG [winter,sprinkler,road,rain,roadandrain] [wet])-    compareFactors "PRIOR FOR ROAD" (posterior jt road) (priorMarginal exampleG [winter,sprinkler,wet,rain,roadandrain] [road])+    compareFactors "PRIOR FOR WINTER" (posterior jt [winter]) (priorMarginal exampleG [sprinkler,wet,road,rain,roadandrain] [winter])+    compareFactors "PRIOR FOR SPRINKLER" (posterior jt [sprinkler]) (priorMarginal exampleG [winter,wet,road,rain,roadandrain] [sprinkler])+    compareFactors "PRIOR FOR WET" (posterior jt [wet]) (priorMarginal exampleG [winter,sprinkler,road,rain,roadandrain] [wet])+    compareFactors "PRIOR FOR ROAD" (posterior jt [road]) (priorMarginal exampleG [winter,sprinkler,wet,rain,roadandrain] [road]) 
Bayes/Test/ReferencePatterns.hs view
@@ -31,7 +31,7 @@ value varmap jt s =    let v =  fromJust $ Map.lookup s varmap     in -    factorToList (fromJust $ posterior jt v) +    factorToList (fromJust $ posterior jt [v])   testWithRef varmap jt s l = assertBool s $ value varmap jt s ~=~ l testWithRefAndPrint varmap jt s l = do
hbayes.cabal view
@@ -7,13 +7,13 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version:             0.4.1+Version:             0.5  -- A short (one-line) description of the package.-Synopsis:            Inference with Discrete Bayesian Networks+Synopsis:            Bayesian Networks  -- A longer description of the package.-Description:  Algorithms for inference with Discrete Bayesian Networks.  +Description:  Algorithms for Bayesian Networks.    It is a very preliminary version. It has only been tested on very simple  examples where it worked. It should be considered as experimental and not used  in any production work.@@ -80,6 +80,12 @@     Bayes.InfluenceDiagram     Bayes.VariableElimination.Buckets     Bayes.Examples.Influence+    Bayes.Sampling+    Bayes.Examples.Sampling+    Bayes.EM+    Bayes.Examples.EMTest+    Bayes.Continuous+    Bayes.Examples.ContinuousSampling   other-modules:     Paths_hbayes     Bayes.ImportExport.HuginNet.Splitting@@ -100,11 +106,11 @@   -- Packages needed in order to build this package.   Build-depends:            base < 5,-    mtl == 2.0.1.0,-    containers == 0.4.2.1,-    array == 0.4.0.0,-    QuickCheck == 2.4.2,-    pretty == 1.1.1.0,+    mtl >= 2.0.1.0,+    containers >= 0.4.2.1,+    array >= 0.4.0.0,+    QuickCheck >= 2.4.2,+    pretty >= 1.1.1.0,     boxes,     vector,     random,@@ -116,4 +122,7 @@     test-framework-quickcheck2,     test-framework,     test-framework-hunit,-    HUnit+    HUnit,+    mwc-random >= 0.12,+    statistics >= 0.10.1,+    gamma >= 0.9