hbayes-0.5: Bayes/Test/ReferencePatterns.hs
{- | A comparison of factor elimination with reference values generated with another bayesian network software
It is a non regression test. The test patterns are not provided with this package.
So, those tests are disabled by default in the hackage version.
-}
module Bayes.Test.ReferencePatterns(
testFileExport
#ifdef LOCAL
, compareAsiaReference
, compareCancerReference
, comparePokerReference
, compareFarmReference
, compareMpeAsia
#endif
) where
import Test.HUnit.Base(assertBool)
import Data.Maybe(fromJust)
import qualified Data.Map as Map
import Bayes.Factor
import Bayes
import Bayes.FactorElimination
import Bayes.VariableElimination(mpe)
import Bayes.Examples(anyExample,example)
import Bayes.FactorElimination.JTree(root)
import Bayes.Tools(withTempFile)
import Bayes.ImportExport
import Bayes.BayesianNetwork
value varmap jt s =
let v = fromJust $ Map.lookup s varmap
in
factorToList (fromJust $ posterior jt [v])
testWithRef varmap jt s l = assertBool s $ value varmap jt s ~=~ l
testWithRefAndPrint varmap jt s l = do
let r = value varmap jt s
putStrLn $ "Computed:" ++ show r
putStrLn $ "Reference:" ++ show l
putStrLn ""
assertBool s $ r ~=~ l
-- | Test that we can import / export the bayesian network, junction tree and variable map
testFileExport :: IO ()
testFileExport = do
let (vars,g) = example
vm = varMap g
jt = createJunctionTree nodeComparisonForTriangulation g
withTempFile $ \f -> do
writeNetworkToFile f g
g' <- readNetworkFromFile f
assertBool "Test graph import/export" $ g == g'
withTempFile $ \f -> do
writeVariableMapAndJunctionTreeToFile f vm jt
(vm',jt') <- readVariableMapAndJunctionTreeToFile f
assertBool "Test jt import/export" $ jt == jt'
assertBool "Test variable map import/export" $ vm == vm'
-- Check that the float values are equal with an accuracy < 0.01%
comparePercent :: Double -> Double -> Bool
comparePercent a b = abs (a-b) < 1e-4
(~=~) a b = and (zipWith comparePercent a b)
#ifdef LOCAL
data Positive = Yes | No deriving(Eq,Enum,Bounded,Show)
-- | Get the name of vertices in the graph for display
rename :: NamedGraph g => g a b -> (TDV s,s) -> (String,s)
rename g = \(a,s) -> (fromJust . vertexLabel g . vertex $ a, s)
-- | Test that a MAP is not always the projection of a MPE
compareMpeAsia = do
(varmap,g) <- anyExample "asia.net"
let [x,b,d,a,s,l,t,e] = map tdv . fromJust $ mapM (flip Map.lookup varmap) ["X","B","D","A","S","L","T","E"] :: [TDV Positive]
m = mpe g [x,d] [b,a,s,l,t,e] [x =: Yes, d =: No]
typedResult = map (map (rename g . tdvi)) m :: [[(String,Positive)]]
assertBool "Test MPE" $ typedResult == [[("E",No),("T",No),("L",No),("S",No),("B",No),("A",No)]]
let m = mpe g [x,d,b,l,t,e] [a,s] [x =: Yes, d =: No]
typedResult = map (map (rename g . tdvi)) m :: [[(String,Positive)]]
assertBool "Test MAP" $ typedResult == [[("S",Yes),("A",No)]]
compareFarmReference = do
(varmap,g) <- anyExample "studfarm.net"
let jt = createJunctionTree nodeComparisonForTriangulation g
assertBool "Junction Tree property" $ junctionTreeProperty jt [] (root jt)
testWithRef varmap jt "L" [0.01,0.99]
testWithRef varmap jt "Ann" [0.01,0.99]
testWithRef varmap jt "Brian" [0.01,0.99]
testWithRef varmap jt "Cecily" [0.01,0.99]
testWithRef varmap jt "K" [0.01,0.99]
testWithRef varmap jt "Fred" [0.01,0.99]
testWithRef varmap jt "Dorothy" [0.01,0.99]
testWithRef varmap jt "Eric" [0.01,0.99]
testWithRef varmap jt "Gwenn" [0.01,0.99]
testWithRef varmap jt "Henry" [0.0091,0.9909]
testWithRef varmap jt "Irene" [0.0099,0.9901]
testWithRef varmap jt "John" [0.0004,0.0087,0.9909]
comparePokerReference = do
(varmap,g) <- anyExample "poker.net"
let jt = createJunctionTree nodeComparisonForTriangulation g
assertBool "Junction Tree property" $ junctionTreeProperty jt [] (root jt)
testWithRef varmap jt "OH0" [0.1672, 0.0445,0.0635,0.4659,0.1694,0.0494,0.0353,0.0024,0.0024]
testWithRef varmap jt "OH1" [0.0265,0.0170,0.0357,0.4125,0.2633,0.1599,0.0676,0.0098,0.0077]
testWithRef varmap jt "OH2" [0.2472,0.0628,0.2903,0.0258,0.2526,0.0881,0.0212,0.0121]
testWithRef varmap jt "SC" [0.2450,0.7116,0.0435]
testWithRef varmap jt "FC" [0.0895,0.6988,0.0445,0.1672]
testWithRef varmap jt "Besthand" [0.6396,0.3604]
testWithRef varmap jt "MH" [0.1250,0.1250,0.1250,0.1250,0.1250,0.1250,0.1250,0.1250]
compareAsiaReference = do
(varmap,g) <- anyExample "asia.net"
let jt = createJunctionTree nodeComparisonForTriangulation g
assertBool "Junction Tree property" $ junctionTreeProperty jt [] (root jt)
testWithRef varmap jt "A" [0.0100, 0.9900]
testWithRef varmap jt "S" [0.5000, 0.5000]
testWithRef varmap jt "T" [0.0104, 0.9896]
testWithRef varmap jt "L" [0.0550, 0.9450]
testWithRef varmap jt "B" [0.4500, 0.5500]
testWithRef varmap jt "E" [0.0648, 0.9352]
testWithRef varmap jt "X" [0.1103, 0.8897]
testWithRef varmap jt "D" [0.4360, 0.5640]
-- | Type defined to set the evidence on the Coma variable
-- from the cancer network.
data Coma = Present | Absent deriving(Eq,Enum,Bounded)
compareCancerReference = do
(varmap,g) <- anyExample "cancer.net"
let jt = createJunctionTree nodeComparisonForTriangulation g
assertBool "Junction Tree property" $ junctionTreeProperty jt [] (root jt)
testWithRef varmap jt "A" [0.2000, 0.8000]
testWithRef varmap jt "B" [0.3200, 0.6800]
testWithRef varmap jt "C" [0.0800, 0.9200]
testWithRef varmap jt "D" [0.3200, 0.6800]
testWithRef varmap jt "E" [0.6160, 0.3840]
let varD = fromJust $ Map.lookup "D" varmap
let jt' = changeEvidence [varD =: Present] jt
testWithRef varmap jt' "A" [0.4250, 0.5750]
testWithRef varmap jt' "B" [0.8000, 0.2000]
testWithRef varmap jt' "C" [0.2000, 0.8000]
testWithRef varmap jt' "D" [1.0000, 0.0000]
testWithRef varmap jt' "E" [0.6400, 0.3600]
let jt'' = changeEvidence [varD =: Absent] jt'
testWithRef varmap jt'' "A" [0.0941, 0.9059]
testWithRef varmap jt'' "B" [0.0941, 0.9059]
testWithRef varmap jt'' "C" [0.0235, 0.9765]
testWithRef varmap jt'' "D" [0.0000, 1.0000]
testWithRef varmap jt'' "E" [0.6047, 0.3953]
#endif