smcdel-1.3.0: src/SMCDEL/Symbolic/K.hs
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, ScopedTypeVariables #-}
{- |
The implementation in "SMCDEL.Symbolic.S5" only works for models where the
epistemic accessibility relation is an equivalence relation.
This is because only those can be described by sets of observational variables.
In fact, not even every S5 relation on distinctly valuated worlds can be modeled with observational variables --- this is why our translation procedure `SMCDEL.Translation.S5` has to add additional atomic propositions.
To overcome this limitation, here we generalize the definition of knowledge structures.
Using well-known methods from temporal model checking, arbitrary relations can also be represented as BDDs.
See for example~\cite{GoroRyan02:BelRevBDD}.
Remember that in a knowledge structure we can identify states with boolean assignments and those are just sets of propositions.
Hence a relation on states with unique valuations can be seen as a relation between sets of propositions.
We can therefore represent it with the BDD of a characteristic function on a double vocabulary, as described in~\cite[Section 5.2]{ClarkeGrumbergPeled1999:MC}.
Intuitively, we construct (the BDD of) a formula which is true exactly for the pairs of boolean assignments that are connected by the relation.
Our symbolic model checker can then also be used for non-S5 models.
For further explanations, see~\cite[Section 8]{BEGS17:SMCDELbeyond}.
-}
module SMCDEL.Symbolic.K where
import Data.Tagged
import Control.Arrow ((&&&),first)
import Data.Dynamic (fromDynamic)
import Data.HasCacBDD hiding (Top,Bot)
import Data.List (delete,intercalate,sort,intersect,nub,(\\))
import qualified Data.Map.Strict as M
import Data.Map.Strict ((!))
import Test.QuickCheck
import SMCDEL.Explicit.K
import SMCDEL.Internal.Help (apply,lfp,powerset)
import SMCDEL.Internal.TexDisplay
import SMCDEL.Language
import SMCDEL.Other.BDD2Form
import SMCDEL.Symbolic.S5 (State,texBDD,boolBddOf,texBddWith,bddEval,relabelWith)
import SMCDEL.Translations.S5 (booloutof)
-- * Translating relations to type-safe BDDs
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
-- | Map p or p' in double vocabulary to p in single 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]
-- | Go from p in double vocabulary to p in single vocabulary.
unmv = map f where
f (P m) | odd m = error "unmv failed: Number is odd!"
| otherwise = P $ m `div` 2
-- | Go from p' in double vocabulary to p in single vocabulary.
uncp = map f where
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 = Tagged $ relabelFun (\n -> (2*n) + 1) b
mvBdd :: Bdd -> RelBDD
mvBdd b = Tagged $ relabelFun (2 *) b
unmvBdd :: RelBDD -> Bdd
unmvBdd (Tagged b) =
relabelFun (\n -> if even n then n `div` 2 else error ("Not even: " ++ show n ++ "in the RelBDD " ++ show b)) b
propRel2bdd :: [Prp] -> M.Map State [State] -> RelBDD
propRel2bdd props relation = pure $ disSet (M.elems $ M.mapWithKey linkbdd relation) where
linkbdd here theres =
con (booloutof (mv here) (mv props))
(disSet [ booloutof (cp there) (cp props) | there <- theres ] )
samplerel :: M.Map State [State]
samplerel = M.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] ] ) ]
-- * Describing Kripke Models with BDDs
{- $
We now want to use BDDs to represent the relations of multiple agents
in a general Kripke Model. Suppose we have a model for the vocabulary
$V$ in which the valuation function assigns to every state a distinct
set of true propositions. To simplify the notation we also write $s$
for the set of propositions true at $s$.
-}
-- | Translate an agent's relation of worlds to a relation of sets of propositions.
-- The given model must have distinct valuations.
relBddOfIn :: Agent -> KripkeModel -> RelBDD
relBddOfIn i (KrM m)
| not (distinctVal (KrM m)) = error "m does not have distinct valuations."
| otherwise = pure $ disSet (M.elems $ M.map linkbdd m) where
linkbdd (mapPropBool,mapAgentReach) =
con
(booloutof (mv here) (mv props))
(disSet [ booloutof (cp there) (cp props) | there<-theres ] )
where
props = M.keys mapPropBool
here = M.keys (M.filter id mapPropBool)
theres = map (truthsInAt (KrM m)) (mapAgentReach ! i)
-- * Belief Structures
data BelStruct = BlS [Prp] -- vocabulary
Bdd -- state law
(M.Map Agent RelBDD) -- observation laws
deriving (Eq,Show)
instance Pointed BelStruct State
type BelScene = (BelStruct,State)
instance Pointed BelStruct Bdd
type MultipointedBelScene = (BelStruct,Bdd)
instance HasVocab BelStruct where
vocabOf (BlS voc _ _) = voc
instance HasAgents BelStruct where
agentsOf (BlS _ _ obdds) = M.keys obdds
-- | Given a formula, compute a BDD that is equivalent to that formula, on a given belief structure.
bddOf :: BelStruct -> Form -> Bdd
bddOf _ Top = top
bddOf _ Bot = bot
bddOf _ (PrpF (P n)) = var n
bddOf bls (Neg form) = neg $ bddOf bls form
bddOf bls (Conj forms) = conSet $ map (bddOf bls) forms
bddOf bls (Disj forms) = disSet $ map (bddOf bls) forms
bddOf bls (Xor forms) = xorSet $ map (bddOf bls) forms
bddOf bls (Impl f g) = imp (bddOf bls f) (bddOf bls g)
bddOf bls (Equi f g) = equ (bddOf bls f) (bddOf bls g)
bddOf bls (Forall ps f) = forallSet (map fromEnum ps) (bddOf bls f)
bddOf bls (Exists ps f) = existsSet (map fromEnum ps) (bddOf bls f)
bddOf bls@(BlS allprops lawbdd obdds) (K i form) = unmvBdd result where
result = forallSet ps' <$> (imp <$> cpBdd lawbdd <*> (imp <$> omegai <*> cpBdd (bddOf bls form)))
ps' = map fromEnum $ cp allprops
omegai = obdds ! i
bddOf bls@(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 bls f)))
ps' = map fromEnum $ cp allprops
omegai = obdds ! i
bddOf bls@(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 bls form) z)))
bddOf bls (Ckw ags form) = dis (bddOf bls (Ck ags form)) (bddOf bls (Ck ags (Neg form)))
bddOf bls@(BlS allprops lawbdd obdds) (Dk ags form) = unmvBdd result where
result = forallSet ps' <$> (imp <$> cpBdd lawbdd <*> (imp <$> omegai <*> cpBdd (bddOf bls form)))
ps' = map fromEnum $ cp allprops
omegai = Tagged $ foldr (con . untag) top [obdds ! i | i <- ags]
bddOf bls@(BlS allprops lawbdd obdds) (Dkw ags form) = unmvBdd result where
result = dis <$> part form <*> part (Neg form)
part f = forallSet ps' <$> (imp <$> cpBdd lawbdd <*> (imp <$> omegai <*> cpBdd (bddOf bls f)))
ps' = map fromEnum $ cp allprops
omegai = Tagged $ foldr (con . untag) top [obdds ! i | i <- ags]
bddOf bls (PubAnnounce f g) =
imp (bddOf bls f) (bddOf (bls `update` f) g)
bddOf bls (PubAnnounceW f g) =
ifthenelse (bddOf bls f)
(bddOf (bls `update` f) g)
(bddOf (bls `update` Neg f) g)
bddOf bls@(BlS props _ _) (Announce ags f g) =
imp (bddOf bls f) (restrict bdd2 (k,True)) where
bdd2 = bddOf (announce bls ags f) g
(P k) = freshp props
bddOf bls@(BlS props _ _) (AnnounceW ags f g) =
ifthenelse (bddOf bls f) bdd2a bdd2b where
bdd2a = restrict (bddOf (announce bls ags f ) g) (k,True)
bdd2b = restrict (bddOf (announce bls ags (Neg f)) g) (k,True)
(P k) = freshp props
bddOf bls (Dia (Dyn dynLabel d) f) =
con (bddOf bls preCon) -- 5. Prefix with "precon AND ..." (diamond!)
. relabelWith copyrelInverse -- 4. Copy back changeProps V_-^o to V_-
. simulateActualEvents -- 3. Simulate actual event(s) [see below]
. substitSimul [ (k, changeLaw ! p) -- 2. Replace changeProps V_- with postcons
| p@(P k) <- changeProps] -- (no "relabelWith copyrel", undone in 4)
. bddOf (bls `update` trf) -- 1. boolean equivalent wrt new struct
$ f
where
changeProps = M.keys changeLaw
copychangeProps = [(freshp $ vocabOf bls ++ addProps)..]
copyrelInverse = zip copychangeProps changeProps
(trf@(Trf addProps addLaw changeLaw _), shiftrel) = shiftPrepare bls trfUnshifted
(preCon,trfUnshifted,simulateActualEvents) =
case fromDynamic d of
-- 3. For a single pointed event, simulate actual event x outof V+
Just ((t,x) :: Event) -> ( preOf (t,x), t, (`restrictSet` actualAss) )
where actualAss = [(newK, P k `elem` x) | (P k, P newK) <- shiftrel]
Nothing -> case fromDynamic d of
-- 3. For a multipointed event, simulate a set of actual events by ...
Just ((t,xsBdd) :: MultipointedEvent) ->
( preOf (t,xsBdd), t
, existsSet (map fromEnum addProps) -- ... replacing addProps with assigments
. con actualsBdd -- ... that satisfy actualsBdd
. con (bddOf bls addLaw) -- ... and a precondition.
) where actualsBdd = relabelWith shiftrel xsBdd
Nothing -> error $ "cannot update belief structure with '" ++ dynLabel ++ "':\n " ++ show d
validViaBdd :: BelStruct -> Form -> Bool
validViaBdd bls@(BlS _ lawbdd _) f = top == imp lawbdd (bddOf bls f)
evalViaBdd :: BelScene -> Form -> Bool
evalViaBdd (bls@(BlS allprops _ _),s) f = let
bdd = bddOf bls 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"
++ " bls: " ++ show bls ++ "\n"
++ " s: " ++ show s ++ "\n"
++ " form: " ++ show f ++ "\n"
++ " bdd: " ++ show bdd ++ "\n"
++ " list: " ++ show list ++ "\n"
++ " b: " ++ show b ++ "\n"
instance Semantics BelStruct where
isTrue = validViaBdd
instance Semantics BelScene where
isTrue = evalViaBdd
instance Semantics MultipointedBelScene where
isTrue (kns@(BlS _ lawBdd _),statesBdd) f =
let a = lawBdd `imp` (statesBdd `imp` bddOf kns f)
in a == top
instance Update BelStruct Form where
checks = [ ] -- unpointed structures can be updated with anything
unsafeUpdate bls@(BlS props lawbdd obs) psi =
BlS props (lawbdd `con` bddOf bls psi) obs
instance Update BelScene Form where
unsafeUpdate (kns,s) psi = (unsafeUpdate kns psi,s)
announce :: BelStruct -> [Agent] -> Form -> BelStruct
announce bls@(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 bls psi))
newobdds = M.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'
-- | Get all states of a knowledge structure.
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
-- * Visualizing Belief Structures
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))) (M.toList obdds)
bddstring (i,os) = "\\Omega_{\\text{" ++ i ++ "}} = " ++ bddprefix ++ os ++ bddsuffix
instance TexAble BelScene where
tex (bls, state) = concat
[ " \\left( \n", tex bls, ", ", tex state, " \\right) \n" ]
instance TexAble MultipointedBelScene where
tex (bls, statesBdd) = concat
[ " \\left( \n"
, tex bls ++ ", "
, " \\begin{array}{l} \\scalebox{0.4}{"
, texBDD statesBdd
, "} \\end{array}\n "
, " \\right)" ]
cleanupObsLaw :: BelScene -> BelScene
cleanupObsLaw (BlS vocab law obs, s) = (BlS vocab law (M.map clean obs), s) where
clean 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
$ nub
$ concatMap (map P . Data.HasCacBDD.allVarsOf . untag)
$ M.elems obs
withoutProps :: [Prp] -> BelStruct -> BelStruct
withoutProps propsToDel (BlS oldProps oldLawBdd oldObs) =
BlS
(oldProps \\ propsToDel)
(existsSet (map fromEnum propsToDel) oldLawBdd)
(M.map (fmap $ existsSet (map fromEnum propsToDel)) oldObs)
equivExtraVocabOf :: [Prp] -> BelStruct -> [(Prp,Prp)]
equivExtraVocabOf mainVocab bls =
[ (p,q) | p <- vocabOf bls \\ mainVocab, q <- vocabOf bls, p > q, validViaBdd bls (PrpF p `Equi` PrpF q) ]
replaceWithIn :: (Prp,Prp) -> BelStruct -> BelStruct
replaceWithIn (p,q) (BlS oldProps oldLaw oldObs) =
BlS (delete p oldProps) (changeBdd oldLaw) (fmap (fmap changeRelBdd) oldObs) where
changeBdd = Data.HasCacBDD.relabel [ (fromEnum p, fromEnum q) ]
changeRelBdd = Data.HasCacBDD.relabel $ sort [ (fromEnum $ mvP p, fromEnum $ mvP q)
, (fromEnum $ cpP p, fromEnum $ cpP q) ]
replaceEquivExtra :: [Prp] -> BelStruct -> (BelStruct,[(Prp,Prp)])
replaceEquivExtra mainVocab startBls = lfp step (startBls,[]) where
step (bls,replRel) = case equivExtraVocabOf mainVocab bls of
[] -> (bls,replRel)
((p,q):_) -> (replaceWithIn (p,q) bls, (p,q):replRel)
instance Optimizable BelStruct where
optimize myVocab bls = fst $ replaceEquivExtra myVocab $
withoutProps ((determinedVocabOf bls `intersect` nonobsVocabOf bls) \\ myVocab) bls
instance Optimizable MultipointedBelScene where
optimize myVocab (oldBls,oldStatesBdd) = (newKns,newStatesBdd) where
intermediateBls = withoutProps ((determinedVocabOf oldBls `intersect` nonobsVocabOf oldBls) \\ myVocab) oldBls
removedProps = vocabOf oldBls \\ vocabOf intermediateBls
intermediateStatesBdd = existsSet (map fromEnum removedProps) oldStatesBdd
(newKns,replRel) = replaceEquivExtra myVocab intermediateBls
newStatesBdd = Data.HasCacBDD.relabel [ (fromEnum p, fromEnum q) | (p,q) <-replRel ] intermediateStatesBdd
instance Arbitrary BelStruct where
arbitrary = do
numExtraVars <- choose (0,2)
let myVocabulary = defaultVocabulary ++ take numExtraVars [freshp defaultVocabulary ..]
(BF statelaw) <- sized (randomboolformWith myVocabulary) `suchThat` (\(BF bf) -> boolBddOf bf /= bot)
obs <- mapM (\i -> do
BF obsLaw <- sized $ randomboolformWith (sort $ mv myVocabulary ++ cp myVocabulary) -- FIXME should rather be a random BDD?
return (i,pure $ boolBddOf obsLaw)
) defaultAgents
return $ BlS myVocabulary (boolBddOf statelaw) (M.fromList obs)
shrink bls = [ withoutProps [p] bls | length (vocabOf bls) > 1, p <- vocabOf bls \\ defaultVocabulary ]
data Transformer = Trf
[Prp] -- addprops
Form -- addlaw
(M.Map Prp Bdd) -- changelaw
(M.Map Agent RelBDD) -- eventObs
deriving (Eq,Show)
noChange :: ([Prp] -> Form -> M.Map Prp Bdd -> M.Map Agent RelBDD -> Transformer)
-> [Prp] -> Form -> M.Map Agent RelBDD -> Transformer
noChange kntrf addprops addlaw = kntrf addprops addlaw M.empty
instance HasAgents Transformer where
agentsOf (Trf _ _ _ obdds) = M.keys obdds
instance HasPrecondition Transformer where
preOf _ = Top
instance Pointed Transformer State
type Event = (Transformer,State)
instance HasPrecondition Event where
preOf (Trf addprops addlaw _ _, x) = simplify $ substitOutOf x addprops addlaw
instance Pointed Transformer Bdd
type MultipointedEvent = (Transformer,Bdd)
instance HasPrecondition MultipointedEvent where
preOf (Trf addprops addlaw _ _, xsBdd) =
simplify $ Exists addprops (Conj [ formOf xsBdd, addlaw ])
instance TexAble Transformer where
tex (Trf addprops addlaw changelaw eventObs) = concat
[ " \\left( \n"
, tex addprops, ", "
, tex addlaw, ", "
, tex changeprops, ", "
, intercalate ", " $ map snd . M.toList $ M.mapWithKey texChange changelaw, ", "
, intercalate ", " eobddstrings
, " \\right) \n"
] where
changeprops = M.keys changelaw
texChange prop changebdd = tex prop ++ " := " ++ tex (formOf changebdd)
eobddstrings = map (bddstring . (fst &&& (texRelBDD . snd))) (M.toList eventObs)
bddstring (i,os) = "\\Omega^+_{\\text{" ++ i ++ "}} = " ++ bddprefix ++ os ++ bddsuffix
instance TexAble Event where
tex (trf, eventFacts) = concat
[ " \\left( \n", tex trf, ", ", tex eventFacts, " \\right) \n" ]
instance TexAble MultipointedEvent where
tex (trf, eventStates) = concat
[ " \\left( \n"
, tex trf ++ ", \\ "
, " \\begin{array}{l} \\scalebox{0.4}{"
, texBDD eventStates
, "} \\end{array}\n "
, " \\right)" ]
-- | shift addprops to ensure that props and newprops are disjoint:
shiftPrepare :: BelStruct -> Transformer -> (Transformer, [(Prp,Prp)])
shiftPrepare (BlS props _ _) (Trf addprops addlaw changelaw eventObs) =
(Trf shiftaddprops addlawShifted changelawShifted eventObsShifted, shiftrel) where
shiftrel = sort $ zip addprops [(freshp props)..]
shiftaddprops = map snd shiftrel
-- apply the shifting to addlaw, changelaw and eventObs:
addlawShifted = replPsInF shiftrel addlaw
changelawShifted = M.map (relabelWith shiftrel) changelaw
-- to shift addObs we need shiftrel in the double vocabulary:
shiftrelMVCP = sort $ zip (mv addprops) (mv shiftaddprops)
++ zip (cp addprops) (cp shiftaddprops)
eventObsShifted = M.map (fmap $ relabelWith shiftrelMVCP) eventObs
instance Update BelScene Event where
unsafeUpdate (bls@(BlS props law obdds),s) (trf, eventFactsUnshifted) = (BlS newprops newlaw newobs, news) where
-- PART 1: SHIFTING addprops to ensure props and newprops are disjoint
(Trf addprops addlaw changelaw addObs, shiftrel) = shiftPrepare bls trf
-- the actual event:
eventFacts = map (apply shiftrel) eventFactsUnshifted
-- PART 2: COPYING the modified propositions
changeprops = M.keys changelaw
copyrel = zip changeprops [(freshp $ props ++ addprops)..]
copychangeprops = map snd copyrel
copyrelMVCP = sort $ zip (mv changeprops) (mv copychangeprops)
++ zip (cp changeprops) (cp copychangeprops)
-- PART 3: actual transformation
newprops = sort $ props ++ addprops ++ copychangeprops
newlaw = conSet $ relabelWith copyrel (con law (bddOf bls addlaw))
: [var (fromEnum q) `equ` relabelWith copyrel (changelaw ! q) | q <- changeprops]
newobs = M.mapWithKey (\i oldobs -> (con . relabelWith copyrelMVCP <$> oldobs) <*> (addObs ! i)) obdds
news = sort $ concat
[ s \\ changeprops
, map (apply copyrel) $ s `intersect` changeprops
, eventFacts
, filter (\ p -> bddEval (s ++ eventFacts) (changelaw ! p)) changeprops ]
instance Update BelStruct Transformer where
checks = [haveSameAgents]
unsafeUpdate bls ctrf = BlS newprops newlaw newobs where
(BlS newprops newlaw newobs, _) = unsafeUpdate (bls,undefined::State) (ctrf,undefined::State) -- using laziness!
instance Update BelScene MultipointedEvent where
unsafeUpdate (bls,s) (trfUnshifted, eventFactsBddUnshifted) =
update (bls,s) (trf,selectedEventState) where
(trf@(Trf addprops addlaw _ _), shiftRel) = shiftPrepare bls trfUnshifted
eventFactsBdd = relabelWith shiftRel eventFactsBddUnshifted
selectedEventState :: State
selectedEventState = map (P . fst) $ filter snd selectedEvent
selectedEvent = case
allSatsWith
(map fromEnum addprops)
(eventFactsBdd `con` restrictSet (bddOf bls addlaw) [ (k, P k `elem` s) | P k <- vocabOf bls ])
of
[] -> error "no selected event"
[this] -> this
more -> error $ "too many selected events: " ++ show more
-- TODO: test this!
instance Update MultipointedBelScene MultipointedEvent where
checks = [haveSameAgents] -- no need to check precondition, we allow an empty set of actual states
unsafeUpdate (bls@(BlS props _ _),statesBdd) (trfUnshifted, eventsBddUnshifted) =
(newBls, newStatesBdd) where
-- shiftPrepare first to ensure that eventsBdd is also shifted
(trf@(Trf addprops _ changelaw _), shiftRel) = shiftPrepare bls trfUnshifted
eventsBdd = relabelWith shiftRel eventsBddUnshifted
(newBls, _) = unsafeUpdate (bls,undefined::State) (trf,undefined::State) -- using laziness!
-- the actual event:
changeprops = M.keys changelaw
copyrel = zip changeprops [(freshp $ props ++ addprops)..]
newStatesBdd = conSet [ relabelWith copyrel statesBdd, eventsBdd ]
trfPost :: Event -> Prp -> Bdd
trfPost (Trf addprops _ changelaw _, x) p
| p `elem` M.keys changelaw = restrictLaw (changelaw ! p) (booloutof x addprops)
| otherwise = boolBddOf $ PrpF p
reduce :: Event -> Form -> Maybe Form
reduce _ Top = Just Top
reduce e Bot = Just $ Neg $ preOf e
reduce e (PrpF p) = Impl (preOf e) <$> Just (formOf $ trfPost e p)
reduce e (Neg f) = Impl (preOf e) . Neg <$> reduce e f
reduce e (Conj fs) = Conj <$> mapM (reduce e) fs
reduce e (Disj fs) = Disj <$> mapM (reduce e) fs
reduce e (Xor fs) = Impl (preOf e) . Xor <$> mapM (reduce e) fs
reduce e (Impl f1 f2) = Impl <$> reduce e f1 <*> reduce e f2
reduce e (Equi f1 f2) = Equi <$> reduce e f1 <*> reduce e f2
reduce _ (Forall _ _) = Nothing
reduce _ (Exists _ _) = Nothing
reduce e@(t@(Trf addprops _ _ eventObs), x) (K a f) =
Impl (preOf e) . Conj <$> sequence
[ K a <$> reduce (t,y) f | y <- powerset addprops -- FIXME is this a bit much?
, tagBddEval (mv x ++ cp y) (eventObs ! a)
]
reduce e (Kw a f) = reduce e (Disj [K a f, K a (Neg f)])
reduce _ Ck {} = Nothing
reduce _ Ckw {} = Nothing
reduce e@(t@(Trf addprops _ _ eventObs), x) (Dk ags f) =
Impl (preOf e) . Conj <$> sequence
[Dk ags <$> reduce (t, y) f |
let omegai = Tagged $ foldr (con . untag) top [eventObs ! i | i <- ags] :: RelBDD,
y <- powerset addprops,
tagBddEval (mv x ++ cp y) omegai]
reduce e (Dkw ags f) = reduce e (Disj [Dk ags f, Dk ags (Neg f)])
reduce _ PubAnnounce {} = Nothing
reduce _ PubAnnounceW {} = Nothing
reduce _ Announce {} = Nothing
reduce _ AnnounceW {} = Nothing
reduce _ Dia {} = Nothing
bddReduce :: BelScene -> Event -> Form -> Bdd
bddReduce scn@(oldBls,_) event@(Trf addprops _ changelaw _, eventFacts) f =
let
changeprops = M.keys changelaw
-- same as in 'transform', to ensure props and addprops are disjoint
shiftaddprops = [(freshp $ vocabOf scn)..]
shiftrel = sort $ zip addprops shiftaddprops
-- apply the shifting to addlaw and changelaw:
changelawShifted = M.map (relabelWith shiftrel) changelaw
(newBlS,_) = update scn event
-- the actual event, shifted
actualAss = [ (shifted, P orig `elem` eventFacts) | (P orig, P shifted) <- shiftrel ]
postconrel = [ (n, changelawShifted ! P n) | (P n) <- changeprops ]
-- reversing V^o to V
copychangeprops = [(freshp $ vocabOf scn ++ map snd shiftrel)..]
copyrelInverse = zip copychangeprops changeprops
in
imp (bddOf oldBls (preOf event)) $ -- 0. check if precondition holds
relabelWith copyrelInverse $ -- 4. changepropscopies -> original changeprops
(`restrictSet` actualAss) $ -- 3. restrict to actual event x outof V+
substitSimul postconrel $ -- 2. replace changeprops with postconditions
bddOf newBlS f -- 1. boolean equivalent wrt new structure
evalViaBddReduce :: BelScene -> Event -> Form -> Bool
evalViaBddReduce (bls,s) event f = evaluateFun (bddReduce (bls,s) event f) (\n -> P n `elem` s)