smcdel-1.0.0: src/SMCDEL/Symbolic/K.hs
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, TypeOperators #-}
module SMCDEL.Symbolic.K where
import Data.Tagged
import Control.Arrow ((&&&),(***),first)
import Data.HasCacBDD hiding (Top,Bot)
import Data.List (intercalate,sort)
import Data.Map.Strict (Map,fromList,toList,elems,(!))
import qualified Data.Map.Strict
import SMCDEL.Language
import SMCDEL.Symbolic.S5 (KnowScene,State,texBDD,boolBddOf,texBddWith)
import SMCDEL.Explicit.S5 (PointedModelS5,KripkeModelS5(KrMS5),World)
import SMCDEL.Explicit.K
import SMCDEL.Translations.S5
import SMCDEL.Internal.Help (apply,lfp)
import SMCDEL.Internal.TexDisplay
problemPM :: PointedModelS5
problemPM = ( KrMS5 [0,1,2,3] [ (alice,[[0],[1,2,3]]), (bob,[[0,1,2],[3]]) ]
[ (0,[(P 1,True ),(P 2,True )]), (1,[(P 1,True ),(P 2,False)])
, (2,[(P 1,False),(P 2,True )]), (3,[(P 1,False),(P 2,False)]) ], 1::World )
problemKNS :: KnowScene
problemKNS = kripkeToKns problemPM
mvP, cpP :: Prp -> Prp
mvP (P n) = P (2*n) -- represent p in the double vocabulary
cpP (P n) = P ((2*n) + 1) -- represent p' in the double vocabulary
unmvcpP :: Prp -> Prp
unmvcpP (P m) | even m = P $ m `div` 2
| otherwise = P $ (m-1) `div` 2
mv, cp :: [Prp] -> [Prp]
mv = map mvP
cp = map cpP
unmv, uncp :: [Prp] -> [Prp]
unmv = map f where -- Go from p in double vocabulary to p in single vocabulary:
f (P m) | odd m = error "unmv failed: Number is odd!"
| otherwise = P $ m `div` 2
uncp = map f where -- Go from p' in double vocabulary to p in single vocabulary:
f (P m) | even m = error "uncp failed: Number is even!"
| otherwise = P $ (m-1) `div` 2
data Dubbel
type RelBDD = Tagged Dubbel Bdd
totalRelBdd, emptyRelBdd :: RelBDD
totalRelBdd = pure $ boolBddOf Top
emptyRelBdd = pure $ boolBddOf Bot
allsamebdd :: [Prp] -> RelBDD
allsamebdd ps = pure $ conSet [boolBddOf $ PrpF p `Equi` PrpF p' | (p,p') <- zip (mv ps) (cp ps)]
class TagBdd a where
tagBddEval :: [Prp] -> Tagged a Bdd -> Bool
tagBddEval truths querybdd = evaluateFun (untag querybdd) (\n -> P n `elem` truths)
instance TagBdd Dubbel
cpBdd :: Bdd -> RelBDD
cpBdd b = pure $ case maxVarOf b of
Nothing -> b
Just m -> relabel [ (n, (2*n) + 1) | n <- [0..m] ] b
mvBdd :: Bdd -> RelBDD
mvBdd b = pure $ case maxVarOf b of
Nothing -> b
Just m -> relabel [ (n, 2*n) | n <- [0..m] ] b
unmvBdd :: RelBDD -> Bdd
unmvBdd (Tagged b) = case maxVarOf b of
Nothing -> b
Just m -> relabel [ (2 * n, n) | n <- [0..m] ] b
propRel2bdd :: [Prp] -> Map State [State] -> RelBDD
propRel2bdd props rel = pure $ disSet (elems $ Data.Map.Strict.mapWithKey linkbdd rel) where
linkbdd here theres =
con (booloutof (mv here) (mv props))
(disSet [ booloutof (cp there) (cp props) | there <- theres ] )
samplerel :: Map State [State]
samplerel = fromList [
( [] , [ [],[P 1],[P 2],[P 1, P 2] ] ),
( [P 1] , [ [P 1], [P 1, P 2] ] ),
( [P 2] , [ [P 2], [P 1, P 2] ] ),
( [P 1, P 2], [ [P 1, P 2] ] ) ]
relBddOfIn :: Agent -> KripkeModel -> RelBDD
relBddOfIn i (KrM m)
| not (distinctVal (KrM m)) = error "m does not have distinct valuations."
| otherwise = pure $ disSet (elems $ Data.Map.Strict.map linkbdd m) where
linkbdd (mapPropBool,mapAgentReach) =
con
(booloutof (mv here) (mv props))
(disSet [ booloutof (cp there) (cp props) | there<-theres ] )
where
props = Data.Map.Strict.keys mapPropBool
here = Data.Map.Strict.keys (Data.Map.Strict.filter id mapPropBool)
theres = map (truthsInAt (KrM m)) (mapAgentReach ! i)
data BelStruct = BlS [Prp] -- vocabulary
Bdd -- state law
(Map Agent RelBDD) -- observation laws
deriving (Eq,Show)
type BelScene = (BelStruct,State)
instance HasVocab BelStruct where
vocabOf (BlS voc _ _) = voc
instance HasVocab BelScene where
vocabOf = vocabOf . fst
instance HasAgents BelStruct where
agentsOf (BlS _ _ obdds) = Data.Map.Strict.keys obdds
instance HasAgents BelScene where
agentsOf = agentsOf . fst
bddOf :: BelStruct -> Form -> Bdd
bddOf _ Top = top
bddOf _ Bot = bot
bddOf _ (PrpF (P n)) = var n
bddOf kns (Neg form) = neg $ bddOf kns form
bddOf kns (Conj forms) = conSet $ map (bddOf kns) forms
bddOf kns (Disj forms) = disSet $ map (bddOf kns) forms
bddOf kns (Xor forms) = xorSet $ map (bddOf kns) forms
bddOf kns (Impl f g) = imp (bddOf kns f) (bddOf kns g)
bddOf kns (Equi f g) = equ (bddOf kns f) (bddOf kns g)
bddOf kns (Forall ps f) = forallSet (map fromEnum ps) (bddOf kns f)
bddOf kns (Exists ps f) = existsSet (map fromEnum ps) (bddOf kns f)
bddOf kns@(BlS allprops lawbdd obdds) (K i form) = unmvBdd result where
result = forallSet ps' <$> (imp <$> cpBdd lawbdd <*> (imp <$> omegai <*> cpBdd (bddOf kns form)))
ps' = map fromEnum $ cp allprops
omegai = obdds ! i
bddOf kns@(BlS allprops lawbdd obdds) (Kw i form) = unmvBdd result where
result = dis <$> part form <*> part (Neg form)
part f = forallSet ps' <$> (imp <$> cpBdd lawbdd <*> (imp <$> omegai <*> cpBdd (bddOf kns f)))
ps' = map fromEnum $ cp allprops
omegai = obdds ! i
bddOf kns@(BlS voc lawbdd obdds) (Ck ags form) = lfp lambda top where
ps' = map fromEnum $ cp voc
lambda :: Bdd -> Bdd
lambda z = unmvBdd $
forallSet ps' <$>
(imp <$> cpBdd lawbdd <*>
(imp <$> (disSet <$> sequence [obdds ! i | i <- ags]) <*>
cpBdd (con (bddOf kns form) z)))
bddOf kns (Ckw ags form) = dis (bddOf kns (Ck ags form)) (bddOf kns (Ck ags (Neg form)))
bddOf kns (PubAnnounce f g) =
imp (bddOf kns f) (bddOf (pubAnnounce kns f) g)
bddOf kns (PubAnnounceW f g) =
ifthenelse (bddOf kns f)
(bddOf (pubAnnounce kns f ) g)
(bddOf (pubAnnounce kns (Neg f)) g)
bddOf kns@(BlS props _ _) (Announce ags f g) =
imp (bddOf kns f) (restrict bdd2 (k,True)) where
bdd2 = bddOf (announce kns ags f) g
(P k) = freshp props
bddOf kns@(BlS props _ _) (AnnounceW ags f g) =
ifthenelse (bddOf kns f) bdd2a bdd2b where
bdd2a = restrict (bddOf (announce kns ags f ) g) (k,True)
bdd2b = restrict (bddOf (announce kns ags (Neg f)) g) (k,True)
(P k) = freshp props
validViaBdd :: BelStruct -> Form -> Bool
validViaBdd kns@(BlS _ lawbdd _) f = top == imp lawbdd (bddOf kns f)
evalViaBdd :: BelScene -> Form -> Bool
evalViaBdd (kns@(BlS allprops _ _),s) f = let
bdd = bddOf kns f
b = restrictSet bdd list
list = [ (n, P n `elem` s) | (P n) <- allprops ]
in
case (b==top,b==bot) of
(True,_) -> True
(_,True) -> False
_ -> error $ "evalViaBdd failed: Composite BDD leftover!\n"
++ " kns: " ++ show kns ++ "\n"
++ " s: " ++ show s ++ "\n"
++ " form: " ++ show f ++ "\n"
++ " bdd: " ++ show bdd ++ "\n"
++ " list: " ++ show list ++ "\n"
++ " b: " ++ show b ++ "\n"
pubAnnounce :: BelStruct -> Form -> BelStruct
pubAnnounce kns@(BlS allprops lawbdd obs) f =
BlS allprops (con lawbdd (bddOf kns f)) obs
pubAnnounceOnScn :: BelScene -> Form -> BelScene
pubAnnounceOnScn (kns,s) psi = if evalViaBdd (kns,s) psi
then (pubAnnounce kns psi,s)
else error "Liar!"
announce :: BelStruct -> [Agent] -> Form -> BelStruct
announce kns@(BlS props lawbdd obdds) ags psi = BlS newprops newlawbdd newobdds where
(P k) = freshp props
newprops = sort $ P k : props
newlawbdd = con lawbdd (imp (var k) (bddOf kns psi))
newobdds = Data.Map.Strict.mapWithKey newOfor obdds
newOfor i oi | i `elem` ags = con <$> oi <*> (equ <$> mvBdd (var k) <*> cpBdd (var k))
| otherwise = con <$> oi <*> (neg <$> cpBdd (var k)) -- p_psi'
statesOf :: BelStruct -> [State]
statesOf (BlS allprops lawbdd _) = map (sort.getTrues) prpsats where
bddvars = map fromEnum allprops
bddsats = allSatsWith bddvars lawbdd
prpsats = map (map (first toEnum)) bddsats
getTrues = map fst . filter snd
texRelBDD :: RelBDD -> String
texRelBDD (Tagged b) = texBddWith texRelProp b where
texRelProp n
| even n = show (n `div` 2)
| otherwise = show ((n - 1) `div` 2) ++ "'"
bddprefix, bddsuffix :: String
bddprefix = "\\begin{array}{l} \\scalebox{0.3}{"
bddsuffix = "} \\end{array} \n"
instance TexAble BelStruct where
tex (BlS props lawbdd obdds) = concat
[ " \\left( \n"
, tex props, ", "
, bddprefix, texBDD lawbdd, bddsuffix
, ", "
, intercalate ", " obddstrings
, " \\right) \n"
] where
obddstrings = map (bddstring . (fst &&& (texRelBDD . snd))) (toList obdds)
bddstring (i,os) = "\\Omega_{\\text{" ++ i ++ "}} = " ++ bddprefix ++ os ++ bddsuffix
instance TexAble BelScene where
tex (kns, state) = concat
[ " \\left( \n", tex kns, ", ", tex state, " \\right) \n" ]
cleanupObsLaw :: BelScene -> BelScene
cleanupObsLaw (BlS vocab law obs, s) = (BlS vocab law newobs, s) where
newobs = Data.Map.Strict.map optimize obs
optimize relbdd = restrictLaw <$> relbdd <*> (con <$> cpBdd law <*> mvBdd law)
determinedVocabOf :: BelStruct -> [Prp]
determinedVocabOf strct = filter (\p -> validViaBdd strct (PrpF p) || validViaBdd strct (Neg $ PrpF p)) (vocabOf strct)
nonobsVocabOf :: BelStruct -> [Prp]
nonobsVocabOf (BlS vocab _law obs) = filter (`notElem` usedVars) vocab where
usedVars =
map unmvcpP
$ sort
$ concatMap (map P . Data.HasCacBDD.allVarsOf . untag . snd)
$ Data.Map.Strict.toList obs
data BelTransf = BlT [Prp] Form (Map Agent RelBDD) deriving (Eq,Show)
type GenEvent = (BelTransf,State)
belTransform :: BelScene -> GenEvent -> BelScene
belTransform (kns@(BlS props lawbdd obdds),s) (BlT addprops addlaw eventObs, eventFacts) =
(BlS (props ++ map snd shiftrel) newlawbdd newobs, sort $ s ++ shiftedEventFacts) where
shiftrel = zip addprops [(freshp props)..]
doubleShiftrel = map (mvP *** mvP) shiftrel ++ map (cpP *** cpP) shiftrel
doubleShiftrelVars = sort $ map (fromEnum *** fromEnum) doubleShiftrel
shiftEventObsBDD o = relabel doubleShiftrelVars <$> o
newobs = fromList [ (i , con <$> (obdds ! i) <*> shiftEventObsBDD (eventObs ! i)) | i <- Data.Map.Strict.keys obdds ]
shiftaddlaw = replPsInF shiftrel addlaw
newlawbdd = con lawbdd (bddOf kns shiftaddlaw)
shiftedEventFacts = map (apply shiftrel) eventFacts
instance TexAble BelTransf where
tex (BlT addprops addlaw eventObs) = concat
[ " \\left( \n"
, tex addprops, ", "
, tex addlaw , ", "
, intercalate ", " eobddstrings
, " \\right) \n"
] where
eobddstrings = map (bddstring . (fst &&& (texRelBDD . snd))) (toList eventObs)
bddstring (i,os) = "\\Omega^+_{\\text{" ++ i ++ "}} = " ++ bddprefix ++ os ++ bddsuffix
instance TexAble GenEvent where
tex (blt, eventFacts) = concat
[ " \\left( \n", tex blt, ", ", tex eventFacts, " \\right) \n" ]
exampleStart :: BelScene
exampleStart = (BlS [P 0] law obs, actual) where
law = boolBddOf Top
obs = fromList [ ("1", mvBdd $ boolBddOf Top), ("2", allsamebdd [P 0]) ]
actual = [P 0]
exampleEvent :: GenEvent
exampleEvent = (BlT [P 1] addlaw eventObs, [P 1]) where
addlaw = PrpF (P 1) `Impl` PrpF (P 0)
eventObs = fromList [ ("1", allsamebdd [P 1]), ("2", cpBdd . boolBddOf $ Neg (PrpF $ P 1)) ]
exampleBlTresult :: BelScene
exampleBlTresult = belTransform exampleStart exampleEvent